Compare commits

...

27 Commits

Author SHA1 Message Date
Jose Olarte III
b6f9533f07 feat: Add bulk admit pending members functionality
- Add "Admit Pending" button to admit all pending members at once
- Implement confirmation dialog with options to add members to contacts
- Hide button when no pending members exist
- Pause auto-refresh during dialog interaction for better UX
- Add notification constants for dialog text and actions
- Support both "Admit and Add to Contacts" and "Admit Only" workflows
- Include comprehensive error handling and success feedback

The dialog shows pending member count and allows users to choose whether
to add admitted members to their contacts list, streamlining the
admission process for organizers.
2025-10-21 21:18:42 +08:00
Jose Olarte III
e9ea89edae feat: enhance members list UI with visual indicators and improved styling
- Sort members list with organizer first, then non-admitted, then admitted
- Add crown icon for meeting organizer identification
- Add spinner icon for non-admitted members
- Implement conditional styling for non-admitted members
- Update button styling to use circle icons instead of rounded backgrounds
- Improve visual hierarchy with better spacing and color coding
2025-10-21 18:13:10 +08:00
1ce7c0486a Merge pull request 'feat: implement member visibility dialog with checkbox selection and refresh' (#208) from meeting-members-set-visibility into master
Reviewed-on: #208
2025-10-21 04:52:14 -04:00
Jose Olarte III
4f3a1b390d feat: auto-show visibility dialog for meeting members
- Show dialog on initial load if members need visibility settings
- Show dialog during auto-refresh only when new members are added (not removed)
- Show dialog on manual refresh if any members need visibility settings
- Remove manual "Set Visibility" buttons from UI as dialog now appears automatically
- Add logic to track previous visibility members and detect changes
- Improve UX by proactively prompting users to set visibility for new meeting members

The dialog now appears automatically in these scenarios:
- Component initialization with members needing visibility
- Auto-refresh when new members join the meeting
- Manual refresh when members need visibility settings
2025-10-17 19:17:47 +08:00
Jose Olarte III
4de4fbecaf refactor: rename SetVisibilityDialog to SetBulkVisibilityDialog and remove unused code
- Rename SetVisibilityDialog.vue to SetBulkVisibilityDialog.vue for better clarity
- Update all component references in MembersList.vue (import, registration, template usage)
- Update component class name from SetVisibilityDialog to SetBulkVisibilityDialog
- Rename calling function name to showSetBulkVisibilityDialog to match class name change
- Remove unused properties and created() method from App.vue

This cleanup removes dead code and improves component naming consistency.
2025-10-17 17:59:41 +08:00
Jose Olarte III
e3598992e7 feat: pause auto-refresh when SetVisibilityDialog is open
- Pause auto-refresh when SetVisibilityDialog becomes visible
- Resume auto-refresh when dialog is closed
- Prevents background refresh interference during visibility settings
- Fix type compatibility for visibilityDialogMembers data structure

This ensures users can interact with the visibility dialog without
the members list refreshing in the background, providing a better
user experience for setting member visibility preferences.
2025-10-16 17:49:59 +08:00
Jose Olarte III
ea19195850 refactor: extract SetVisibilityDialog into standalone component
- Extract "Set Visibility to Meeting Members" dialog from App.vue into dedicated SetVisibilityDialog.vue component
- Move dialog logic directly to MembersList.vue for better component coupling
- Remove unnecessary intermediate state management from App.vue
- Clean up redundant style definitions (rely on existing Tailwind CSS classes)
- Remove unused logger imports and debug functions
- Add explanatory comment for Vue template constant pattern

This improves maintainability by isolating dialog functionality and follows established component patterns in the codebase.
2025-10-16 17:18:56 +08:00
Jose Olarte III
ca545fd4b8 feat: add auto-refresh with countdown to MembersList
- Auto-refresh members list every 10 seconds
- Display countdown timer in refresh buttons
- Manual refresh resets countdown to 10 seconds
2025-10-15 20:25:01 +08:00
Jose Olarte III
07b538cadc feat: implement member visibility dialog with checkbox selection and refresh
- Add "Set Visibility" dialog for meeting members who need visibility settings
- Filter members to show only those not in contacts or without seesMe set
- Implement checkbox selection with "Select All" functionality
- Add reactive checkbox behavior with proper state management
- Default all checkboxes to checked when dialog opens
- Implement "Set Visibility" action to add contacts and set seesMe property
- Add success notifications with count of affected members
- Disable "Set Visibility" button when no members are selected
- Use notification callbacks for data refresh
- Hide "Set Visibility" buttons when no members need visibility settings
- Add proper dialog state management and cleanup
- Ensure dialog closes before triggering data refresh to prevent stale states

The implementation provides a smooth user experience for managing member visibility settings with proper state synchronization between components.
2025-10-14 21:21:35 +08:00
Jose Olarte III
b84546686a WIP: button and icon additions
- Mirrored "Refresh" and "Visibility" buttons on top and bottom of member list
- Added back info icons for list actions
- When clicked, Person icon shows informative notification
2025-10-13 21:38:12 +08:00
Jose Olarte III
461ee84d2a WIP: meeting members adjustments 2025-10-12 23:30:03 +08:00
Jose Olarte III
acf7d611e8 WIP: mockup for set visibility dialog 2025-10-09 21:56:50 +08:00
b0d13b3cd4 Merge pull request 'feat: disable zoom and fix iOS viewport issues' (#206) from ios-disable-zoom into master
Reviewed-on: #206
2025-10-08 06:04:32 -04:00
Jose Olarte III
5256681089 Merge branch 'master' into ios-disable-zoom 2025-10-08 18:03:27 +08:00
Jose Olarte III
225b34d480 feat: improve text overflow handling across UI components
- Add overflow-hidden, text-ellipsis and truncate classes to long text elements in list items and views to prevent text overflow
- Ensure proper text wrapping and ellipsis display for long content
2025-10-07 19:00:12 +08:00
d9f9460be7 Merge pull request 'refactor: standardize view headings across all components' (#207) from view-headings-refresh into master
Reviewed-on: #207
2025-10-07 05:17:05 -04:00
Jose Olarte III
b1026a9854 Linting 2025-10-07 16:38:35 +08:00
Jose Olarte III
cba33c6ad9 Merge branch 'master' into view-headings-refresh 2025-10-07 16:37:36 +08:00
Jose Olarte III
756688bf75 feat: restored TopMessage
- Added back TopMessage tag, placed inside #Content for better positioning
- Styled TopMessage for better visibility
2025-10-06 18:42:05 +08:00
7599b37c01 feat: add a 'not found' page 2025-10-05 15:31:08 -06:00
a4024537c2 Merge branch 'star-projects2' 2025-10-05 13:33:58 -06:00
Jose Olarte III
be8230d046 refactor: standardize view headings across all components
- Add consistent view heading IDs and structure
- Add consistent help buttons and back navigation
- Improve spacing and typography consistency
2025-10-03 21:49:35 +08:00
284fee9ded Merge pull request 'feat: removed "cannot upload images" notification' (#205) from remove-cannot-upload-images-notification into master
Reviewed-on: #205
2025-10-03 02:18:35 -04:00
Jose Olarte III
88778a167c WIP: sub view heading adjustments 2025-10-01 18:38:43 +08:00
Jose Olarte III
f4144c7469 feat: disable zoom and fix iOS viewport issues
- Add user-scalable=no and interactive-widget=overlays-content to viewport meta tag
- Implement iOS viewport height fixes to prevent keyboard-related layout shifts
- Use dynamic viewport height (100dvh) for better mobile support
- Add fixed positioning and overflow controls to prevent viewport changes
- Enable scrolling only within #app container for better UX
2025-09-30 21:06:13 +08:00
Jose Olarte III
eca6dfe9d7 feat: removed "cannot upload images" notification
- Redundant notification removed
- In-section message given "warning message" styling
2025-09-30 16:23:29 +08:00
Jose Olarte III
a6d282e59b WIP: HomeView heading adjustments 2025-09-29 21:28:48 +08:00
63 changed files with 1980 additions and 742 deletions

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, user-scalable=no, interactive-widget=overlays-content" />
<!-- CORS headers removed to allow images from any domain -->
@@ -13,4 +13,4 @@
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
</html>

View File

@@ -7,6 +7,24 @@
html {
font-family: 'Work Sans', ui-sans-serif, system-ui, sans-serif !important;
}
/* Fix iOS viewport height changes when keyboard appears/disappears */
html, body {
height: 100%;
height: 100vh;
height: 100dvh; /* Dynamic viewport height for better mobile support */
overflow: hidden; /* Disable all scrolling on html and body */
position: fixed; /* Force fixed positioning to prevent viewport changes */
width: 100%;
top: 0;
left: 0;
}
#app {
height: 100vh;
height: 100dvh;
overflow-y: auto;
}
}
@layer components {

View File

@@ -78,8 +78,11 @@
</div>
<!-- Description -->
<p class="font-medium">
<a class="cursor-pointer" @click="emitLoadClaim(record.jwtId)">
<p class="font-medium overflow-hidden">
<a
class="block cursor-pointer overflow-hidden text-ellipsis"
@click="emitLoadClaim(record.jwtId)"
>
<vue-markdown
:source="truncatedDescription"
class="markdown-content"

View File

@@ -46,7 +46,7 @@
<span class="text-xs truncate">{{ contact.did }}</span>
</div>
<div class="text-sm">
<div class="text-sm truncate">
{{ contact.notes }}
</div>
</div>

View File

@@ -11,7 +11,7 @@
<!-- Members List -->
<div v-else>
<div class="text-center text-red-600 py-4">
<div class="text-center text-red-600 my-4">
{{ decryptionErrorMessage() }}
</div>
@@ -23,131 +23,160 @@
to set it.
</div>
<div>
<span
<ul class="list-disc text-sm ps-4 space-y-2 mb-4">
<li
v-if="membersToShow().length > 0 && showOrganizerTools && isOrganizer"
class="inline-flex items-center flex-wrap"
>
<span class="inline-flex items-center">
&bull; Click
<span
class="mx-2 min-w-[24px] min-h-[24px] w-6 h-6 flex items-center justify-center rounded-full bg-blue-100 text-blue-600"
>
<font-awesome icon="plus" class="text-sm" />
</span>
/
<span
class="mx-2 min-w-[24px] min-h-[24px] w-6 h-6 flex items-center justify-center rounded-full bg-blue-100 text-blue-600"
>
<font-awesome icon="minus" class="text-sm" />
</span>
to add/remove them to/from the meeting.
</span>
</span>
</div>
<div>
<span
v-if="membersToShow().length > 0"
class="inline-flex items-center"
>
&bull; Click
<span
class="mx-2 w-8 h-8 flex items-center justify-center rounded-full bg-green-100 text-green-600"
>
<font-awesome icon="circle-user" class="text-xl" />
</span>
Click
<font-awesome icon="circle-plus" class="text-blue-500 text-sm" />
/
<font-awesome icon="circle-minus" class="text-rose-500 text-sm" />
to add/remove them to/from the meeting.
</li>
<li v-if="membersToShow().length > 0">
Click
<font-awesome icon="circle-user" class="text-green-600 text-sm" />
to add them to your contacts.
</span>
</div>
</li>
</ul>
<div class="flex justify-center">
<div class="flex justify-between">
<!--
always have at least one refresh button even without members in case the organizer
changes the password
-->
<button
class="btn-action-refresh"
title="Refresh members list"
@click="fetchMembers"
class="text-sm 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"
title="Refresh members list now"
@click="manualRefresh"
>
<font-awesome icon="rotate" :class="{ 'fa-spin': isLoading }" />
Refresh
<span class="text-xs">({{ countdownTimer }}s)</span>
</button>
<button
v-if="getPendingMembersCount() > 0"
class="text-sm bg-gradient-to-b from-blue-100 to-blue-200 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.2)] text-blue-800 px-3 py-1.5 rounded-md"
@click="showAdmitAllPendingDialog"
>
<font-awesome icon="circle-plus" class="text-blue-500" />
Admit Pending
</button>
</div>
<div
v-for="member in membersToShow()"
:key="member.member.memberId"
class="mt-2 p-4 bg-gray-50 rounded-lg"
<ul
v-if="membersToShow().length > 0"
class="border-t border-slate-300 my-2"
>
<div class="flex items-center justify-between">
<div class="flex items-center">
<h3 class="text-lg font-medium">
{{ member.name || unnamedMember }}
</h3>
<div
v-if="!getContactFor(member.did) && member.did !== activeDid"
class="flex justify-end"
>
<button
class="btn-add-contact"
title="Add as contact"
@click="addAsContact(member)"
<li
v-for="member in membersToShow()"
:key="member.member.memberId"
:class="[
'border-b px-2 sm:px-3 py-1.5',
{
'bg-blue-50 border-t border-blue-300 -mt-[1px]':
!member.member.admitted,
},
{ 'border-slate-300': member.member.admitted },
]"
>
<div class="flex items-center gap-2 justify-between">
<div class="flex items-center gap-1 overflow-hidden">
<h3
:class="[
'font-semibold truncate',
{ 'text-slate-500': !member.member.admitted },
]"
>
<font-awesome icon="circle-user" class="text-xl" />
</button>
<font-awesome
v-if="member.member.memberId === members[0]?.memberId"
icon="crown"
class="fa-fw text-amber-400"
/>
<font-awesome
v-if="!member.member.admitted"
icon="hourglass-half"
class="fa-fw text-slate-400"
/>
{{ member.name || unnamedMember }}
</h3>
<div
v-if="!getContactFor(member.did) && member.did !== activeDid"
class="flex items-center gap-1.5 ms-1"
>
<button
class="btn-add-contact"
title="Add as contact"
@click="addAsContact(member)"
>
<font-awesome icon="circle-user" />
</button>
<button
class="btn-info-contact"
title="Contact Info"
@click="
informAboutAddingContact(
getContactFor(member.did) !== undefined,
)
"
>
<font-awesome icon="circle-info" />
</button>
</div>
</div>
<button
v-if="member.did !== activeDid"
class="btn-info-contact"
title="Contact info"
@click="
informAboutAddingContact(
getContactFor(member.did) !== undefined,
)
"
>
<font-awesome icon="circle-info" class="text-base" />
</button>
</div>
<div class="flex">
<span
v-if="
showOrganizerTools && isOrganizer && member.did !== activeDid
"
class="flex items-center"
class="flex items-center gap-1.5"
>
<button
class="btn-admission"
:class="
member.member.admitted
? 'btn-admission-remove'
: 'btn-admission-add'
"
:title="
member.member.admitted ? 'Remove member' : 'Admit member'
"
@click="checkWhetherContactBeforeAdmitting(member)"
>
<font-awesome
:icon="member.member.admitted ? 'minus' : 'plus'"
class="text-sm"
:icon="
member.member.admitted ? 'circle-minus' : 'circle-plus'
"
/>
</button>
<button
class="btn-info-admission"
title="Admission info"
title="Admission Info"
@click="informAboutAdmission()"
>
<font-awesome icon="circle-info" class="text-base" />
<font-awesome icon="circle-info" />
</button>
</span>
</div>
</div>
<p class="text-sm text-gray-600 truncate">
{{ member.did }}
</p>
</div>
<div v-if="membersToShow().length > 0" class="flex justify-center mt-4">
<p class="text-xs text-gray-600 truncate">
{{ member.did }}
</p>
</li>
</ul>
<div v-if="membersToShow().length > 0" class="flex justify-between">
<!--
always have at least one refresh button even without members in case the organizer
changes the password
-->
<button
class="btn-action-refresh"
title="Refresh members list"
@click="fetchMembers"
class="text-sm 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"
title="Refresh members list now"
@click="manualRefresh"
>
<font-awesome icon="rotate" :class="{ 'fa-spin': isLoading }" />
Refresh
<span class="text-xs">({{ countdownTimer }}s)</span>
</button>
</div>
@@ -156,6 +185,15 @@
</p>
</div>
</div>
<!-- Set Visibility Dialog Component -->
<SetBulkVisibilityDialog
:visible="showSetVisibilityDialog"
:members-data="visibilityDialogMembers"
:active-did="activeDid"
:api-server="apiServer"
@close="closeSetVisibilityDialog"
/>
</template>
<script lang="ts">
@@ -176,8 +214,10 @@ import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
import {
NOTIFY_ADD_CONTACT_FIRST,
NOTIFY_CONTINUE_WITHOUT_ADDING,
NOTIFY_ADMIT_ALL_PENDING,
} from "@/constants/notifications";
import { SOMEONE_UNNAMED } from "@/constants/entities";
import SetBulkVisibilityDialog from "./SetBulkVisibilityDialog.vue";
interface Member {
admitted: boolean;
@@ -193,6 +233,9 @@ interface DecryptedMember {
}
@Component({
components: {
SetBulkVisibilityDialog,
},
mixins: [PlatformServiceMixin],
})
export default class MembersList extends Vue {
@@ -219,8 +262,25 @@ export default class MembersList extends Vue {
missingMyself = false;
activeDid = "";
apiServer = "";
// Set Visibility Dialog state
showSetVisibilityDialog = false;
visibilityDialogMembers: Array<{
did: string;
name: string;
isContact: boolean;
member: { memberId: string };
}> = [];
contacts: Array<Contact> = [];
// Auto-refresh functionality
countdownTimer = 10;
autoRefreshInterval: NodeJS.Timeout | null = null;
lastRefreshTime = 0;
// Track previous visibility members to detect changes
previousVisibilityMembers: string[] = [];
/**
* Get the unnamed member constant
*/
@@ -242,6 +302,21 @@ export default class MembersList extends Vue {
this.firstName = settings.firstName || "";
await this.fetchMembers();
await this.loadContacts();
// Start auto-refresh
this.startAutoRefresh();
// Check if we should show the visibility dialog on initial load
this.checkAndShowVisibilityDialog();
}
async refreshData() {
// Force refresh both contacts and members
await this.loadContacts();
await this.fetchMembers();
// Check if we should show the visibility dialog after refresh
this.checkAndShowVisibilityDialog();
}
async fetchMembers() {
@@ -329,22 +404,49 @@ export default class MembersList extends Vue {
}
membersToShow(): DecryptedMember[] {
let members: DecryptedMember[] = [];
if (this.isOrganizer) {
if (this.showOrganizerTools) {
return this.decryptedMembers;
members = this.decryptedMembers;
} else {
return this.decryptedMembers.filter(
members = this.decryptedMembers.filter(
(member: DecryptedMember) => member.member.admitted,
);
}
} else {
// non-organizers only get visible members from server
members = this.decryptedMembers;
}
// non-organizers only get visible members from server
return this.decryptedMembers;
// Sort members according to priority:
// 1. Organizer at the top
// 2. Non-admitted members next
// 3. Everyone else after
return members.sort((a, b) => {
// Check if either member is the organizer (first member in original list)
const aIsOrganizer = a.member.memberId === this.members[0]?.memberId;
const bIsOrganizer = b.member.memberId === this.members[0]?.memberId;
// Organizer always comes first
if (aIsOrganizer && !bIsOrganizer) return -1;
if (!aIsOrganizer && bIsOrganizer) return 1;
// If both are organizers or neither are organizers, sort by admission status
if (aIsOrganizer && bIsOrganizer) return 0; // Both organizers, maintain original order
// Non-admitted members come before admitted members
if (!a.member.admitted && b.member.admitted) return -1;
if (a.member.admitted && !b.member.admitted) return 1;
// If admission status is the same, maintain original order
return 0;
});
}
informAboutAdmission() {
this.notify.info(
"This is to register people in Time Safari and to admit them to the meeting. A '+' symbol means they are not yet admitted and you can register and admit them. A '-' means you can remove them, but they will stay registered.",
"This is to register people in Time Safari and to admit them to the meeting. A (+) symbol means they are not yet admitted and you can register and admit them. A (-) symbol means you can remove them, but they will stay registered.",
TIMEOUTS.VERY_LONG,
);
}
@@ -371,6 +473,80 @@ export default class MembersList extends Vue {
return this.contacts.find((contact) => contact.did === did);
}
getMembersForVisibility() {
return this.decryptedMembers
.filter((member) => {
// Exclude the current user
if (member.did === this.activeDid) {
return false;
}
const contact = this.getContactFor(member.did);
// Include members who:
// 1. Haven't been added as contacts yet, OR
// 2. Are contacts but don't have visibility set (seesMe property)
return !contact || !contact.seesMe;
})
.map((member) => ({
did: member.did,
name: member.name,
isContact: !!this.getContactFor(member.did),
member: {
memberId: member.member.memberId.toString(),
},
}));
}
/**
* Check if we should show the visibility dialog
* Returns true if there are members for visibility and either:
* - This is the first time (no previous members tracked), OR
* - New members have been added since last check (not removed)
*/
shouldShowVisibilityDialog(): boolean {
const currentMembers = this.getMembersForVisibility();
if (currentMembers.length === 0) {
return false;
}
// If no previous members tracked, show dialog
if (this.previousVisibilityMembers.length === 0) {
return true;
}
// Check if new members have been added (not just any change)
const currentMemberIds = currentMembers.map((m) => m.did);
const previousMemberIds = this.previousVisibilityMembers;
// Find new members (members in current but not in previous)
const newMembers = currentMemberIds.filter(
(id) => !previousMemberIds.includes(id),
);
// Only show dialog if there are new members added
return newMembers.length > 0;
}
/**
* Update the tracking of previous visibility members
*/
updatePreviousVisibilityMembers() {
const currentMembers = this.getMembersForVisibility();
this.previousVisibilityMembers = currentMembers.map((m) => m.did);
}
/**
* Show the visibility dialog if conditions are met
*/
checkAndShowVisibilityDialog() {
if (this.shouldShowVisibilityDialog()) {
this.showSetBulkVisibilityDialog();
}
this.updatePreviousVisibilityMembers();
}
checkWhetherContactBeforeAdmitting(decrMember: DecryptedMember) {
const contact = this.getContactFor(decrMember.did);
if (!decrMember.member.admitted && !contact) {
@@ -508,6 +684,187 @@ export default class MembersList extends Vue {
this.notify.error(message, TIMEOUTS.LONG);
}
}
showSetBulkVisibilityDialog() {
// Filter members to show only those who need visibility set
const membersForVisibility = this.getMembersForVisibility();
// Pause auto-refresh when dialog opens
this.stopAutoRefresh();
// Open the dialog directly
this.visibilityDialogMembers = membersForVisibility;
this.showSetVisibilityDialog = true;
}
startAutoRefresh() {
this.lastRefreshTime = Date.now();
this.countdownTimer = 10;
this.autoRefreshInterval = setInterval(() => {
const now = Date.now();
const timeSinceLastRefresh = (now - this.lastRefreshTime) / 1000;
if (timeSinceLastRefresh >= 10) {
// Time to refresh
this.refreshData();
this.lastRefreshTime = now;
this.countdownTimer = 10;
} else {
// Update countdown
this.countdownTimer = Math.max(
0,
Math.round(10 - timeSinceLastRefresh),
);
}
}, 1000); // Update every second
}
stopAutoRefresh() {
if (this.autoRefreshInterval) {
clearInterval(this.autoRefreshInterval);
this.autoRefreshInterval = null;
}
}
manualRefresh() {
// Clear existing auto-refresh interval
if (this.autoRefreshInterval) {
clearInterval(this.autoRefreshInterval);
this.autoRefreshInterval = null;
}
// Trigger immediate refresh and restart timer
this.refreshData();
this.startAutoRefresh();
// Always show dialog on manual refresh if there are members for visibility
if (this.getMembersForVisibility().length > 0) {
this.showSetBulkVisibilityDialog();
}
}
// Set Visibility Dialog methods
closeSetVisibilityDialog() {
this.showSetVisibilityDialog = false;
this.visibilityDialogMembers = [];
// Refresh data when dialog is closed
this.refreshData();
// Resume auto-refresh when dialog is closed
this.startAutoRefresh();
}
/**
* Get count of pending (non-admitted) members
*/
getPendingMembersCount(): number {
return this.decryptedMembers.filter(
(member) => !member.member.admitted && member.did !== this.activeDid,
).length;
}
/**
* Get list of pending members
*/
getPendingMembers(): DecryptedMember[] {
return this.decryptedMembers.filter(
(member) => !member.member.admitted && member.did !== this.activeDid,
);
}
/**
* Show the admit all pending members dialog
*/
showAdmitAllPendingDialog() {
const pendingCount = this.getPendingMembersCount();
if (pendingCount === 0) {
this.notify.info(
"There are no pending members to admit.",
TIMEOUTS.STANDARD,
);
return;
}
// Pause auto-refresh when dialog opens
this.stopAutoRefresh();
const dialogText = NOTIFY_ADMIT_ALL_PENDING.text.replace(
"{count}",
pendingCount.toString(),
);
this.$notify(
{
group: "modal",
type: "confirm",
title: NOTIFY_ADMIT_ALL_PENDING.title,
text: dialogText,
yesText: NOTIFY_ADMIT_ALL_PENDING.yesText,
noText: NOTIFY_ADMIT_ALL_PENDING.noText,
onYes: async () => {
await this.admitAllPendingMembers(true); // true = add to contacts
// Resume auto-refresh after action
this.startAutoRefresh();
},
onNo: async () => {
await this.admitAllPendingMembers(false); // false = don't add to contacts
// Resume auto-refresh after action
this.startAutoRefresh();
},
onCancel: async () => {
// Do nothing - user cancelled
// Resume auto-refresh after cancellation
this.startAutoRefresh();
},
},
TIMEOUTS.MODAL,
);
}
/**
* Admit all pending members with optional contact addition
*/
async admitAllPendingMembers(addToContacts: boolean) {
const pendingMembers = this.getPendingMembers();
if (pendingMembers.length === 0) {
return;
}
try {
// Process each pending member
for (const member of pendingMembers) {
// Add to contacts if requested and not already a contact
if (addToContacts && !this.getContactFor(member.did)) {
await this.addAsContact(member);
}
// Admit the member
await this.toggleAdmission(member);
}
// Show success message
const contactMessage = addToContacts ? " and added to your contacts" : "";
this.notify.success(
`All ${pendingMembers.length} pending members have been admitted${contactMessage}.`,
TIMEOUTS.STANDARD,
);
} catch (error) {
this.$logAndConsole(
"Error admitting all pending members: " + errorStringForLog(error),
true,
);
this.notify.error(
"Failed to admit some members. Please try again.",
TIMEOUTS.LONG,
);
}
}
beforeDestroy() {
this.stopAutoRefresh();
}
}
</script>
@@ -522,29 +879,26 @@ export default class MembersList extends Vue {
.btn-add-contact {
/* stylelint-disable-next-line at-rule-no-unknown */
@apply ml-2 w-8 h-8 flex items-center justify-center rounded-full
bg-green-100 text-green-600 hover:bg-green-200 hover:text-green-800
transition-colors;
}
.btn-info-contact {
/* stylelint-disable-next-line at-rule-no-unknown */
@apply ml-2 mb-2 w-6 h-6 flex items-center justify-center rounded-full
bg-slate-100 text-slate-500 hover:bg-slate-200 hover:text-slate-800
transition-colors;
}
.btn-admission {
/* stylelint-disable-next-line at-rule-no-unknown */
@apply mr-2 w-6 h-6 flex items-center justify-center rounded-full
bg-blue-100 text-blue-600 hover:bg-blue-200 hover:text-blue-800
@apply text-lg text-green-600 hover:text-green-800
transition-colors;
}
.btn-info-contact,
.btn-info-admission {
/* stylelint-disable-next-line at-rule-no-unknown */
@apply mr-2 mb-2 w-6 h-6 flex items-center justify-center rounded-full
bg-slate-100 text-slate-500 hover:bg-slate-200 hover:text-slate-800
@apply text-slate-400 hover:text-slate-600
transition-colors;
}
.btn-admission-add {
/* stylelint-disable-next-line at-rule-no-unknown */
@apply text-lg text-blue-500 hover:text-blue-700
transition-colors;
}
.btn-admission-remove {
/* stylelint-disable-next-line at-rule-no-unknown */
@apply text-lg text-rose-500 hover:text-rose-700
transition-colors;
}
</style>

View File

@@ -0,0 +1,333 @@
<template>
<div v-if="visible" class="dialog-overlay">
<div class="dialog">
<div class="text-slate-900 text-center">
<h3 class="text-lg font-semibold leading-[1.25] mb-2">
Set Visibility to Meeting Members
</h3>
<p class="text-sm mb-4">
Would you like to <b>make your activities visible</b> to the following
members? (This will also add them as contacts if they aren't already.)
</p>
<!-- Custom table area - you can customize this -->
<div v-if="shouldInitializeSelection" class="mb-4">
<table
class="w-full border-collapse border border-slate-300 text-sm text-start"
>
<thead v-if="membersData && membersData.length > 0">
<tr class="bg-slate-100 font-medium">
<th class="border border-slate-300 px-3 py-2">
<label class="flex items-center gap-2">
<input
type="checkbox"
:checked="isAllSelected"
:indeterminate="isIndeterminate"
@change="toggleSelectAll"
/>
Select All
</label>
</th>
</tr>
</thead>
<tbody>
<!-- Dynamic data from MembersList -->
<tr v-if="!membersData || membersData.length === 0">
<td
class="border border-slate-300 px-3 py-2 text-center italic text-gray-500"
>
No members need visibility settings
</td>
</tr>
<tr
v-for="member in membersData || []"
:key="member.member.memberId"
>
<td class="border border-slate-300 px-3 py-2">
<div class="flex items-center justify-between gap-2">
<label class="flex items-center gap-2">
<input
type="checkbox"
:checked="isMemberSelected(member.did)"
@change="toggleMemberSelection(member.did)"
/>
{{ member.name || SOMEONE_UNNAMED }}
</label>
<!-- Friend indicator - only show if they are already a contact -->
<font-awesome
v-if="member.isContact"
icon="user-circle"
class="fa-fw ms-auto text-slate-400 cursor-pointer hover:text-slate-600"
@click="showContactInfo"
/>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<div class="space-y-2">
<button
v-if="membersData && membersData.length > 0"
:disabled="!hasSelectedMembers"
:class="[
'block w-full text-center text-md font-bold uppercase px-2 py-2 rounded-md',
hasSelectedMembers
? 'bg-blue-600 text-white cursor-pointer'
: 'bg-slate-400 text-slate-200 cursor-not-allowed',
]"
@click="setVisibilityForSelectedMembers"
>
Set Visibility
</button>
<button
class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white px-2 py-2 rounded-md"
@click="cancel"
>
{{
membersData && membersData.length > 0 ? "Maybe Later" : "Cancel"
}}
</button>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Vue, Component, Prop } from "vue-facing-decorator";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { SOMEONE_UNNAMED } from "@/constants/entities";
import { setVisibilityUtil } from "@/libs/endorserServer";
import { createNotifyHelpers } from "@/utils/notify";
interface MemberData {
did: string;
name: string;
isContact: boolean;
member: {
memberId: string;
};
}
@Component({
mixins: [PlatformServiceMixin],
})
export default class SetBulkVisibilityDialog extends Vue {
@Prop({ default: false }) visible!: boolean;
@Prop({ default: () => [] }) membersData!: MemberData[];
@Prop({ default: "" }) activeDid!: string;
@Prop({ default: "" }) apiServer!: string;
// Vue notification system
$notify!: (
notification: { group: string; type: string; title: string; text: string },
timeout?: number,
) => void;
// Notification system
notify!: ReturnType<typeof createNotifyHelpers>;
// Component state
selectedMembers: string[] = [];
selectionInitialized = false;
// Constants
// In Vue templates, imported constants need to be explicitly made available to the template
readonly SOMEONE_UNNAMED = SOMEONE_UNNAMED;
get hasSelectedMembers() {
return this.selectedMembers.length > 0;
}
get isAllSelected() {
if (!this.membersData || this.membersData.length === 0) return false;
return this.membersData.every((member) =>
this.selectedMembers.includes(member.did),
);
}
get isIndeterminate() {
if (!this.membersData || this.membersData.length === 0) return false;
const selectedCount = this.membersData.filter((member) =>
this.selectedMembers.includes(member.did),
).length;
return selectedCount > 0 && selectedCount < this.membersData.length;
}
get shouldInitializeSelection() {
// This method will initialize selection when the dialog opens
if (!this.selectionInitialized) {
this.initializeSelection();
this.selectionInitialized = true;
}
return true;
}
created() {
this.notify = createNotifyHelpers(this.$notify);
}
initializeSelection() {
// Reset selection when dialog opens
this.selectedMembers = [];
// Select all by default
this.selectedMembers = this.membersData.map((member) => member.did);
}
resetSelection() {
this.selectedMembers = [];
this.selectionInitialized = false;
}
toggleSelectAll() {
if (!this.membersData || this.membersData.length === 0) return;
if (this.isAllSelected) {
// Deselect all
this.selectedMembers = [];
} else {
// Select all
this.selectedMembers = this.membersData.map((member) => member.did);
}
}
toggleMemberSelection(memberDid: string) {
const index = this.selectedMembers.indexOf(memberDid);
if (index > -1) {
this.selectedMembers.splice(index, 1);
} else {
this.selectedMembers.push(memberDid);
}
}
isMemberSelected(memberDid: string) {
return this.selectedMembers.includes(memberDid);
}
async setVisibilityForSelectedMembers() {
try {
const selectedMembers = this.membersData.filter((member) =>
this.selectedMembers.includes(member.did),
);
let successCount = 0;
for (const member of selectedMembers) {
try {
// If they're not a contact yet, add them as a contact first
if (!member.isContact) {
await this.addAsContact(member);
}
// Set their seesMe to true
await this.updateContactVisibility(member.did, true);
successCount++;
} catch (error) {
// eslint-disable-next-line no-console
console.error(`Error processing member ${member.did}:`, error);
// Continue with other members even if one fails
}
}
// Show success notification
this.$notify(
{
group: "alert",
type: "success",
title: "Visibility Set Successfully",
text: `Visibility set for ${successCount} member${successCount === 1 ? "" : "s"}.`,
},
5000,
);
// Emit success event
this.$emit("success", successCount);
this.close();
} catch (error) {
// eslint-disable-next-line no-console
console.error("Error setting visibility:", error);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: "Failed to set visibility for some members. Please try again.",
},
5000,
);
}
}
async addAsContact(member: { did: string; name: string }) {
try {
const newContact = {
did: member.did,
name: member.name,
};
await this.$insertContact(newContact);
} catch (err) {
// eslint-disable-next-line no-console
console.error("Error adding contact:", err);
if (err instanceof Error && err.message?.indexOf("already exists") > -1) {
// Contact already exists, continue
} else {
throw err; // Re-throw if it's not a duplicate error
}
}
}
async updateContactVisibility(did: string, seesMe: boolean) {
try {
// Get the contact object
const contact = await this.$getContact(did);
if (!contact) {
throw new Error(`Contact not found for DID: ${did}`);
}
// Use the proper API to set visibility on the server
const result = await setVisibilityUtil(
this.activeDid,
this.apiServer,
this.axios,
contact,
seesMe,
);
if (!result.success) {
throw new Error(result.error || "Failed to set visibility");
}
} catch (err) {
// eslint-disable-next-line no-console
console.error("Error updating contact visibility:", err);
throw err;
}
}
showContactInfo() {
this.$notify(
{
group: "alert",
type: "info",
title: "Contact Info",
text: "This user is already your contact, but your activities are not visible to them yet.",
},
5000,
);
}
close() {
this.resetSelection();
this.$emit("close");
}
cancel() {
this.close();
}
}
</script>

View File

@@ -1,16 +1,9 @@
<template>
<div
class="absolute right-5 top-[max(0.75rem,env(safe-area-inset-top),var(--safe-area-inset-top,0px))]"
v-if="message"
class="-mt-6 bg-rose-100 border border-t-0 border-dashed border-rose-600 text-rose-900 text-sm text-center font-semibold rounded-b-md px-3 py-2 mb-3"
>
<span class="align-center text-red-500 mr-2">{{ message }}</span>
<span class="ml-2">
<router-link
:to="{ name: 'help' }"
class="text-xs uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-1 rounded-md ml-1"
>
Help
</router-link>
</span>
{{ message }}
</div>
</template>

View File

@@ -8,7 +8,7 @@
<!-- show spinner if loading limits -->
<div
v-if="loadingLimits"
class="text-center"
class="text-slate-500 text-center italic mb-4"
role="status"
aria-live="polite"
>
@@ -19,7 +19,10 @@
aria-hidden="true"
></font-awesome>
</div>
<div class="mb-4 text-center">
<div
v-if="limitsMessage"
class="bg-amber-200 text-amber-900 border-amber-500 border-dashed border text-center rounded-md overflow-hidden px-4 py-3 mb-4"
>
{{ limitsMessage }}
</div>
<div v-if="endorserLimits">

View File

@@ -59,7 +59,7 @@ export const PASSKEYS_ENABLED =
export interface NotificationIface {
group: string; // "alert" | "modal"
type: string; // "toast" | "info" | "success" | "warning" | "danger"
title: string;
title?: string;
text?: string;
callback?: (success: boolean) => Promise<void>; // if this triggered an action
noText?: string;
@@ -68,4 +68,11 @@ export interface NotificationIface {
onYes?: () => Promise<void>;
promptToStopAsking?: boolean;
yesText?: string;
membersData?: Array<{
member: { admitted: boolean; content: string; memberId: number };
name: string;
did: string;
isContact: boolean;
contact?: { did: string; name?: string; seesMe?: boolean };
}>; // For passing member data to visibility dialog
}

View File

@@ -471,6 +471,14 @@ export const NOTIFY_CONTINUE_WITHOUT_ADDING = {
noText: "No, Cancel",
};
// Used in: MembersList.vue (complex modal for admitting all pending members)
export const NOTIFY_ADMIT_ALL_PENDING = {
title: "Admit All Pending Members",
text: "You are about to admit {count} pending member/s. Would you also like to add them to your Contacts list?",
yesText: "Admit and Add to Contacts",
noText: "Admit Only",
};
// HelpNotificationsView.vue specific constants
// Used in: HelpNotificationsView.vue (sendTestWebPushMessage method - not subscribed error)
export const NOTIFY_PUSH_NOT_SUBSCRIBED = {

View File

@@ -29,6 +29,7 @@ import {
faCircle,
faCircleCheck,
faCircleInfo,
faCircleMinus,
faCirclePlus,
faCircleQuestion,
faCircleRight,
@@ -37,6 +38,7 @@ import {
faCoins,
faComment,
faCopy,
faCrown,
faDollar,
faDownload,
faEllipsis,
@@ -58,6 +60,7 @@ import {
faHand,
faHandHoldingDollar,
faHandHoldingHeart,
faHourglassHalf,
faHouseChimney,
faImage,
faImagePortrait,
@@ -123,6 +126,7 @@ library.add(
faCircle,
faCircleCheck,
faCircleInfo,
faCircleMinus,
faCirclePlus,
faCircleQuestion,
faCircleRight,
@@ -131,6 +135,7 @@ library.add(
faCoins,
faComment,
faCopy,
faCrown,
faDollar,
faDownload,
faEllipsis,
@@ -152,6 +157,7 @@ library.add(
faHand,
faHandHoldingDollar,
faHandHoldingHeart,
faHourglassHalf,
faHouseChimney,
faImage,
faImagePortrait,

View File

@@ -285,6 +285,16 @@ const routes: Array<RouteRecordRaw> = [
name: "user-profile",
component: () => import("../views/UserProfileView.vue"),
},
// Catch-all route for 404 errors - must be last
{
path: "/:pathMatch(.*)*",
name: "not-found",
component: () => import("../views/NotFoundView.vue"),
meta: {
title: "Page Not Found",
requiresAuth: false,
},
},
];
const isElectron = window.location.protocol === "file:";

View File

@@ -1,6 +1,5 @@
<template>
<QuickNav selected="Profile" />
<TopMessage />
<!-- CONTENT -->
<main
@@ -9,10 +8,22 @@
role="main"
aria-label="Account Profile"
>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light">
Your Identity
</h1>
<TopMessage />
<!-- Main View Heading -->
<div class="flex gap-4 items-center mb-8">
<h1 id="ViewHeading" class="text-2xl font-bold leading-none">
Your Identity
</h1>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- ID notice -->
<div
@@ -1453,6 +1464,8 @@ export default class AccountViewView extends Vue {
if (imageResp && imageResp.status === 200) {
this.imageLimits = imageResp.data;
} else {
this.limitsMessage = ACCOUNT_VIEW_CONSTANTS.LIMITS.NO_IMAGE_ACCESS;
}
const endorserResp = await fetchEndorserRateLimits(

View File

@@ -1,19 +1,27 @@
<template>
<QuickNav />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Back -->
<button
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw" />
</button>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Raw Claim
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div class="flex">

View File

@@ -2,19 +2,27 @@
<QuickNav />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Back -->
<button
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
aria-label="Go back"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="fa-fw" />
</button>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Verifiable Claim Details
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Details -->
@@ -80,19 +88,22 @@
</button>
</div>
</div>
<div class="text-sm">
<div data-testId="description">
<div class="text-sm overflow-hidden">
<div
data-testId="description"
class="overflow-hidden text-ellipsis"
>
<font-awesome icon="message" class="fa-fw text-slate-400" />
<vue-markdown
:source="claimDescription"
class="markdown-content"
/>
</div>
<div>
<div class="overflow-hidden text-ellipsis">
<font-awesome icon="user" class="fa-fw text-slate-400" />
{{ didInfo(veriClaim.issuer) }}
</div>
<div>
<div class="overflow-hidden text-ellipsis">
<font-awesome icon="calendar" class="fa-fw text-slate-400" />
Recorded
{{ formattedIssueDate }}

View File

@@ -1,18 +1,27 @@
<template>
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Cancel -->
<router-link
:to="{ name: 'account' }"
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
><font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</router-link>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Confirm Contact
</h1>
<!-- Back -->
<router-link
class="order-first text-lg text-center leading-none p-1"
:to="{ name: 'account' }"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</router-link>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<p class="text-center text-xl mb-4 font-light">

View File

@@ -1,18 +1,11 @@
<template>
<QuickNav />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Back -->
<button
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="fa-fw" />
</button>
<TopMessage />
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
<span
v-if="
libsUtil.isGiveRecordTheUserCanConfirm(
@@ -25,8 +18,24 @@
>
Do you agree?
</span>
<span v-else> Confirmation Details </span>
<span v-else>Confirmation Details</span>
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div v-if="giveDetails && !isLoading">

View File

@@ -2,18 +2,27 @@
<QuickNav selected="Contacts" />
<section class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Header -->
<div class="mb-8">
<router-link
:to="{ name: 'contacts' }"
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
>
<font-awesome icon="chevron-left" class="fa-fw" />
</router-link>
<h1 class="text-4xl text-center font-light pt-4">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Transferred with {{ contact?.name }}
</h1>
<!-- Back -->
<router-link
class="order-first text-lg text-center leading-none p-1"
:to="{ name: 'contacts' }"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</router-link>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Info Messages -->

View File

@@ -1,19 +1,28 @@
<template>
<QuickNav selected="Contacts" />
<TopMessage />
<section id="ContactEdit" class="p-6 max-w-3xl mx-auto">
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-4xl text-center font-light relative px-7">
<!-- Back -->
<button
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="fa-fw" />
</button>
<TopMessage />
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
{{ contact?.name || AppString.NO_CONTACT_NAME }}
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Contact Name -->

View File

@@ -2,17 +2,27 @@
<QuickNav selected="Home"></QuickNav>
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-2xl text-center font-semibold relative px-7">
<!-- Back -->
<router-link
:to="{ name: 'home' }"
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
><font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</router-link>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
{{ stepType === "giver" ? "Given by..." : "Given to..." }}
</h1>
<!-- Back -->
<router-link
class="order-first text-lg text-center leading-none p-1"
:to="{ name: 'home' }"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</router-link>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Results List -->

View File

@@ -1,20 +1,28 @@
<template>
<QuickNav selected="Contacts"></QuickNav>
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Contact Import
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Contact Import
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div v-if="checkingImports" class="text-center">
<font-awesome icon="spinner" class="animate-spin" />

View File

@@ -2,26 +2,27 @@
<!-- CONTENT -->
<section id="Content" class="relative w-[100vw] h-[100vh]">
<div :class="mainContentClasses">
<div class="mb-4">
<h1 class="text-xl text-center font-semibold relative">
<!-- Back -->
<a
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="handleBack"
>
<font-awesome icon="chevron-left" class="fa-fw" />
</a>
<!-- Quick Help -->
<a
class="text-xl text-center text-blue-500 px-2 py-1 absolute -right-2 -top-1"
@click="toastQRCodeHelp()"
>
<font-awesome icon="circle-question" class="fa-fw" />
</a>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-4">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Share Contact Info
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="handleBack"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Quick Help -->
<a
class="block text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
@click="toastQRCodeHelp()"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</a>
</div>
<div
@@ -235,7 +236,7 @@ export default class ContactQRScanFull extends Vue {
* Computed property for main content container CSS classes
*/
get mainContentClasses(): string {
return "p-6 bg-white w-full max-w-[calc((100vh-max(env(safe-area-inset-top),var(--safe-area-inset-top,0px))-max(env(safe-area-inset-bottom),var(--safe-area-inset-bottom,0px)))*0.4)] mx-auto";
return "p-4 bg-white w-full max-w-[calc((100vh-max(env(safe-area-inset-top),var(--safe-area-inset-top,0px))-max(env(safe-area-inset-bottom),var(--safe-area-inset-bottom,0px)))*0.4)] mx-auto";
}
/**

View File

@@ -1,26 +1,27 @@
<template>
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<div class="mb-2">
<h1 class="text-2xl text-center font-semibold relative px-7">
<!-- Back -->
<a
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="handleBack"
>
<font-awesome icon="chevron-left" class="fa-fw" />
</a>
<!-- Quick Help -->
<a
class="text-2xl text-center text-blue-500 px-2 py-1 absolute -right-2 -top-1"
@click="toastQRCodeHelp()"
>
<font-awesome icon="circle-question" class="fa-fw" />
</a>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Share Contact Info
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="handleBack"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Quick Help -->
<a
class="block text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
@click="toastQRCodeHelp()"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</a>
</div>
<div v-if="!givenName" :class="nameWarningClasses">

View File

@@ -1,14 +1,25 @@
<template>
<QuickNav selected="Contacts" />
<TopMessage />
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light">
Your Contacts
</h1>
<TopMessage />
<div class="flex justify-between py-2 mt-8">
<!-- Main View Heading -->
<div class="flex gap-4 items-center mb-4">
<h1 id="ViewHeading" class="text-2xl font-bold leading-none">
Your Contacts
</h1>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div class="flex justify-between py-2 mt-4">
<span />
<span>
<a

View File

@@ -1,22 +1,31 @@
<template>
<QuickNav selected="Contacts" />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 id="ViewHeading" class="text-lg text-center font-light relative px-7">
<!-- Go to 'contacts' instead of just 'back' because they could get here from an edit page
(and going back there is annoying). -->
<router-link
:to="{ name: 'contacts' }"
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</router-link>
<TopMessage />
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Identifier Details
</h1>
<!-- Back -->
<router-link
class="order-first text-lg text-center leading-none p-1"
:to="{ name: 'contacts' }"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</router-link>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Identity Details -->
@@ -25,7 +34,7 @@
class="bg-slate-100 rounded-md overflow-hidden px-4 py-3 mb-4"
>
<div>
<h2 class="text-xl font-semibold">
<h2 class="text-xl font-semibold overflow-hidden text-ellipsis">
{{ contactFromDid?.name || "(no name)" }}
<router-link
:to="{ name: 'contact-edit', params: { did: contactFromDid?.did } }"

View File

@@ -1,7 +1,15 @@
<template>
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<h1>Invalid Deep Link</h1>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1
class="grow text-rose-500 text-xl text-center font-semibold leading-tight"
>
Invalid Deep Link
</h1>
</div>
<div class="error-details">
<div class="error-message">
<h3>Error Details</h3>
@@ -114,11 +122,6 @@ onMounted(() => {
</script>
<style scoped>
h1 {
color: #ff4444;
margin-bottom: 24px;
}
h2,
h3 {
color: #333;

View File

@@ -2,9 +2,12 @@
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<div class="mb-4">
<h1 class="text-2xl text-center font-semibold relative px-7">
Redirecting to Time Safari
</h1>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Redirecting to Time Safari
</h1>
</div>
<div v-if="destinationUrl" class="space-y-4">
<!-- Platform-specific messaging -->

View File

@@ -1,13 +1,22 @@
<template>
<QuickNav selected="Discover" />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light">
Discover Projects & People
</h1>
<TopMessage />
<!-- Main View Heading -->
<div class="flex gap-4 items-center mb-4">
<h1 id="ViewHeading" class="text-2xl font-bold leading-none">Discover</h1>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<OnboardingDialog ref="onboardingDialog" />
@@ -273,8 +282,8 @@
/>
</div>
<div class="grow">
<h2 class="text-base font-semibold">
<div class="grow overflow-hidden">
<h2 class="text-base font-semibold truncate">
{{ project.name || unnamedProject }}
</h2>
<div class="text-sm">
@@ -904,7 +913,7 @@ export default class DiscoverView extends Vue {
public computedLocalTabStyleClassNames() {
return {
"inline-block": true,
"py-3": true,
"py-2": true,
"rounded-t-lg": true,
"border-b-2": true,
@@ -922,7 +931,7 @@ export default class DiscoverView extends Vue {
public computedMappedTabStyleClassNames() {
return {
"inline-block": true,
"py-3": true,
"py-2": true,
"rounded-t-lg": true,
"border-b-2": true,
@@ -940,7 +949,7 @@ export default class DiscoverView extends Vue {
public computedRemoteTabStyleClassNames() {
return {
"inline-block": true,
"py-3": true,
"py-2": true,
"rounded-t-lg": true,
"border-b-2": true,
@@ -958,7 +967,7 @@ export default class DiscoverView extends Vue {
public computedProjectsTabStyleClassNames() {
return {
"inline-block": true,
"py-3": true,
"py-2": true,
"rounded-t-lg": true,
"border-b-2": true,
@@ -976,7 +985,7 @@ export default class DiscoverView extends Vue {
public computedPeopleTabStyleClassNames() {
return {
"inline-block": true,
"py-3": true,
"py-2": true,
"rounded-t-lg": true,
"border-b-2": true,

View File

@@ -1,24 +1,33 @@
<template>
<QuickNav />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-2xl text-center font-semibold relative px-7 mb-2">
<TopMessage />
<div class="mb-8">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-4">
<h1 class="grow text-xl text-center font-semibold leading-tight">
What Was Given
</h1>
<!-- Back -->
<div
v-if="!hideBackButton"
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
<a
class="order-first text-lg text-center leading-none p-1"
@click="cancelBack()"
>
<font-awesome icon="chevron-left" class="fa-fw" />
</div>
What Was Given
</h1>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<h2 class="text-lg font-normal text-center overflow-hidden">
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<h2 class="text-lg font-normal leading-tight text-center overflow-hidden">
<div class="truncate">
From
{{

View File

@@ -3,22 +3,27 @@
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Notification Types
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- eslint-disable prettier/prettier -->

View File

@@ -34,22 +34,27 @@
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="goBack()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Notification Help
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="goBack()"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- eslint-disable prettier/prettier -->

View File

@@ -3,11 +3,9 @@
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Don't include 'back' button since this is shown in a different window. -->
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Time Safari Onboarding Instructions
</h1>
</div>

View File

@@ -3,23 +3,25 @@
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw" />
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Help
<span class="text-xs text-gray-500">{{ package.version }}</span>
<span class="text-xs font-medium text-slate-500 uppercase">{{
package.version
}}</span>
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Spacer (no Help button) -->
<div class="p-3 pe-3.5 pb-3.5"></div>
</div>
<!-- eslint-disable prettier/prettier max-len -->

View File

@@ -6,7 +6,6 @@ Raymer * @version 1.0.0 */
<template>
<QuickNav selected="Home" />
<TopMessage />
<!-- CONTENT -->
<section
@@ -14,10 +13,25 @@ Raymer * @version 1.0.0 */
class="p-6 pb-24 max-w-3xl mx-auto"
:data-active-did="activeDid"
>
<h1 id="ViewHeading" class="text-4xl text-center font-light mb-8">
{{ AppString.APP_NAME }}
<span class="text-xs text-gray-500">{{ package.version }}</span>
</h1>
<TopMessage />
<!-- Main View Heading -->
<div class="flex gap-4 items-center mb-4">
<h1 id="ViewHeading" class="text-2xl font-bold leading-none">
{{ AppString.APP_NAME }}
<span class="text-xs font-medium text-slate-500 uppercase">{{
package.version
}}</span>
</h1>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<OnboardingDialog ref="onboardingDialog" />
@@ -97,9 +111,9 @@ Raymer * @version 1.0.0 */
<!-- Record Quick-Action -->
<div class="mb-6">
<div class="flex gap-2 items-center mb-2">
<h2 class="text-xl font-bold">Record something given by:</h2>
<h2 class="font-bold">Record something given by:</h2>
<button
class="block ms-auto text-center text-white bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-2 rounded-full"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
@click="openGiftedPrompts()"
>
<font-awesome
@@ -143,10 +157,10 @@ Raymer * @version 1.0.0 */
<!-- Results List -->
<div class="mt-4 mb-4">
<div class="flex gap-2 items-center mb-3">
<h2 class="text-xl font-bold">Latest Activity</h2>
<h2 class="font-bold">Latest Activity</h2>
<button
v-if="resultsAreFiltered()"
class="block ms-auto text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-2 rounded-full"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
@click="openFeedFilters()"
>
<font-awesome
@@ -156,7 +170,7 @@ Raymer * @version 1.0.0 */
</button>
<button
v-else
class="block ms-auto text-center text-white bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-2 rounded-full"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
@click="openFeedFilters()"
>
<font-awesome

View File

@@ -1,18 +1,27 @@
<template>
<QuickNav selected="Profile"></QuickNav>
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Cancel -->
<router-link
:to="{ name: 'account' }"
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
><font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</router-link>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Switch Identity
</h1>
<!-- Back -->
<router-link
class="order-first text-lg text-center leading-none p-1"
:to="{ name: 'account' }"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</router-link>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Identity List -->

View File

@@ -1,17 +1,26 @@
<template>
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Cancel -->
<button
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left"></font-awesome>
</button>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Import Existing Identifier
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Import Account Form -->
<p class="text-center text-xl mb-4 font-light">

View File

@@ -1,20 +1,29 @@
<template>
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Cancel -->
<button
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left"></font-awesome>
</button>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Derive from Existing Identity
</h1>
</div>
<!-- Import Account Form -->
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Import Account Form -->
<div>
<p class="text-center text-xl mb-4 font-light">
Will increment the maximum known derivation path from the existing seed.

View File

@@ -1,20 +1,31 @@
<template>
<QuickNav selected="Invite" />
<TopMessage />
<QuickNav selected="Contacts" />
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<TopMessage />
<!-- Heading -->
<h1 class="text-4xl text-center font-light">Invitations</h1>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Invitations
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<ul class="ml-8 mt-4 list-outside list-disc w-5/6">
<li>

View File

@@ -1,22 +1,31 @@
<!-- This is useful in an environment where the download doesn't work. -->
<template>
<QuickNav selected="" />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Back Button -->
<div class="relative px-7">
<h1
class="text-lg text-center font-light px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="mr-2" />
</h1>
</div>
<TopMessage />
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light mb-6">Logs</h1>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">Logs</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Error Message -->
<div

View File

@@ -2,17 +2,27 @@
<QuickNav selected="Home"></QuickNav>
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Back -->
<font-awesome
icon="chevron-left"
class="fa-fw text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
/>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
New Activity For You
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Display a single row with the name of "New Offers To You" with a count. -->

View File

@@ -22,18 +22,27 @@
-->
<template>
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Cancel -->
<button
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</button>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Edit Identity
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<input

View File

@@ -2,19 +2,27 @@
<QuickNav selected="Projects"></QuickNav>
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Cancel -->
<!-- Back -->
<button
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</button>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Edit Project Idea
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Project Details -->

View File

@@ -3,22 +3,27 @@
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Your Identity
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div class="flex justify-center py-12">

View File

@@ -0,0 +1,88 @@
<template>
<div
class="min-h-screen bg-gray-50 flex flex-col justify-start pt-2 sm:px-6 lg:px-8"
>
<div class="sm:mx-auto sm:w-full sm:max-w-md">
<div class="text-center">
<div class="mx-auto h-24 w-24 text-gray-400">
<svg
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="12" cy="12" r="10" stroke-width="1.5" />
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 8v4m0 4h.01"
/>
</svg>
</div>
<h1 class="mt-4 text-3xl font-extrabold text-gray-900">Not Found</h1>
<p class="text-sm text-gray-600">
The page you're looking for doesn't exist.
</p>
<div class="mt-1">
<button
class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
@click="goBack"
>
<svg
class="-ml-1 mr-2 h-5 w-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M10 19l-7-7m0 0l7-7m-7 7h18"
/>
</svg>
Go Back
</button>
</div>
<div class="mt-16">
<button
class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
@click="goHome"
>
<svg
class="-ml-1 mr-2 h-5 w-5"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2
2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1
1 0 011 1v4a1 1 0 001 1m-6 0h6"
></path>
</svg>
Go Home
</button>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useRouter } from "vue-router";
const router = useRouter();
const goHome = () => {
router.push("/");
};
const goBack = () => {
router.go(-1);
};
</script>

View File

@@ -1,24 +1,32 @@
<template>
<QuickNav />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Back -->
<div
v-if="!hideBackButton"
class="text-lg text-center font-light relative px-7"
>
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
<TopMessage />
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
What Is Offered
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="cancelBack()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Heading -->
<h1 class="text-4xl text-center font-light px-4 mb-4">What Is Offered</h1>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<h1 class="text-xl font-bold text-center mb-4">
<span> Offer to {{ recipientDisplayName }} </span>

View File

@@ -1,12 +1,26 @@
<template>
<QuickNav selected="Contacts" />
<TopMessage />
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light mb-8">
Onboarding Meetings
</h1>
<TopMessage />
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Onboarding Meetings
</h1>
<!-- Spacer (no Back button) -->
<div class="order-first p-3 pe-3.5 pb-3.5"></div>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Loading State -->
<div v-if="isLoading" class="flex justify-center items-center py-8">

View File

@@ -1,12 +1,26 @@
<template>
<QuickNav selected="Contacts" />
<TopMessage />
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light mb-8">
Meeting Members
</h1>
<TopMessage />
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Meeting Members
</h1>
<!-- Spacer (no Back button) -->
<div class="order-first p-3 pe-3.5 pb-3.5"></div>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Loading Animation -->
<div
@@ -63,6 +77,7 @@ import {
} from "../libs/endorserServer";
import { generateSaveAndActivateIdentity } from "../libs/util";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { NotificationIface } from "../constants/app";
@Component({
components: {
@@ -83,6 +98,7 @@ export default class OnboardMeetingMembersView extends Vue {
projectLink = "";
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
$notify!: (notification: NotificationIface, timeout?: number) => void;
userNameDialog!: InstanceType<typeof UserNameDialog>;

View File

@@ -1,12 +1,26 @@
<template>
<QuickNav selected="Contacts" />
<TopMessage />
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light">
Onboarding Meeting
</h1>
<TopMessage />
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Onboarding Meeting
</h1>
<!-- Spacer (no Back button) -->
<div class="order-first p-3 pe-3.5 pb-3.5"></div>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Existing Meeting Section -->
<div
@@ -216,26 +230,28 @@
class="mt-8 p-4 border rounded-lg bg-white shadow"
>
<div class="flex items-center justify-between">
<h2 class="text-2xl">Meeting Members</h2>
</div>
<div class="mt-4">
&bull; Page for Members
<span
class="ml-4 cursor-pointer text-blue-600"
title="Click to copy link for members"
@click="copyMembersLinkToClipboard"
>
<font-awesome icon="link" />
</span>
<a
v-if="!!currentMeeting.password"
:href="onboardMeetingMembersLink()"
class="ml-4 text-blue-600"
target="_blank"
>
<font-awesome icon="external-link" />
</a>
<h2 class="font-bold">Meeting Members</h2>
</div>
<ul class="list-disc text-sm mt-4 mb-2 ps-4 space-y-2">
<li>
Page for Members:
<span
class="ml-4 cursor-pointer text-blue-600"
title="Click to copy link for members"
@click="copyMembersLinkToClipboard"
>
<font-awesome icon="link" />
</span>
<a
v-if="!!currentMeeting.password"
:href="onboardMeetingMembersLink()"
class="ml-4 text-blue-600"
target="_blank"
>
<font-awesome icon="external-link" />
</a>
</li>
</ul>
<MembersList
:password="currentMeeting.password || ''"

View File

@@ -1,48 +1,58 @@
<template>
<QuickNav />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb">
<div>
<h1 class="text-center text-lg font-light relative px-7">
<!-- Back -->
<button
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</button>
<TopMessage />
<div class="mb-4">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-4">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Project Idea
</h1>
<h2 class="text-center text-xl font-semibold">
{{ name }}
<button
v-if="activeDid === issuer || activeDid === agentDid"
title="Edit"
data-testId="editClaimButton"
@click="onEditClick()"
>
<font-awesome icon="pen" class="text-sm text-blue-500 ml-2 mb-1" />
</button>
<button
:title="
isStarred
? 'Remove from starred projects'
: 'Add to starred projects'
"
@click="toggleStar()"
>
<font-awesome
:icon="isStarred ? 'star' : ['far', 'star']"
:class="isStarred ? 'text-yellow-500' : 'text-slate-500'"
class="text-sm ml-2 mb-1"
/>
</button>
</h2>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<h2 class="text-center text-lg font-normal overflow-hidden text-ellipsis">
{{ name }}
<button
v-if="activeDid === issuer || activeDid === agentDid"
title="Edit"
data-testId="editClaimButton"
@click="onEditClick()"
>
<font-awesome icon="pen" class="text-sm text-blue-500 ml-2" />
</button>
<button
:title="
isStarred
? 'Remove from starred projects'
: 'Add to starred projects'
"
@click="toggleStar()"
>
<font-awesome
:icon="isStarred ? 'star' : ['far', 'star']"
:class="isStarred ? 'text-yellow-500' : 'text-slate-500'"
class="text-sm ml-2"
/>
</button>
</h2>
</div>
<!-- Project Details -->
@@ -147,7 +157,7 @@
</div>
<div class="text-sm text-slate-500">
<div v-if="!expanded">
<div v-if="!expanded" class="overflow-hidden text-ellipsis">
<vue-markdown
:source="truncatedDesc"
class="mb-4 markdown-content"
@@ -159,7 +169,7 @@
>... Read More</a
>
</div>
<div v-else>
<div v-else class="overflow-hidden text-ellipsis">
<vue-markdown :source="description" class="mb-4 markdown-content" />
<a
v-if="description.length >= truncateLength"
@@ -298,7 +308,10 @@
/>{{ offer.amount }}
</span>
</div>
<div v-if="offer.objectDescription" class="text-slate-500">
<div
v-if="offer.objectDescription"
class="text-slate-500 overflow-hidden text-ellipsis"
>
<font-awesome icon="comment" class="fa-fw text-slate-400" />
{{ offer.objectDescription }}
</div>
@@ -440,7 +453,10 @@
<font-awesome icon="calendar" class="fa-fw text-slate-400" />
{{ give.issuedAt?.substring(0, 10) }}
</div>
<div v-if="give.description" class="text-slate-500">
<div
v-if="give.description"
class="text-slate-500 overflow-hidden text-ellipsis"
>
<font-awesome icon="comment" class="fa-fw text-slate-400" />
{{ give.description }}
</div>
@@ -547,7 +563,10 @@
<font-awesome icon="calendar" class="fa-fw text-slate-400" />
{{ give.issuedAt?.substring(0, 10) }}
</div>
<div v-if="give.description" class="text-slate-500">
<div
v-if="give.description"
class="text-slate-500 overflow-hidden text-ellipsis"
>
<font-awesome icon="comment" class="fa-fw text-slate-400" />
{{ give.description }}
</div>

View File

@@ -1,17 +1,28 @@
<template>
<QuickNav selected="Projects" />
<TopMessage />
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light">
Your Project Ideas
</h1>
<TopMessage />
<!-- Main View Heading -->
<div class="flex gap-4 items-center mb-4">
<h1 id="ViewHeading" class="text-2xl font-bold leading-none">
Your Ideas
</h1>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<OnboardingDialog ref="onboardingDialog" />
<!-- Result Tabs -->
<div class="text-center text-slate-500 border-b border-slate-300 mt-8">
<div class="text-center text-slate-500 border-b border-slate-300 mt-4">
<ul class="flex flex-wrap justify-center gap-4 -mb-px">
<li>
<a
@@ -107,8 +118,8 @@
/>
</div>
<div>
<div>
<div class="overflow-hidden">
<div class="text-sm truncate">
To
{{
offer.fulfillsPlanHandleId
@@ -121,7 +132,7 @@
)
}}
</div>
<div>
<div class="truncate">
{{ offer.objectDescription }}
</div>
@@ -243,7 +254,7 @@
</div>
<div class="grow overflow-hidden">
<h2 class="text-base font-semibold">
<h2 class="text-base font-semibold truncate">
{{ project.name || unnamedProject }}
</h2>
<div class="text-sm truncate">
@@ -646,7 +657,7 @@ export default class ProjectsView extends Vue {
get offerTabClasses() {
return {
"inline-block": true,
"py-3": true,
"py-2": true,
"rounded-t-lg": true,
"border-b-2": true,
active: this.showOffers,
@@ -664,7 +675,7 @@ export default class ProjectsView extends Vue {
* @returns String with CSS classes for the floating new project button
*/
get newProjectButtonClasses() {
return "fixed right-6 top-24 text-center text-4xl leading-none bg-green-600 text-white w-14 py-2.5 rounded-full";
return "fixed right-6 top-14 text-center text-4xl leading-none bg-green-600 text-white w-14 py-2.5 rounded-full";
}
/**
@@ -706,7 +717,7 @@ export default class ProjectsView extends Vue {
get projectTabClasses() {
return {
"inline-block": true,
"py-3": true,
"py-2": true,
"rounded-t-lg": true,
"border-b-2": true,
active: this.showProjects,

View File

@@ -1,23 +1,32 @@
<template>
<QuickNav />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
<TopMessage />
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Beginning of BVC Saturday Meeting
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="goBack()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light px-4 mb-4">
Beginning of BVC Saturday Meeting
</h1>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div>
<h2 class="text-2xl m-2">You're Here</h2>

View File

@@ -1,20 +1,32 @@
<template>
<QuickNav />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1 :class="backButtonClasses" @click="$router.back()">
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<TopMessage />
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light px-4 mb-4">
End of BVC Saturday Meeting
</h1>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
End of BVC Saturday Meeting
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div>
<h2 class="text-2xl m-2">Confirm</h2>

View File

@@ -1,23 +1,32 @@
<template>
<QuickNav />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<TopMessage />
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light px-4 mb-4">
Bountiful Voluntaryist Community Actions
</h1>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Bountiful Voluntaryist Community Actions
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div>
<router-link

View File

@@ -2,17 +2,27 @@
<QuickNav selected="Home"></QuickNav>
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Back -->
<font-awesome
icon="chevron-left"
class="fa-fw text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
/>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Offers to Your Projects
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div v-if="newOffersToUserProjects.length === 0">

View File

@@ -2,17 +2,27 @@
<QuickNav selected="Home"></QuickNav>
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 class="text-lg text-center font-light relative px-7">
<!-- Back -->
<font-awesome
icon="chevron-left"
class="fa-fw text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
/>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Offers to You
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div v-if="newOffersToUser.length === 0">

View File

@@ -1,24 +1,27 @@
<template>
<QuickNav />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="goBack"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Area for Nearby Search
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="goBack()"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div class="px-2 py-4">

View File

@@ -28,31 +28,29 @@
-->
<template>
<QuickNav selected="Profile" />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="goBack"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
<!-- Sub View Heading -->
<div class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Seed Backup
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Seed Backup
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="goBack()"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<div class="flex justify-between py-2">
<span />
<span>
<router-link :to="{ name: 'help' }" :class="helpButtonClass">
Help
</router-link>
</span>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div v-if="activeAccount">

View File

@@ -1,26 +1,31 @@
<template>
<QuickNav />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-2 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div>
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<button
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
aria-label="Go back"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw" />
</button>
</div>
<TopMessage />
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Share Your Contact Info
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div class="flex justify-center mt-8">

View File

@@ -39,10 +39,28 @@
<QuickNav />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Image
</h1>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Image
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div v-if="imageBlob">
<div v-if="uploading" class="text-center mb-4">
<font-awesome icon="spinner" class="fa-spin-pulse" />

View File

@@ -3,26 +3,31 @@
id="Content"
class="p-6 pb-24 min-h-screen flex flex-col justify-center"
>
<!-- Breadcrumb -->
<div>
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="goBack"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Generate an Identity
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="goBack()"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- id used by puppeteer test script -->
<div id="start-question" class="mt-8">
<div id="start-question">
<div class="max-w-3xl mx-auto">
<p class="text-center text-xl font-light">
How do you want to create this identifier?

View File

@@ -3,22 +3,27 @@
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Achievements & Statistics
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div>

View File

@@ -3,22 +3,25 @@
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div class="mb-8">
<!-- Back -->
<div class="text-lg text-center font-light relative px-7">
<h1
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</h1>
</div>
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">Test</h1>
<!-- Heading -->
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
Test
</h1>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<div v-if="isNotProdServer">

View File

@@ -1,22 +1,31 @@
<template>
<QuickNav selected="Discover" />
<TopMessage />
<!-- CONTENT -->
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
<!-- Breadcrumb -->
<div id="ViewBreadcrumb" class="mb-8">
<h1 id="ViewHeading" class="text-lg text-center font-light relative px-7">
<!-- Back -->
<button
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
@click="$router.back()"
>
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
</button>
<TopMessage />
<!-- Sub View Heading -->
<div id="SubViewHeading" class="flex gap-4 items-start mb-8">
<h1 class="grow text-xl text-center font-semibold leading-tight">
Individual Profile
</h1>
<div class="text-sm text-center text-slate-500"></div>
<!-- Back -->
<a
class="order-first text-lg text-center leading-none p-1"
@click="$router.go(-1)"
>
<font-awesome icon="chevron-left" class="block text-center w-[1em]" />
</a>
<!-- Help button -->
<router-link
:to="{ name: 'help' }"
class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
>
<font-awesome icon="question" class="block text-center w-[1em]" />
</router-link>
</div>
<!-- Loading Animation -->