Compare commits
2
Commits
main
...
remove-indexdb
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae919a802b | ||
|
|
b81b0c8e0a |
@@ -52,6 +52,9 @@ def file_handle(name, fileList, file_path, metaInfoOnly):
|
||||
createTime, updateTime = getFileCreateTime(file_path)
|
||||
workspace_info = json_data.get('extra', {}).get('workspace_info', {})
|
||||
workflow_id = workspace_info.get('id', str(uuid.uuid4()))
|
||||
saveLock = workspace_info.get('saveLock', False)
|
||||
cloudID = workspace_info.get('cloudID', None)
|
||||
coverMediaPath = workspace_info.get('coverMediaPath', None)
|
||||
# Update JSON data with new ID if needed and write back to file
|
||||
if 'id' not in workspace_info:
|
||||
if 'extra' not in json_data:
|
||||
@@ -66,6 +69,9 @@ def file_handle(name, fileList, file_path, metaInfoOnly):
|
||||
'name': name,
|
||||
'type': "workflow",
|
||||
'id': workflow_id,
|
||||
'saveLock': saveLock,
|
||||
'cloudID': cloudID,
|
||||
'coverMediaPath': coverMediaPath,
|
||||
'createTime': createTime,
|
||||
'updateTime': updateTime
|
||||
}
|
||||
|
||||
@@ -337,7 +337,6 @@ export default function App() {
|
||||
json: workflow.json,
|
||||
name: newFlowName || workflow.name,
|
||||
parentFolderID: workflow.parentFolderID,
|
||||
tags: workflow.tags,
|
||||
});
|
||||
flow && (await loadWorkflowID(flow.id));
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
|
||||
export namespace TwowaySyncAPI {
|
||||
export async function moveWorkflow(
|
||||
workflow: Workflow,
|
||||
curRelPath: string,
|
||||
newParentFolderRelPath: string,
|
||||
) {
|
||||
try {
|
||||
@@ -20,7 +20,7 @@ export namespace TwowaySyncAPI {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
path: getWorkflowRelPath(workflow),
|
||||
path: curRelPath,
|
||||
newParentPath: newParentFolderRelPath,
|
||||
}),
|
||||
});
|
||||
@@ -62,7 +62,7 @@ export namespace TwowaySyncAPI {
|
||||
}
|
||||
|
||||
export async function renameWorkflow(
|
||||
{ parentFolderID, name }: Pick<Workflow, "name" | "parentFolderID">,
|
||||
{ relPath, id }: { relPath: string; id: string },
|
||||
newName: string,
|
||||
) {
|
||||
try {
|
||||
@@ -72,7 +72,7 @@ export namespace TwowaySyncAPI {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
path: joinRelPath(parentFolderID ?? "", name + ".json"),
|
||||
path: relPath,
|
||||
newName: newName,
|
||||
}),
|
||||
});
|
||||
@@ -103,6 +103,11 @@ export namespace TwowaySyncAPI {
|
||||
flow.extra[COMFYSPACE_TRACKING_FIELD_NAME] = {};
|
||||
}
|
||||
flow.extra[COMFYSPACE_TRACKING_FIELD_NAME].id = workflow.id;
|
||||
flow.extra[COMFYSPACE_TRACKING_FIELD_NAME].saveLock = workflow.saveLock;
|
||||
flow.extra[COMFYSPACE_TRACKING_FIELD_NAME].cloudID = workflow.cloudID;
|
||||
flow.extra[COMFYSPACE_TRACKING_FIELD_NAME].coverMediaPath =
|
||||
workflow.coverMediaPath;
|
||||
|
||||
const response = await fetchApi("/workspace/file/save", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
@@ -143,12 +148,8 @@ export namespace TwowaySyncAPI {
|
||||
console.error("Error deleting file:", error);
|
||||
}
|
||||
}
|
||||
export async function createWorkflow({
|
||||
parentFolderID,
|
||||
name,
|
||||
json,
|
||||
id,
|
||||
}: Workflow) {
|
||||
export async function createWorkflow(workflow: Workflow) {
|
||||
const { parentFolderID, name, json, id } = workflow;
|
||||
let jsonObj: any = JSON.parse(json);
|
||||
if (jsonObj.extra == null) {
|
||||
jsonObj.extra = {};
|
||||
@@ -157,6 +158,10 @@ export namespace TwowaySyncAPI {
|
||||
jsonObj.extra[COMFYSPACE_TRACKING_FIELD_NAME] = {};
|
||||
}
|
||||
jsonObj.extra[COMFYSPACE_TRACKING_FIELD_NAME].id = id; // to avoid overwriting deps
|
||||
jsonObj.extra[COMFYSPACE_TRACKING_FIELD_NAME].saveLock = workflow.saveLock;
|
||||
jsonObj.extra[COMFYSPACE_TRACKING_FIELD_NAME].cloudID = workflow.cloudID;
|
||||
jsonObj.extra[COMFYSPACE_TRACKING_FIELD_NAME].coverMediaPath =
|
||||
workflow.coverMediaPath;
|
||||
const input: { parentFolderPath: string; name: string; json: string } = {
|
||||
parentFolderPath: sanitizeRelPath(parentFolderID ?? ""),
|
||||
name: name,
|
||||
@@ -188,18 +193,26 @@ export namespace TwowaySyncAPI {
|
||||
}
|
||||
}
|
||||
export async function getFile({
|
||||
parentFolderID,
|
||||
name,
|
||||
relPath,
|
||||
id,
|
||||
}: {
|
||||
parentFolderID: string | null;
|
||||
relPath: string;
|
||||
id: string;
|
||||
name: string;
|
||||
}): Promise<{
|
||||
json?: Object;
|
||||
json?: {
|
||||
extra: {
|
||||
[COMFYSPACE_TRACKING_FIELD_NAME]: {
|
||||
id: string;
|
||||
saveLock: boolean;
|
||||
cloudID: string | null;
|
||||
coverMediaPath: string | null;
|
||||
};
|
||||
};
|
||||
};
|
||||
createTime?: number;
|
||||
updateTime?: number;
|
||||
error?: string;
|
||||
}> {
|
||||
const relPath = joinRelPath(parentFolderID ?? "", name + ".json");
|
||||
try {
|
||||
const response = await fetchApi("/workspace/get_workflow_file", {
|
||||
method: "POST",
|
||||
@@ -236,6 +249,9 @@ export type ScanLocalFile = {
|
||||
name: string;
|
||||
id: string;
|
||||
json: string;
|
||||
saveLock: boolean;
|
||||
cloudID: string | null;
|
||||
coverMediaPath: string | null;
|
||||
createTime: number;
|
||||
updateTime: number;
|
||||
lastOpenedTime?: number;
|
||||
|
||||
@@ -21,6 +21,7 @@ import { COMFYSPACE_TRACKING_FIELD_NAME } from "../const";
|
||||
export class WorkflowsTable extends TableBase<Workflow> {
|
||||
static readonly TABLE_NAME = "workflows";
|
||||
private _curWorkflow: Workflow | null = null;
|
||||
workflowIDPathMap: Record<string, string> = {};
|
||||
public get curWorkflow() {
|
||||
return this._curWorkflow;
|
||||
}
|
||||
@@ -60,20 +61,8 @@ export class WorkflowsTable extends TableBase<Workflow> {
|
||||
return true;
|
||||
}
|
||||
|
||||
public async listByIndex(
|
||||
index: keyof Workflow,
|
||||
value: string,
|
||||
): Promise<Workflow[]> {
|
||||
const list = await super.listByIndex(index, value);
|
||||
const twoWaySyncEnabled = await userSettingsTable?.getSetting("twoWaySync");
|
||||
if (!twoWaySyncEnabled) {
|
||||
return list;
|
||||
}
|
||||
// for two way sync we need to varify if it really exists in disk
|
||||
const results = await Promise.all(
|
||||
list.map(async (f) => await this.get(f.id)),
|
||||
);
|
||||
return results.filter((f) => f != null) as Workflow[];
|
||||
public async listByIndex(): Promise<Workflow[]> {
|
||||
throw new Error("Method not allowed.");
|
||||
}
|
||||
|
||||
async generateUniqueName(name?: string, parentFolderID?: string) {
|
||||
@@ -131,8 +120,6 @@ export class WorkflowsTable extends TableBase<Workflow> {
|
||||
};
|
||||
//add to IndexDB
|
||||
await indexdb.workflows.add(newWorkflow);
|
||||
// add to disk file db
|
||||
this.saveDiskDB();
|
||||
// add to my_workflows/
|
||||
const twoWaySyncEnabled = await userSettingsTable?.getSetting("twoWaySync");
|
||||
if (twoWaySyncEnabled) {
|
||||
@@ -143,20 +130,10 @@ export class WorkflowsTable extends TableBase<Workflow> {
|
||||
}
|
||||
|
||||
// disallow TableBase.update()
|
||||
async update(
|
||||
_id: string,
|
||||
_change: Partial<Workflow>,
|
||||
): Promise<Workflow | null> {
|
||||
async update(): Promise<Workflow | null> {
|
||||
throw new Error("Method not allowed.");
|
||||
}
|
||||
|
||||
public async updateTopFields(
|
||||
id: string,
|
||||
change: Pick<Partial<Workflow>, "topFieldsConfig">,
|
||||
): Promise<Workflow | null> {
|
||||
return this._update(id, change);
|
||||
}
|
||||
|
||||
public async updateMetaInfo(
|
||||
id: string,
|
||||
change: Omit<Partial<Workflow>, "id" | "name" | "parentFolderID" | "json">,
|
||||
@@ -167,26 +144,33 @@ export class WorkflowsTable extends TableBase<Workflow> {
|
||||
id: string,
|
||||
change: Partial<Workflow>,
|
||||
): Promise<Workflow | null> {
|
||||
//update indexdb
|
||||
await indexdb.workflows.update(id, change);
|
||||
const newWorkflow = (await indexdb.workflows.get(id)) ?? null;
|
||||
const cur = await this.get(id);
|
||||
if (!cur) {
|
||||
return null;
|
||||
}
|
||||
const newWorkflow = {
|
||||
...cur,
|
||||
...change,
|
||||
};
|
||||
await TwowaySyncAPI.saveWorkflow(newWorkflow);
|
||||
|
||||
//update curWorkflow RAM
|
||||
if (this._curWorkflow && this._curWorkflow.id === id) {
|
||||
this._curWorkflow = newWorkflow;
|
||||
}
|
||||
this.saveDiskDB();
|
||||
return newWorkflow;
|
||||
}
|
||||
|
||||
async updateFolder(id: string, change: Pick<Workflow, "parentFolderID">) {
|
||||
const twoWaySyncEnabled = await userSettingsTable?.getSetting("twoWaySync");
|
||||
const oldWorkflow = await this.get(id);
|
||||
const newWorkflow = await this.updateMetaInfo(id, change as any);
|
||||
if (!newWorkflow || !oldWorkflow) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (twoWaySyncEnabled) {
|
||||
await TwowaySyncAPI.moveWorkflow(oldWorkflow, change.parentFolderID!);
|
||||
const relPath = this.workflowIDPathMap[id];
|
||||
if (!relPath) {
|
||||
alert("Error: workflow not found. Cannot move workflow.");
|
||||
return;
|
||||
}
|
||||
await TwowaySyncAPI.moveWorkflow(relPath, change.parentFolderID!);
|
||||
}
|
||||
}
|
||||
public async genLastManualSavedJson(id: string) {
|
||||
@@ -194,25 +178,31 @@ export class WorkflowsTable extends TableBase<Workflow> {
|
||||
return changelog?.json;
|
||||
}
|
||||
public async updateName(id: string, change: Pick<Workflow, "name">) {
|
||||
const before = await this.get(id);
|
||||
const path = this.workflowIDPathMap[id];
|
||||
if (!path) {
|
||||
alert("Error: workflow not found. Cannot rename workflow.");
|
||||
return;
|
||||
}
|
||||
const twoWaySyncEnabled = await userSettingsTable?.getSetting("twoWaySync");
|
||||
if (twoWaySyncEnabled) {
|
||||
before &&
|
||||
(await TwowaySyncAPI.renameWorkflow(before, change.name + ".json"));
|
||||
const success = await TwowaySyncAPI.renameWorkflow(
|
||||
{
|
||||
relPath: path,
|
||||
id: id,
|
||||
},
|
||||
change.name + ".json",
|
||||
);
|
||||
if (success) {
|
||||
this.workflowIDPathMap[id] =
|
||||
`${path.split("/").slice(0, -1).join("/")}/${change.name}.json`
|
||||
.split("/")
|
||||
.filter((part) => part !== "")
|
||||
.join("/");
|
||||
}
|
||||
}
|
||||
return await this.updateMetaInfo(id, change as any);
|
||||
}
|
||||
public async updateFlow(id: string, input: Pick<Workflow, "json">) {
|
||||
const before = await this.get(id, false);
|
||||
if (before == null) {
|
||||
return;
|
||||
}
|
||||
const beforeStr = JSON.stringify(before.json);
|
||||
const afterStr = JSON.stringify(input.json);
|
||||
if (beforeStr === afterStr) {
|
||||
// no change detected
|
||||
return;
|
||||
}
|
||||
const after = await this._update(id, {
|
||||
updateTime: Date.now(),
|
||||
json: input.json,
|
||||
@@ -275,17 +265,10 @@ export class WorkflowsTable extends TableBase<Workflow> {
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
await indexdb.workflows.bulkAdd(newWorkflows);
|
||||
this.saveDiskDB();
|
||||
} catch (e) {
|
||||
console.error("batchCreateFlows error", e);
|
||||
}
|
||||
}
|
||||
|
||||
public async deleteFlow(id: string) {
|
||||
const workflow = await this.get(id);
|
||||
|
||||
if (workflow) {
|
||||
const twoWaySyncEnabled =
|
||||
await userSettingsTable?.getSetting("twoWaySync");
|
||||
@@ -293,9 +276,6 @@ export class WorkflowsTable extends TableBase<Workflow> {
|
||||
await TwowaySyncAPI.deleteWorkflow(workflow);
|
||||
}
|
||||
}
|
||||
//add to IndexDB
|
||||
await indexdb.workflows.delete(id);
|
||||
this.saveDiskDB();
|
||||
}
|
||||
|
||||
public async batchDeleteFlow(ids: string[]) {
|
||||
@@ -308,8 +288,6 @@ export class WorkflowsTable extends TableBase<Workflow> {
|
||||
await TwowaySyncAPI.deleteWorkflow(flow);
|
||||
}
|
||||
}
|
||||
await indexdb.workflows.bulkDelete(ids);
|
||||
this.saveDiskDB();
|
||||
}
|
||||
|
||||
public async listFolderContent(
|
||||
@@ -339,28 +317,55 @@ export class WorkflowsTable extends TableBase<Workflow> {
|
||||
public async get(
|
||||
id: string,
|
||||
fetchJsonContentOnDisk = true, //if false, only get the meta info from indexdb
|
||||
): Promise<Workflow | undefined> {
|
||||
): Promise<
|
||||
| {
|
||||
id: string;
|
||||
name: string;
|
||||
parentFolderID?: string | null;
|
||||
saveLock?: boolean;
|
||||
cloudID?: string | null;
|
||||
coverMediaPath?: string | null;
|
||||
json: string;
|
||||
updateTime: number;
|
||||
createTime: number;
|
||||
}
|
||||
| undefined
|
||||
> {
|
||||
const twoWaySyncEnabled = await userSettingsTable?.getSetting("twoWaySync");
|
||||
const wf = await indexdb.workflows.get(id);
|
||||
if (!twoWaySyncEnabled || !fetchJsonContentOnDisk) {
|
||||
return wf;
|
||||
if (!twoWaySyncEnabled) {
|
||||
return await indexdb.workflows.get(id);
|
||||
}
|
||||
// two way sync mode
|
||||
if (wf == null) {
|
||||
const rel = this.workflowIDPathMap[id];
|
||||
if (!rel) {
|
||||
return undefined;
|
||||
}
|
||||
const data = await TwowaySyncAPI.getFile({
|
||||
parentFolderID: wf.parentFolderID ?? null,
|
||||
name: wf.name,
|
||||
id: wf.id,
|
||||
relPath: rel,
|
||||
id: id,
|
||||
});
|
||||
|
||||
if (!data.json) {
|
||||
return undefined;
|
||||
}
|
||||
const workspaceInfo = data.json?.extra?.[COMFYSPACE_TRACKING_FIELD_NAME];
|
||||
if (!workspaceInfo || workspaceInfo.id !== id) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
...wf,
|
||||
id: workspaceInfo.id,
|
||||
name:
|
||||
rel
|
||||
.split("/")
|
||||
.pop()
|
||||
?.replace(/\.json$/, "") ?? "Untitled Flow",
|
||||
parentFolderID: rel.split("/").slice(0, -1).join("/"),
|
||||
saveLock: workspaceInfo.saveLock,
|
||||
cloudID: workspaceInfo.cloudID,
|
||||
coverMediaPath: workspaceInfo.coverMediaPath,
|
||||
json: JSON.stringify(data.json),
|
||||
updateTime: data.updateTime ?? Date.now(),
|
||||
createTime: data.createTime ?? Date.now(),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -63,18 +63,6 @@ export default function MetadataForm({ media }: { media: Media | null }) {
|
||||
|
||||
const [topFields, setTopFields] = useState<TopFieldType[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (curFlowID) {
|
||||
const topFieldsConfig = (await workflowsTable?.get(curFlowID))
|
||||
?.topFieldsConfig;
|
||||
if (topFieldsConfig) {
|
||||
setTopFields(topFieldsConfig);
|
||||
setShowAllInputs(false);
|
||||
}
|
||||
}
|
||||
})();
|
||||
}, [curFlowID]);
|
||||
const updateTopField = (field: TopFieldType) => {
|
||||
if (
|
||||
isInTopField(topFields, {
|
||||
@@ -87,19 +75,9 @@ export default function MetadataForm({ media }: { media: Media | null }) {
|
||||
(v) => v.name !== field.name || v.promptKey !== field.promptKey,
|
||||
);
|
||||
setTopFields(topFieldsConfig);
|
||||
if (curFlowID) {
|
||||
workflowsTable?.updateTopFields(curFlowID, {
|
||||
topFieldsConfig,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const topFieldsConfig = [...topFields, field];
|
||||
setTopFields(topFieldsConfig);
|
||||
if (curFlowID) {
|
||||
workflowsTable?.updateTopFields(curFlowID, {
|
||||
topFieldsConfig,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ export default function ServerEventListener() {
|
||||
name: version.name,
|
||||
authorID: version.authorID,
|
||||
json: version.json,
|
||||
api_prompt: null,
|
||||
});
|
||||
newversion && loadWorkflowID(existingWorkflow.id, newversion.id);
|
||||
}
|
||||
@@ -56,6 +57,7 @@ export default function ServerEventListener() {
|
||||
name: version.name,
|
||||
json: version.json,
|
||||
authorID: version.authorID,
|
||||
api_prompt: null,
|
||||
createTime: Date.now(),
|
||||
});
|
||||
await loadWorkflowID(newWorkflow.id, newverison?.id);
|
||||
|
||||
@@ -11,14 +11,16 @@ export interface Workflow extends SortableItem {
|
||||
id: string;
|
||||
json: string;
|
||||
name: string;
|
||||
coverMediaPath?: string | null;
|
||||
saveLock?: boolean;
|
||||
cloudID?: string | null;
|
||||
createTime: number;
|
||||
|
||||
// will be deprecated
|
||||
privacy?: WorkflowPrivacy;
|
||||
tags?: string[];
|
||||
parentFolderID?: string | null; //TODO remove undefined, use null only
|
||||
coverMediaPath?: string;
|
||||
cloudID?: string; // TODO will be deprecated
|
||||
cloudOrigin?: string;
|
||||
saveLock?: boolean;
|
||||
latestImage?: string;
|
||||
topFieldsConfig?: TopFieldType[];
|
||||
}
|
||||
@@ -65,7 +67,7 @@ export type WorkflowVersion = {
|
||||
workflowID: string;
|
||||
json: string;
|
||||
createTime: number;
|
||||
api_prompt: string;
|
||||
api_prompt: string | null;
|
||||
cloudID?: string;
|
||||
cloudOrigin?: string;
|
||||
authorID?: string;
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
ScanLocalFolder,
|
||||
scanLocalFiles,
|
||||
} from "../apis/TwowaySyncApi";
|
||||
import { isFolder } from "../db-tables/WorkspaceDB";
|
||||
import { isFolder, workflowsTable } from "../db-tables/WorkspaceDB";
|
||||
import { indexdb } from "../db-tables/indexdb";
|
||||
import { Folder, Workflow } from "../types/dbTypes";
|
||||
import { sortFileItem } from "../utils";
|
||||
@@ -34,27 +34,33 @@ export async function scanMyWorkflowsDir(
|
||||
return folder;
|
||||
} else {
|
||||
// is workflow
|
||||
// const existingWorkflow = (await indexdb.workflows
|
||||
// ?.get(file.id)
|
||||
// .catch((err) => {
|
||||
// console.error("Error getting workflow from indexdb", err);
|
||||
// return null;
|
||||
// })) ?? {
|
||||
// createTime: Date.now(),
|
||||
// updateTime: Date.now(),
|
||||
// };
|
||||
|
||||
const existingWorkflow = (await indexdb.workflows
|
||||
?.get(file.id)
|
||||
.catch((err) => {
|
||||
console.error("Error getting workflow from indexdb", err);
|
||||
return null;
|
||||
})) ?? {
|
||||
createTime: Date.now(),
|
||||
updateTime: Date.now(),
|
||||
};
|
||||
if (workflowsTable) {
|
||||
workflowsTable.workflowIDPathMap[file.id] = relPath;
|
||||
}
|
||||
|
||||
const newWorkflow: Workflow = {
|
||||
...existingWorkflow,
|
||||
// ...existingWorkflow,
|
||||
id: file.id,
|
||||
json: file.json ?? "{}",
|
||||
cloudID: file.cloudID,
|
||||
coverMediaPath: file.coverMediaPath,
|
||||
saveLock: file.saveLock,
|
||||
name: fileName.replace(/\.json$/, ""),
|
||||
parentFolderID: parentRelPath,
|
||||
createTime: file.createTime,
|
||||
// setting updateTime will result latestVersionChcek() always fail if in
|
||||
// workflow.get() not pull updateTime from file
|
||||
// updateTime: file.updateTime,
|
||||
updateTime: file.updateTime,
|
||||
};
|
||||
return newWorkflow;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user