bb-plane-fork/web/core/local-db/utils/utils.ts
Satish Gandham 9fb353ef54
[WEB-2706] chore: Switch to wa-sqlite (#5859)
* fix layout switching when filter is not yet completely fetched

* add layout in issue filter params

* Handle cases when DB intilization failed

* chore: permission layer and updated issues v1 query from workspace to project level

* - Switch to using wa-sqlite instead of sqlite-wasm

* Code cleanup and fix indexes

* Add missing files

* - Import only required functions from sentry
- Wait till all the tables are created

* Skip workspace sync if one is already in progress.

* Sync workspace without using transaction

* Minor cleanup

* Close DB connection before deleting files
Fix clear OPFS on safari

* Fix type issue

* Improve issue insert performance

* Refactor workspace sync

* Close the DB connection while switching workspaces

* Update web/core/local-db/worker/db.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Worker cleanup and error handling

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update web/core/local-db/worker/db.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update web/core/local-db/storage.sqlite.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update web/core/local-db/worker/db.ts

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Code cleanup

* Set default order by to created at and descending

* Wait for transactions to complete.

---------

Co-authored-by: rahulramesha <rahulramesham@gmail.com>
Co-authored-by: gurusainath <gurusainath007@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-10-24 15:35:02 +05:30

176 lines
5.1 KiB
TypeScript

import { captureException } from "@sentry/nextjs";
import pick from "lodash/pick";
import { TIssue } from "@plane/types";
import { rootStore } from "@/lib/store-context";
import { persistence } from "../storage.sqlite";
import { updateIssue } from "./load-issues";
export const log = (...args: any) => {
if ((window as any).DEBUG) {
console.log(...args);
}
};
export const logError = (e: any) => {
if (e?.result?.errorClass === "SQLite3Error") {
e = parseSQLite3Error(e);
}
console.error(e);
captureException(e);
};
export const logInfo = console.info;
export const updatePersistentLayer = async (issueIds: string | string[]) => {
if (typeof issueIds === "string") {
issueIds = [issueIds];
}
issueIds.forEach(async (issueId) => {
const dbIssue = await persistence.getIssue(issueId);
const issue = rootStore.issue.issues.getIssueById(issueId);
if (issue) {
// JSON.parse(JSON.stringify(issue)) is used to remove the mobx observables
const issuePartial = pick({ ...dbIssue, ...JSON.parse(JSON.stringify(issue)) }, [
"id",
"name",
"state_id",
"sort_order",
"completed_at",
"estimate_point",
"priority",
"start_date",
"target_date",
"sequence_id",
"project_id",
"parent_id",
"created_at",
"updated_at",
"created_by",
"updated_by",
"is_draft",
"archived_at",
"state__group",
"cycle_id",
"link_count",
"attachment_count",
"sub_issues_count",
"assignee_ids",
"label_ids",
"module_ids",
"type_id",
"description_html",
]);
updateIssue({ ...issuePartial, is_local_update: 1 });
}
});
};
export const wrapDateTime = (field: string) => {
const DATE_TIME_FIELDS = ["created_at", "updated_at", "completed_at", "start_date", "target_date"];
if (DATE_TIME_FIELDS.includes(field)) {
return `datetime(${field})`;
}
return field;
};
export const getGroupedIssueResults = (issueResults: (TIssue & { group_id?: string; total_issues: number })[]): any => {
const groupedResults: {
[key: string]: {
results: TIssue[];
total_results: number;
};
} = {};
for (const issue of issueResults) {
const { group_id, total_issues } = issue;
const groupId = group_id ? group_id : "None";
if (groupedResults?.[groupId] !== undefined && Array.isArray(groupedResults?.[groupId]?.results)) {
groupedResults?.[groupId]?.results.push(issue);
} else {
groupedResults[groupId] = { results: [issue], total_results: total_issues };
}
}
return groupedResults;
};
export const getSubGroupedIssueResults = (
issueResults: (TIssue & { group_id?: string; total_issues: number; sub_group_id?: string })[]
): any => {
const subGroupedResults: {
[key: string]: {
results: {
[key: string]: {
results: TIssue[];
total_results: number;
};
};
total_results: number;
};
} = {};
for (const issue of issueResults) {
const { group_id, total_issues, sub_group_id } = issue;
const groupId = group_id ? group_id : "None";
const subGroupId = sub_group_id ? sub_group_id : "None";
if (subGroupedResults?.[groupId] === undefined) {
subGroupedResults[groupId] = { results: {}, total_results: 0 };
}
if (
subGroupedResults[groupId].results[subGroupId] !== undefined &&
Array.isArray(subGroupedResults[groupId].results[subGroupId]?.results)
) {
subGroupedResults[groupId].results[subGroupId]?.results.push(issue);
} else {
subGroupedResults[groupId].results[subGroupId] = { results: [issue], total_results: total_issues };
}
}
const groupByKeys = Object.keys(subGroupedResults);
for (const groupByKey of groupByKeys) {
let totalIssues = 0;
const groupedResults = subGroupedResults[groupByKey]?.results ?? {};
const subGroupByKeys = Object.keys(groupedResults);
for (const subGroupByKey of subGroupByKeys) {
const subGroupedResultsCount = groupedResults[subGroupByKey].total_results ?? 0;
totalIssues += subGroupedResultsCount;
}
subGroupedResults[groupByKey].total_results = totalIssues;
}
return subGroupedResults;
};
export const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
const parseSQLite3Error = (error: any) => {
error.result = JSON.stringify(error.result);
return error;
};
export const clearOPFS = async () => {
const storageManager = window.navigator.storage;
const fileSystemDirectoryHandle = await storageManager.getDirectory();
const userAgent = navigator.userAgent;
const isChrome = userAgent.includes("Chrome") && !userAgent.includes("Edg") && !userAgent.includes("OPR");
if (isChrome) {
await (fileSystemDirectoryHandle as any).remove({ recursive: true });
return;
}
const entries = await (fileSystemDirectoryHandle as any).entries();
for await (const entry of entries) {
const [name] = entry;
try {
await fileSystemDirectoryHandle.removeEntry(name);
} catch (e) {
console.log("Error", e);
}
}
};