Skip to content

Commit

Permalink
New Menu & Workflow Management (comfyanonymous#3112)
Browse files Browse the repository at this point in the history
* menu

* wip

* wip

* wip

* wip

* wip

* workflow saving/loading

* Support inserting workflows
Move buttosn to top of lists

* fix session storage
implement renaming

* temp

* refactor, better workflow instance management

* wip

* progress on progress

* added send to workflow
various fixes

* Support multiple image loaders

* Support dynamic size breakpoints based on content

* various fixes
add close unsaved warning

* Add filtering tree

* prevent renaming unsaved

* fix zindex on hover

* fix top offset

* use filename as workflow name

* resize on setting change

* hide element until it is drawn

* remove glow

* Fix export name

* Fix test, revert accidental changes to groupNode

* Fix colors on all themes

* show hover items on smaller screen (mobile)

* remove debugging code

* dialog fix

* Dont reorder open workflows
Allow elements around canvas

* Toggle body display on setting change

* Fix menu disappearing on chrome

* Increase delay when typing, remove margin on Safari, fix dialog location

* Fix overflow issue on iOS

* Add reset view button
Prevent view changes causing history entries

* Bottom menu wip

* Various fixes

* Fix merge

* Fix breaking old menu position

* Fix merge adding restore view to loadGraphData
  • Loading branch information
pythongosssss authored Jun 25, 2024
1 parent eab211b commit 90aebb6
Show file tree
Hide file tree
Showing 35 changed files with 3,986 additions and 312 deletions.
91 changes: 78 additions & 13 deletions app/user_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import os
import re
import uuid
import glob
import shutil
from aiohttp import web
from comfy.cli_args import args
from folder_paths import user_directory
Expand Down Expand Up @@ -56,16 +58,16 @@ def get_request_user_filepath(self, request, file, type="userdata", create_dir=T
if os.path.commonpath((root_dir, user_root)) != root_dir:
return None

parent = user_root

if file is not None:
# prevent leaving /{type}/{user}
path = os.path.abspath(os.path.join(user_root, file))
if os.path.commonpath((user_root, path)) != user_root:
return None

parent = os.path.split(path)[0]

if create_dir and not os.path.exists(parent):
os.mkdir(parent)
os.makedirs(parent, exist_ok=True)

return path

Expand Down Expand Up @@ -108,33 +110,96 @@ async def post_users(request):
user_id = self.add_user(username)
return web.json_response(user_id)

@routes.get("/userdata/{file}")
async def getuserdata(request):
file = request.match_info.get("file", None)
if not file:
@routes.get("/userdata")
async def listuserdata(request):
directory = request.rel_url.query.get('dir', '')
if not directory:
return web.Response(status=400)

path = self.get_request_user_filepath(request, file)
path = self.get_request_user_filepath(request, directory)
if not path:
return web.Response(status=403)

if not os.path.exists(path):
return web.Response(status=404)

return web.FileResponse(path)
recurse = request.rel_url.query.get('recurse', '').lower() == "true"
results = glob.glob(os.path.join(
glob.escape(path), '**/*'), recursive=recurse)
results = [os.path.relpath(x, path) for x in results if os.path.isfile(x)]

split_path = request.rel_url.query.get('split', '').lower() == "true"
if split_path:
results = [[x] + x.split(os.sep) for x in results]

@routes.post("/userdata/{file}")
async def post_userdata(request):
file = request.match_info.get("file", None)
return web.json_response(results)

def get_user_data_path(request, check_exists = False, param = "file"):
file = request.match_info.get(param, None)
if not file:
return web.Response(status=400)

path = self.get_request_user_filepath(request, file)
if not path:
return web.Response(status=403)

if check_exists and not os.path.exists(path):
return web.Response(status=404)

return path

@routes.get("/userdata/{file}")
async def getuserdata(request):
path = get_user_data_path(request, check_exists=True)
if not isinstance(path, str):
return path

return web.FileResponse(path)

@routes.post("/userdata/{file}")
async def post_userdata(request):
path = get_user_data_path(request)
if not isinstance(path, str):
return path

overwrite = request.query["overwrite"] != "false"
if not overwrite and os.path.exists(path):
return web.Response(status=409)

body = await request.read()

with open(path, "wb") as f:
f.write(body)

return web.Response(status=200)
resp = os.path.relpath(path, self.get_request_user_filepath(request, None))
return web.json_response(resp)

@routes.delete("/userdata/{file}")
async def delete_userdata(request):
path = get_user_data_path(request, check_exists=True)
if not isinstance(path, str):
return path

os.remove(path)

return web.Response(status=204)

@routes.post("/userdata/{file}/move/{dest}")
async def move_userdata(request):
source = get_user_data_path(request, check_exists=True)
if not isinstance(source, str):
return source

dest = get_user_data_path(request, check_exists=False, param="dest")
if not isinstance(source, str):
return dest

overwrite = request.query["overwrite"] != "false"
if not overwrite and os.path.exists(dest):
return web.Response(status=409)

print(f"moving '{source}' -> '{dest}'")
shutil.move(source, dest)

resp = os.path.relpath(dest, self.get_request_user_filepath(request, None))
return web.json_response(resp)
1 change: 1 addition & 0 deletions tests-ui/utils/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export function mockApi(config = {}) {
storeUserData: jest.fn((file, data) => {
userData[file] = data;
}),
listUserData: jest.fn(() => [])
};
jest.mock("../../web/scripts/api", () => ({
get api() {
Expand Down
30 changes: 27 additions & 3 deletions web/extensions/core/colorPalette.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ const colorPalettes = {
"border-color": "#4e4e4e",
"tr-even-bg-color": "#222",
"tr-odd-bg-color": "#353535",
"content-bg": "#4e4e4e",
"content-fg": "#fff",
"content-hover-bg": "#222",
"content-hover-fg": "#fff"
}
},
},
Expand Down Expand Up @@ -120,6 +124,10 @@ const colorPalettes = {
"border-color": "#888",
"tr-even-bg-color": "#f9f9f9",
"tr-odd-bg-color": "#fff",
"content-bg": "#e0e0e0",
"content-fg": "#222",
"content-hover-bg": "#adadad",
"content-hover-fg": "#222"
}
},
},
Expand Down Expand Up @@ -176,6 +184,10 @@ const colorPalettes = {
"border-color": "#657b83", // Base00
"tr-even-bg-color": "#002b36",
"tr-odd-bg-color": "#073642",
"content-bg": "#657b83",
"content-fg": "#fdf6e3",
"content-hover-bg": "#002b36",
"content-hover-fg": "#fdf6e3"
}
},
},
Expand Down Expand Up @@ -244,7 +256,11 @@ const colorPalettes = {
"error-text": "#ff4444",
"border-color": "#6e7581",
"tr-even-bg-color": "#2b2f38",
"tr-odd-bg-color": "#242730"
"tr-odd-bg-color": "#242730",
"content-bg": "#6e7581",
"content-fg": "#fff",
"content-hover-bg": "#2b2f38",
"content-hover-fg": "#fff"
}
},
},
Expand Down Expand Up @@ -313,7 +329,11 @@ const colorPalettes = {
"error-text": "#ff4444",
"border-color": "#545d70",
"tr-even-bg-color": "#2e3440",
"tr-odd-bg-color": "#161b22"
"tr-odd-bg-color": "#161b22",
"content-bg": "#545d70",
"content-fg": "#e5eaf0",
"content-hover-bg": "#2e3440",
"content-hover-fg": "#e5eaf0"
}
},
},
Expand Down Expand Up @@ -382,7 +402,11 @@ const colorPalettes = {
"error-text": "#ff4444",
"border-color": "#30363d",
"tr-even-bg-color": "#161b22",
"tr-odd-bg-color": "#13171d"
"tr-odd-bg-color": "#13171d",
"content-bg": "#30363d",
"content-fg": "#e5eaf0",
"content-hover-bg": "#161b22",
"content-hover-fg": "#e5eaf0"
}
},
}
Expand Down
2 changes: 1 addition & 1 deletion web/extensions/core/groupNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -1278,4 +1278,4 @@ const ext = {
}
};

app.registerExtension(ext);
app.registerExtension(ext);
Loading

0 comments on commit 90aebb6

Please sign in to comment.