forked from trent_larson/crowd-funder-for-time-pwa
refactor: standardize notify helper usage and document migration workflow
- Refactor notify usage in GiftedDialog.vue, AccountViewView.vue, ClaimView.vue, and DataExportSection.vue: • Use notify as a property initialized in created() with createNotifyHelpers(this.$notify) • Remove getter-based notify patterns for consistency and lifecycle safety • Fix linter/type errors related to notify property initialization - Add mandatory per-file migration workflow to doc/migration-progress-tracker.md: • For each file: (1) migrate to PlatformServiceMixin, (2) immediately standardize notify usage and fix linter/type errors • Clarifies this two-step process is required for every file, not as a global sweep All migrated files are now consistent, maintainable, and ready for further migration work.
This commit is contained in:
@@ -1,5 +1,17 @@
|
|||||||
# Migration Progress Tracker: PlatformServiceMixin & 52-File Migration
|
# Migration Progress Tracker: PlatformServiceMixin & 52-File Migration
|
||||||
|
|
||||||
|
## Per-File Migration Workflow (MANDATORY)
|
||||||
|
|
||||||
|
For each file migrated:
|
||||||
|
1. **First**, migrate to PlatformServiceMixin (replace all databaseUtil usage, etc.).
|
||||||
|
2. **Immediately after**, standardize notify helper usage (property + created() pattern) and fix any related linter/type errors.
|
||||||
|
|
||||||
|
**This two-step process is to be followed for every file, not as a global sweep at the end.**
|
||||||
|
|
||||||
|
Anyone picking up this migration should follow this workflow for consistency and completeness.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
This document tracks the progress of the 2-day sprint to complete PlatformServiceMixin implementation and migrate all 52 files from databaseUtil imports to PlatformServiceMixin usage.
|
This document tracks the progress of the 2-day sprint to complete PlatformServiceMixin implementation and migrate all 52 files from databaseUtil imports to PlatformServiceMixin usage.
|
||||||
@@ -176,7 +188,7 @@ export default class ComponentName extends Vue {
|
|||||||
- [ ] UserProfileView.vue
|
- [ ] UserProfileView.vue
|
||||||
|
|
||||||
### **Components (15 files) - Priority 2**
|
### **Components (15 files) - Priority 2**
|
||||||
**Progress**: 2/15 (13%)
|
**Progress**: 3/15 (20%)
|
||||||
|
|
||||||
- [x] UserNameDialog.vue ✅ **MIGRATED**
|
- [x] UserNameDialog.vue ✅ **MIGRATED**
|
||||||
- [ ] ActivityListItem.vue
|
- [ ] ActivityListItem.vue
|
||||||
@@ -190,7 +202,7 @@ export default class ComponentName extends Vue {
|
|||||||
- [ ] EntitySummaryButton.vue
|
- [ ] EntitySummaryButton.vue
|
||||||
- [x] FeedFilters.vue ✅ **MIGRATED**
|
- [x] FeedFilters.vue ✅ **MIGRATED**
|
||||||
- [ ] GiftDetailsStep.vue
|
- [ ] GiftDetailsStep.vue
|
||||||
- [ ] GiftedDialog.vue
|
- [x] GiftedDialog.vue ✅ **MIGRATED**
|
||||||
- [ ] GiftedPrompts.vue
|
- [ ] GiftedPrompts.vue
|
||||||
- [ ] HiddenDidDialog.vue
|
- [ ] HiddenDidDialog.vue
|
||||||
- [ ] IconRenderer.vue
|
- [ ] IconRenderer.vue
|
||||||
@@ -273,8 +285,8 @@ find src -name "*.vue" -o -name "*.ts" | xargs grep -l "import.*databaseUtil" |
|
|||||||
|
|
||||||
### **Overall Progress**
|
### **Overall Progress**
|
||||||
- **Total files to migrate**: 52
|
- **Total files to migrate**: 52
|
||||||
- **Files migrated**: 2
|
- **Files migrated**: 3
|
||||||
- **Progress**: 4%
|
- **Progress**: 6%
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ import { logger } from '../utils/logger';
|
|||||||
logger.debug('[Migration] Starting migration process...');
|
logger.debug('[Migration] Starting migration process...');
|
||||||
const result = await migrateAll();
|
const result = await migrateAll();
|
||||||
logger.debug('[Migration] Migration completed:', result);
|
logger.debug('[Migration] Migration completed:', result);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Benefits of PlatformServiceMixin Approach
|
## Benefits of PlatformServiceMixin Approach
|
||||||
|
|
||||||
|
|||||||
@@ -98,9 +98,7 @@ export default class DataExportSection extends Vue {
|
|||||||
* Notification helper for consistent notification patterns
|
* Notification helper for consistent notification patterns
|
||||||
* Created as a getter to ensure $notify is available when called
|
* Created as a getter to ensure $notify is available when called
|
||||||
*/
|
*/
|
||||||
get notify() {
|
notify!: ReturnType<typeof createNotifyHelpers>;
|
||||||
return createNotifyHelpers(this.$notify);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NOTE: PlatformServiceMixin provides both concise helpers (e.g. $contacts, capabilities)
|
* NOTE: PlatformServiceMixin provides both concise helpers (e.g. $contacts, capabilities)
|
||||||
@@ -156,5 +154,9 @@ export default class DataExportSection extends Vue {
|
|||||||
this.isExporting = false;
|
this.isExporting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.notify = createNotifyHelpers(this.$notify);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
:to-project-id="toProjectId"
|
:to-project-id="toProjectId"
|
||||||
:giver="giver"
|
:giver="giver"
|
||||||
:receiver="receiver"
|
:receiver="receiver"
|
||||||
:notify="$notify"
|
:notify="notify"
|
||||||
@entity-selected="handleEntitySelected"
|
@entity-selected="handleEntitySelected"
|
||||||
@cancel="cancel"
|
@cancel="cancel"
|
||||||
/>
|
/>
|
||||||
@@ -62,17 +62,16 @@ import {
|
|||||||
getHeaders,
|
getHeaders,
|
||||||
} from "../libs/endorserServer";
|
} from "../libs/endorserServer";
|
||||||
import * as libsUtil from "../libs/util";
|
import * as libsUtil from "../libs/util";
|
||||||
// Removed unused imports: db, retrieveSettingsForActiveAccount
|
|
||||||
import { Contact } from "../db/tables/contacts";
|
import { Contact } from "../db/tables/contacts";
|
||||||
import * as databaseUtil from "../db/databaseUtil";
|
|
||||||
import { retrieveAccountDids } from "../libs/util";
|
import { retrieveAccountDids } from "../libs/util";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
|
|
||||||
import EntityIcon from "../components/EntityIcon.vue";
|
import EntityIcon from "../components/EntityIcon.vue";
|
||||||
import ProjectIcon from "../components/ProjectIcon.vue";
|
import ProjectIcon from "../components/ProjectIcon.vue";
|
||||||
import EntitySelectionStep from "../components/EntitySelectionStep.vue";
|
import EntitySelectionStep from "../components/EntitySelectionStep.vue";
|
||||||
import GiftDetailsStep from "../components/GiftDetailsStep.vue";
|
import GiftDetailsStep from "../components/GiftDetailsStep.vue";
|
||||||
import { PlanData } from "../interfaces/records";
|
import { PlanData } from "../interfaces/records";
|
||||||
|
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||||
|
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
@@ -81,9 +80,10 @@ import { PlanData } from "../interfaces/records";
|
|||||||
EntitySelectionStep,
|
EntitySelectionStep,
|
||||||
GiftDetailsStep,
|
GiftDetailsStep,
|
||||||
},
|
},
|
||||||
|
mixins: [PlatformServiceMixin],
|
||||||
})
|
})
|
||||||
export default class GiftedDialog extends Vue {
|
export default class GiftedDialog extends Vue {
|
||||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
notify!: ReturnType<typeof createNotifyHelpers>;
|
||||||
|
|
||||||
@Prop() fromProjectId = "";
|
@Prop() fromProjectId = "";
|
||||||
@Prop() toProjectId = "";
|
@Prop() toProjectId = "";
|
||||||
@@ -230,17 +230,11 @@ export default class GiftedDialog extends Vue {
|
|||||||
this.updateEntityTypes();
|
this.updateEntityTypes();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
|
const settings = await this.$settings();
|
||||||
this.apiServer = settings.apiServer || "";
|
this.apiServer = settings.apiServer || "";
|
||||||
this.activeDid = settings.activeDid || "";
|
this.activeDid = settings.activeDid || "";
|
||||||
|
|
||||||
const platformService = PlatformServiceFactory.getInstance();
|
this.allContacts = await this.$contacts();
|
||||||
const result = await platformService.dbQuery(`SELECT * FROM contacts`);
|
|
||||||
if (result) {
|
|
||||||
this.allContacts = databaseUtil.mapQueryResultToValues(
|
|
||||||
result,
|
|
||||||
) as unknown as Contact[];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.allMyDids = await retrieveAccountDids();
|
this.allMyDids = await retrieveAccountDids();
|
||||||
|
|
||||||
@@ -264,17 +258,11 @@ export default class GiftedDialog extends Vue {
|
|||||||
}
|
}
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
logger.error("Error retrieving settings from database:", err);
|
logger.error("Error retrieving settings from database:", err);
|
||||||
this.$notify(
|
this.notify.error(
|
||||||
{
|
err instanceof Error
|
||||||
group: "alert",
|
? err.message
|
||||||
type: "danger",
|
: "There was an error retrieving your settings.",
|
||||||
title: "Error",
|
TIMEOUTS.MODAL,
|
||||||
text:
|
|
||||||
err instanceof Error
|
|
||||||
? err.message
|
|
||||||
: "There was an error retrieving your settings.",
|
|
||||||
},
|
|
||||||
-1,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,68 +307,37 @@ export default class GiftedDialog extends Vue {
|
|||||||
|
|
||||||
async confirm() {
|
async confirm() {
|
||||||
if (!this.activeDid) {
|
if (!this.activeDid) {
|
||||||
this.$notify(
|
this.notify.error(
|
||||||
{
|
"You must select an identifier before you can record a give.",
|
||||||
group: "alert",
|
TIMEOUTS.STANDARD,
|
||||||
type: "danger",
|
|
||||||
title: "Error",
|
|
||||||
text: "You must select an identifier before you can record a give.",
|
|
||||||
},
|
|
||||||
3000,
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parseFloat(this.amountInput) < 0) {
|
if (parseFloat(this.amountInput) < 0) {
|
||||||
this.$notify(
|
this.notify.error("You may not send a negative number.", TIMEOUTS.SHORT);
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
text: "You may not send a negative number.",
|
|
||||||
title: "",
|
|
||||||
},
|
|
||||||
2000,
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.description && !parseFloat(this.amountInput)) {
|
if (!this.description && !parseFloat(this.amountInput)) {
|
||||||
this.$notify(
|
this.notify.error(
|
||||||
{
|
`You must enter a description or some number of ${
|
||||||
group: "alert",
|
this.libsUtil.UNIT_LONG[this.unitCode]
|
||||||
type: "danger",
|
}.`,
|
||||||
title: "Error",
|
TIMEOUTS.SHORT,
|
||||||
text: `You must enter a description or some number of ${
|
|
||||||
this.libsUtil.UNIT_LONG[this.unitCode]
|
|
||||||
}.`,
|
|
||||||
},
|
|
||||||
2000,
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for person conflict
|
// Check for person conflict
|
||||||
if (this.hasPersonConflict) {
|
if (this.hasPersonConflict) {
|
||||||
this.$notify(
|
this.notify.error(
|
||||||
{
|
"You cannot select the same person as both giver and recipient.",
|
||||||
group: "alert",
|
TIMEOUTS.STANDARD,
|
||||||
type: "danger",
|
|
||||||
title: "Error",
|
|
||||||
text: "You cannot select the same person as both giver and recipient.",
|
|
||||||
},
|
|
||||||
3000,
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.close();
|
this.close();
|
||||||
this.$notify(
|
this.notify.toast("Recording the give...", undefined, TIMEOUTS.BRIEF);
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "toast",
|
|
||||||
text: "Recording the give...",
|
|
||||||
title: "",
|
|
||||||
},
|
|
||||||
1000,
|
|
||||||
);
|
|
||||||
// this is asynchronous, but we don't need to wait for it to complete
|
// this is asynchronous, but we don't need to wait for it to complete
|
||||||
await this.recordGive(
|
await this.recordGive(
|
||||||
(this.giver?.did as string) || null,
|
(this.giver?.did as string) || null,
|
||||||
@@ -460,25 +417,12 @@ export default class GiftedDialog extends Vue {
|
|||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
const errorMessage = this.getGiveCreationErrorMessage(result);
|
const errorMessage = this.getGiveCreationErrorMessage(result);
|
||||||
logger.error("Error with give creation result:", result);
|
logger.error("Error with give creation result:", result);
|
||||||
this.$notify(
|
this.notify.error(
|
||||||
{
|
errorMessage || "There was an error creating the give.",
|
||||||
group: "alert",
|
TIMEOUTS.MODAL,
|
||||||
type: "danger",
|
|
||||||
title: "Error",
|
|
||||||
text: errorMessage || "There was an error creating the give.",
|
|
||||||
},
|
|
||||||
-1,
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.$notify(
|
this.notify.success("That gift was recorded.", TIMEOUTS.VERY_LONG);
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "success",
|
|
||||||
title: "Success",
|
|
||||||
text: `That gift was recorded.`,
|
|
||||||
},
|
|
||||||
7000,
|
|
||||||
);
|
|
||||||
if (this.callbackOnSuccess) {
|
if (this.callbackOnSuccess) {
|
||||||
this.callbackOnSuccess(amount);
|
this.callbackOnSuccess(amount);
|
||||||
}
|
}
|
||||||
@@ -490,15 +434,7 @@ export default class GiftedDialog extends Vue {
|
|||||||
error.userMessage ||
|
error.userMessage ||
|
||||||
serverMessageForUser(error) ||
|
serverMessageForUser(error) ||
|
||||||
"There was an error recording the give.";
|
"There was an error recording the give.";
|
||||||
this.$notify(
|
this.notify.error(errorMessage, TIMEOUTS.MODAL);
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Error",
|
|
||||||
text: errorMessage,
|
|
||||||
},
|
|
||||||
-1,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,15 +454,7 @@ export default class GiftedDialog extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
explainData() {
|
explainData() {
|
||||||
this.$notify(
|
this.notify.info(libsUtil.PRIVACY_MESSAGE, TIMEOUTS.MODAL);
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "success",
|
|
||||||
title: "Data Sharing",
|
|
||||||
text: libsUtil.PRIVACY_MESSAGE,
|
|
||||||
},
|
|
||||||
-1,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
selectGiver(contact?: Contact) {
|
selectGiver(contact?: Contact) {
|
||||||
@@ -566,15 +494,7 @@ export default class GiftedDialog extends Vue {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("Error loading projects:", error);
|
logger.error("Error loading projects:", error);
|
||||||
this.$notify(
|
this.notify.error("Failed to load projects", TIMEOUTS.STANDARD);
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Error",
|
|
||||||
text: "Failed to load projects",
|
|
||||||
},
|
|
||||||
3000,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -696,6 +616,10 @@ export default class GiftedDialog extends Vue {
|
|||||||
amountInput: this.amountInput,
|
amountInput: this.amountInput,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.notify = createNotifyHelpers(this.$notify);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -185,3 +185,4 @@ export default class IdentitySection extends Vue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -276,3 +276,4 @@ export const NotificationMixin = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -817,6 +817,10 @@ import {
|
|||||||
|
|
||||||
const inputImportFileNameRef = ref<Blob>();
|
const inputImportFileNameRef = ref<Blob>();
|
||||||
|
|
||||||
|
interface UserNameDialogRef {
|
||||||
|
open: (cb: (name?: string) => void) => void;
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
EntityIcon,
|
EntityIcon,
|
||||||
@@ -908,6 +912,10 @@ export default class AccountViewView extends Vue {
|
|||||||
private profileService!: ProfileService;
|
private profileService!: ProfileService;
|
||||||
private notify!: ReturnType<typeof createNotifyHelpers>;
|
private notify!: ReturnType<typeof createNotifyHelpers>;
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.notify = createNotifyHelpers(this.$notify);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Async function executed when the component is mounted.
|
* Async function executed when the component is mounted.
|
||||||
* Initializes the component's state with values from the database,
|
* Initializes the component's state with values from the database,
|
||||||
@@ -916,7 +924,6 @@ export default class AccountViewView extends Vue {
|
|||||||
* @throws Will display specific messages to the user based on different errors.
|
* @throws Will display specific messages to the user based on different errors.
|
||||||
*/
|
*/
|
||||||
async mounted(): Promise<void> {
|
async mounted(): Promise<void> {
|
||||||
this.notify = createNotifyHelpers(this.$notify);
|
|
||||||
this.profileService = createProfileService(
|
this.profileService = createProfileService(
|
||||||
this.axios,
|
this.axios,
|
||||||
this.partnerApiServer,
|
this.partnerApiServer,
|
||||||
@@ -1601,7 +1608,7 @@ export default class AccountViewView extends Vue {
|
|||||||
|
|
||||||
// IdentitySection event handlers
|
// IdentitySection event handlers
|
||||||
onEditName() {
|
onEditName() {
|
||||||
const dialog = this.$refs.userNameDialog as any;
|
const dialog = this.$refs.userNameDialog as UserNameDialogRef | undefined;
|
||||||
if (dialog && typeof dialog.open === "function") {
|
if (dialog && typeof dialog.open === "function") {
|
||||||
dialog.open((name?: string) => {
|
dialog.open((name?: string) => {
|
||||||
if (name) this.givenName = name;
|
if (name) this.givenName = name;
|
||||||
@@ -1613,7 +1620,10 @@ export default class AccountViewView extends Vue {
|
|||||||
title: "Dialog Error",
|
title: "Dialog Error",
|
||||||
text: "Name dialog not available.",
|
text: "Name dialog not available.",
|
||||||
});
|
});
|
||||||
console.error("UserNameDialog ref is missing or open() is not a function", dialog);
|
logger.error(
|
||||||
|
"UserNameDialog ref is missing or open() is not a function",
|
||||||
|
dialog,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onShowQrCode() {
|
onShowQrCode() {
|
||||||
|
|||||||
@@ -578,8 +578,7 @@ export default class ClaimView extends Vue {
|
|||||||
libsUtil = libsUtil;
|
libsUtil = libsUtil;
|
||||||
serverUtil = serverUtil;
|
serverUtil = serverUtil;
|
||||||
|
|
||||||
// Add notification helpers
|
notify!: ReturnType<typeof createNotifyHelpers>;
|
||||||
private notify = createNotifyHelpers(this.$notify);
|
|
||||||
|
|
||||||
// =================================================
|
// =================================================
|
||||||
// COMPUTED PROPERTIES
|
// COMPUTED PROPERTIES
|
||||||
@@ -746,6 +745,8 @@ export default class ClaimView extends Vue {
|
|||||||
this.windowDeepLink = `${APP_SERVER}/deep-link/claim/${claimId}`;
|
this.windowDeepLink = `${APP_SERVER}/deep-link/claim/${claimId}`;
|
||||||
|
|
||||||
this.canShare = !!navigator.share;
|
this.canShare = !!navigator.share;
|
||||||
|
|
||||||
|
this.notify = createNotifyHelpers(this.$notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert a space before any capital letters except the initial letter
|
// insert a space before any capital letters except the initial letter
|
||||||
|
|||||||
Reference in New Issue
Block a user