forked from jsnbuchanan/crowd-funder-for-time-pwa
- Create DatabaseMigration.vue with vue-facing-decorator and Tailwind CSS - Add complete UI for comparing and migrating data between Dexie and SQLite - Implement real-time loading states, error handling, and success feedback - Add navigation link to Account page for easy access - Include export functionality for comparison data - Create comprehensive documentation in doc/database-migration-guide.md - Fix all linting issues and ensure code quality standards - Support both contact and settings migration with overwrite options - Add visual difference analysis with summary cards and detailed breakdowns The component provides a professional interface for the migrationService.ts, enabling users to safely transfer data between database systems during the transition from Dexie to SQLite storage.
320 lines
8.1 KiB
TypeScript
320 lines
8.1 KiB
TypeScript
import {
|
|
createRouter,
|
|
createWebHistory,
|
|
createMemoryHistory,
|
|
RouteLocationNormalized,
|
|
RouteRecordRaw,
|
|
} from "vue-router";
|
|
import { logger } from "../utils/logger";
|
|
|
|
const routes: Array<RouteRecordRaw> = [
|
|
{
|
|
path: "/account",
|
|
name: "account",
|
|
component: () => import("../views/AccountViewView.vue"),
|
|
},
|
|
{
|
|
path: "/claim/:id?",
|
|
name: "claim",
|
|
component: () => import("../views/ClaimView.vue"),
|
|
},
|
|
{
|
|
path: "/claim-add-raw/:id?",
|
|
name: "claim-add-raw",
|
|
component: () => import("../views/ClaimAddRawView.vue"),
|
|
},
|
|
{
|
|
path: "/claim-cert/:id",
|
|
name: "claim-cert",
|
|
component: () => import("../views/ClaimCertificateView.vue"),
|
|
},
|
|
{
|
|
path: "/confirm-contact",
|
|
name: "confirm-contact",
|
|
component: () => import("../views/ConfirmContactView.vue"),
|
|
},
|
|
{
|
|
path: "/confirm-gift/:id?",
|
|
name: "confirm-gift",
|
|
component: () => import("../views/ConfirmGiftView.vue"),
|
|
},
|
|
{
|
|
path: "/contact-amounts",
|
|
name: "contact-amounts",
|
|
component: () => import("../views/ContactAmountsView.vue"),
|
|
},
|
|
{
|
|
path: "/contact-edit/:did",
|
|
name: "contact-edit",
|
|
component: () => import("../views/ContactEditView.vue"),
|
|
},
|
|
{
|
|
path: "/contact-gift",
|
|
name: "contact-gift",
|
|
component: () => import("../views/ContactGiftingView.vue"),
|
|
},
|
|
{
|
|
path: "/contact-import/:jwt?",
|
|
name: "contact-import",
|
|
component: () => import("../views/ContactImportView.vue"),
|
|
},
|
|
{
|
|
path: "/contact-qr",
|
|
name: "contact-qr",
|
|
component: () => import("../views/ContactQRScanShowView.vue"),
|
|
},
|
|
{
|
|
path: "/contact-qr-scan-full",
|
|
name: "contact-qr-scan-full",
|
|
component: () => import("../views/ContactQRScanFullView.vue"),
|
|
},
|
|
{
|
|
path: "/contacts",
|
|
name: "contacts",
|
|
component: () => import("../views/ContactsView.vue"),
|
|
},
|
|
{
|
|
path: "/did/:did?",
|
|
name: "did",
|
|
component: () => import("../views/DIDView.vue"),
|
|
},
|
|
{
|
|
path: "/discover",
|
|
name: "discover",
|
|
component: () => import("../views/DiscoverView.vue"),
|
|
},
|
|
{
|
|
path: "/gifted-details",
|
|
name: "gifted-details",
|
|
component: () => import("../views/GiftedDetailsView.vue"),
|
|
},
|
|
{
|
|
path: "/help",
|
|
name: "help",
|
|
component: () => import("../views/HelpView.vue"),
|
|
},
|
|
{
|
|
path: "/help-notifications",
|
|
name: "help-notifications",
|
|
component: () => import("../views/HelpNotificationsView.vue"),
|
|
},
|
|
{
|
|
path: "/help-notification-types",
|
|
name: "help-notification-types",
|
|
component: () => import("../views/HelpNotificationTypesView.vue"),
|
|
},
|
|
{
|
|
path: "/help-onboarding",
|
|
name: "help-onboarding",
|
|
component: () => import("../views/HelpOnboardingView.vue"),
|
|
},
|
|
{
|
|
path: "/",
|
|
name: "home",
|
|
component: () => import("../views/HomeView.vue"),
|
|
},
|
|
{
|
|
path: "/identity-switcher",
|
|
name: "identity-switcher",
|
|
component: () => import("../views/IdentitySwitcherView.vue"),
|
|
},
|
|
{
|
|
path: "/import-account",
|
|
name: "import-account",
|
|
component: () => import("../views/ImportAccountView.vue"),
|
|
},
|
|
{
|
|
path: "/import-derive",
|
|
name: "import-derive",
|
|
component: () => import("../views/ImportDerivedAccountView.vue"),
|
|
},
|
|
{
|
|
path: "/invite-one",
|
|
name: "invite-one",
|
|
component: () => import("../views/InviteOneView.vue"),
|
|
},
|
|
{
|
|
path: "/invite-one-accept/:jwt?",
|
|
name: "InviteOneAcceptView",
|
|
component: () => import("../views/InviteOneAcceptView.vue"),
|
|
},
|
|
{
|
|
path: "/logs",
|
|
name: "logs",
|
|
component: () => import("../views/LogView.vue"),
|
|
},
|
|
{
|
|
path: "/database-migration",
|
|
name: "database-migration",
|
|
component: () => import("../views/DatabaseMigration.vue"),
|
|
},
|
|
{
|
|
path: "/new-activity",
|
|
name: "new-activity",
|
|
component: () => import("../views/NewActivityView.vue"),
|
|
},
|
|
{
|
|
path: "/new-edit-account",
|
|
name: "new-edit-account",
|
|
component: () => import("../views/NewEditAccountView.vue"),
|
|
},
|
|
{
|
|
path: "/new-edit-project",
|
|
name: "new-edit-project",
|
|
component: () => import("../views/NewEditProjectView.vue"),
|
|
},
|
|
{
|
|
path: "/new-identifier",
|
|
name: "new-identifier",
|
|
component: () => import("../views/NewIdentifierView.vue"),
|
|
},
|
|
{
|
|
path: "/offer-details/:id?",
|
|
name: "offer-details",
|
|
component: () => import("../views/OfferDetailsView.vue"),
|
|
},
|
|
{
|
|
path: "/onboard-meeting-list",
|
|
name: "onboard-meeting-list",
|
|
component: () => import("../views/OnboardMeetingListView.vue"),
|
|
},
|
|
{
|
|
path: "/onboard-meeting-members/:groupId",
|
|
name: "onboard-meeting-members",
|
|
component: () => import("../views/OnboardMeetingMembersView.vue"),
|
|
},
|
|
{
|
|
path: "/onboard-meeting-setup",
|
|
name: "onboard-meeting-setup",
|
|
component: () => import("../views/OnboardMeetingSetupView.vue"),
|
|
},
|
|
{
|
|
path: "/project/:id?",
|
|
name: "project",
|
|
component: () => import("../views/ProjectViewView.vue"),
|
|
},
|
|
{
|
|
path: "/projects",
|
|
name: "projects",
|
|
component: () => import("../views/ProjectsView.vue"),
|
|
},
|
|
{
|
|
path: "/quick-action-bvc",
|
|
name: "quick-action-bvc",
|
|
component: () => import("../views/QuickActionBvcView.vue"),
|
|
},
|
|
{
|
|
path: "/quick-action-bvc-begin",
|
|
name: "quick-action-bvc-begin",
|
|
component: () => import("../views/QuickActionBvcBeginView.vue"),
|
|
},
|
|
{
|
|
path: "/quick-action-bvc-end",
|
|
name: "quick-action-bvc-end",
|
|
component: () => import("../views/QuickActionBvcEndView.vue"),
|
|
},
|
|
{
|
|
path: "/recent-offers-to-user",
|
|
name: "recent-offers-to-user",
|
|
component: () => import("../views/RecentOffersToUserView.vue"),
|
|
},
|
|
{
|
|
path: "/recent-offers-to-user-projects",
|
|
name: "recent-offers-to-user-projects",
|
|
component: () => import("../views/RecentOffersToUserProjectsView.vue"),
|
|
},
|
|
{
|
|
path: "/search-area",
|
|
name: "search-area",
|
|
component: () => import("../views/SearchAreaView.vue"),
|
|
},
|
|
{
|
|
path: "/seed-backup",
|
|
name: "seed-backup",
|
|
component: () => import("../views/SeedBackupView.vue"),
|
|
},
|
|
{
|
|
path: "/share-my-contact-info",
|
|
name: "share-my-contact-info",
|
|
component: () => import("../views/ShareMyContactInfoView.vue"),
|
|
},
|
|
{
|
|
path: "/shared-photo",
|
|
name: "shared-photo",
|
|
component: () => import("../views/SharedPhotoView.vue"),
|
|
},
|
|
|
|
// /share-target is also an endpoint in the service worker
|
|
|
|
{
|
|
path: "/start",
|
|
name: "start",
|
|
component: () => import("../views/StartView.vue"),
|
|
},
|
|
{
|
|
path: "/statistics",
|
|
name: "statistics",
|
|
component: () => import("../views/StatisticsView.vue"),
|
|
},
|
|
{
|
|
path: "/test",
|
|
name: "test",
|
|
component: () => import("../views/TestView.vue"),
|
|
},
|
|
{
|
|
path: "/user-profile/:id?",
|
|
name: "user-profile",
|
|
component: () => import("../views/UserProfileView.vue"),
|
|
},
|
|
{
|
|
path: "/deep-link-error",
|
|
name: "deep-link-error",
|
|
component: () => import("../views/DeepLinkErrorView.vue"),
|
|
meta: {
|
|
title: "Invalid Deep Link",
|
|
requiresAuth: false,
|
|
},
|
|
},
|
|
];
|
|
|
|
const isElectron = window.location.protocol === "file:";
|
|
const initialPath = isElectron
|
|
? window.location.pathname.split("/dist-electron/www/")[1] || "/"
|
|
: window.location.pathname;
|
|
|
|
const history = isElectron
|
|
? createMemoryHistory() // Memory history for Electron
|
|
: createWebHistory("/"); // Add base path for web apps
|
|
|
|
/** @type {*} */
|
|
const router = createRouter({
|
|
history,
|
|
routes,
|
|
});
|
|
|
|
// Replace initial URL to start at `/` if necessary
|
|
router.replace(initialPath || "/");
|
|
|
|
const errorHandler = (
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
error: any,
|
|
to: RouteLocationNormalized,
|
|
from: RouteLocationNormalized,
|
|
) => {
|
|
// Handle the error here
|
|
logger.error("Caught in top level error handler:", error, to, from);
|
|
alert("Something is very wrong. Try reloading or restarting the app.");
|
|
|
|
// You can also perform additional actions, such as displaying an error message or redirecting the user to a specific page
|
|
};
|
|
|
|
router.onError(errorHandler); // Assign the error handler to the router instance
|
|
|
|
// router.beforeEach((to, from, next) => {
|
|
// console.log("Navigating to view:", to.name);
|
|
// console.log("From view:", from.name);
|
|
// next();
|
|
// });
|
|
|
|
export default router;
|