Files
crowd-funder-for-time-pwa/src/views/IdentitySwitcherView.vue
Matthew Raymer c9536dd643 refactor: Replace console logging with logger utility
- Add logger import across multiple view components
- Replace console.error/warn/log with logger methods
- Update error handling to use structured logging
- Improve type safety for error objects
- Add crypto-browserify polyfill for browser environment

The changes improve logging by:
1. Using consistent logging interface
2. Adding structured error logging
3. Improving error type safety
4. Centralizing logging configuration
5. Fixing browser compatibility issues

Affected files:
- Multiple view components
- vite.config.ts
- Build configuration
2025-03-11 09:35:55 +00:00

205 lines
6.4 KiB
Vue

<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>
Switch Identity
</h1>
</div>
<!-- Identity List -->
<!-- Current Identity - Display First! -->
<div
v-if="activeDid && !activeDidInIdentities"
class="block bg-slate-100 rounded-md flex items-center px-4 py-3 mb-4"
>
<font-awesome
icon="circle-check"
class="fa-fw text-red-600 text-xl mr-3"
></font-awesome>
<div class="text-sm text-slate-500">
<div class="overflow-hidden truncate">
<b>ID:</b> <code>{{ activeDid }}</code>
</div>
<b
>There is a data corruption error: this identity is selected but it is
not in storage. You cannot send any more claims with this identity
until you import the seed again. This may require reinstalling the
app; if you know how, you can also clear out the TimeSafariAccounts
IndexedDB. Be sure to back up all your Settings & Contacts first.</b
>
</div>
</div>
<!-- Other Identity/ies -->
<ul class="mb-4">
<li v-for="ident in otherIdentities" :key="ident.did">
<div class="flex items-center justify-between mb-2">
<div
class="flex flex-grow items-center bg-slate-100 rounded-md px-4 py-3 mb-2 truncate cursor-pointer"
@click="switchAccount(ident.did)"
>
<font-awesome
v-if="ident.did === activeDid"
icon="circle-check"
class="fa-fw text-blue-600 text-xl mr-3"
/>
<font-awesome
v-else
icon="circle"
class="fa-fw text-slate-400 text-xl mr-3"
/>
<span class="flex-grow overflow-hidden">
<div class="text-sm text-slate-500 truncate">
<b>ID:</b> <code>{{ ident.did }}</code>
</div>
</span>
</div>
<div>
<font-awesome
v-if="ident.did === activeDid"
icon="trash-can"
class="text-slate-400 text-xl ml-2 mr-2 cursor-pointer"
@click="notifyCannotDelete()"
/>
<font-awesome
v-else
icon="trash-can"
class="text-red-600 text-xl ml-2 mr-2 cursor-pointer"
@click="deleteAccount(ident.id)"
/>
</div>
</div>
</li>
</ul>
<!-- Actions -->
<!-- id used by puppeteer test script -->
<router-link
id="start-link"
:to="{ name: 'start' }"
class="block text-center text-lg font-bold 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-2 py-3 rounded-md mb-2"
>
Add Another Identity&hellip;
</router-link>
<a
href="#"
class="block w-full text-center text-md uppercase 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-1.5 py-2 rounded-md mb-8"
@click="switchAccount('0')"
>
No Identity
</a>
</section>
</template>
<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import {
accountsDBPromise,
db,
retrieveSettingsForActiveAccount,
} from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { retrieveAllAccountsMetadata } from "../libs/util";
import { logger } from "../utils/logger";
@Component({ components: { QuickNav } })
export default class IdentitySwitcherView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
public activeDid = "";
public activeDidInIdentities = false;
public apiServer = "";
public apiServerInput = "";
public otherIdentities: Array<{ id: string; did: string }> = [];
async created() {
try {
const settings = await retrieveSettingsForActiveAccount();
this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || "";
this.apiServerInput = settings.apiServer || "";
const accounts = await retrieveAllAccountsMetadata();
for (let n = 0; n < accounts.length; n++) {
const acct = accounts[n];
this.otherIdentities.push({
id: (acct.id ?? 0).toString(),
did: acct.did,
});
if (acct.did && this.activeDid === acct.did) {
this.activeDidInIdentities = true;
}
}
} catch (err) {
this.$notify(
{
group: "alert",
type: "danger",
title: "Error Loading Accounts",
text: "Clear your cache and start over (after data backup).",
},
5000,
);
logger.error("Telling user to clear cache at page create because:", err);
}
}
async switchAccount(did?: string) {
// 0 means none
if (did === "0") {
did = undefined;
}
await db.open();
await db.settings.update(MASTER_SETTINGS_KEY, {
activeDid: did,
});
this.$router.push({ name: "account" });
}
async deleteAccount(id: string) {
this.$notify(
{
group: "modal",
type: "confirm",
title: "Delete Identity?",
text: "Are you sure you want to erase this identity? (There is no undo. You may want to select it and back it up just in case.)",
onYes: async () => {
// one of the few times we use accountsDBPromise directly; try to avoid more usage
const accountsDB = await accountsDBPromise;
await accountsDB.accounts.delete(id);
this.otherIdentities = this.otherIdentities.filter(
(ident) => ident.id !== id,
);
},
},
-1,
);
}
notifyCannotDelete() {
this.$notify(
{
group: "alert",
type: "warning",
title: "Cannot Delete",
text: "You cannot delete the active identity. Set to another identity or 'no identity' first.",
},
3000,
);
}
}
</script>