forked from trent_larson/crowd-funder-for-time-pwa
Complete DIDView.vue triple migration and refactor template handlers
- Fix DIDView.vue notification migration: add missing NOTIFY_SERVER_ACCESS_ERROR and NOTIFY_NO_IDENTITY_ERROR imports - Refactor 5 inline template handlers to proper class methods (goBack, toggleDidDetails, showLargeProfileImage, showLargeIdenticon, hideLargeImage) - Update notification validation script to exclude createNotifyHelpers initialization patterns - DIDView.vue now fully compliant: database migration + SQL abstraction + notification migration complete Improves code organization, testability, and follows Vue.js best practices for template/class separation. All linting passes without errors.
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
<!-- Back -->
|
||||
<button
|
||||
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
||||
@click="$router.go(-1)"
|
||||
@click="goBack"
|
||||
>
|
||||
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
|
||||
</button>
|
||||
@@ -32,10 +32,7 @@
|
||||
<font-awesome icon="pen" class="text-sm text-blue-500 ml-2 mb-1" />
|
||||
</router-link>
|
||||
</h2>
|
||||
<button
|
||||
class="ml-2 mr-2 mt-4"
|
||||
@click="showDidDetails = !showDidDetails"
|
||||
>
|
||||
<button class="ml-2 mr-2 mt-4" @click="toggleDidDetails">
|
||||
Details
|
||||
<font-awesome
|
||||
v-if="showDidDetails"
|
||||
@@ -60,7 +57,7 @@
|
||||
:icon-size="96"
|
||||
:profile-image-url="contactFromDid?.profileImageUrl"
|
||||
class="inline-block align-text-bottom border border-slate-300 rounded"
|
||||
@click="showLargeIdenticonUrl = contactFromDid?.profileImageUrl"
|
||||
@click="showLargeProfileImage"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
@@ -160,7 +157,7 @@
|
||||
:entity-id="viewingDid"
|
||||
:icon-size="64"
|
||||
class="inline-block align-middle border border-slate-300 rounded-md mr-1"
|
||||
@click="showLargeIdenticonId = viewingDid"
|
||||
@click="showLargeIdenticon"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -177,10 +174,7 @@
|
||||
:icon-size="512"
|
||||
:profile-image-url="showLargeIdenticonUrl"
|
||||
class="flex w-11/12 max-w-sm mx-auto mb-3 overflow-hidden bg-white rounded-lg shadow-lg"
|
||||
@click="
|
||||
showLargeIdenticonId = undefined;
|
||||
showLargeIdenticonUrl = undefined;
|
||||
"
|
||||
@click="hideLargeImage"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -266,7 +260,7 @@ import TopMessage from "../components/TopMessage.vue";
|
||||
import { NotificationIface } from "../constants/app";
|
||||
import { Contact } from "../db/tables/contacts";
|
||||
import { BoundingBox } from "../db/tables/settings";
|
||||
import * as databaseUtil from "../db/databaseUtil";
|
||||
|
||||
import {
|
||||
GenericCredWrapper,
|
||||
GenericVerifiableCredential,
|
||||
@@ -284,6 +278,16 @@ import * as libsUtil from "../libs/util";
|
||||
import EntityIcon from "../components/EntityIcon.vue";
|
||||
import { logger } from "../utils/logger";
|
||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
||||
import {
|
||||
NOTIFY_DEFAULT_TO_ACTIVE_DID,
|
||||
NOTIFY_CONTACT_DELETED,
|
||||
NOTIFY_CONTACT_DELETE_FAILED,
|
||||
NOTIFY_REGISTRATION_SUCCESS,
|
||||
NOTIFY_REGISTRATION_ERROR,
|
||||
NOTIFY_SERVER_ACCESS_ERROR,
|
||||
NOTIFY_NO_IDENTITY_ERROR,
|
||||
} from "@/constants/notifications";
|
||||
|
||||
/**
|
||||
* DIDView Component
|
||||
@@ -310,6 +314,8 @@ export default class DIDView extends Vue {
|
||||
$route!: RouteLocationNormalizedLoaded;
|
||||
$router!: Router;
|
||||
|
||||
notify!: ReturnType<typeof createNotifyHelpers>;
|
||||
|
||||
libsUtil = libsUtil;
|
||||
yaml = yaml;
|
||||
|
||||
@@ -331,6 +337,13 @@ export default class DIDView extends Vue {
|
||||
didInfoForContact = didInfoForContact;
|
||||
displayAmount = displayAmount;
|
||||
|
||||
/**
|
||||
* Initializes notification helpers
|
||||
*/
|
||||
created() {
|
||||
this.notify = createNotifyHelpers(this.$notify);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the view with DID information
|
||||
*
|
||||
@@ -355,7 +368,7 @@ export default class DIDView extends Vue {
|
||||
* Initializes component settings from active account
|
||||
*/
|
||||
private async initializeSettings() {
|
||||
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
|
||||
const settings = await this.$accountSettings();
|
||||
this.activeDid = settings.activeDid || "";
|
||||
this.apiServer = settings.apiServer || "";
|
||||
}
|
||||
@@ -384,14 +397,10 @@ export default class DIDView extends Vue {
|
||||
* Notifies user that we're showing their DID info by default
|
||||
*/
|
||||
private notifyDefaultToActiveDID() {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "toast",
|
||||
title: "Your Info",
|
||||
text: "No user was specified so showing your info.",
|
||||
},
|
||||
3000,
|
||||
this.notify.toast(
|
||||
NOTIFY_DEFAULT_TO_ACTIVE_DID.title,
|
||||
NOTIFY_DEFAULT_TO_ACTIVE_DID.message,
|
||||
TIMEOUTS.SHORT,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -402,17 +411,10 @@ export default class DIDView extends Vue {
|
||||
private async loadContactInformation() {
|
||||
if (!this.viewingDid) return;
|
||||
|
||||
const dbContacts = await this.$dbQuery(
|
||||
"SELECT * FROM contacts WHERE did = ?",
|
||||
[this.viewingDid],
|
||||
);
|
||||
const contacts = databaseUtil.mapQueryResultToValues(
|
||||
dbContacts,
|
||||
) as unknown as Contact[];
|
||||
const contact = await this.$getContact(this.viewingDid);
|
||||
|
||||
// Safely check if contact exists before assigning
|
||||
if (contacts && contacts.length > 0) {
|
||||
this.contactFromDid = contacts[0];
|
||||
if (contact) {
|
||||
this.contactFromDid = contact;
|
||||
this.contactYaml = yaml.dump(this.contactFromDid);
|
||||
} else {
|
||||
this.contactFromDid = undefined;
|
||||
@@ -442,6 +444,33 @@ export default class DIDView extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigation helper methods
|
||||
*/
|
||||
goBack() {
|
||||
this.$router.go(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* UI state helper methods
|
||||
*/
|
||||
toggleDidDetails() {
|
||||
this.showDidDetails = !this.showDidDetails;
|
||||
}
|
||||
|
||||
showLargeProfileImage() {
|
||||
this.showLargeIdenticonUrl = this.contactFromDid?.profileImageUrl;
|
||||
}
|
||||
|
||||
showLargeIdenticon() {
|
||||
this.showLargeIdenticonId = this.viewingDid;
|
||||
}
|
||||
|
||||
hideLargeImage() {
|
||||
this.showLargeIdenticonId = undefined;
|
||||
this.showLargeIdenticonUrl = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts user to confirm contact deletion
|
||||
* Shows additional warning if contact has visibility permissions
|
||||
@@ -457,18 +486,9 @@ export default class DIDView extends Vue {
|
||||
message +=
|
||||
" Note that they can see your activity, so if you want to hide your activity from them then you should do that first.";
|
||||
}
|
||||
this.$notify(
|
||||
{
|
||||
group: "modal",
|
||||
type: "confirm",
|
||||
title: "Delete",
|
||||
text: message,
|
||||
onYes: async () => {
|
||||
await this.deleteContact(contact);
|
||||
},
|
||||
},
|
||||
-1,
|
||||
);
|
||||
this.notify.confirm(message, async () => {
|
||||
await this.deleteContact(contact);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -477,17 +497,13 @@ export default class DIDView extends Vue {
|
||||
* @param contact - Contact object to be deleted
|
||||
*/
|
||||
async deleteContact(contact: Contact) {
|
||||
await this.$dbExec("DELETE FROM contacts WHERE did = ?", [contact.did]);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "success",
|
||||
title: "Deleted",
|
||||
text: "Contact has been removed.",
|
||||
},
|
||||
3000,
|
||||
);
|
||||
this.$router.push({ name: "contacts" });
|
||||
const success = await this.$deleteContact(contact.did);
|
||||
if (success) {
|
||||
this.notify.success(NOTIFY_CONTACT_DELETED.message, TIMEOUTS.SHORT);
|
||||
this.$router.push({ name: "contacts" });
|
||||
} else {
|
||||
this.notify.error(NOTIFY_CONTACT_DELETE_FAILED.message, TIMEOUTS.LONG);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -497,24 +513,16 @@ export default class DIDView extends Vue {
|
||||
* @param contact - Contact to be registered
|
||||
*/
|
||||
async confirmRegister(contact: Contact) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "modal",
|
||||
type: "confirm",
|
||||
title: "Register",
|
||||
text:
|
||||
"Are you sure you want to register " +
|
||||
libsUtil.nameForContact(this.contactFromDid, false) +
|
||||
(contact.registered
|
||||
? " -- especially since they are already marked as registered"
|
||||
: "") +
|
||||
"?",
|
||||
onYes: async () => {
|
||||
await this.register(contact);
|
||||
},
|
||||
},
|
||||
-1,
|
||||
);
|
||||
const message =
|
||||
"Are you sure you want to register " +
|
||||
libsUtil.nameForContact(this.contactFromDid, false) +
|
||||
(contact.registered
|
||||
? " -- especially since they are already marked as registered"
|
||||
: "") +
|
||||
"?";
|
||||
this.notify.confirm(message, async () => {
|
||||
await this.register(contact);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -524,7 +532,7 @@ export default class DIDView extends Vue {
|
||||
* @param contact - Contact to register
|
||||
*/
|
||||
async register(contact: Contact) {
|
||||
this.$notify({ group: "alert", type: "toast", title: "Sent..." }, 1000);
|
||||
this.notify.toast("Processing", "Sent...", TIMEOUTS.SHORT);
|
||||
|
||||
try {
|
||||
const regResult = await register(
|
||||
@@ -535,32 +543,17 @@ export default class DIDView extends Vue {
|
||||
);
|
||||
if (regResult.success) {
|
||||
contact.registered = true;
|
||||
await this.$dbExec("UPDATE contacts SET registered = ? WHERE did = ?", [
|
||||
true,
|
||||
contact.did,
|
||||
]);
|
||||
await this.$updateContact(contact.did, { registered: true });
|
||||
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "success",
|
||||
title: "Registration Success",
|
||||
text:
|
||||
(contact.name || "That unnamed person") + " has been registered.",
|
||||
},
|
||||
5000,
|
||||
const name = contact.name || "That unnamed person";
|
||||
this.notify.success(
|
||||
`${name} ${NOTIFY_REGISTRATION_SUCCESS.message}`,
|
||||
TIMEOUTS.LONG,
|
||||
);
|
||||
} else {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Registration Error",
|
||||
text:
|
||||
(regResult.error as string) ||
|
||||
"Something went wrong during registration.",
|
||||
},
|
||||
5000,
|
||||
this.notify.error(
|
||||
(regResult.error as string) || NOTIFY_REGISTRATION_ERROR.message,
|
||||
TIMEOUTS.LONG,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -582,15 +575,7 @@ export default class DIDView extends Vue {
|
||||
userMessage = error as string;
|
||||
}
|
||||
// Now set that error for the user to see.
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Registration Error",
|
||||
text: userMessage,
|
||||
},
|
||||
5000,
|
||||
);
|
||||
this.notify.error(userMessage, TIMEOUTS.LONG);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,15 +609,7 @@ export default class DIDView extends Vue {
|
||||
if (response.status !== 200) {
|
||||
const details = await response.text();
|
||||
logger.error("Problem with full search:", details);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: `There was a problem accessing the server. Try again later.`,
|
||||
},
|
||||
5000,
|
||||
);
|
||||
this.notify.error(NOTIFY_SERVER_ACCESS_ERROR.message, TIMEOUTS.LONG);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -642,14 +619,9 @@ export default class DIDView extends Vue {
|
||||
} catch (e: unknown) {
|
||||
logger.error("Error with feed load:", e);
|
||||
const error = e as { userMessage?: string };
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error",
|
||||
text: error.userMessage || "There was a problem retrieving claims.",
|
||||
},
|
||||
3000,
|
||||
this.notify.error(
|
||||
error.userMessage || "There was a problem retrieving claims.",
|
||||
TIMEOUTS.SHORT,
|
||||
);
|
||||
} finally {
|
||||
this.isLoading = false;
|
||||
@@ -728,21 +700,12 @@ export default class DIDView extends Vue {
|
||||
const visibilityPrompt = visibility
|
||||
? "Are you sure you want to make your activity visible to them?"
|
||||
: "Are you sure you want to hide all your activity from them?";
|
||||
this.$notify(
|
||||
{
|
||||
group: "modal",
|
||||
type: "confirm",
|
||||
title: "Set Visibility",
|
||||
text: visibilityPrompt,
|
||||
onYes: async () => {
|
||||
const success = await this.setVisibility(contact, visibility, true);
|
||||
if (success) {
|
||||
contact.seesMe = visibility; // didn't work inside setVisibility
|
||||
}
|
||||
},
|
||||
},
|
||||
-1,
|
||||
);
|
||||
this.notify.confirm(visibilityPrompt, async () => {
|
||||
const success = await this.setVisibility(contact, visibility, true);
|
||||
if (success) {
|
||||
contact.seesMe = visibility; // didn't work inside setVisibility
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -758,27 +721,16 @@ export default class DIDView extends Vue {
|
||||
visibility: boolean,
|
||||
showSuccessAlert: boolean,
|
||||
) {
|
||||
// TODO: Implement proper visibility setting using mixin methods
|
||||
// For now, just update local database
|
||||
await this.$dbExec("UPDATE contacts SET seesMe = ? WHERE did = ?", [
|
||||
visibility,
|
||||
contact.did,
|
||||
]);
|
||||
// Update contact visibility using mixin method
|
||||
await this.$updateContact(contact.did, { seesMe: visibility });
|
||||
|
||||
if (showSuccessAlert) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "success",
|
||||
title: "Visibility Set",
|
||||
text:
|
||||
(contact.name || "That user") +
|
||||
" can " +
|
||||
(visibility ? "" : "not ") +
|
||||
"see your activity.",
|
||||
},
|
||||
3000,
|
||||
);
|
||||
const message =
|
||||
(contact.name || "That user") +
|
||||
" can " +
|
||||
(visibility ? "" : "not ") +
|
||||
"see your activity.";
|
||||
this.notify.success(message, TIMEOUTS.SHORT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -796,15 +748,7 @@ export default class DIDView extends Vue {
|
||||
encodeURIComponent(contact.did);
|
||||
const headers = await getHeaders(this.activeDid);
|
||||
if (!headers["Authorization"]) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "No Identity",
|
||||
text: "There is no identity to use to check visibility.",
|
||||
},
|
||||
3000,
|
||||
);
|
||||
this.notify.error(NOTIFY_NO_IDENTITY_ERROR.message, TIMEOUTS.SHORT);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -814,48 +758,22 @@ export default class DIDView extends Vue {
|
||||
const visibility = resp.data;
|
||||
contact.seesMe = visibility;
|
||||
//console.log("Visi check:", visibility, contact.seesMe, contact.did);
|
||||
await this.$dbExec("UPDATE contacts SET seesMe = ? WHERE did = ?", [
|
||||
visibility,
|
||||
contact.did,
|
||||
]);
|
||||
await this.$updateContact(contact.did, { seesMe: visibility });
|
||||
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "info",
|
||||
title: "Visibility Refreshed",
|
||||
text:
|
||||
libsUtil.nameForContact(contact, true) +
|
||||
" can" +
|
||||
(visibility ? "" : " not") +
|
||||
" see your activity.",
|
||||
},
|
||||
3000,
|
||||
);
|
||||
const message =
|
||||
libsUtil.nameForContact(contact, true) +
|
||||
" can" +
|
||||
(visibility ? "" : " not") +
|
||||
" see your activity.";
|
||||
this.notify.info(message, TIMEOUTS.SHORT);
|
||||
} else {
|
||||
logger.error("Got bad server response checking visibility:", resp);
|
||||
const message = resp.data.error?.message || "Got bad server response.";
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error Checking Visibility",
|
||||
text: message,
|
||||
},
|
||||
5000,
|
||||
);
|
||||
this.notify.error(message, TIMEOUTS.LONG);
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error("Caught error from request to check visibility:", err);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error Checking Visibility",
|
||||
text: "Check connectivity and try again.",
|
||||
},
|
||||
3000,
|
||||
);
|
||||
this.notify.error("Check connectivity and try again.", TIMEOUTS.SHORT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -869,21 +787,12 @@ export default class DIDView extends Vue {
|
||||
const contentVisibilityPrompt = view
|
||||
? "Are you sure you want to see their content?"
|
||||
: "Are you sure you want to hide their content from you?";
|
||||
this.$notify(
|
||||
{
|
||||
group: "modal",
|
||||
type: "confirm",
|
||||
title: "Set Content Visibility",
|
||||
text: contentVisibilityPrompt,
|
||||
onYes: async () => {
|
||||
const success = await this.setViewContent(contact, view);
|
||||
if (success) {
|
||||
contact.iViewContent = view; // see visibility note about not working inside setVisibility
|
||||
}
|
||||
},
|
||||
},
|
||||
-1,
|
||||
);
|
||||
this.notify.confirm(contentVisibilityPrompt, async () => {
|
||||
const success = await this.setViewContent(contact, view);
|
||||
if (success) {
|
||||
contact.iViewContent = view; // see visibility note about not working inside setVisibility
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -894,22 +803,12 @@ export default class DIDView extends Vue {
|
||||
* @returns Boolean indicating success
|
||||
*/
|
||||
async setViewContent(contact: Contact, visibility: boolean) {
|
||||
await this.$dbExec("UPDATE contacts SET iViewContent = ? WHERE did = ?", [
|
||||
visibility,
|
||||
contact.did,
|
||||
]);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "success",
|
||||
title: "Visibility Set",
|
||||
text:
|
||||
"You will" +
|
||||
(visibility ? "" : " not") +
|
||||
` see ${contact.name}'s activity.`,
|
||||
},
|
||||
3000,
|
||||
);
|
||||
await this.$updateContact(contact.did, { iViewContent: visibility });
|
||||
const message =
|
||||
"You will" +
|
||||
(visibility ? "" : " not") +
|
||||
` see ${contact.name}'s activity.`;
|
||||
this.notify.success(message, TIMEOUTS.SHORT);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user