forked from trent_larson/crowd-funder-for-time-pwa
feat: add starred project list in search, refactor variable names
This commit is contained in:
@@ -125,10 +125,10 @@ const MIGRATIONS = [
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "003_add_starredProjectIds_to_settings",
|
||||
name: "005_add_starredPlanHandleIds_to_settings",
|
||||
sql: `
|
||||
ALTER TABLE settings ADD COLUMN starredProjectIds TEXT;
|
||||
ALTER TABLE settings ADD COLUMN lastAckedStarredProjectChangesJwtId TEXT;
|
||||
ALTER TABLE settings ADD COLUMN starredPlanHandleIds TEXT DEFAULT '[]'; -- JSON string
|
||||
ALTER TABLE settings ADD COLUMN lastAckedStarredPlanChangesJwtId TEXT;
|
||||
`,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -158,7 +158,10 @@ export async function retrieveSettingsForDefaultAccount(): Promise<Settings> {
|
||||
result.values,
|
||||
)[0] as Settings;
|
||||
settings.searchBoxes = parseJsonField(settings.searchBoxes, []);
|
||||
settings.starredProjectIds = parseJsonField(settings.starredProjectIds, []);
|
||||
settings.starredPlanHandleIds = parseJsonField(
|
||||
settings.starredPlanHandleIds,
|
||||
[],
|
||||
);
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
@@ -225,8 +228,8 @@ export async function retrieveSettingsForActiveAccount(): Promise<Settings> {
|
||||
}
|
||||
|
||||
settings.searchBoxes = parseJsonField(settings.searchBoxes, []);
|
||||
settings.starredProjectIds = parseJsonField(
|
||||
settings.starredProjectIds,
|
||||
settings.starredPlanHandleIds = parseJsonField(
|
||||
settings.starredPlanHandleIds,
|
||||
[],
|
||||
);
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ export type Settings = {
|
||||
|
||||
lastAckedOfferToUserJwtId?: string; // the last JWT ID for offer-to-user that they've acknowledged seeing
|
||||
lastAckedOfferToUserProjectsJwtId?: string; // the last JWT ID for offers-to-user's-projects that they've acknowledged seeing
|
||||
lastAckedStarredProjectChangesJwtId?: string; // the last JWT ID for starred project changes that they've acknowledged seeing
|
||||
lastAckedStarredPlanChangesJwtId?: string; // the last JWT ID for starred plan changes that they've acknowledged seeing
|
||||
|
||||
// The claim list has a most recent one used in notifications that's separate from the last viewed
|
||||
lastNotifiedClaimId?: string;
|
||||
@@ -62,19 +62,17 @@ export type Settings = {
|
||||
showGeneralAdvanced?: boolean; // Show advanced features which don't have their own flag
|
||||
showShortcutBvc?: boolean; // Show shortcut for Bountiful Voluntaryist Community actions
|
||||
|
||||
// List of starred project handleIds
|
||||
starredProjectIds?: Array<string>;
|
||||
|
||||
starredPlanHandleIds?: string[]; // Array of starred plan handle IDs
|
||||
vapid?: string; // VAPID (Voluntary Application Server Identification) field for web push
|
||||
warnIfProdServer?: boolean; // Warn if using a production server
|
||||
warnIfTestServer?: boolean; // Warn if using a testing server
|
||||
webPushServer?: string; // Web Push server URL
|
||||
};
|
||||
|
||||
// type of settings where the searchBoxes are JSON strings instead of objects
|
||||
// type of settings where the values are JSON strings instead of objects
|
||||
export type SettingsWithJsonStrings = Settings & {
|
||||
searchBoxes: string;
|
||||
starredProjectIds: string;
|
||||
starredPlanHandleIds: string;
|
||||
};
|
||||
|
||||
export function checkIsAnyFeedFilterOn(settings: Settings): boolean {
|
||||
@@ -91,6 +89,11 @@ export const SettingsSchema = {
|
||||
/**
|
||||
* Constants.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is deprecated.
|
||||
* It only remains for those with a PWA who have not migrated, but we'll soon remove it.
|
||||
*/
|
||||
export const MASTER_SETTINGS_KEY = "1";
|
||||
|
||||
export const DEFAULT_PASSKEY_EXPIRATION_MINUTES = 15;
|
||||
|
||||
@@ -93,7 +93,10 @@ export interface PlanData {
|
||||
name: string;
|
||||
/**
|
||||
* The identifier of the project record -- different from jwtId
|
||||
* (Maybe we should use the jwtId to iterate through the records instead.)
|
||||
*
|
||||
* This has been used to iterate through plan records, because jwtId ordering doesn't match
|
||||
* chronological create ordering, though it does match most recent edit order (in reverse order).
|
||||
* (It may be worthwhile to order by jwtId instead. It is an indexed field.)
|
||||
**/
|
||||
rowId?: string;
|
||||
}
|
||||
|
||||
@@ -793,18 +793,18 @@ export async function getNewOffersToUserProjects(
|
||||
* @param axios - axios instance
|
||||
* @param apiServer - endorser API server URL
|
||||
* @param activeDid - user's DID for authentication
|
||||
* @param starredProjectIds - array of starred project handle IDs
|
||||
* @param afterId - JWT ID to check for changes after (from lastAckedStarredProjectChangesJwtId)
|
||||
* @param starredPlanHandleIds - array of starred project handle IDs
|
||||
* @param afterId - JWT ID to check for changes after (from lastAckedStarredPlanChangesJwtId)
|
||||
* @returns { data: Array<PlanSummaryAndPreviousClaim>, hitLimit: boolean }
|
||||
*/
|
||||
export async function getStarredProjectsWithChanges(
|
||||
axios: Axios,
|
||||
apiServer: string,
|
||||
activeDid: string,
|
||||
starredProjectIds: string[],
|
||||
starredPlanHandleIds: string[],
|
||||
afterId?: string,
|
||||
): Promise<{ data: Array<PlanSummaryAndPreviousClaim>; hitLimit: boolean }> {
|
||||
if (!starredProjectIds || starredProjectIds.length === 0) {
|
||||
if (!starredPlanHandleIds || starredPlanHandleIds.length === 0) {
|
||||
return { data: [], hitLimit: false };
|
||||
}
|
||||
|
||||
@@ -817,7 +817,7 @@ export async function getStarredProjectsWithChanges(
|
||||
const headers = await getHeaders(activeDid);
|
||||
|
||||
const requestBody = {
|
||||
planIds: starredProjectIds,
|
||||
planIds: starredPlanHandleIds,
|
||||
afterId: afterId,
|
||||
};
|
||||
|
||||
|
||||
@@ -85,7 +85,6 @@
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||
|
||||
@Component({
|
||||
mixins: [PlatformServiceMixin],
|
||||
@@ -197,10 +196,10 @@ This tests the helper method only - no database interaction`;
|
||||
const success = await this.$saveSettings(testSettings);
|
||||
|
||||
if (success) {
|
||||
// Now query the raw database to see how it's actually stored
|
||||
// Now query the raw database to see how it's actually stored.
|
||||
// Note that new users probably have settings with ID of 1 but old migrated users might skip to 2.
|
||||
const rawResult = await this.$dbQuery(
|
||||
"SELECT searchBoxes FROM settings WHERE id = ?",
|
||||
[MASTER_SETTINGS_KEY],
|
||||
"SELECT searchBoxes FROM settings limit 1",
|
||||
);
|
||||
|
||||
if (rawResult?.values?.length) {
|
||||
|
||||
@@ -249,13 +249,13 @@ export const PlatformServiceMixin = {
|
||||
// Keep null values as null
|
||||
}
|
||||
|
||||
// Handle JSON fields like contactMethods
|
||||
if (column === "contactMethods" && typeof value === "string") {
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
} catch {
|
||||
value = [];
|
||||
}
|
||||
// Convert SQLite JSON strings to objects/arrays
|
||||
if (
|
||||
column === "contactMethods" ||
|
||||
column === "searchBoxes" ||
|
||||
column === "starredPlanHandleIds"
|
||||
) {
|
||||
value = this._parseJsonField(value, []);
|
||||
}
|
||||
|
||||
obj[column] = value;
|
||||
|
||||
@@ -56,16 +56,26 @@
|
||||
href="#"
|
||||
:class="computedStarredTabStyleClassNames()"
|
||||
@click="
|
||||
projects = [];
|
||||
userProfiles = [];
|
||||
isStarredActive = true;
|
||||
isLocalActive = false;
|
||||
isMappedActive = false;
|
||||
isAnywhereActive = false;
|
||||
isStarredActive = true;
|
||||
isSearchVisible = false;
|
||||
tempSearchBox = null;
|
||||
loadStarred();
|
||||
searchStarred();
|
||||
"
|
||||
>
|
||||
Starred
|
||||
<!-- restore when the links don't jump around for different numbers
|
||||
<span
|
||||
class="font-semibold text-sm bg-slate-200 px-1.5 py-0.5 rounded-md"
|
||||
v-if="isLocalActive"
|
||||
>
|
||||
{{ localCount > -1 ? localCount : "?" }}
|
||||
</span>
|
||||
-->
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
@@ -75,6 +85,7 @@
|
||||
@click="
|
||||
projects = [];
|
||||
userProfiles = [];
|
||||
isStarredActive = false;
|
||||
isLocalActive = true;
|
||||
isMappedActive = false;
|
||||
isAnywhereActive = false;
|
||||
@@ -102,6 +113,7 @@
|
||||
@click="
|
||||
projects = [];
|
||||
userProfiles = [];
|
||||
isStarredActive = false;
|
||||
isLocalActive = false;
|
||||
isMappedActive = true;
|
||||
isAnywhereActive = false;
|
||||
@@ -122,6 +134,7 @@
|
||||
@click="
|
||||
projects = [];
|
||||
userProfiles = [];
|
||||
isStarredActive = false;
|
||||
isLocalActive = false;
|
||||
isMappedActive = false;
|
||||
isAnywhereActive = true;
|
||||
@@ -222,7 +235,9 @@
|
||||
that search.</span
|
||||
>
|
||||
<span v-else-if="isStarredActive">
|
||||
<p>You have no starred projects. Star some projects to see them here.</p>
|
||||
<p>
|
||||
You have no starred projects. Star some projects to see them here.
|
||||
</p>
|
||||
<p class="mt-4">
|
||||
When you star projects, you will get a notice on the front page when
|
||||
they change.
|
||||
@@ -360,10 +375,8 @@ import {
|
||||
didInfo,
|
||||
errorStringForLog,
|
||||
getHeaders,
|
||||
getPlanFromCache,
|
||||
} from "../libs/endorserServer";
|
||||
import { OnboardPage, retrieveAccountDids } from "../libs/util";
|
||||
import { parseJsonField } from "../db/databaseUtil";
|
||||
import { logger } from "../utils/logger";
|
||||
import { UserProfile } from "@/libs/partnerServer";
|
||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||
@@ -416,10 +429,12 @@ export default class DiscoverView extends Vue {
|
||||
allMyDids: Array<string> = [];
|
||||
apiServer = "";
|
||||
isLoading = false;
|
||||
|
||||
isLocalActive = false;
|
||||
isMappedActive = false;
|
||||
isAnywhereActive = true;
|
||||
isStarredActive = false;
|
||||
|
||||
isProjectsActive = true;
|
||||
isPeopleActive = false;
|
||||
isSearchVisible = true;
|
||||
@@ -505,7 +520,7 @@ export default class DiscoverView extends Vue {
|
||||
};
|
||||
this.requestTiles(mapRef.leafletObject); // not ideal because I found this from experimentation, not documentation
|
||||
} else if (this.isStarredActive) {
|
||||
await this.loadStarred();
|
||||
await this.searchStarred();
|
||||
} else {
|
||||
await this.searchAll();
|
||||
}
|
||||
@@ -576,7 +591,7 @@ export default class DiscoverView extends Vue {
|
||||
}
|
||||
}
|
||||
|
||||
public async loadStarred() {
|
||||
public async searchStarred() {
|
||||
this.resetCounts();
|
||||
|
||||
// Clear any previous results
|
||||
@@ -588,52 +603,37 @@ export default class DiscoverView extends Vue {
|
||||
|
||||
// Get starred project IDs from settings
|
||||
const settings = await this.$accountSettings();
|
||||
const starredIds: string[] = parseJsonField(
|
||||
settings.starredProjectIds,
|
||||
[],
|
||||
);
|
||||
|
||||
const starredIds = settings.starredPlanHandleIds || [];
|
||||
if (starredIds.length === 0) {
|
||||
// No starred projects
|
||||
return;
|
||||
}
|
||||
|
||||
// Load each starred project using getPlanFromCache
|
||||
const projectPromises = starredIds.map(async (handleId) => {
|
||||
try {
|
||||
const project = await getPlanFromCache(
|
||||
handleId,
|
||||
this.axios,
|
||||
this.apiServer,
|
||||
this.activeDid,
|
||||
);
|
||||
if (project) {
|
||||
// Convert PlanSummaryRecord to PlanData
|
||||
return {
|
||||
description: project.description,
|
||||
handleId: project.handleId,
|
||||
image: project.image,
|
||||
issuerDid: project.issuerDid,
|
||||
name: project.name || UNNAMED_PROJECT,
|
||||
rowId: project.jwtId,
|
||||
} as PlanData;
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
logger.warn(`Failed to load starred project ${handleId}:`, error);
|
||||
return null;
|
||||
}
|
||||
// This could be optimized to only pull those not already in the cache (endorserServer.ts)
|
||||
|
||||
const planHandleIdsJson = JSON.stringify(starredIds);
|
||||
const endpoint =
|
||||
this.apiServer +
|
||||
"/api/v2/report/plans?planHandleIds=" +
|
||||
encodeURIComponent(planHandleIdsJson);
|
||||
const response = await this.axios.get(endpoint, {
|
||||
headers: await getHeaders(this.activeDid),
|
||||
});
|
||||
if (response.status !== 200) {
|
||||
this.notify.error("Failed to load starred projects", TIMEOUTS.SHORT);
|
||||
return;
|
||||
}
|
||||
const starredPlans: PlanData[] = response.data.data;
|
||||
if (response.data.hitLimit) {
|
||||
// someday we'll have to let them incrementally load the rest
|
||||
this.notify.warning(
|
||||
"Beware: you have so many starred projects that we cannot load them all.",
|
||||
TIMEOUTS.SHORT,
|
||||
);
|
||||
}
|
||||
|
||||
const projects = await Promise.all(projectPromises);
|
||||
|
||||
// Filter out null results and add to projects array
|
||||
const validProjects = projects.filter(
|
||||
(project): project is PlanData =>
|
||||
project !== null && project !== undefined,
|
||||
);
|
||||
|
||||
this.projects = validProjects;
|
||||
this.projects = starredPlans;
|
||||
} catch (error: unknown) {
|
||||
logger.error("Error loading starred projects:", error);
|
||||
this.notify.error(
|
||||
@@ -738,6 +738,8 @@ export default class DiscoverView extends Vue {
|
||||
const latestProject = this.projects[this.projects.length - 1];
|
||||
if (this.isLocalActive || this.isMappedActive) {
|
||||
this.searchLocal(latestProject.rowId);
|
||||
} else if (this.isStarredActive) {
|
||||
this.searchStarred();
|
||||
} else if (this.isAnywhereActive) {
|
||||
this.searchAll(latestProject.rowId);
|
||||
}
|
||||
@@ -881,6 +883,24 @@ export default class DiscoverView extends Vue {
|
||||
this.$router.push(route);
|
||||
}
|
||||
|
||||
public computedStarredTabStyleClassNames() {
|
||||
return {
|
||||
"inline-block": true,
|
||||
"py-3": true,
|
||||
"rounded-t-lg": true,
|
||||
"border-b-2": true,
|
||||
|
||||
active: this.isStarredActive,
|
||||
"text-black": this.isStarredActive,
|
||||
"border-black": this.isStarredActive,
|
||||
"font-semibold": this.isStarredActive,
|
||||
|
||||
"text-blue-600": !this.isStarredActive,
|
||||
"border-transparent": !this.isStarredActive,
|
||||
"hover:border-slate-400": !this.isStarredActive,
|
||||
};
|
||||
}
|
||||
|
||||
public computedLocalTabStyleClassNames() {
|
||||
return {
|
||||
"inline-block": true,
|
||||
@@ -935,24 +955,6 @@ export default class DiscoverView extends Vue {
|
||||
};
|
||||
}
|
||||
|
||||
public computedStarredTabStyleClassNames() {
|
||||
return {
|
||||
"inline-block": true,
|
||||
"py-3": true,
|
||||
"rounded-t-lg": true,
|
||||
"border-b-2": true,
|
||||
|
||||
active: this.isStarredActive,
|
||||
"text-black": this.isStarredActive,
|
||||
"border-black": this.isStarredActive,
|
||||
"font-semibold": this.isStarredActive,
|
||||
|
||||
"text-blue-600": !this.isStarredActive,
|
||||
"border-transparent": !this.isStarredActive,
|
||||
"hover:border-slate-400": !this.isStarredActive,
|
||||
};
|
||||
}
|
||||
|
||||
public computedProjectsTabStyleClassNames() {
|
||||
return {
|
||||
"inline-block": true,
|
||||
|
||||
@@ -413,14 +413,14 @@ export default class HomeView extends Vue {
|
||||
isRegistered = false;
|
||||
lastAckedOfferToUserJwtId?: string; // the last JWT ID for offer-to-user that they've acknowledged seeing
|
||||
lastAckedOfferToUserProjectsJwtId?: string; // the last JWT ID for offers-to-user's-projects that they've acknowledged seeing
|
||||
lastAckedStarredProjectChangesJwtId?: string; // the last JWT ID for starred project changes that they've acknowledged seeing
|
||||
lastAckedStarredPlanChangesJwtId?: string; // the last JWT ID for starred project changes that they've acknowledged seeing
|
||||
newOffersToUserHitLimit: boolean = false;
|
||||
newOffersToUserProjectsHitLimit: boolean = false;
|
||||
newStarredProjectChangesHitLimit: boolean = false;
|
||||
numNewOffersToUser: number = 0; // number of new offers-to-user
|
||||
numNewOffersToUserProjects: number = 0; // number of new offers-to-user's-projects
|
||||
numNewStarredProjectChanges: number = 0; // number of new starred project changes
|
||||
starredProjectIds: Array<string> = []; // list of starred project IDs
|
||||
starredPlanHandleIds: Array<string> = []; // list of starred project IDs
|
||||
searchBoxes: Array<{
|
||||
name: string;
|
||||
bbox: BoundingBox;
|
||||
@@ -565,12 +565,12 @@ export default class HomeView extends Vue {
|
||||
this.lastAckedOfferToUserJwtId = settings.lastAckedOfferToUserJwtId;
|
||||
this.lastAckedOfferToUserProjectsJwtId =
|
||||
settings.lastAckedOfferToUserProjectsJwtId;
|
||||
this.lastAckedStarredProjectChangesJwtId =
|
||||
settings.lastAckedStarredProjectChangesJwtId;
|
||||
this.lastAckedStarredPlanChangesJwtId =
|
||||
settings.lastAckedStarredPlanChangesJwtId;
|
||||
this.searchBoxes = settings.searchBoxes || [];
|
||||
this.showShortcutBvc = !!settings.showShortcutBvc;
|
||||
this.starredProjectIds = databaseUtil.parseJsonField(
|
||||
settings.starredProjectIds,
|
||||
this.starredPlanHandleIds = databaseUtil.parseJsonField(
|
||||
settings.starredPlanHandleIds,
|
||||
[],
|
||||
);
|
||||
this.isAnyFeedFilterOn = checkIsAnyFeedFilterOn(settings);
|
||||
@@ -715,14 +715,14 @@ export default class HomeView extends Vue {
|
||||
* @requires Active DID
|
||||
*/
|
||||
private async loadNewStarredProjectChanges() {
|
||||
if (this.activeDid && this.starredProjectIds.length > 0) {
|
||||
if (this.activeDid && this.starredPlanHandleIds.length > 0) {
|
||||
try {
|
||||
const starredProjectChanges = await getStarredProjectsWithChanges(
|
||||
this.axios,
|
||||
this.apiServer,
|
||||
this.activeDid,
|
||||
this.starredProjectIds,
|
||||
this.lastAckedStarredProjectChangesJwtId,
|
||||
this.starredPlanHandleIds,
|
||||
this.lastAckedStarredPlanChangesJwtId,
|
||||
);
|
||||
this.numNewStarredProjectChanges = starredProjectChanges.data.length;
|
||||
this.newStarredProjectChangesHitLimit = starredProjectChanges.hitLimit;
|
||||
|
||||
@@ -338,14 +338,14 @@ export default class NewActivityView extends Vue {
|
||||
apiServer = "";
|
||||
lastAckedOfferToUserJwtId = "";
|
||||
lastAckedOfferToUserProjectsJwtId = "";
|
||||
lastAckedStarredProjectChangesJwtId = "";
|
||||
lastAckedStarredPlanChangesJwtId = "";
|
||||
newOffersToUser: Array<OfferSummaryRecord> = [];
|
||||
newOffersToUserHitLimit = false;
|
||||
newOffersToUserProjects: Array<OfferToPlanSummaryRecord> = [];
|
||||
newOffersToUserProjectsHitLimit = false;
|
||||
newStarredProjectChanges: Array<PlanSummaryAndPreviousClaim> = [];
|
||||
newStarredProjectChangesHitLimit = false;
|
||||
starredProjectIds: Array<string> = [];
|
||||
starredPlanHandleIds: Array<string> = [];
|
||||
planDifferences: Record<
|
||||
string,
|
||||
Record<string, { old: unknown; new: unknown }>
|
||||
@@ -367,10 +367,10 @@ export default class NewActivityView extends Vue {
|
||||
this.lastAckedOfferToUserJwtId = settings.lastAckedOfferToUserJwtId || "";
|
||||
this.lastAckedOfferToUserProjectsJwtId =
|
||||
settings.lastAckedOfferToUserProjectsJwtId || "";
|
||||
this.lastAckedStarredProjectChangesJwtId =
|
||||
settings.lastAckedStarredProjectChangesJwtId || "";
|
||||
this.starredProjectIds = databaseUtil.parseJsonField(
|
||||
settings.starredProjectIds,
|
||||
this.lastAckedStarredPlanChangesJwtId =
|
||||
settings.lastAckedStarredPlanChangesJwtId || "";
|
||||
this.starredPlanHandleIds = databaseUtil.parseJsonField(
|
||||
settings.starredPlanHandleIds,
|
||||
[],
|
||||
);
|
||||
|
||||
@@ -397,14 +397,14 @@ export default class NewActivityView extends Vue {
|
||||
this.newOffersToUserProjectsHitLimit = offersToUserProjectsData.hitLimit;
|
||||
|
||||
// Load starred project changes if user has starred projects
|
||||
if (this.starredProjectIds.length > 0) {
|
||||
if (this.starredPlanHandleIds.length > 0) {
|
||||
try {
|
||||
const starredProjectChangesData = await getStarredProjectsWithChanges(
|
||||
this.axios,
|
||||
this.apiServer,
|
||||
this.activeDid,
|
||||
this.starredProjectIds,
|
||||
this.lastAckedStarredProjectChangesJwtId,
|
||||
this.starredPlanHandleIds,
|
||||
this.lastAckedStarredPlanChangesJwtId,
|
||||
);
|
||||
this.newStarredProjectChanges = starredProjectChangesData.data;
|
||||
this.newStarredProjectChangesHitLimit =
|
||||
@@ -513,7 +513,7 @@ export default class NewActivityView extends Vue {
|
||||
this.newStarredProjectChanges.length > 0
|
||||
) {
|
||||
await this.$saveUserSettings(this.activeDid, {
|
||||
lastAckedStarredProjectChangesJwtId:
|
||||
lastAckedStarredPlanChangesJwtId:
|
||||
this.newStarredProjectChanges[0].plan.jwtId,
|
||||
});
|
||||
this.notify.info(
|
||||
@@ -530,14 +530,14 @@ export default class NewActivityView extends Vue {
|
||||
if (index !== -1 && index < this.newStarredProjectChanges.length - 1) {
|
||||
// Set to the next change's jwtId
|
||||
await this.$saveUserSettings(this.activeDid, {
|
||||
lastAckedStarredProjectChangesJwtId:
|
||||
lastAckedStarredPlanChangesJwtId:
|
||||
this.newStarredProjectChanges[index + 1].plan.jwtId,
|
||||
});
|
||||
} else {
|
||||
// it's the last entry (or not found), so just keep it the same
|
||||
await this.$saveUserSettings(this.activeDid, {
|
||||
lastAckedStarredProjectChangesJwtId:
|
||||
this.lastAckedStarredProjectChangesJwtId,
|
||||
lastAckedStarredPlanChangesJwtId:
|
||||
this.lastAckedStarredPlanChangesJwtId,
|
||||
});
|
||||
}
|
||||
this.notify.info(
|
||||
|
||||
@@ -27,12 +27,6 @@
|
||||
>
|
||||
<font-awesome icon="pen" class="text-sm text-blue-500 ml-2 mb-1" />
|
||||
</button>
|
||||
<button title="Copy Link to Project" @click="onCopyLinkClick()">
|
||||
<font-awesome
|
||||
icon="link"
|
||||
class="text-sm text-slate-500 ml-2 mb-1"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
:title="
|
||||
isStarred
|
||||
@@ -830,11 +824,8 @@ export default class ProjectViewView extends Vue {
|
||||
this.loadTotals();
|
||||
|
||||
// Check if this project is starred when settings are loaded
|
||||
if (this.projectId && settings.starredProjectIds) {
|
||||
const starredIds: string[] = databaseUtil.parseJsonField(
|
||||
settings.starredProjectIds,
|
||||
[],
|
||||
);
|
||||
if (this.projectId && settings.starredPlanHandleIds) {
|
||||
const starredIds = settings.starredPlanHandleIds || [];
|
||||
this.isStarred = starredIds.includes(this.projectId);
|
||||
}
|
||||
}
|
||||
@@ -1513,10 +1504,7 @@ export default class ProjectViewView extends Vue {
|
||||
if (!this.isStarred) {
|
||||
// Add to starred projects
|
||||
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
|
||||
const starredIds: string[] = databaseUtil.parseJsonField(
|
||||
settings.starredProjectIds,
|
||||
[],
|
||||
);
|
||||
const starredIds = settings.starredPlanHandleIds || [];
|
||||
|
||||
if (!starredIds.includes(this.projectId)) {
|
||||
const newStarredIds = [...starredIds, this.projectId];
|
||||
@@ -1524,43 +1512,42 @@ export default class ProjectViewView extends Vue {
|
||||
const result = await databaseUtil.updateDidSpecificSettings(
|
||||
this.activeDid,
|
||||
// @ts-expect-error until we use SettingsWithJsonString properly
|
||||
{ starredProjectIds: newIdsParam },
|
||||
{ starredPlanHandleIds: newIdsParam },
|
||||
);
|
||||
if (!result) {
|
||||
if (result) {
|
||||
this.isStarred = true;
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
"Still getting a bad result from SQL update to star a project.",
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!settings.lastAckedStarredProjectChangesJwtId) {
|
||||
if (!settings.lastAckedStarredPlanChangesJwtId) {
|
||||
await databaseUtil.updateDidSpecificSettings(this.activeDid, {
|
||||
lastAckedStarredProjectChangesJwtId: settings.lastViewedClaimId,
|
||||
lastAckedStarredPlanChangesJwtId: settings.lastViewedClaimId,
|
||||
});
|
||||
}
|
||||
this.isStarred = true;
|
||||
} else {
|
||||
// Remove from starred projects
|
||||
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
|
||||
const starredIds: string[] = databaseUtil.parseJsonField(
|
||||
settings.starredProjectIds,
|
||||
[],
|
||||
);
|
||||
const starredIds = settings.starredPlanHandleIds || [];
|
||||
|
||||
const updatedIds = starredIds.filter((id) => id !== this.projectId);
|
||||
const newIdsParam = JSON.stringify(updatedIds);
|
||||
const result = await databaseUtil.updateDidSpecificSettings(
|
||||
this.activeDid,
|
||||
// @ts-expect-error until we use SettingsWithJsonString properly
|
||||
{ starredProjectIds: newIdsParam },
|
||||
{ starredPlanHandleIds: newIdsParam },
|
||||
);
|
||||
if (!result) {
|
||||
if (result) {
|
||||
this.isStarred = false;
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(
|
||||
"Still getting a bad result from SQL update to unstar a project.",
|
||||
logger.error(
|
||||
"Got a bad result from SQL update to unstar a project.",
|
||||
);
|
||||
}
|
||||
this.isStarred = false;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error("Error toggling star status:", error);
|
||||
|
||||
Reference in New Issue
Block a user