mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 19:23:42 +08:00
fix(ui/workflows): rework editor layout, free property panel, slim route chunk
This commit is contained in:
parent
32507d2157
commit
4aad813f2d
6
.gitignore
vendored
6
.gitignore
vendored
@ -29,6 +29,12 @@ nbbuild/
|
|||||||
nbdist/
|
nbdist/
|
||||||
.nb-gradle/
|
.nb-gradle/
|
||||||
|
|
||||||
|
### frontend build artifacts ###
|
||||||
|
# Vite's primary output goes to mateclaw-server/.../static; the only thing
|
||||||
|
# that lands here is rollup-plugin-visualizer's stats.html when running
|
||||||
|
# ANALYZE=1 pnpm build.
|
||||||
|
mateclaw-ui/dist/
|
||||||
|
|
||||||
### maven ###
|
### maven ###
|
||||||
target/
|
target/
|
||||||
*.war
|
*.war
|
||||||
|
|||||||
@ -18,6 +18,11 @@ RUN pnpm install --frozen-lockfile
|
|||||||
COPY mateclaw-ui/ ./
|
COPY mateclaw-ui/ ./
|
||||||
# Override outDir: vite.config.ts writes to ../mateclaw-server/…/static which
|
# Override outDir: vite.config.ts writes to ../mateclaw-server/…/static which
|
||||||
# is outside this container; call vite directly to control --outDir.
|
# is outside this container; call vite directly to control --outDir.
|
||||||
|
# The earlier escape hatch (NODE_OPTIONS=--max-old-space-size=6144) was
|
||||||
|
# retired after the workflow route adopted precise Monaco imports + async
|
||||||
|
# component loading + named manualChunks; the single-chunk peak now sits
|
||||||
|
# below ~1 GB so the default Node heap is enough. Re-add the flag if a
|
||||||
|
# future feature reintroduces a 4 MB+ chunk and the build OOMs.
|
||||||
# Skipping vue-tsc here is intentional — type errors are caught in CI, not in
|
# Skipping vue-tsc here is intentional — type errors are caught in CI, not in
|
||||||
# the production Docker image build.
|
# the production Docker image build.
|
||||||
RUN pnpm exec vite build --outDir /static --emptyOutDir
|
RUN pnpm exec vite build --outDir /static --emptyOutDir
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
"description": "MateClaw - Personal AI Assistant Web Console",
|
"description": "MateClaw - Personal AI Assistant Web Console",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "node --max-old-space-size=6144 ./node_modules/vue-tsc/bin/vue-tsc.js && node --max-old-space-size=6144 ./node_modules/vite/bin/vite.js build",
|
"build": "vue-tsc --noEmit && vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"lint": "eslint src --ext .ts,.vue --fix"
|
"lint": "eslint src --ext .ts,.vue --fix"
|
||||||
},
|
},
|
||||||
@ -47,6 +47,7 @@
|
|||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
"eslint-plugin-vue": "^9.32.0",
|
"eslint-plugin-vue": "^9.32.0",
|
||||||
|
"rollup-plugin-visualizer": "^7.0.1",
|
||||||
"tailwindcss": "^4.0.6",
|
"tailwindcss": "^4.0.6",
|
||||||
"typescript": "~5.7.2",
|
"typescript": "~5.7.2",
|
||||||
"vite": "^7.3.1",
|
"vite": "^7.3.1",
|
||||||
|
|||||||
216
mateclaw-ui/pnpm-lock.yaml
generated
216
mateclaw-ui/pnpm-lock.yaml
generated
@ -111,6 +111,9 @@ importers:
|
|||||||
eslint-plugin-vue:
|
eslint-plugin-vue:
|
||||||
specifier: ^9.32.0
|
specifier: ^9.32.0
|
||||||
version: 9.33.0(eslint@9.39.4(jiti@2.6.1))
|
version: 9.33.0(eslint@9.39.4(jiti@2.6.1))
|
||||||
|
rollup-plugin-visualizer:
|
||||||
|
specifier: ^7.0.1
|
||||||
|
version: 7.0.1(rollup@4.60.1)
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^4.0.6
|
specifier: ^4.0.6
|
||||||
version: 4.2.2
|
version: 4.2.2
|
||||||
@ -948,10 +951,18 @@ packages:
|
|||||||
alien-signals@3.1.2:
|
alien-signals@3.1.2:
|
||||||
resolution: {integrity: sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw==}
|
resolution: {integrity: sha512-d9dYqZTS90WLiU0I5c6DHj/HcKkF8ZyGN3G5x8wSbslulz70KOxaqCT0hQCo9KOyhVqzqGojvNdJXoTumZOtcw==}
|
||||||
|
|
||||||
|
ansi-regex@6.2.2:
|
||||||
|
resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
ansi-styles@4.3.0:
|
ansi-styles@4.3.0:
|
||||||
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
ansi-styles@6.2.3:
|
||||||
|
resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
argparse@2.0.1:
|
argparse@2.0.1:
|
||||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||||
|
|
||||||
@ -993,6 +1004,10 @@ packages:
|
|||||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
bundle-name@4.1.0:
|
||||||
|
resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
call-bind-apply-helpers@1.0.2:
|
call-bind-apply-helpers@1.0.2:
|
||||||
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@ -1017,6 +1032,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ==}
|
resolution: {integrity: sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ==}
|
||||||
engines: {node: '>=22.0.0'}
|
engines: {node: '>=22.0.0'}
|
||||||
|
|
||||||
|
cliui@9.0.1:
|
||||||
|
resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
color-convert@2.0.1:
|
color-convert@2.0.1:
|
||||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||||
engines: {node: '>=7.0.0'}
|
engines: {node: '>=7.0.0'}
|
||||||
@ -1238,6 +1257,18 @@ packages:
|
|||||||
deep-is@0.1.4:
|
deep-is@0.1.4:
|
||||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||||
|
|
||||||
|
default-browser-id@5.0.1:
|
||||||
|
resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
default-browser@5.5.0:
|
||||||
|
resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
define-lazy-prop@3.0.0:
|
||||||
|
resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
delaunator@5.1.0:
|
delaunator@5.1.0:
|
||||||
resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==}
|
resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==}
|
||||||
|
|
||||||
@ -1270,6 +1301,9 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
vue: ^3.3.0
|
vue: ^3.3.0
|
||||||
|
|
||||||
|
emoji-regex@10.6.0:
|
||||||
|
resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==}
|
||||||
|
|
||||||
enhanced-resolve@5.20.1:
|
enhanced-resolve@5.20.1:
|
||||||
resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==}
|
resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==}
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
@ -1423,6 +1457,14 @@ packages:
|
|||||||
function-bind@1.1.2:
|
function-bind@1.1.2:
|
||||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||||
|
|
||||||
|
get-caller-file@2.0.5:
|
||||||
|
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
||||||
|
engines: {node: 6.* || 8.* || >= 10.*}
|
||||||
|
|
||||||
|
get-east-asian-width@1.6.0:
|
||||||
|
resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
get-intrinsic@1.3.0:
|
get-intrinsic@1.3.0:
|
||||||
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
|
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@ -1505,6 +1547,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
|
resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
is-docker@3.0.0:
|
||||||
|
resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
|
||||||
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
is-extglob@2.1.1:
|
is-extglob@2.1.1:
|
||||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -1513,6 +1560,15 @@ packages:
|
|||||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
is-in-ssh@1.0.0:
|
||||||
|
resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
|
is-inside-container@1.0.0:
|
||||||
|
resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
|
||||||
|
engines: {node: '>=14.16'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
is-promise@2.2.2:
|
is-promise@2.2.2:
|
||||||
resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==}
|
resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==}
|
||||||
|
|
||||||
@ -1520,6 +1576,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==}
|
resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
is-wsl@3.1.1:
|
||||||
|
resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==}
|
||||||
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
isexe@2.0.0:
|
isexe@2.0.0:
|
||||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||||
|
|
||||||
@ -1746,6 +1806,10 @@ packages:
|
|||||||
nth-check@2.1.1:
|
nth-check@2.1.1:
|
||||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||||
|
|
||||||
|
open@11.0.0:
|
||||||
|
resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@ -1827,6 +1891,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==}
|
resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==}
|
||||||
engines: {node: ^10 || ^12 || >=14}
|
engines: {node: ^10 || ^12 || >=14}
|
||||||
|
|
||||||
|
powershell-utils@0.1.0:
|
||||||
|
resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
prelude-ls@1.2.1:
|
prelude-ls@1.2.1:
|
||||||
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@ -1856,6 +1924,19 @@ packages:
|
|||||||
robust-predicates@3.0.3:
|
robust-predicates@3.0.3:
|
||||||
resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==}
|
resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==}
|
||||||
|
|
||||||
|
rollup-plugin-visualizer@7.0.1:
|
||||||
|
resolution: {integrity: sha512-UJUT4+1Ho4OcWmPYU3sYXgUqI8B8Ayfe06MX7y0qCJ1K8aGoKtR/NDd/2nZqM7ADkrzny+I99Ul7GgyoiVNAgg==}
|
||||||
|
engines: {node: '>=22'}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
rolldown: 1.x || ^1.0.0-beta || ^1.0.0-rc
|
||||||
|
rollup: 2.x || 3.x || 4.x
|
||||||
|
peerDependenciesMeta:
|
||||||
|
rolldown:
|
||||||
|
optional: true
|
||||||
|
rollup:
|
||||||
|
optional: true
|
||||||
|
|
||||||
rollup@4.60.1:
|
rollup@4.60.1:
|
||||||
resolution: {integrity: sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==}
|
resolution: {integrity: sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==}
|
||||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||||
@ -1864,6 +1945,10 @@ packages:
|
|||||||
roughjs@4.6.6:
|
roughjs@4.6.6:
|
||||||
resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==}
|
resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==}
|
||||||
|
|
||||||
|
run-applescript@7.1.0:
|
||||||
|
resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
rw@1.3.3:
|
rw@1.3.3:
|
||||||
resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
|
resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
|
||||||
|
|
||||||
@ -1887,6 +1972,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
source-map@0.7.6:
|
||||||
|
resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
|
||||||
|
engines: {node: '>= 12'}
|
||||||
|
|
||||||
speakingurl@14.0.1:
|
speakingurl@14.0.1:
|
||||||
resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
|
resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@ -1894,6 +1983,14 @@ packages:
|
|||||||
state-local@1.0.7:
|
state-local@1.0.7:
|
||||||
resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==}
|
resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==}
|
||||||
|
|
||||||
|
string-width@7.2.0:
|
||||||
|
resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
strip-ansi@7.2.0:
|
||||||
|
resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
strip-json-comments@3.1.1:
|
strip-json-comments@3.1.1:
|
||||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@ -2080,10 +2177,30 @@ packages:
|
|||||||
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
wrap-ansi@9.0.2:
|
||||||
|
resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
wsl-utils@0.3.1:
|
||||||
|
resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
xml-name-validator@4.0.0:
|
xml-name-validator@4.0.0:
|
||||||
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
|
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
|
y18n@5.0.8:
|
||||||
|
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
yargs-parser@22.0.0:
|
||||||
|
resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==}
|
||||||
|
engines: {node: ^20.19.0 || ^22.12.0 || >=23}
|
||||||
|
|
||||||
|
yargs@18.0.0:
|
||||||
|
resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==}
|
||||||
|
engines: {node: ^20.19.0 || ^22.12.0 || >=23}
|
||||||
|
|
||||||
yocto-queue@0.1.0:
|
yocto-queue@0.1.0:
|
||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -2826,10 +2943,14 @@ snapshots:
|
|||||||
|
|
||||||
alien-signals@3.1.2: {}
|
alien-signals@3.1.2: {}
|
||||||
|
|
||||||
|
ansi-regex@6.2.2: {}
|
||||||
|
|
||||||
ansi-styles@4.3.0:
|
ansi-styles@4.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
color-convert: 2.0.1
|
color-convert: 2.0.1
|
||||||
|
|
||||||
|
ansi-styles@6.2.3: {}
|
||||||
|
|
||||||
argparse@2.0.1: {}
|
argparse@2.0.1: {}
|
||||||
|
|
||||||
async-validator@4.2.5: {}
|
async-validator@4.2.5: {}
|
||||||
@ -2874,6 +2995,10 @@ snapshots:
|
|||||||
node-releases: 2.0.37
|
node-releases: 2.0.37
|
||||||
update-browserslist-db: 1.2.3(browserslist@4.28.2)
|
update-browserslist-db: 1.2.3(browserslist@4.28.2)
|
||||||
|
|
||||||
|
bundle-name@4.1.0:
|
||||||
|
dependencies:
|
||||||
|
run-applescript: 7.1.0
|
||||||
|
|
||||||
call-bind-apply-helpers@1.0.2:
|
call-bind-apply-helpers@1.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
@ -2901,6 +3026,12 @@ snapshots:
|
|||||||
'@chevrotain/types': 12.0.0
|
'@chevrotain/types': 12.0.0
|
||||||
'@chevrotain/utils': 12.0.0
|
'@chevrotain/utils': 12.0.0
|
||||||
|
|
||||||
|
cliui@9.0.1:
|
||||||
|
dependencies:
|
||||||
|
string-width: 7.2.0
|
||||||
|
strip-ansi: 7.2.0
|
||||||
|
wrap-ansi: 9.0.2
|
||||||
|
|
||||||
color-convert@2.0.1:
|
color-convert@2.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
color-name: 1.1.4
|
color-name: 1.1.4
|
||||||
@ -3138,6 +3269,15 @@ snapshots:
|
|||||||
|
|
||||||
deep-is@0.1.4: {}
|
deep-is@0.1.4: {}
|
||||||
|
|
||||||
|
default-browser-id@5.0.1: {}
|
||||||
|
|
||||||
|
default-browser@5.5.0:
|
||||||
|
dependencies:
|
||||||
|
bundle-name: 4.1.0
|
||||||
|
default-browser-id: 5.0.1
|
||||||
|
|
||||||
|
define-lazy-prop@3.0.0: {}
|
||||||
|
|
||||||
delaunator@5.1.0:
|
delaunator@5.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
robust-predicates: 3.0.3
|
robust-predicates: 3.0.3
|
||||||
@ -3188,6 +3328,8 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
|
emoji-regex@10.6.0: {}
|
||||||
|
|
||||||
enhanced-resolve@5.20.1:
|
enhanced-resolve@5.20.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
@ -3381,6 +3523,10 @@ snapshots:
|
|||||||
|
|
||||||
function-bind@1.1.2: {}
|
function-bind@1.1.2: {}
|
||||||
|
|
||||||
|
get-caller-file@2.0.5: {}
|
||||||
|
|
||||||
|
get-east-asian-width@1.6.0: {}
|
||||||
|
|
||||||
get-intrinsic@1.3.0:
|
get-intrinsic@1.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind-apply-helpers: 1.0.2
|
call-bind-apply-helpers: 1.0.2
|
||||||
@ -3454,16 +3600,28 @@ snapshots:
|
|||||||
|
|
||||||
internmap@2.0.3: {}
|
internmap@2.0.3: {}
|
||||||
|
|
||||||
|
is-docker@3.0.0: {}
|
||||||
|
|
||||||
is-extglob@2.1.1: {}
|
is-extglob@2.1.1: {}
|
||||||
|
|
||||||
is-glob@4.0.3:
|
is-glob@4.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-extglob: 2.1.1
|
is-extglob: 2.1.1
|
||||||
|
|
||||||
|
is-in-ssh@1.0.0: {}
|
||||||
|
|
||||||
|
is-inside-container@1.0.0:
|
||||||
|
dependencies:
|
||||||
|
is-docker: 3.0.0
|
||||||
|
|
||||||
is-promise@2.2.2: {}
|
is-promise@2.2.2: {}
|
||||||
|
|
||||||
is-what@5.5.0: {}
|
is-what@5.5.0: {}
|
||||||
|
|
||||||
|
is-wsl@3.1.1:
|
||||||
|
dependencies:
|
||||||
|
is-inside-container: 1.0.0
|
||||||
|
|
||||||
isexe@2.0.0: {}
|
isexe@2.0.0: {}
|
||||||
|
|
||||||
jiti@2.6.1: {}
|
jiti@2.6.1: {}
|
||||||
@ -3673,6 +3831,15 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
boolbase: 1.0.0
|
boolbase: 1.0.0
|
||||||
|
|
||||||
|
open@11.0.0:
|
||||||
|
dependencies:
|
||||||
|
default-browser: 5.5.0
|
||||||
|
define-lazy-prop: 3.0.0
|
||||||
|
is-in-ssh: 1.0.0
|
||||||
|
is-inside-container: 1.0.0
|
||||||
|
powershell-utils: 0.1.0
|
||||||
|
wsl-utils: 0.3.1
|
||||||
|
|
||||||
optionator@0.9.4:
|
optionator@0.9.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
deep-is: 0.1.4
|
deep-is: 0.1.4
|
||||||
@ -3749,6 +3916,8 @@ snapshots:
|
|||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
source-map-js: 1.2.1
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
|
powershell-utils@0.1.0: {}
|
||||||
|
|
||||||
prelude-ls@1.2.1: {}
|
prelude-ls@1.2.1: {}
|
||||||
|
|
||||||
promise-worker-transferable@1.0.4:
|
promise-worker-transferable@1.0.4:
|
||||||
@ -3768,6 +3937,15 @@ snapshots:
|
|||||||
|
|
||||||
robust-predicates@3.0.3: {}
|
robust-predicates@3.0.3: {}
|
||||||
|
|
||||||
|
rollup-plugin-visualizer@7.0.1(rollup@4.60.1):
|
||||||
|
dependencies:
|
||||||
|
open: 11.0.0
|
||||||
|
picomatch: 4.0.4
|
||||||
|
source-map: 0.7.6
|
||||||
|
yargs: 18.0.0
|
||||||
|
optionalDependencies:
|
||||||
|
rollup: 4.60.1
|
||||||
|
|
||||||
rollup@4.60.1:
|
rollup@4.60.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/estree': 1.0.8
|
'@types/estree': 1.0.8
|
||||||
@ -3806,6 +3984,8 @@ snapshots:
|
|||||||
points-on-curve: 0.2.0
|
points-on-curve: 0.2.0
|
||||||
points-on-path: 0.2.1
|
points-on-path: 0.2.1
|
||||||
|
|
||||||
|
run-applescript@7.1.0: {}
|
||||||
|
|
||||||
rw@1.3.3: {}
|
rw@1.3.3: {}
|
||||||
|
|
||||||
safer-buffer@2.1.2: {}
|
safer-buffer@2.1.2: {}
|
||||||
@ -3820,10 +4000,22 @@ snapshots:
|
|||||||
|
|
||||||
source-map-js@1.2.1: {}
|
source-map-js@1.2.1: {}
|
||||||
|
|
||||||
|
source-map@0.7.6: {}
|
||||||
|
|
||||||
speakingurl@14.0.1: {}
|
speakingurl@14.0.1: {}
|
||||||
|
|
||||||
state-local@1.0.7: {}
|
state-local@1.0.7: {}
|
||||||
|
|
||||||
|
string-width@7.2.0:
|
||||||
|
dependencies:
|
||||||
|
emoji-regex: 10.6.0
|
||||||
|
get-east-asian-width: 1.6.0
|
||||||
|
strip-ansi: 7.2.0
|
||||||
|
|
||||||
|
strip-ansi@7.2.0:
|
||||||
|
dependencies:
|
||||||
|
ansi-regex: 6.2.2
|
||||||
|
|
||||||
strip-json-comments@3.1.1: {}
|
strip-json-comments@3.1.1: {}
|
||||||
|
|
||||||
stylis@4.4.0: {}
|
stylis@4.4.0: {}
|
||||||
@ -3960,8 +4152,32 @@ snapshots:
|
|||||||
|
|
||||||
word-wrap@1.2.5: {}
|
word-wrap@1.2.5: {}
|
||||||
|
|
||||||
|
wrap-ansi@9.0.2:
|
||||||
|
dependencies:
|
||||||
|
ansi-styles: 6.2.3
|
||||||
|
string-width: 7.2.0
|
||||||
|
strip-ansi: 7.2.0
|
||||||
|
|
||||||
|
wsl-utils@0.3.1:
|
||||||
|
dependencies:
|
||||||
|
is-wsl: 3.1.1
|
||||||
|
powershell-utils: 0.1.0
|
||||||
|
|
||||||
xml-name-validator@4.0.0: {}
|
xml-name-validator@4.0.0: {}
|
||||||
|
|
||||||
|
y18n@5.0.8: {}
|
||||||
|
|
||||||
|
yargs-parser@22.0.0: {}
|
||||||
|
|
||||||
|
yargs@18.0.0:
|
||||||
|
dependencies:
|
||||||
|
cliui: 9.0.1
|
||||||
|
escalade: 3.2.0
|
||||||
|
get-caller-file: 2.0.5
|
||||||
|
string-width: 7.2.0
|
||||||
|
y18n: 5.0.8
|
||||||
|
yargs-parser: 22.0.0
|
||||||
|
|
||||||
yocto-queue@0.1.0: {}
|
yocto-queue@0.1.0: {}
|
||||||
|
|
||||||
zrender@6.0.0:
|
zrender@6.0.0:
|
||||||
|
|||||||
@ -634,6 +634,19 @@ html.dark body::before {
|
|||||||
box-shadow: var(--mc-shadow-soft);
|
box-shadow: var(--mc-shadow-soft);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* While a workflow canvas is in fullscreen mode, suppress the backdrop
|
||||||
|
filter on every page frame. A non-`none` backdrop-filter promotes the
|
||||||
|
element to a containing block for position:fixed descendants, which
|
||||||
|
pinned the fullscreen canvas to the frame's top-left instead of the
|
||||||
|
viewport. The frames sit behind the fullscreen overlay anyway, so
|
||||||
|
the blur has no visible cost during this transient state. */
|
||||||
|
body.workflow-canvas-fullscreen .mc-page-frame {
|
||||||
|
backdrop-filter: none;
|
||||||
|
}
|
||||||
|
body.workflow-canvas-fullscreen .mc-page-frame::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.mc-page-frame::before {
|
.mc-page-frame::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
@ -123,6 +123,11 @@ const props = withDefaults(defineProps<Props>(), { canvasId: 'workflow-canvas' }
|
|||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(e: 'select-step', payload: StepNodeData | null): void
|
(e: 'select-step', payload: StepNodeData | null): void
|
||||||
(e: 'insert-step', payload: { afterIndex: number; modeType: string }): void
|
(e: 'insert-step', payload: { afterIndex: number; modeType: string }): void
|
||||||
|
/** Toggled by the fullscreen button. The parent uses this to float the
|
||||||
|
* property inspector above the fullscreen overlay (otherwise the panel,
|
||||||
|
* which lives as a flex sibling outside this component, gets hidden
|
||||||
|
* behind the z-index: 2000 fixed canvas). */
|
||||||
|
(e: 'update:fullscreen', value: boolean): void
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
function onAddNode(e: Event) {
|
function onAddNode(e: Event) {
|
||||||
@ -238,15 +243,29 @@ watch(fullscreen, (on) => {
|
|||||||
document.addEventListener('keydown', handleEsc)
|
document.addEventListener('keydown', handleEsc)
|
||||||
// Lock page scroll behind the overlay.
|
// Lock page scroll behind the overlay.
|
||||||
document.body.style.overflow = 'hidden'
|
document.body.style.overflow = 'hidden'
|
||||||
|
// The settings layout's mc-page-frame uses backdrop-filter, which
|
||||||
|
// promotes it to a containing block for position:fixed descendants
|
||||||
|
// (CSS containment spec). That makes our `inset: 0` anchor to the
|
||||||
|
// frame instead of the viewport, leaving the canvas pinned to the
|
||||||
|
// top-left of the page rather than truly fullscreen. Suppress the
|
||||||
|
// filter while fullscreen is active — the frames sit behind the
|
||||||
|
// overlay anyway, so dropping the blur has no visible cost.
|
||||||
|
document.body.classList.add('workflow-canvas-fullscreen')
|
||||||
} else {
|
} else {
|
||||||
document.removeEventListener('keydown', handleEsc)
|
document.removeEventListener('keydown', handleEsc)
|
||||||
document.body.style.overflow = ''
|
document.body.style.overflow = ''
|
||||||
|
document.body.classList.remove('workflow-canvas-fullscreen')
|
||||||
}
|
}
|
||||||
|
emit('update:fullscreen', on)
|
||||||
})
|
})
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
window.removeEventListener('mateclaw:workflow-step-select', handleDomStepSelect as EventListener)
|
window.removeEventListener('mateclaw:workflow-step-select', handleDomStepSelect as EventListener)
|
||||||
document.removeEventListener('keydown', handleEsc)
|
document.removeEventListener('keydown', handleEsc)
|
||||||
document.body.style.overflow = ''
|
document.body.style.overflow = ''
|
||||||
|
// Unmounting while in fullscreen (route change, panel close) must
|
||||||
|
// restore the page frame's backdrop blur — otherwise we leave the
|
||||||
|
// rest of the app permanently transparent.
|
||||||
|
document.body.classList.remove('workflow-canvas-fullscreen')
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -16,7 +16,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onBeforeUnmount, watch } from 'vue'
|
import { computed, onBeforeUnmount, watch } from 'vue'
|
||||||
import { VueMonacoEditor, loader } from '@guolao/vue-monaco-editor'
|
import { VueMonacoEditor, loader } from '@guolao/vue-monaco-editor'
|
||||||
import * as monaco from 'monaco-editor'
|
// Precise imports replace `import * as monaco from 'monaco-editor'` — the
|
||||||
|
// barrel pulled in TypeScript / CSS / HTML language workers (~8.7 MB) that
|
||||||
|
// this JSON editor never touches. The editor.api entry exposes the same
|
||||||
|
// `monaco` namespace surface we need (registerLanguage, KeyMod, etc.).
|
||||||
|
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'
|
||||||
|
import 'monaco-editor/esm/vs/language/json/monaco.contribution.js'
|
||||||
// Vite's ?worker imports — Monaco loads its language workers as separate
|
// Vite's ?worker imports — Monaco loads its language workers as separate
|
||||||
// JS bundles, and without this MonacoEnvironment shim the editor falls
|
// JS bundles, and without this MonacoEnvironment shim the editor falls
|
||||||
// back to fetching from a CDN URL ('vs/base/worker/workerMain.js') that
|
// back to fetching from a CDN URL ('vs/base/worker/workerMain.js') that
|
||||||
|
|||||||
@ -2178,6 +2178,7 @@ export default {
|
|||||||
tabs: {
|
tabs: {
|
||||||
canvas: 'Canvas',
|
canvas: 'Canvas',
|
||||||
json: 'JSON',
|
json: 'JSON',
|
||||||
|
runs: 'Runs ({count})',
|
||||||
},
|
},
|
||||||
canvas: {
|
canvas: {
|
||||||
empty: 'The current draft has no steps. Add one in the JSON editor or pick a template.',
|
empty: 'The current draft has no steps. Add one in the JSON editor or pick a template.',
|
||||||
|
|||||||
@ -2190,6 +2190,7 @@ export default {
|
|||||||
tabs: {
|
tabs: {
|
||||||
canvas: '画布视图',
|
canvas: '画布视图',
|
||||||
json: 'JSON 编辑',
|
json: 'JSON 编辑',
|
||||||
|
runs: '运行 ({count})',
|
||||||
},
|
},
|
||||||
canvas: {
|
canvas: {
|
||||||
empty: '当前草稿没有任何步骤,先在 JSON 编辑器中添加步骤或选择一个模板。',
|
empty: '当前草稿没有任何步骤,先在 JSON 编辑器中添加步骤或选择一个模板。',
|
||||||
|
|||||||
@ -43,35 +43,46 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, onMounted, onBeforeUnmount } from 'vue'
|
import { computed, ref, watch, onMounted, onBeforeUnmount } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 折叠状态
|
// Routes that benefit from extra editor width — the sub-nav auto-collapses
|
||||||
|
// to a 56px rail unless the user has explicitly toggled it open.
|
||||||
|
const COMPACT_ROUTES = ['/settings/workflows', '/settings/triggers']
|
||||||
|
|
||||||
const navCollapsed = ref(localStorage.getItem('mc-settings-nav-collapsed') === 'true')
|
const navCollapsed = ref(localStorage.getItem('mc-settings-nav-collapsed') === 'true')
|
||||||
const userExplicit = ref(localStorage.getItem('mc-settings-nav-collapsed') === 'true')
|
const userExplicit = ref(localStorage.getItem('mc-settings-nav-collapsed') !== null)
|
||||||
let mediumQuery: MediaQueryList | null = null
|
let mediumQuery: MediaQueryList | null = null
|
||||||
|
|
||||||
function toggleNav() {
|
function toggleNav() {
|
||||||
navCollapsed.value = !navCollapsed.value
|
navCollapsed.value = !navCollapsed.value
|
||||||
userExplicit.value = navCollapsed.value
|
userExplicit.value = true
|
||||||
localStorage.setItem('mc-settings-nav-collapsed', String(navCollapsed.value))
|
localStorage.setItem('mc-settings-nav-collapsed', String(navCollapsed.value))
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMediumChange(e: MediaQueryListEvent | MediaQueryList) {
|
function isCompactRoute(path: string): boolean {
|
||||||
if (e.matches && !userExplicit.value) {
|
return COMPACT_ROUTES.some((p) => path.startsWith(p))
|
||||||
navCollapsed.value = true
|
|
||||||
} else if (!e.matches && !userExplicit.value) {
|
|
||||||
navCollapsed.value = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function recomputeAuto() {
|
||||||
|
if (userExplicit.value) return
|
||||||
|
const compact = isCompactRoute(route.path) || !!mediumQuery?.matches
|
||||||
|
navCollapsed.value = compact
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMediumChange(_e: MediaQueryListEvent | MediaQueryList) {
|
||||||
|
recomputeAuto()
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => route.path, recomputeAuto)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
mediumQuery = window.matchMedia('(max-width: 1200px)')
|
mediumQuery = window.matchMedia('(max-width: 1200px)')
|
||||||
handleMediumChange(mediumQuery)
|
recomputeAuto()
|
||||||
mediumQuery.addEventListener('change', handleMediumChange)
|
mediumQuery.addEventListener('change', handleMediumChange)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<div class="workflows-grid">
|
<div class="workflows-grid">
|
||||||
<!-- left: list -->
|
<!-- left: list -->
|
||||||
<aside class="workflows-list mc-surface-card">
|
<aside class="workflows-list">
|
||||||
<div class="list-header">
|
<div class="list-header">
|
||||||
<span>{{ t('workflows.defined', { count: workflows.length }) }}</span>
|
<span>{{ t('workflows.defined', { count: workflows.length }) }}</span>
|
||||||
<button class="btn-ghost" @click="reload">{{ t('workflows.refresh') }}</button>
|
<button class="btn-ghost" @click="reload">{{ t('workflows.refresh') }}</button>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<!-- middle: editor -->
|
<!-- middle: editor -->
|
||||||
<section class="workflows-editor mc-surface-card" v-if="selected">
|
<section class="workflows-editor" v-if="selected">
|
||||||
<header class="editor-header">
|
<header class="editor-header">
|
||||||
<input v-model="selected.name" class="editor-name" :placeholder="t('workflows.namePlaceholder')" />
|
<input v-model="selected.name" class="editor-name" :placeholder="t('workflows.namePlaceholder')" />
|
||||||
<input v-model="selected.description" class="editor-desc" :placeholder="t('workflows.descPlaceholder')" />
|
<input v-model="selected.description" class="editor-desc" :placeholder="t('workflows.descPlaceholder')" />
|
||||||
@ -61,30 +61,32 @@
|
|||||||
<button class="tab-btn" :class="{ active: editorTab === 'json' }" @click="editorTab = 'json'">
|
<button class="tab-btn" :class="{ active: editorTab === 'json' }" @click="editorTab = 'json'">
|
||||||
{{ t('workflows.tabs.json') }}
|
{{ t('workflows.tabs.json') }}
|
||||||
</button>
|
</button>
|
||||||
|
<button class="tab-btn" :class="{ active: editorTab === 'runs' }" @click="onSwitchToRuns">
|
||||||
|
{{ t('workflows.tabs.runs', { count: runs.length + pausedRuns.length }) }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="editorTab === 'canvas'" class="canvas-pane">
|
<div v-if="editorTab === 'canvas'" class="canvas-pane" :class="{ 'canvas-fullscreen': canvasFullscreen }">
|
||||||
<WorkflowCanvas
|
<WorkflowCanvas
|
||||||
v-model="canvasModel"
|
v-model="canvasModel"
|
||||||
:canvas-id="`wf-${selected.id}`"
|
:canvas-id="`wf-${selected.id}`"
|
||||||
@select-step="onCanvasSelect"
|
@select-step="onCanvasSelect"
|
||||||
@insert-step="onInsertStep"
|
@insert-step="onInsertStep"
|
||||||
>
|
@update:fullscreen="canvasFullscreen = $event"
|
||||||
<template v-if="canvasSelection" #panel>
|
/>
|
||||||
<StepPropertyPanel
|
<StepPropertyPanel
|
||||||
:step="selectedStep"
|
v-if="canvasSelection"
|
||||||
:index="canvasSelection.index"
|
:step="selectedStep"
|
||||||
:available-agents="availableAgents"
|
:index="canvasSelection.index"
|
||||||
:available-channels="availableChannels"
|
:available-agents="availableAgents"
|
||||||
@patch="onStepPatch"
|
:available-channels="availableChannels"
|
||||||
@duplicate="onStepDuplicate"
|
@patch="onStepPatch"
|
||||||
@delete="onStepDelete"
|
@duplicate="onStepDuplicate"
|
||||||
/>
|
@delete="onStepDelete"
|
||||||
</template>
|
/>
|
||||||
</WorkflowCanvas>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="json-pane">
|
<div v-else-if="editorTab === 'json'" class="json-pane">
|
||||||
<div class="editor-toolbar">
|
<div class="editor-toolbar">
|
||||||
<label class="template-picker">
|
<label class="template-picker">
|
||||||
<span>{{ t('workflows.templates.label') }}</span>
|
<span>{{ t('workflows.templates.label') }}</span>
|
||||||
@ -108,6 +110,81 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-else class="runs-pane">
|
||||||
|
<section v-if="pausedRuns.length" class="paused-section">
|
||||||
|
<header class="paused-header">
|
||||||
|
<span>{{ t('workflows.paused.header', { count: pausedRuns.length }) }}</span>
|
||||||
|
<button class="btn-ghost" @click="reloadPausedRuns">{{ t('workflows.refresh') }}</button>
|
||||||
|
</header>
|
||||||
|
<ul class="paused-list">
|
||||||
|
<li v-for="entry in pausedRuns" :key="entry.run.id" class="paused-row">
|
||||||
|
<div class="paused-row-line">
|
||||||
|
<span class="run-state state-paused">paused</span>
|
||||||
|
<span class="paused-run-hash">{{ t('workflows.paused.runHash', { id: entry.run.id }) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="paused-meta" v-if="entry.pause">
|
||||||
|
<div><span>{{ t('workflows.paused.pauseTokenLabel') }}:</span>
|
||||||
|
<code class="pause-token">{{ truncateToken(entry.pause.pauseToken) }}</code></div>
|
||||||
|
<div v-if="entry.pause.pausedAt">
|
||||||
|
<span>{{ t('workflows.paused.pausedAtLabel') }}:</span> {{ formatTime(entry.pause.pausedAt) }}
|
||||||
|
</div>
|
||||||
|
<div v-if="entry.pause.resumeDeadline">
|
||||||
|
<span>{{ t('workflows.paused.deadlineLabel') }}:</span> {{ formatTime(entry.pause.resumeDeadline) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="paused-actions" v-if="entry.pause">
|
||||||
|
<button class="resume-btn approve" :disabled="resumingId === entry.run.id"
|
||||||
|
@click="onResume(entry, 'approved')">
|
||||||
|
{{ t('workflows.paused.resumeApproved') }}
|
||||||
|
</button>
|
||||||
|
<button class="resume-btn reject" :disabled="resumingId === entry.run.id"
|
||||||
|
@click="onResume(entry, 'rejected')">
|
||||||
|
{{ t('workflows.paused.resumeRejected') }}
|
||||||
|
</button>
|
||||||
|
<button class="resume-btn neutral" :disabled="resumingId === entry.run.id"
|
||||||
|
@click="onResume(entry, 'timeout')">
|
||||||
|
{{ t('workflows.paused.resumeTimeout') }}
|
||||||
|
</button>
|
||||||
|
<button class="resume-btn neutral" :disabled="resumingId === entry.run.id"
|
||||||
|
@click="onResume(entry, 'cancelled')">
|
||||||
|
{{ t('workflows.paused.resumeCancelled') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<header class="runs-header">
|
||||||
|
<span>{{ t('workflows.runs.header', { count: runs.length }) }}</span>
|
||||||
|
<button class="btn-ghost" @click="reloadRuns">{{ t('workflows.refresh') }}</button>
|
||||||
|
</header>
|
||||||
|
<ul class="runs-list">
|
||||||
|
<li v-for="run in runs" :key="run.id" class="run-row" @click="loadRun(run.id)">
|
||||||
|
<div class="run-row-line">
|
||||||
|
<span class="run-state" :class="'state-' + run.state">{{ run.state }}</span>
|
||||||
|
<span class="run-time">{{ formatTime(run.startedAt) }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="run-row-meta">
|
||||||
|
<span>{{ t('workflows.runs.runHash', { id: run.id }) }}</span>
|
||||||
|
<span v-if="run.triggeredBy">· {{ run.triggeredBy }}</span>
|
||||||
|
<span v-if="run.errorMessage" class="run-err">· {{ run.errorMessage }}</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li v-if="!runs.length" class="runs-empty">{{ t('workflows.runs.empty') }}</li>
|
||||||
|
</ul>
|
||||||
|
<section v-if="runDetail" class="run-detail">
|
||||||
|
<div class="run-detail-title">{{ t('workflows.runs.detailTitle', { id: runDetail.run.id, state: runDetail.run.state }) }}</div>
|
||||||
|
<ol class="run-steps">
|
||||||
|
<li v-for="step in runDetail.steps" :key="step.id">
|
||||||
|
<span class="step-state" :class="'state-' + step.state">{{ step.state }}</span>
|
||||||
|
<span class="step-name">{{ step.stepName || t('workflows.unnamed') }}</span>
|
||||||
|
<span v-if="step.durationMs != null" class="step-duration">{{ step.durationMs }} ms</span>
|
||||||
|
<span v-if="step.errorMessage" class="step-err">{{ step.errorMessage }}</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="compileErrors.length" class="errors-panel">
|
<div v-if="compileErrors.length" class="errors-panel">
|
||||||
<div class="errors-title">{{ t('workflows.compileErrorsTitle', { count: compileErrors.length }) }}</div>
|
<div class="errors-title">{{ t('workflows.compileErrorsTitle', { count: compileErrors.length }) }}</div>
|
||||||
<ul>
|
<ul>
|
||||||
@ -123,85 +200,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="workflows-empty mc-surface-card" v-else>
|
<section class="workflows-empty" v-else>
|
||||||
<p>{{ t('workflows.selectHint') }}</p>
|
<p>{{ t('workflows.selectHint') }}</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- right: runs -->
|
|
||||||
<aside class="workflows-runs mc-surface-card" v-if="selected">
|
|
||||||
<section v-if="pausedRuns.length" class="paused-section">
|
|
||||||
<header class="paused-header">
|
|
||||||
<span>{{ t('workflows.paused.header', { count: pausedRuns.length }) }}</span>
|
|
||||||
<button class="btn-ghost" @click="reloadPausedRuns">{{ t('workflows.refresh') }}</button>
|
|
||||||
</header>
|
|
||||||
<ul class="paused-list">
|
|
||||||
<li v-for="entry in pausedRuns" :key="entry.run.id" class="paused-row">
|
|
||||||
<div class="paused-row-line">
|
|
||||||
<span class="run-state state-paused">paused</span>
|
|
||||||
<span class="paused-run-hash">{{ t('workflows.paused.runHash', { id: entry.run.id }) }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="paused-meta" v-if="entry.pause">
|
|
||||||
<div><span>{{ t('workflows.paused.pauseTokenLabel') }}:</span>
|
|
||||||
<code class="pause-token">{{ truncateToken(entry.pause.pauseToken) }}</code></div>
|
|
||||||
<div v-if="entry.pause.pausedAt">
|
|
||||||
<span>{{ t('workflows.paused.pausedAtLabel') }}:</span> {{ formatTime(entry.pause.pausedAt) }}
|
|
||||||
</div>
|
|
||||||
<div v-if="entry.pause.resumeDeadline">
|
|
||||||
<span>{{ t('workflows.paused.deadlineLabel') }}:</span> {{ formatTime(entry.pause.resumeDeadline) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="paused-actions" v-if="entry.pause">
|
|
||||||
<button class="resume-btn approve" :disabled="resumingId === entry.run.id"
|
|
||||||
@click="onResume(entry, 'approved')">
|
|
||||||
{{ t('workflows.paused.resumeApproved') }}
|
|
||||||
</button>
|
|
||||||
<button class="resume-btn reject" :disabled="resumingId === entry.run.id"
|
|
||||||
@click="onResume(entry, 'rejected')">
|
|
||||||
{{ t('workflows.paused.resumeRejected') }}
|
|
||||||
</button>
|
|
||||||
<button class="resume-btn neutral" :disabled="resumingId === entry.run.id"
|
|
||||||
@click="onResume(entry, 'timeout')">
|
|
||||||
{{ t('workflows.paused.resumeTimeout') }}
|
|
||||||
</button>
|
|
||||||
<button class="resume-btn neutral" :disabled="resumingId === entry.run.id"
|
|
||||||
@click="onResume(entry, 'cancelled')">
|
|
||||||
{{ t('workflows.paused.resumeCancelled') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<header class="runs-header">
|
|
||||||
<span>{{ t('workflows.runs.header', { count: runs.length }) }}</span>
|
|
||||||
<button class="btn-ghost" @click="reloadRuns">{{ t('workflows.refresh') }}</button>
|
|
||||||
</header>
|
|
||||||
<ul class="runs-list">
|
|
||||||
<li v-for="run in runs" :key="run.id" class="run-row" @click="loadRun(run.id)">
|
|
||||||
<div class="run-row-line">
|
|
||||||
<span class="run-state" :class="'state-' + run.state">{{ run.state }}</span>
|
|
||||||
<span class="run-time">{{ formatTime(run.startedAt) }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="run-row-meta">
|
|
||||||
<span>{{ t('workflows.runs.runHash', { id: run.id }) }}</span>
|
|
||||||
<span v-if="run.triggeredBy">· {{ run.triggeredBy }}</span>
|
|
||||||
<span v-if="run.errorMessage" class="run-err">· {{ run.errorMessage }}</span>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li v-if="!runs.length" class="runs-empty">{{ t('workflows.runs.empty') }}</li>
|
|
||||||
</ul>
|
|
||||||
<section v-if="runDetail" class="run-detail">
|
|
||||||
<div class="run-detail-title">{{ t('workflows.runs.detailTitle', { id: runDetail.run.id, state: runDetail.run.state }) }}</div>
|
|
||||||
<ol class="run-steps">
|
|
||||||
<li v-for="step in runDetail.steps" :key="step.id">
|
|
||||||
<span class="step-state" :class="'state-' + step.state">{{ step.state }}</span>
|
|
||||||
<span class="step-name">{{ step.stepName || t('workflows.unnamed') }}</span>
|
|
||||||
<span v-if="step.durationMs != null" class="step-duration">{{ step.durationMs }} ms</span>
|
|
||||||
<span v-if="step.errorMessage" class="step-err">{{ step.errorMessage }}</span>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</section>
|
|
||||||
</aside>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -213,7 +214,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, ref, watch } from 'vue'
|
import { computed, defineAsyncComponent, onMounted, ref, watch } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { mcConfirm } from '@/components/common/useConfirm'
|
import { mcConfirm } from '@/components/common/useConfirm'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
@ -234,9 +235,18 @@ import {
|
|||||||
} from '@/api'
|
} from '@/api'
|
||||||
import type { Channel } from '@/types'
|
import type { Channel } from '@/types'
|
||||||
import { useWorkspaceStore } from '@/stores/useWorkspaceStore'
|
import { useWorkspaceStore } from '@/stores/useWorkspaceStore'
|
||||||
import WorkflowCanvas from '@/components/workflow/WorkflowCanvas.vue'
|
// Lazy-load the canvas + Monaco editor — each pulls a heavy vendor chunk
|
||||||
|
// (@vue-flow/* and monaco-editor respectively). Keeping them out of the
|
||||||
|
// route's main chunk means /settings/workflows starts as ~500 KB instead
|
||||||
|
// of 4 MB, and the Docker production build no longer needs the
|
||||||
|
// --max-old-space-size=6144 escape hatch.
|
||||||
|
const WorkflowCanvas = defineAsyncComponent(
|
||||||
|
() => import('@/components/workflow/WorkflowCanvas.vue'),
|
||||||
|
)
|
||||||
|
const WorkflowJsonEditor = defineAsyncComponent(
|
||||||
|
() => import('@/components/workflow/WorkflowJsonEditor.vue'),
|
||||||
|
)
|
||||||
import StepPropertyPanel from '@/components/workflow/StepPropertyPanel.vue'
|
import StepPropertyPanel from '@/components/workflow/StepPropertyPanel.vue'
|
||||||
import WorkflowJsonEditor from '@/components/workflow/WorkflowJsonEditor.vue'
|
|
||||||
import CreateWorkflowDialog from '@/components/workflow/CreateWorkflowDialog.vue'
|
import CreateWorkflowDialog from '@/components/workflow/CreateWorkflowDialog.vue'
|
||||||
import PublishDialog from '@/components/workflow/PublishDialog.vue'
|
import PublishDialog from '@/components/workflow/PublishDialog.vue'
|
||||||
import GenerateWorkflowDialog from '@/components/workflow/GenerateWorkflowDialog.vue'
|
import GenerateWorkflowDialog from '@/components/workflow/GenerateWorkflowDialog.vue'
|
||||||
@ -285,7 +295,13 @@ const templateChoice = ref('')
|
|||||||
// the JSON) and the raw JSON editor. Canvas is the default — most
|
// the JSON) and the raw JSON editor. Canvas is the default — most
|
||||||
// authors visit the page to make sense of an existing flow rather
|
// authors visit the page to make sense of an existing flow rather
|
||||||
// than to type fresh JSON.
|
// than to type fresh JSON.
|
||||||
const editorTab = ref<'canvas' | 'json'>('canvas')
|
const editorTab = ref<'canvas' | 'json' | 'runs'>('canvas')
|
||||||
|
|
||||||
|
async function onSwitchToRuns() {
|
||||||
|
editorTab.value = 'runs'
|
||||||
|
await reloadRuns()
|
||||||
|
await reloadPausedRuns()
|
||||||
|
}
|
||||||
|
|
||||||
// The canvas reads from `draftJson` directly. We keep the model write
|
// The canvas reads from `draftJson` directly. We keep the model write
|
||||||
// path on the JSON editor only — the canvas is purely a derived view
|
// path on the JSON editor only — the canvas is purely a derived view
|
||||||
@ -296,6 +312,12 @@ const canvasModel = computed({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const canvasSelection = ref<StepNodeData | null>(null)
|
const canvasSelection = ref<StepNodeData | null>(null)
|
||||||
|
// Mirrors the WorkflowCanvas's internal fullscreen flag so we can float
|
||||||
|
// the property inspector above the fixed-position overlay. Without this,
|
||||||
|
// clicking a node in fullscreen would emit a selection but the panel —
|
||||||
|
// rendered as a flex sibling outside the canvas — sits underneath the
|
||||||
|
// z-index: 2000 overlay and reads as "panel doesn't open".
|
||||||
|
const canvasFullscreen = ref(false)
|
||||||
function onCanvasSelect(payload: StepNodeData | null) {
|
function onCanvasSelect(payload: StepNodeData | null) {
|
||||||
canvasSelection.value = payload
|
canvasSelection.value = payload
|
||||||
}
|
}
|
||||||
@ -830,21 +852,53 @@ watch(workspaceId, async () => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.workflows-page :deep(.mc-page-header) {
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.workflows-page :deep(.header-actions) {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
align-self: center;
|
||||||
}
|
}
|
||||||
.workflows-grid {
|
.workflows-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 280px 1fr 320px;
|
grid-template-columns: minmax(220px, 260px) minmax(0, 1fr);
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
min-height: 480px;
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
.workflows-list,
|
.workflows-list,
|
||||||
.workflows-editor,
|
.workflows-editor,
|
||||||
.workflows-runs,
|
|
||||||
.workflows-empty {
|
.workflows-empty {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
border: 1px solid var(--mc-border-light, rgba(0, 0, 0, 0.06));
|
||||||
|
border-radius: 10px;
|
||||||
|
background: var(--mc-bg-elevated, rgba(255, 255, 255, 0.4));
|
||||||
|
}
|
||||||
|
.workflows-list {
|
||||||
|
/* Slightly recessed so the editor reads as primary surface. */
|
||||||
|
background: var(--mc-bg-sunken, rgba(0, 0, 0, 0.02));
|
||||||
|
}
|
||||||
|
.runs-pane {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
min-height: 360px;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
.list-header,
|
.list-header,
|
||||||
.runs-header {
|
.runs-header {
|
||||||
@ -1146,7 +1200,7 @@ button:disabled {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
min-height: 420px;
|
min-height: 320px;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
.canvas-pane > .workflow-canvas {
|
.canvas-pane > .workflow-canvas {
|
||||||
@ -1166,6 +1220,40 @@ button:disabled {
|
|||||||
max-height: 360px;
|
max-height: 360px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Fullscreen mode: the canvas itself becomes a fixed overlay
|
||||||
|
(z-index: 2000). Float the panel above it so the same flex sibling
|
||||||
|
stays interactive — the previous behaviour where the panel slipped
|
||||||
|
underneath the overlay made it look like the property panel had
|
||||||
|
broken when fullscreen was on.
|
||||||
|
|
||||||
|
bottom: 180px reserves room for vue-flow's MiniMap (~150px tall) at
|
||||||
|
the bottom-right corner. Without it, the panel covers the minimap
|
||||||
|
and the user loses overview navigation. The panel scrolls internally
|
||||||
|
when content exceeds the shortened height. */
|
||||||
|
.canvas-pane.canvas-fullscreen {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
.canvas-pane.canvas-fullscreen > .step-panel {
|
||||||
|
position: fixed;
|
||||||
|
top: 56px;
|
||||||
|
right: 14px;
|
||||||
|
bottom: 180px;
|
||||||
|
width: min(360px, 30vw);
|
||||||
|
max-height: none;
|
||||||
|
z-index: 2001;
|
||||||
|
box-shadow: 0 18px 40px rgba(0, 0, 0, 0.22);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
@media (max-width: 760px) {
|
||||||
|
.canvas-pane.canvas-fullscreen > .step-panel {
|
||||||
|
top: auto;
|
||||||
|
left: 10px;
|
||||||
|
right: 10px;
|
||||||
|
bottom: 10px;
|
||||||
|
width: auto;
|
||||||
|
height: min(56vh, 420px);
|
||||||
|
}
|
||||||
|
}
|
||||||
.canvas-inspector {
|
.canvas-inspector {
|
||||||
background: var(--mc-bg-elevated, rgba(0, 0, 0, 0.02));
|
background: var(--mc-bg-elevated, rgba(0, 0, 0, 0.02));
|
||||||
border: 1px solid var(--mc-border, rgba(0, 0, 0, 0.08));
|
border: 1px solid var(--mc-border, rgba(0, 0, 0, 0.08));
|
||||||
@ -1221,7 +1309,7 @@ button:disabled {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
min-height: 360px;
|
min-height: 280px;
|
||||||
}
|
}
|
||||||
.paused-section {
|
.paused-section {
|
||||||
border-bottom: 1px dashed var(--mc-border-light, rgba(0, 0, 0, 0.08));
|
border-bottom: 1px dashed var(--mc-border-light, rgba(0, 0, 0, 0.08));
|
||||||
@ -1326,7 +1414,7 @@ button:disabled {
|
|||||||
can breathe on tablets, and stack everything vertically below 720px
|
can breathe on tablets, and stack everything vertically below 720px
|
||||||
so the page is usable on a phone. The runs panel becomes a
|
so the page is usable on a phone. The runs panel becomes a
|
||||||
collapsible details element on small screens. */
|
collapsible details element on small screens. */
|
||||||
@media (max-width: 1100px) {
|
@media (max-width: 1300px) {
|
||||||
.workflows-grid {
|
.workflows-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
import tailwindcss from '@tailwindcss/vite'
|
import tailwindcss from '@tailwindcss/vite'
|
||||||
|
import { visualizer } from 'rollup-plugin-visualizer'
|
||||||
import { resolve } from 'path'
|
import { resolve } from 'path'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@ -17,6 +18,15 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
tailwindcss(),
|
tailwindcss(),
|
||||||
|
// ANALYZE=1 pnpm build writes dist/stats.html. Skipped on normal builds so
|
||||||
|
// CI artifact upload is opt-in and the Docker image build doesn't waste
|
||||||
|
// memory generating an HTML report it never reads.
|
||||||
|
process.env.ANALYZE && visualizer({
|
||||||
|
filename: 'dist/stats.html',
|
||||||
|
open: false,
|
||||||
|
gzipSize: true,
|
||||||
|
brotliSize: true,
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
@ -51,5 +61,33 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
outDir: '../mateclaw-server/src/main/resources/static',
|
outDir: '../mateclaw-server/src/main/resources/static',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
|
// Cap warning so a future barrel import (see history with monaco) trips
|
||||||
|
// the build log instead of slipping in silently.
|
||||||
|
chunkSizeWarningLimit: 1024,
|
||||||
|
rollupOptions: {
|
||||||
|
output: {
|
||||||
|
// Pin heavy vendor libs to named chunks. Two reasons:
|
||||||
|
// 1. Cache: bumping a business chunk doesn't invalidate the
|
||||||
|
// monaco / vue-flow bundles, so returning visitors only
|
||||||
|
// re-download the few KB that actually changed.
|
||||||
|
// 2. Rollup minify peak heap: keeping monaco out of the route
|
||||||
|
// chunk lets each Worker on the chunk run with a smaller
|
||||||
|
// working set, which is what blew up the Docker build at
|
||||||
|
// 1.3.0 (needed --max-old-space-size=6144 as a band-aid).
|
||||||
|
manualChunks: {
|
||||||
|
'vendor-monaco': ['monaco-editor', '@guolao/vue-monaco-editor'],
|
||||||
|
'vendor-vue-flow': [
|
||||||
|
'@vue-flow/core',
|
||||||
|
'@vue-flow/background',
|
||||||
|
'@vue-flow/controls',
|
||||||
|
'@vue-flow/minimap',
|
||||||
|
],
|
||||||
|
'vendor-mermaid': ['mermaid'],
|
||||||
|
'vendor-echarts': ['echarts'],
|
||||||
|
'vendor-element': ['element-plus', '@element-plus/icons-vue'],
|
||||||
|
'vendor-markdown': ['marked', 'marked-highlight', 'highlight.js', 'dompurify'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user