2024-09-24 19:01:34 +05:30
|
|
|
import { TIssue } from "@plane/types";
|
|
|
|
|
import { rootStore } from "@/lib/store-context";
|
|
|
|
|
import { IssueService } from "@/services/issue";
|
|
|
|
|
import { persistence } from "../storage.sqlite";
|
|
|
|
|
import { ARRAY_FIELDS, PRIORITY_MAP } from "./constants";
|
|
|
|
|
import { issueSchema } from "./schemas";
|
2024-10-24 15:35:02 +05:30
|
|
|
import { log } from "./utils";
|
2024-09-24 19:01:34 +05:30
|
|
|
|
|
|
|
|
export const PROJECT_OFFLINE_STATUS: Record<string, boolean> = {};
|
|
|
|
|
|
|
|
|
|
export const addIssue = async (issue: any) => {
|
2024-10-24 15:35:02 +05:30
|
|
|
if (document.hidden || !rootStore.user.localDBEnabled || !persistence.db) return;
|
|
|
|
|
await persistence.db.exec("BEGIN;");
|
|
|
|
|
await stageIssueInserts(issue);
|
|
|
|
|
await persistence.db.exec("COMMIT;");
|
2024-09-24 19:01:34 +05:30
|
|
|
};
|
|
|
|
|
|
2024-11-26 19:12:39 +05:30
|
|
|
export const addIssuesBulk = async (issues: any, batchSize = 50) => {
|
2024-10-24 15:35:02 +05:30
|
|
|
if (!rootStore.user.localDBEnabled || !persistence.db) return;
|
2024-11-04 16:54:13 +05:30
|
|
|
if (!issues.length) return;
|
2024-10-24 15:35:02 +05:30
|
|
|
const insertStart = performance.now();
|
|
|
|
|
await persistence.db.exec("BEGIN;");
|
2024-09-24 19:01:34 +05:30
|
|
|
|
|
|
|
|
for (let i = 0; i < issues.length; i += batchSize) {
|
|
|
|
|
const batch = issues.slice(i, i + batchSize);
|
|
|
|
|
|
2024-11-26 19:12:39 +05:30
|
|
|
const promises = [];
|
2024-10-24 15:35:02 +05:30
|
|
|
for (let j = 0; j < batch.length; j++) {
|
|
|
|
|
const issue = batch[j];
|
2024-09-24 19:01:34 +05:30
|
|
|
if (!issue.type_id) {
|
|
|
|
|
issue.type_id = "";
|
|
|
|
|
}
|
2024-11-26 19:12:39 +05:30
|
|
|
promises.push(stageIssueInserts(issue));
|
2024-10-24 15:35:02 +05:30
|
|
|
}
|
2024-11-26 19:12:39 +05:30
|
|
|
await Promise.all(promises);
|
2024-09-24 19:01:34 +05:30
|
|
|
}
|
2024-10-24 15:35:02 +05:30
|
|
|
await persistence.db.exec("COMMIT;");
|
|
|
|
|
|
|
|
|
|
const insertEnd = performance.now();
|
2024-11-26 19:12:39 +05:30
|
|
|
log("Inserted issues in ", `${insertEnd - insertStart}ms`, batchSize, issues.length);
|
2024-09-24 19:01:34 +05:30
|
|
|
};
|
|
|
|
|
export const deleteIssueFromLocal = async (issue_id: any) => {
|
2024-10-24 15:35:02 +05:30
|
|
|
if (!rootStore.user.localDBEnabled || !persistence.db) return;
|
2024-09-24 19:01:34 +05:30
|
|
|
|
2024-10-28 14:14:57 +05:30
|
|
|
const deleteQuery = `DELETE from issues where id='${issue_id}'`;
|
2024-09-24 19:01:34 +05:30
|
|
|
const deleteMetaQuery = `delete from issue_meta where issue_id='${issue_id}'`;
|
|
|
|
|
|
2024-10-28 14:14:57 +05:30
|
|
|
await persistence.db.exec("BEGIN;");
|
|
|
|
|
|
|
|
|
|
await persistence.db.exec(deleteQuery);
|
|
|
|
|
await persistence.db.exec(deleteMetaQuery);
|
|
|
|
|
await persistence.db.exec("COMMIT;");
|
2024-09-24 19:01:34 +05:30
|
|
|
};
|
2024-09-26 14:04:59 +05:30
|
|
|
// @todo: Update deletes the issue description from local. Implement a separate update.
|
|
|
|
|
export const updateIssue = async (issue: TIssue & { is_local_update: number }) => {
|
2024-10-24 15:35:02 +05:30
|
|
|
if (document.hidden || !rootStore.user.localDBEnabled || !persistence.db) return;
|
2024-09-24 19:01:34 +05:30
|
|
|
|
|
|
|
|
const issue_id = issue.id;
|
|
|
|
|
// delete the issue and its meta data
|
|
|
|
|
await deleteIssueFromLocal(issue_id);
|
2024-10-28 14:14:57 +05:30
|
|
|
await addIssue(issue);
|
2024-09-24 19:01:34 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const syncDeletesToLocal = async (workspaceId: string, projectId: string, queries: any) => {
|
2024-10-24 15:35:02 +05:30
|
|
|
if (!rootStore.user.localDBEnabled || !persistence.db) return;
|
2024-09-24 19:01:34 +05:30
|
|
|
|
|
|
|
|
const issueService = new IssueService();
|
|
|
|
|
const response = await issueService.getDeletedIssues(workspaceId, projectId, queries);
|
|
|
|
|
if (Array.isArray(response)) {
|
|
|
|
|
response.map(async (issue) => deleteIssueFromLocal(issue));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-10-24 15:35:02 +05:30
|
|
|
const stageIssueInserts = async (issue: any) => {
|
2024-09-24 19:01:34 +05:30
|
|
|
const issue_id = issue.id;
|
|
|
|
|
issue.priority_proxy = PRIORITY_MAP[issue.priority as keyof typeof PRIORITY_MAP];
|
|
|
|
|
|
|
|
|
|
const keys = Object.keys(issueSchema);
|
|
|
|
|
const sanitizedIssue = keys.reduce((acc: any, key) => {
|
|
|
|
|
if (issue[key] || issue[key] === 0) {
|
|
|
|
|
acc[key] = issue[key];
|
|
|
|
|
}
|
|
|
|
|
return acc;
|
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
|
|
const columns = "'" + Object.keys(sanitizedIssue).join("','") + "'";
|
|
|
|
|
|
|
|
|
|
const values = Object.values(sanitizedIssue)
|
|
|
|
|
.map((value) => {
|
|
|
|
|
if (value === null) {
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
if (typeof value === "object") {
|
2024-09-26 14:04:59 +05:30
|
|
|
return `'${JSON.stringify(value).replace(/'/g, "''")}'`;
|
2024-09-24 19:01:34 +05:30
|
|
|
}
|
|
|
|
|
if (typeof value === "string") {
|
2024-09-26 14:04:59 +05:30
|
|
|
return `'${value.replace(/'/g, "''")}'`;
|
2024-09-24 19:01:34 +05:30
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
})
|
|
|
|
|
.join(", ");
|
|
|
|
|
|
|
|
|
|
const query = `INSERT OR REPLACE INTO issues (${columns}) VALUES (${values});`;
|
2024-10-28 14:14:57 +05:30
|
|
|
await persistence.db.exec(query);
|
2024-09-24 19:01:34 +05:30
|
|
|
|
2024-10-24 15:35:02 +05:30
|
|
|
await persistence.db.exec({
|
2024-09-24 19:01:34 +05:30
|
|
|
sql: `DELETE from issue_meta where issue_id='${issue_id}'`,
|
|
|
|
|
});
|
|
|
|
|
|
2024-10-28 14:14:57 +05:30
|
|
|
const metaPromises: Promise<any>[] = [];
|
|
|
|
|
|
2024-09-24 19:01:34 +05:30
|
|
|
ARRAY_FIELDS.forEach((field) => {
|
|
|
|
|
const values = issue[field];
|
|
|
|
|
if (values && values.length) {
|
|
|
|
|
values.forEach((val: any) => {
|
2024-10-28 14:14:57 +05:30
|
|
|
const p = persistence.db.exec({
|
2024-09-24 19:01:34 +05:30
|
|
|
sql: `INSERT OR REPLACE into issue_meta(issue_id,key,value) values (?,?,?) `,
|
|
|
|
|
bind: [issue_id, field, val],
|
|
|
|
|
});
|
2024-10-28 14:14:57 +05:30
|
|
|
metaPromises.push(p);
|
2024-09-24 19:01:34 +05:30
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// Added for empty fields?
|
2024-10-28 14:14:57 +05:30
|
|
|
const p = persistence.db.exec({
|
2024-09-24 19:01:34 +05:30
|
|
|
sql: `INSERT OR REPLACE into issue_meta(issue_id,key,value) values (?,?,?) `,
|
|
|
|
|
bind: [issue_id, field, ""],
|
|
|
|
|
});
|
2024-10-28 14:14:57 +05:30
|
|
|
metaPromises.push(p);
|
2024-09-24 19:01:34 +05:30
|
|
|
}
|
|
|
|
|
});
|
2024-10-28 14:14:57 +05:30
|
|
|
|
|
|
|
|
await Promise.all(metaPromises);
|
2024-09-24 19:01:34 +05:30
|
|
|
};
|