forked from jsnbuchanan/crowd-funder-for-time-pwa
fix all copies for externally-shared links to redirected deep links
This commit is contained in:
@@ -77,7 +77,7 @@
|
|||||||
If you'd like an introduction,
|
If you'd like an introduction,
|
||||||
<a
|
<a
|
||||||
class="text-blue-500"
|
class="text-blue-500"
|
||||||
@click="copyToClipboard('A link to this page', windowLocation)"
|
@click="copyToClipboard('A link to this page', deepLinkUrl)"
|
||||||
>click here to copy this page, paste it into a message, and ask if
|
>click here to copy this page, paste it into a message, and ask if
|
||||||
they'll tell you more about the {{ roleName }}.</a
|
they'll tell you more about the {{ roleName }}.</a
|
||||||
>
|
>
|
||||||
@@ -104,7 +104,7 @@ import * as R from "ramda";
|
|||||||
import { useClipboard } from "@vueuse/core";
|
import { useClipboard } from "@vueuse/core";
|
||||||
import { Contact } from "../db/tables/contacts";
|
import { Contact } from "../db/tables/contacts";
|
||||||
import * as serverUtil from "../libs/endorserServer";
|
import * as serverUtil from "../libs/endorserServer";
|
||||||
import { NotificationIface } from "../constants/app";
|
import { APP_SERVER, NotificationIface } from "../constants/app";
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export default class HiddenDidDialog extends Vue {
|
export default class HiddenDidDialog extends Vue {
|
||||||
@@ -117,7 +117,8 @@ export default class HiddenDidDialog extends Vue {
|
|||||||
activeDid = "";
|
activeDid = "";
|
||||||
allMyDids: Array<string> = [];
|
allMyDids: Array<string> = [];
|
||||||
canShare = false;
|
canShare = false;
|
||||||
windowLocation = window.location.href;
|
deepLinkPathSuffix = "";
|
||||||
|
deepLinkUrl = window.location.href; // this is changed to a deep link in the setup
|
||||||
|
|
||||||
R = R;
|
R = R;
|
||||||
serverUtil = serverUtil;
|
serverUtil = serverUtil;
|
||||||
@@ -129,17 +130,21 @@ export default class HiddenDidDialog extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open(
|
open(
|
||||||
|
deepLinkPathSuffix: string,
|
||||||
roleName: string,
|
roleName: string,
|
||||||
visibleToDids: string[],
|
visibleToDids: string[],
|
||||||
allContacts: Array<Contact>,
|
allContacts: Array<Contact>,
|
||||||
activeDid: string,
|
activeDid: string,
|
||||||
allMyDids: Array<string>,
|
allMyDids: Array<string>,
|
||||||
) {
|
) {
|
||||||
|
this.deepLinkPathSuffix = deepLinkPathSuffix;
|
||||||
this.roleName = roleName;
|
this.roleName = roleName;
|
||||||
this.visibleToDids = visibleToDids;
|
this.visibleToDids = visibleToDids;
|
||||||
this.allContacts = allContacts;
|
this.allContacts = allContacts;
|
||||||
this.activeDid = activeDid;
|
this.activeDid = activeDid;
|
||||||
this.allMyDids = allMyDids;
|
this.allMyDids = allMyDids;
|
||||||
|
|
||||||
|
this.deepLinkUrl = APP_SERVER + "/deep-link/" + this.deepLinkPathSuffix;
|
||||||
this.isOpen = true;
|
this.isOpen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,11 +178,11 @@ export default class HiddenDidDialog extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClickShareClaim() {
|
onClickShareClaim() {
|
||||||
this.copyToClipboard("A link to this page", this.windowLocation);
|
this.copyToClipboard("A link to this page", this.deepLinkUrl);
|
||||||
window.navigator.share({
|
window.navigator.share({
|
||||||
title: "Help Connect Me",
|
title: "Help Connect Me",
|
||||||
text: "I'm trying to find the people who recorded this. Can you help me?",
|
text: "I'm trying to find the people who recorded this. Can you help me?",
|
||||||
url: this.windowLocation,
|
url: this.deepLinkUrl,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1074,7 +1074,8 @@ export async function generateEndorserJwtUrlForAccount(
|
|||||||
|
|
||||||
const vcJwt = await createEndorserJwtForDid(account.did, contactInfo);
|
const vcJwt = await createEndorserJwtForDid(account.did, contactInfo);
|
||||||
|
|
||||||
const viewPrefix = APP_SERVER + CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI;
|
const viewPrefix =
|
||||||
|
APP_SERVER + "/deep-link" + CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI;
|
||||||
return viewPrefix + vcJwt;
|
return viewPrefix + vcJwt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ import {
|
|||||||
} from "../interfaces/deepLinks";
|
} from "../interfaces/deepLinks";
|
||||||
import { logConsoleAndDb } from "../db/databaseUtil";
|
import { logConsoleAndDb } from "../db/databaseUtil";
|
||||||
import type { DeepLinkError } from "../interfaces/deepLinks";
|
import type { DeepLinkError } from "../interfaces/deepLinks";
|
||||||
import { logger } from "@/utils/logger";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles processing and routing of deep links in the application.
|
* Handles processing and routing of deep links in the application.
|
||||||
|
|||||||
@@ -49,21 +49,32 @@
|
|||||||
v-if="veriClaim.id"
|
v-if="veriClaim.id"
|
||||||
:to="'/claim-cert/' + encodeURIComponent(veriClaim.id)"
|
:to="'/claim-cert/' + encodeURIComponent(veriClaim.id)"
|
||||||
class="text-blue-500 mt-2"
|
class="text-blue-500 mt-2"
|
||||||
title="Printable Certificate"
|
title="View Printable Certificate"
|
||||||
>
|
>
|
||||||
<font-awesome
|
<font-awesome
|
||||||
icon="square"
|
icon="square"
|
||||||
class="text-white bg-yellow-500 p-1"
|
class="text-white bg-yellow-500 p-1"
|
||||||
/>
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
<button
|
||||||
|
v-if="veriClaim.id"
|
||||||
|
class="text-blue-500 ml-2 mt-2"
|
||||||
|
title="Copy Printable Certificate Link"
|
||||||
|
@click="
|
||||||
|
copyToClipboard(
|
||||||
|
'A link to the certificate page',
|
||||||
|
`${APP_SERVER}/deep-link/claim-cert/${veriClaim.id}`,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<font-awesome icon="link" class="text-yellow-500 p-1" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- show link icon to copy this URL to the clipboard -->
|
<!-- show link icon to copy this URL to the clipboard -->
|
||||||
<div class="flex justify-end w-full">
|
<div class="flex justify-end w-full">
|
||||||
<button
|
<button
|
||||||
title="Copy Link"
|
title="Copy Link"
|
||||||
@click="
|
@click="copyToClipboard('A link to this page', windowDeepLink)"
|
||||||
copyToClipboard('A link to this page', window.location.href)
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<font-awesome icon="link" class="text-slate-500" />
|
<font-awesome icon="link" class="text-slate-500" />
|
||||||
</button>
|
</button>
|
||||||
@@ -405,7 +416,7 @@
|
|||||||
contacts can see more details:
|
contacts can see more details:
|
||||||
<a
|
<a
|
||||||
class="text-blue-500"
|
class="text-blue-500"
|
||||||
@click="copyToClipboard('A link to this page', windowLocation)"
|
@click="copyToClipboard('A link to this page', windowDeepLink)"
|
||||||
>click to copy this page info</a
|
>click to copy this page info</a
|
||||||
>
|
>
|
||||||
and see if they can make an introduction. Someone is connected to
|
and see if they can make an introduction. Someone is connected to
|
||||||
@@ -428,7 +439,7 @@
|
|||||||
If you'd like an introduction,
|
If you'd like an introduction,
|
||||||
<a
|
<a
|
||||||
class="text-blue-500"
|
class="text-blue-500"
|
||||||
@click="copyToClipboard('A link to this page', windowLocation)"
|
@click="copyToClipboard('A link to this page', windowDeepLink)"
|
||||||
>share this page with them and ask if they'll tell you more about
|
>share this page with them and ask if they'll tell you more about
|
||||||
about the participants.</a
|
about the participants.</a
|
||||||
>
|
>
|
||||||
@@ -546,7 +557,7 @@ import { useClipboard } from "@vueuse/core";
|
|||||||
import { GenericVerifiableCredential } from "../interfaces";
|
import { GenericVerifiableCredential } from "../interfaces";
|
||||||
import GiftedDialog from "../components/GiftedDialog.vue";
|
import GiftedDialog from "../components/GiftedDialog.vue";
|
||||||
import QuickNav from "../components/QuickNav.vue";
|
import QuickNav from "../components/QuickNav.vue";
|
||||||
import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
|
import { APP_SERVER, NotificationIface, USE_DEXIE_DB } from "../constants/app";
|
||||||
import * as databaseUtil from "../db/databaseUtil";
|
import * as databaseUtil from "../db/databaseUtil";
|
||||||
import { db } from "../db/index";
|
import { db } from "../db/index";
|
||||||
import { logConsoleAndDb } from "../db/databaseUtil";
|
import { logConsoleAndDb } from "../db/databaseUtil";
|
||||||
@@ -593,8 +604,9 @@ export default class ClaimView extends Vue {
|
|||||||
veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
|
veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
|
||||||
veriClaimDump = "";
|
veriClaimDump = "";
|
||||||
veriClaimDidsVisible: { [key: string]: string[] } = {};
|
veriClaimDidsVisible: { [key: string]: string[] } = {};
|
||||||
windowLocation = window.location.href;
|
windowDeepLink = window.location.href; // changed in the setup for deep linking
|
||||||
|
|
||||||
|
APP_SERVER = APP_SERVER;
|
||||||
R = R;
|
R = R;
|
||||||
yaml = yaml;
|
yaml = yaml;
|
||||||
libsUtil = libsUtil;
|
libsUtil = libsUtil;
|
||||||
@@ -671,6 +683,7 @@ export default class ClaimView extends Vue {
|
|||||||
5000,
|
5000,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
this.windowDeepLink = `${APP_SERVER}/deep-link/claim/${claimId}`;
|
||||||
|
|
||||||
this.canShare = !!navigator.share;
|
this.canShare = !!navigator.share;
|
||||||
}
|
}
|
||||||
@@ -1006,11 +1019,11 @@ export default class ClaimView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClickShareClaim() {
|
onClickShareClaim() {
|
||||||
this.copyToClipboard("A link to this page", this.windowLocation);
|
this.copyToClipboard("A link to this page", this.windowDeepLink);
|
||||||
window.navigator.share({
|
window.navigator.share({
|
||||||
title: "Help Connect Me",
|
title: "Help Connect Me",
|
||||||
text: "I'm trying to find the people who recorded this. Can you help me?",
|
text: "I'm trying to find the people who recorded this. Can you help me?",
|
||||||
url: this.windowLocation,
|
url: this.windowDeepLink,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -436,7 +436,7 @@ import { Component, Vue } from "vue-facing-decorator";
|
|||||||
import { useClipboard } from "@vueuse/core";
|
import { useClipboard } from "@vueuse/core";
|
||||||
import { RouteLocationNormalizedLoaded, Router } from "vue-router";
|
import { RouteLocationNormalizedLoaded, Router } from "vue-router";
|
||||||
import QuickNav from "../components/QuickNav.vue";
|
import QuickNav from "../components/QuickNav.vue";
|
||||||
import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
|
import { APP_SERVER, NotificationIface, USE_DEXIE_DB } from "../constants/app";
|
||||||
import { db, retrieveSettingsForActiveAccount } from "../db/index";
|
import { db, retrieveSettingsForActiveAccount } from "../db/index";
|
||||||
import { Contact } from "../db/tables/contacts";
|
import { Contact } from "../db/tables/contacts";
|
||||||
import * as databaseUtil from "../db/databaseUtil";
|
import * as databaseUtil from "../db/databaseUtil";
|
||||||
@@ -494,7 +494,7 @@ export default class ConfirmGiftView extends Vue {
|
|||||||
veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
|
veriClaim = serverUtil.BLANK_GENERIC_SERVER_RECORD;
|
||||||
veriClaimDump = "";
|
veriClaimDump = "";
|
||||||
veriClaimDidsVisible: { [key: string]: string[] } = {};
|
veriClaimDidsVisible: { [key: string]: string[] } = {};
|
||||||
windowLocation = window.location.href;
|
windowLocation = window.location.href; // this is changed to a deep link in the setup
|
||||||
|
|
||||||
R = R;
|
R = R;
|
||||||
yaml = yaml;
|
yaml = yaml;
|
||||||
@@ -566,6 +566,9 @@ export default class ConfirmGiftView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const claimId = decodeURIComponent(pathParam);
|
const claimId = decodeURIComponent(pathParam);
|
||||||
|
|
||||||
|
this.windowLocation = APP_SERVER + "/deep-link/confirm-gift/" + claimId;
|
||||||
|
|
||||||
await this.loadClaim(claimId, this.activeDid);
|
await this.loadClaim(claimId, this.activeDid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,12 +679,12 @@ export default class ConfirmGiftView extends Vue {
|
|||||||
/**
|
/**
|
||||||
* Add participant (giver/recipient) name & URL info
|
* Add participant (giver/recipient) name & URL info
|
||||||
*/
|
*/
|
||||||
|
this.giverName = this.didInfo(this.giveDetails?.agentDid);
|
||||||
if (this.giveDetails?.agentDid) {
|
if (this.giveDetails?.agentDid) {
|
||||||
this.giverName = this.didInfo(this.giveDetails.agentDid);
|
|
||||||
this.urlForNewGive += `&giverDid=${encodeURIComponent(this.giveDetails.agentDid)}&giverName=${encodeURIComponent(this.giverName)}`;
|
this.urlForNewGive += `&giverDid=${encodeURIComponent(this.giveDetails.agentDid)}&giverName=${encodeURIComponent(this.giverName)}`;
|
||||||
}
|
}
|
||||||
|
this.recipientName = this.didInfo(this.giveDetails?.recipientDid);
|
||||||
if (this.giveDetails?.recipientDid) {
|
if (this.giveDetails?.recipientDid) {
|
||||||
this.recipientName = this.didInfo(this.giveDetails.recipientDid);
|
|
||||||
this.urlForNewGive += `&recipientDid=${encodeURIComponent(this.giveDetails.recipientDid)}&recipientName=${encodeURIComponent(this.recipientName)}`;
|
this.urlForNewGive += `&recipientDid=${encodeURIComponent(this.giveDetails.recipientDid)}&recipientName=${encodeURIComponent(this.recipientName)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -124,12 +124,14 @@ import * as databaseUtil from "../db/databaseUtil";
|
|||||||
import {
|
import {
|
||||||
CONTACT_CSV_HEADER,
|
CONTACT_CSV_HEADER,
|
||||||
CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI,
|
CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI,
|
||||||
|
generateEndorserJwtUrlForAccount,
|
||||||
setVisibilityUtil,
|
setVisibilityUtil,
|
||||||
} from "../libs/endorserServer";
|
} from "../libs/endorserServer";
|
||||||
import UserNameDialog from "../components/UserNameDialog.vue";
|
import UserNameDialog from "../components/UserNameDialog.vue";
|
||||||
import { retrieveAccountMetadata } from "../libs/util";
|
import { retrieveAccountMetadata } from "../libs/util";
|
||||||
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
||||||
import { parseJsonField } from "../db/databaseUtil";
|
import { parseJsonField } from "../db/databaseUtil";
|
||||||
|
import { Account } from "@/db/tables/accounts";
|
||||||
|
|
||||||
interface QRScanResult {
|
interface QRScanResult {
|
||||||
rawValue?: string;
|
rawValue?: string;
|
||||||
@@ -157,6 +159,7 @@ export default class ContactQRScanFull extends Vue {
|
|||||||
apiServer = "";
|
apiServer = "";
|
||||||
givenName = "";
|
givenName = "";
|
||||||
isRegistered = false;
|
isRegistered = false;
|
||||||
|
profileImageUrl = "";
|
||||||
qrValue = "";
|
qrValue = "";
|
||||||
ETHR_DID_PREFIX = ETHR_DID_PREFIX;
|
ETHR_DID_PREFIX = ETHR_DID_PREFIX;
|
||||||
|
|
||||||
@@ -179,6 +182,7 @@ export default class ContactQRScanFull extends Vue {
|
|||||||
this.apiServer = settings.apiServer || "";
|
this.apiServer = settings.apiServer || "";
|
||||||
this.givenName = settings.firstName || "";
|
this.givenName = settings.firstName || "";
|
||||||
this.isRegistered = !!settings.isRegistered;
|
this.isRegistered = !!settings.isRegistered;
|
||||||
|
this.profileImageUrl = settings.profileImageUrl || "";
|
||||||
|
|
||||||
const account = await retrieveAccountMetadata(this.activeDid);
|
const account = await retrieveAccountMetadata(this.activeDid);
|
||||||
if (account) {
|
if (account) {
|
||||||
@@ -588,9 +592,17 @@ export default class ContactQRScanFull extends Vue {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onCopyUrlToClipboard() {
|
async onCopyUrlToClipboard() {
|
||||||
|
const account = await libsUtil.retrieveFullyDecryptedAccount(this.activeDid) as Account;
|
||||||
|
const jwtUrl = await generateEndorserJwtUrlForAccount(
|
||||||
|
account,
|
||||||
|
this.isRegistered,
|
||||||
|
this.givenName,
|
||||||
|
this.profileImageUrl,
|
||||||
|
true,
|
||||||
|
);
|
||||||
useClipboard()
|
useClipboard()
|
||||||
.copy(this.qrValue)
|
.copy(jwtUrl)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -177,6 +177,7 @@ import { getContactJwtFromJwtUrl } from "../libs/crypto";
|
|||||||
import {
|
import {
|
||||||
CONTACT_CSV_HEADER,
|
CONTACT_CSV_HEADER,
|
||||||
CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI,
|
CONTACT_IMPORT_CONFIRM_URL_PATH_TIME_SAFARI,
|
||||||
|
generateEndorserJwtUrlForAccount,
|
||||||
register,
|
register,
|
||||||
setVisibilityUtil,
|
setVisibilityUtil,
|
||||||
} from "../libs/endorserServer";
|
} from "../libs/endorserServer";
|
||||||
@@ -187,6 +188,7 @@ import { logger } from "../utils/logger";
|
|||||||
import { QRScannerFactory } from "@/services/QRScanner/QRScannerFactory";
|
import { QRScannerFactory } from "@/services/QRScanner/QRScannerFactory";
|
||||||
import { CameraState } from "@/services/QRScanner/types";
|
import { CameraState } from "@/services/QRScanner/types";
|
||||||
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
||||||
|
import { Account } from "@/db/tables/accounts";
|
||||||
|
|
||||||
interface QRScanResult {
|
interface QRScanResult {
|
||||||
rawValue?: string;
|
rawValue?: string;
|
||||||
@@ -216,6 +218,7 @@ export default class ContactQRScanShow extends Vue {
|
|||||||
isRegistered = false;
|
isRegistered = false;
|
||||||
qrValue = "";
|
qrValue = "";
|
||||||
isScanning = false;
|
isScanning = false;
|
||||||
|
profileImageUrl = "";
|
||||||
error: string | null = null;
|
error: string | null = null;
|
||||||
|
|
||||||
// QR Scanner properties
|
// QR Scanner properties
|
||||||
@@ -253,6 +256,7 @@ export default class ContactQRScanShow extends Vue {
|
|||||||
this.hideRegisterPromptOnNewContact =
|
this.hideRegisterPromptOnNewContact =
|
||||||
!!settings.hideRegisterPromptOnNewContact;
|
!!settings.hideRegisterPromptOnNewContact;
|
||||||
this.isRegistered = !!settings.isRegistered;
|
this.isRegistered = !!settings.isRegistered;
|
||||||
|
this.profileImageUrl = settings.profileImageUrl || "";
|
||||||
|
|
||||||
const account = await libsUtil.retrieveAccountMetadata(this.activeDid);
|
const account = await libsUtil.retrieveAccountMetadata(this.activeDid);
|
||||||
if (account) {
|
if (account) {
|
||||||
@@ -667,10 +671,17 @@ export default class ContactQRScanShow extends Vue {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onCopyUrlToClipboard() {
|
async onCopyUrlToClipboard() {
|
||||||
//this.onScanDetect([{ rawValue: this.qrValue }]); // good for testing
|
const account = await libsUtil.retrieveFullyDecryptedAccount(this.activeDid) as Account;
|
||||||
|
const jwtUrl = await generateEndorserJwtUrlForAccount(
|
||||||
|
account,
|
||||||
|
this.isRegistered,
|
||||||
|
this.givenName,
|
||||||
|
this.profileImageUrl,
|
||||||
|
true,
|
||||||
|
);
|
||||||
useClipboard()
|
useClipboard()
|
||||||
.copy(this.qrValue)
|
.copy(jwtUrl)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.$notify(
|
this.$notify(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -126,7 +126,6 @@
|
|||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<button
|
<button
|
||||||
v-if="showGiveNumbers"
|
v-if="showGiveNumbers"
|
||||||
href=""
|
|
||||||
class="text-md bg-gradient-to-b shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-3 py-1.5 rounded-md"
|
class="text-md bg-gradient-to-b shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-3 py-1.5 rounded-md"
|
||||||
:class="showGiveAmountsClassNames()"
|
:class="showGiveAmountsClassNames()"
|
||||||
@click="toggleShowGiveTotals()"
|
@click="toggleShowGiveTotals()"
|
||||||
@@ -142,7 +141,6 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
href=""
|
|
||||||
class="text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-3 py-1.5 rounded-md"
|
class="text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-3 py-1.5 rounded-md"
|
||||||
@click="toggleShowContactAmounts()"
|
@click="toggleShowContactAmounts()"
|
||||||
>
|
>
|
||||||
@@ -493,7 +491,7 @@ export default class ContactsView extends Vue {
|
|||||||
private async processContactJwt() {
|
private async processContactJwt() {
|
||||||
// handle a contact sent via URL
|
// handle a contact sent via URL
|
||||||
//
|
//
|
||||||
// For external links, use /contact-import/:jwt with a JWT that has an array of contacts
|
// For external links, use /deep-link/contact-import/:jwt with a JWT that has an array of contacts
|
||||||
// because that will do better error checking for things like missing data on iOS platforms.
|
// because that will do better error checking for things like missing data on iOS platforms.
|
||||||
const importedContactJwt = this.$route.query["contactJwt"] as string;
|
const importedContactJwt = this.$route.query["contactJwt"] as string;
|
||||||
if (importedContactJwt) {
|
if (importedContactJwt) {
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ export default class InviteOneView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inviteLink(jwt: string): string {
|
inviteLink(jwt: string): string {
|
||||||
return APP_SERVER + "/invite-one-accept/" + jwt;
|
return APP_SERVER + "/deep-link/invite-one-accept/" + jwt;
|
||||||
}
|
}
|
||||||
|
|
||||||
copyInviteAndNotify(inviteId: string, jwt: string) {
|
copyInviteAndNotify(inviteId: string, jwt: string) {
|
||||||
|
|||||||
@@ -720,7 +720,7 @@ export default class OnboardMeetingView extends Vue {
|
|||||||
|
|
||||||
onboardMeetingMembersLink(): string {
|
onboardMeetingMembersLink(): string {
|
||||||
if (this.currentMeeting) {
|
if (this.currentMeeting) {
|
||||||
return `${APP_SERVER}/onboard-meeting-members/${this.currentMeeting?.groupId}?password=${encodeURIComponent(
|
return `${APP_SERVER}/deep-link/onboard-meeting-members/${this.currentMeeting?.groupId}?password=${encodeURIComponent(
|
||||||
this.currentMeeting?.password || "",
|
this.currentMeeting?.password || "",
|
||||||
)}`;
|
)}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,12 @@
|
|||||||
>
|
>
|
||||||
<font-awesome icon="pen" class="text-sm text-blue-500 ml-2 mb-1" />
|
<font-awesome icon="pen" class="text-sm text-blue-500 ml-2 mb-1" />
|
||||||
</button>
|
</button>
|
||||||
|
<button title="Copy Link to Project" @click="onCopyLinkClick()">
|
||||||
|
<font-awesome
|
||||||
|
icon="link"
|
||||||
|
class="text-sm text-slate-500 ml-2 mb-1"
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,7 +61,11 @@
|
|||||||
<span class="truncate inline-block max-w-[calc(100%-2rem)]">
|
<span class="truncate inline-block max-w-[calc(100%-2rem)]">
|
||||||
{{ issuerInfoObject?.displayName }}
|
{{ issuerInfoObject?.displayName }}
|
||||||
</span>
|
</span>
|
||||||
<span class="inline-flex items-center">
|
|
||||||
|
<span
|
||||||
|
v-if="!serverUtil.isHiddenDid(issuer)"
|
||||||
|
class="inline-flex items-center"
|
||||||
|
>
|
||||||
<router-link
|
<router-link
|
||||||
:to="{
|
:to="{
|
||||||
path: '/did/' + encodeURIComponent(issuer),
|
path: '/did/' + encodeURIComponent(issuer),
|
||||||
@@ -113,7 +123,7 @@
|
|||||||
class="fa-fw text-slate-400"
|
class="fa-fw text-slate-400"
|
||||||
></font-awesome>
|
></font-awesome>
|
||||||
<a
|
<a
|
||||||
:href="addScheme(url)"
|
:href="ensureScheme(url)"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="underline text-blue-500"
|
class="underline text-blue-500"
|
||||||
>
|
>
|
||||||
@@ -632,7 +642,7 @@ import TopMessage from "../components/TopMessage.vue";
|
|||||||
import QuickNav from "../components/QuickNav.vue";
|
import QuickNav from "../components/QuickNav.vue";
|
||||||
import EntityIcon from "../components/EntityIcon.vue";
|
import EntityIcon from "../components/EntityIcon.vue";
|
||||||
import ProjectIcon from "../components/ProjectIcon.vue";
|
import ProjectIcon from "../components/ProjectIcon.vue";
|
||||||
import { NotificationIface, USE_DEXIE_DB } from "../constants/app";
|
import { APP_SERVER, NotificationIface, USE_DEXIE_DB } from "../constants/app";
|
||||||
import * as databaseUtil from "../db/databaseUtil";
|
import * as databaseUtil from "../db/databaseUtil";
|
||||||
import {
|
import {
|
||||||
db,
|
db,
|
||||||
@@ -646,6 +656,7 @@ import { retrieveAccountDids } from "../libs/util";
|
|||||||
import HiddenDidDialog from "../components/HiddenDidDialog.vue";
|
import HiddenDidDialog from "../components/HiddenDidDialog.vue";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
||||||
|
import { useClipboard } from "@vueuse/core";
|
||||||
/**
|
/**
|
||||||
* Project View Component
|
* Project View Component
|
||||||
* @author Matthew Raymer
|
* @author Matthew Raymer
|
||||||
@@ -842,6 +853,28 @@ export default class ProjectViewView extends Vue {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCopyLinkClick() {
|
||||||
|
const shortestProjectId = this.projectId.startsWith(
|
||||||
|
serverUtil.ENDORSER_CH_HANDLE_PREFIX,
|
||||||
|
)
|
||||||
|
? this.projectId.substring(serverUtil.ENDORSER_CH_HANDLE_PREFIX.length)
|
||||||
|
: this.projectId;
|
||||||
|
const deepLink = `${APP_SERVER}/deep-link/project/${shortestProjectId}`;
|
||||||
|
useClipboard()
|
||||||
|
.copy(deepLink)
|
||||||
|
.then(() => {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "toast",
|
||||||
|
title: "Copied",
|
||||||
|
text: "A link to this project was copied to the clipboard.",
|
||||||
|
},
|
||||||
|
2000,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Isn't there a better way to make this available to the template?
|
// Isn't there a better way to make this available to the template?
|
||||||
expandText() {
|
expandText() {
|
||||||
this.expanded = true;
|
this.expanded = true;
|
||||||
@@ -1304,7 +1337,7 @@ export default class ProjectViewView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// return an HTTPS URL if it's not a global URL
|
// return an HTTPS URL if it's not a global URL
|
||||||
addScheme(url: string) {
|
ensureScheme(url: string) {
|
||||||
if (!libsUtil.isGlobalUri(url)) {
|
if (!libsUtil.isGlobalUri(url)) {
|
||||||
return "https://" + url;
|
return "https://" + url;
|
||||||
}
|
}
|
||||||
@@ -1465,7 +1498,13 @@ export default class ProjectViewView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
openHiddenDidDialog() {
|
openHiddenDidDialog() {
|
||||||
|
const shortestProjectId = this.projectId.startsWith(
|
||||||
|
serverUtil.ENDORSER_CH_HANDLE_PREFIX,
|
||||||
|
)
|
||||||
|
? this.projectId.substring(serverUtil.ENDORSER_CH_HANDLE_PREFIX.length)
|
||||||
|
: this.projectId;
|
||||||
(this.$refs.hiddenDidDialog as HiddenDidDialog).open(
|
(this.$refs.hiddenDidDialog as HiddenDidDialog).open(
|
||||||
|
"project/" + shortestProjectId,
|
||||||
"creator",
|
"creator",
|
||||||
this.issuerVisibleToDids,
|
this.issuerVisibleToDids,
|
||||||
this.allContacts,
|
this.allContacts,
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ export default class ShareMyContactInfoView extends Vue {
|
|||||||
group: "alert",
|
group: "alert",
|
||||||
type: "info",
|
type: "info",
|
||||||
title: "Copied",
|
title: "Copied",
|
||||||
text: "Your contact info was copied to the clipboard. Have them paste it in the box on their 'Contacts' screen.",
|
text: "Your contact info was copied to the clipboard. Have them click on it, or paste it in the box on their 'Contacts' screen.",
|
||||||
},
|
},
|
||||||
5000,
|
5000,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
</button>
|
</button>
|
||||||
Individual Profile
|
Individual Profile
|
||||||
</h1>
|
</h1>
|
||||||
|
<div class="text-sm text-center text-slate-500">
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Loading Animation -->
|
<!-- Loading Animation -->
|
||||||
@@ -32,6 +35,12 @@
|
|||||||
<div class="text-sm">
|
<div class="text-sm">
|
||||||
<font-awesome icon="user" class="fa-fw text-slate-400"></font-awesome>
|
<font-awesome icon="user" class="fa-fw text-slate-400"></font-awesome>
|
||||||
{{ didInfo(profile.issuerDid, activeDid, allMyDids, allContacts) }}
|
{{ didInfo(profile.issuerDid, activeDid, allMyDids, allContacts) }}
|
||||||
|
<button
|
||||||
|
title="Copy Link to Profile"
|
||||||
|
@click="onCopyLinkClick()"
|
||||||
|
>
|
||||||
|
<font-awesome icon="link" class="text-sm text-slate-500 ml-2 mb-1" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="profile.description" class="mt-4 text-slate-600">
|
<p v-if="profile.description" class="mt-4 text-slate-600">
|
||||||
{{ profile.description }}
|
{{ profile.description }}
|
||||||
@@ -100,6 +109,7 @@ import { Router, RouteLocationNormalizedLoaded } from "vue-router";
|
|||||||
import QuickNav from "../components/QuickNav.vue";
|
import QuickNav from "../components/QuickNav.vue";
|
||||||
import TopMessage from "../components/TopMessage.vue";
|
import TopMessage from "../components/TopMessage.vue";
|
||||||
import {
|
import {
|
||||||
|
APP_SERVER,
|
||||||
DEFAULT_PARTNER_API_SERVER,
|
DEFAULT_PARTNER_API_SERVER,
|
||||||
NotificationIface,
|
NotificationIface,
|
||||||
USE_DEXIE_DB,
|
USE_DEXIE_DB,
|
||||||
@@ -113,6 +123,7 @@ import { retrieveAccountDids } from "../libs/util";
|
|||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
||||||
import { Settings } from "@/db/tables/settings";
|
import { Settings } from "@/db/tables/settings";
|
||||||
|
import { useClipboard } from "@vueuse/core";
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
LMap,
|
LMap,
|
||||||
@@ -186,6 +197,10 @@ export default class UserProfileView extends Vue {
|
|||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
this.profile = result.data;
|
this.profile = result.data;
|
||||||
|
if (this.profile && this.profile.rowId !== profileId) {
|
||||||
|
// currently the server returns "rowid" with lowercase "i"; remove when that's fixed
|
||||||
|
this.profile.rowId = profileId;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Failed to load profile");
|
throw new Error("Failed to load profile");
|
||||||
}
|
}
|
||||||
@@ -204,5 +219,23 @@ export default class UserProfileView extends Vue {
|
|||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCopyLinkClick() {
|
||||||
|
console.log("onCopyLinkClick", this.profile);
|
||||||
|
const deepLink = `${APP_SERVER}/deep-link/user-profile/${this.profile?.rowId}`;
|
||||||
|
useClipboard()
|
||||||
|
.copy(deepLink)
|
||||||
|
.then(() => {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "toast",
|
||||||
|
title: "Copied",
|
||||||
|
text: "A link to this profile was copied to the clipboard.",
|
||||||
|
},
|
||||||
|
2000,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user