show more redeemed info & action on the invites, refactor onboarding instructions
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<!-- similar to ContactNameDialog -->
|
||||
<!-- similar to UserNameDialog -->
|
||||
<template>
|
||||
<div v-if="visible" class="dialog-overlay">
|
||||
<div class="dialog">
|
||||
<h1 class="text-xl font-bold text-center mb-4">Inviter's Name</h1>
|
||||
<h1 class="text-xl font-bold text-center mb-4">Contact Name</h1>
|
||||
Note that their name is only stored on this device.
|
||||
<input
|
||||
type="text"
|
||||
@@ -37,7 +37,7 @@
|
||||
import { Vue, Component } from "vue-facing-decorator";
|
||||
|
||||
@Component
|
||||
export default class UserNameDialog extends Vue {
|
||||
export default class ContactNameDialog extends Vue {
|
||||
callback: (name?: string) => void = () => {};
|
||||
newText = "";
|
||||
visible = false;
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
<div class="dialog">
|
||||
<h1 class="text-xl font-bold text-center mb-4">Invitation & Notes</h1>
|
||||
|
||||
These are optional notes for your use, to make comments for to recall
|
||||
later when redeemed by someone. These notes are sent to the server. If you
|
||||
want to store your own way, the invitation ID is: {{ inviteIdentifier }}
|
||||
These are optional notes for your use; they are comments to help you
|
||||
recall who it is when they accept it. These notes are sent to the server.
|
||||
If you want to store your own way, the invitation ID is:
|
||||
{{ inviteIdentifier }}
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Notes"
|
||||
|
||||
@@ -39,12 +39,12 @@
|
||||
|
||||
<textarea
|
||||
type="text"
|
||||
placeholder="URL or DID, Name, Public Key, Next Public Key Hash"
|
||||
placeholder="New URL or DID, Name, Public Key, Next Public Key Hash"
|
||||
class="block w-full rounded-l border border-r-0 border-slate-400 px-3 py-2 h-10"
|
||||
v-model="contactInput"
|
||||
/>
|
||||
<button
|
||||
class="px-4 rounded-r bg-slate-200 border border-l-0 border-slate-400"
|
||||
class="px-4 rounded-r bg-green-200 border border-l-0 border-green-400"
|
||||
@click="onClickNewContact()"
|
||||
>
|
||||
<fa icon="plus" class="fa-fw" />
|
||||
|
||||
@@ -12,6 +12,24 @@
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
To invite someone, generate a link to send to them from this page:
|
||||
<router-link
|
||||
:to="{ name: 'invite-one' }"
|
||||
class="bg-gradient-to-b from-green-400 to-green-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md"
|
||||
>
|
||||
<fa icon="envelope-open-text" class="fa-fw text-xl"
|
||||
/></router-link>
|
||||
</p>
|
||||
<p>That's all it takes.</p>
|
||||
<p>Watch that page to see when people accept their invite.</p>
|
||||
<p>
|
||||
That page is also reachable from the Contacts <fa icon="users" /> page
|
||||
though the invitation <fa icon="envelope-open-text" /> icon.
|
||||
</p>
|
||||
|
||||
<h1 class="font-bold text-xl">Advanced</h1>
|
||||
The following are optional steps for even more functionality:
|
||||
<!-- eslint-disable prettier/prettier -->
|
||||
<div class="ml-4">
|
||||
<h1 class="font-bold text-xl">Install</h1>
|
||||
@@ -25,25 +43,36 @@
|
||||
</div>
|
||||
|
||||
<h1 class="font-bold text-xl">Add Contact & Register</h1>
|
||||
<p>
|
||||
You share even more information such as your picture and name when
|
||||
you share with your QR code at these links: <fa icon="qrcode" /> Scanning
|
||||
those with your cameras will automatically register people and add them
|
||||
to each other's contact lists.
|
||||
</p>
|
||||
<p>
|
||||
The following are more detailed manual steps:
|
||||
</p>
|
||||
<div>
|
||||
<p>
|
||||
3) Have them follow their yellow prompts.
|
||||
</p>
|
||||
<p>
|
||||
4) Add them to your contacts <fa icon="users" />
|
||||
4) Scan their QR, or have them tap on it to copy their info and send it to you.
|
||||
Then you can add them to your Contacts <fa icon="users" />
|
||||
</p>
|
||||
<p>
|
||||
5) Register them <fa icon="person-circle-question" />
|
||||
5) You can register them at their info page <fa icon="circle-info" />
|
||||
and click on the register button <fa icon="person-circle-question" />
|
||||
</p>
|
||||
<p>
|
||||
6) Add yourself to their contacts <fa icon="users" />
|
||||
6) Add yourself to their Contacts <fa icon="users" />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<h1 class="font-bold text-xl">Enable Notifications</h1>
|
||||
<div>
|
||||
<p>
|
||||
7) Enable notifications from <fa icon="circle-user" />
|
||||
7) Enable notifications from the Account page <fa icon="circle-user" />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<!-- New Project -->
|
||||
<button
|
||||
v-if="isRegistered"
|
||||
class="fixed right-6 top-12 text-center text-4xl leading-none bg-blue-600 text-white w-14 py-2.5 rounded-full"
|
||||
class="fixed right-6 top-12 text-center text-4xl leading-none bg-green-600 text-white w-14 py-2.5 rounded-full"
|
||||
@click="createInvite()"
|
||||
>
|
||||
<fa icon="plus" class="fa-fw"></fa>
|
||||
@@ -35,7 +35,7 @@
|
||||
<th class="py-2">ID</th>
|
||||
<th class="py-2">Notes</th>
|
||||
<th class="py-2">Expires At</th>
|
||||
<th class="py-2">Redeemed By</th>
|
||||
<th class="py-2">Redeemed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -45,7 +45,7 @@
|
||||
class="border-t"
|
||||
>
|
||||
<td
|
||||
class="py-2 text-center text-blue-500"
|
||||
class="py-2 text-center text-blue-500 cursor-pointer"
|
||||
@click="copyInviteAndNotify(invite.inviteIdentifier, invite.jwt)"
|
||||
title="{{ inviteLink(invite.jwt) }}"
|
||||
>
|
||||
@@ -58,7 +58,16 @@
|
||||
{{ invite.expiresAt.substring(0, 10) }}
|
||||
</td>
|
||||
<td class="py-2 text-center">
|
||||
{{ invite.redeemedAt?.substring(0, 10) }}
|
||||
<br />
|
||||
{{ getTruncatedRedeemedBy(invite.redeemedBy) }}
|
||||
<br />
|
||||
<fa
|
||||
v-if="invite.redeemedBy && !contactsRedeemed[invite.redeemedBy]"
|
||||
icon="plus"
|
||||
class="bg-green-600 text-white px-1 py-1 rounded-full cursor-pointer"
|
||||
@click="addNewContact(invite.redeemedBy)"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<fa
|
||||
@@ -70,6 +79,7 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<ContactNameDialog ref="contactNameDialog" />
|
||||
</div>
|
||||
<p v-else class="mt-6 text-center">No invites found.</p>
|
||||
</section>
|
||||
@@ -79,11 +89,12 @@ import axios from "axios";
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
import { useClipboard } from "@vueuse/core";
|
||||
|
||||
import { db, retrieveSettingsForActiveAccount } from "../db";
|
||||
import ContactNameDialog from "@/components/ContactNameDialog.vue";
|
||||
import QuickNav from "@/components/QuickNav.vue";
|
||||
import TopMessage from "@/components/TopMessage.vue";
|
||||
import InviteDialog from "@/components/InviteDialog.vue";
|
||||
import { APP_SERVER, NotificationIface } from "@/constants/app";
|
||||
import { db, retrieveSettingsForActiveAccount } from "@/db";
|
||||
import { createInviteJwt, getHeaders } from "@/libs/endorserServer";
|
||||
|
||||
interface Invite {
|
||||
@@ -91,11 +102,12 @@ interface Invite {
|
||||
expiresAt: string;
|
||||
jwt: string;
|
||||
notes: string;
|
||||
redeemedAt: string | null;
|
||||
redeemedBy: string | null;
|
||||
}
|
||||
|
||||
@Component({
|
||||
components: { QuickNav, TopMessage, InviteDialog },
|
||||
components: { ContactNameDialog, QuickNav, TopMessage, InviteDialog },
|
||||
})
|
||||
export default class InviteOneView extends Vue {
|
||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||
@@ -103,6 +115,7 @@ export default class InviteOneView extends Vue {
|
||||
invites: Invite[] = [];
|
||||
activeDid: string = "";
|
||||
apiServer: string = "";
|
||||
contactsRedeemed = {};
|
||||
isRegistered: boolean = false;
|
||||
|
||||
async mounted() {
|
||||
@@ -119,6 +132,17 @@ export default class InviteOneView extends Vue {
|
||||
{ headers },
|
||||
);
|
||||
this.invites = response.data.data;
|
||||
|
||||
const baseContacts = await db.contacts.toArray();
|
||||
for (const invite of this.invites) {
|
||||
const contact = baseContacts.find(
|
||||
(contact) => contact.did === invite.redeemedBy,
|
||||
);
|
||||
if (contact) {
|
||||
this.contactsRedeemed[invite.redeemedBy] = contact;
|
||||
}
|
||||
}
|
||||
console.log("contactsRedeemed", this.contactsRedeemed);
|
||||
} catch (error) {
|
||||
console.error("Error fetching invites:", error);
|
||||
this.$notify(
|
||||
@@ -140,6 +164,9 @@ export default class InviteOneView extends Vue {
|
||||
|
||||
getTruncatedRedeemedBy(redeemedBy: string | null): string {
|
||||
if (!redeemedBy) return "";
|
||||
if (this.contactsRedeemed[redeemedBy]) {
|
||||
return this.contactsRedeemed[redeemedBy].name;
|
||||
}
|
||||
if (redeemedBy.length <= 19) return redeemedBy;
|
||||
return `${redeemedBy.slice(0, 13)}...${redeemedBy.slice(-3)}`;
|
||||
}
|
||||
@@ -215,6 +242,7 @@ export default class InviteOneView extends Vue {
|
||||
expiresAt: expiresAt,
|
||||
jwt: inviteJwt,
|
||||
notes: notes,
|
||||
redeemedAt: null,
|
||||
redeemedBy: null,
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -229,6 +257,28 @@ export default class InviteOneView extends Vue {
|
||||
);
|
||||
}
|
||||
|
||||
addNewContact(did) {
|
||||
(this.$refs.contactNameDialog as ContactNameDialog).open((name) => {
|
||||
// the person obviously registered themselves and this user already granted visibility, so we just add them
|
||||
const contact = {
|
||||
did: did,
|
||||
name: name,
|
||||
registered: true,
|
||||
};
|
||||
db.contacts.add(contact);
|
||||
this.contactsRedeemed[did] = contact;
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "success",
|
||||
title: "Contact Added",
|
||||
text: `${name} has been added to your contacts.`,
|
||||
},
|
||||
3000,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
deleteInvite(inviteId: string, notes: string) {
|
||||
this.$notify(
|
||||
{
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<!-- New Project -->
|
||||
<button
|
||||
v-if="isRegistered && showProjects"
|
||||
class="fixed right-6 top-24 text-center text-4xl leading-none bg-blue-600 text-white w-14 py-2.5 rounded-full"
|
||||
class="fixed right-6 top-24 text-center text-4xl leading-none bg-green-600 text-white w-14 py-2.5 rounded-full"
|
||||
@click="onClickNewProject()"
|
||||
>
|
||||
<fa icon="plus" class="fa-fw"></fa>
|
||||
|
||||
Reference in New Issue
Block a user