pinokiod 7.1.47 → 7.1.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/kernel/bin/bluefairy.js +1 -1
- package/package.json +1 -1
- package/server/index.js +20 -9
- package/server/public/common.js +105 -0
- package/server/public/task-launcher.css +92 -0
- package/server/public/task-launcher.js +92 -0
- package/server/public/universal-launcher.js +18 -7
- package/server/views/task_install.ejs +5 -1
- package/server/views/task_launch.ejs +8 -4
package/kernel/bin/bluefairy.js
CHANGED
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -7140,7 +7140,7 @@ class Server {
|
|
|
7140
7140
|
return
|
|
7141
7141
|
}
|
|
7142
7142
|
const links = await taskWorkspaceLinks.listTaskWorkspaces(task.id, {
|
|
7143
|
-
root: task.config
|
|
7143
|
+
root: getTaskLaunchPath(task.config),
|
|
7144
7144
|
pruneMissing: true
|
|
7145
7145
|
})
|
|
7146
7146
|
const items = links.workspaces.map((workspace) => {
|
|
@@ -7938,12 +7938,23 @@ class Server {
|
|
|
7938
7938
|
}
|
|
7939
7939
|
return `${baseName}-${Date.now()}`
|
|
7940
7940
|
}
|
|
7941
|
-
const
|
|
7941
|
+
const normalizeTaskLaunchPath = (taskPath) => {
|
|
7942
|
+
const normalizedPath = typeof taskPath === "string" ? taskPath.trim() : ""
|
|
7943
|
+
return normalizedPath === "tasks" ? "workspaces" : normalizedPath
|
|
7944
|
+
}
|
|
7945
|
+
const getTaskLaunchPath = (taskConfig) => {
|
|
7942
7946
|
const validatedTaskConfig = taskPackages.validateTaskConfig(taskConfig)
|
|
7943
|
-
|
|
7947
|
+
return normalizeTaskLaunchPath(validatedTaskConfig.path)
|
|
7948
|
+
}
|
|
7949
|
+
const usesWorkspaceTaskPath = (taskConfig) => {
|
|
7950
|
+
return getTaskLaunchPath(taskConfig) === "workspaces"
|
|
7951
|
+
}
|
|
7952
|
+
const getTaskLaunchRoot = (taskConfig) => {
|
|
7953
|
+
const launchPath = getTaskLaunchPath(taskConfig)
|
|
7954
|
+
if (launchPath === "workspaces") {
|
|
7944
7955
|
return path.resolve(getTerminalWorkspacesRoot())
|
|
7945
7956
|
}
|
|
7946
|
-
return path.resolve(this.kernel.path(
|
|
7957
|
+
return path.resolve(this.kernel.path(launchPath))
|
|
7947
7958
|
}
|
|
7948
7959
|
const extractTaskInputValuesFromPayload = (payload) => {
|
|
7949
7960
|
const legacyValues = taskPackages.extractInputValues(payload)
|
|
@@ -8194,7 +8205,7 @@ class Server {
|
|
|
8194
8205
|
const shareState = await buildTaskShareState(req, task)
|
|
8195
8206
|
const taskUi = buildTaskPresentationState(task, shareState)
|
|
8196
8207
|
const sidebarContext = await buildTaskSidebarContext()
|
|
8197
|
-
const suggestedFolderName = task && task.config && task.config
|
|
8208
|
+
const suggestedFolderName = task && task.config && usesWorkspaceTaskPath(task.config)
|
|
8198
8209
|
? ""
|
|
8199
8210
|
: taskPackages.slugify(task && task.config ? task.config.title : task.id, task && task.id ? task.id : "task")
|
|
8200
8211
|
const renderedPrompt = taskPackages.applyTemplateValues(task.template, promptValues)
|
|
@@ -9460,7 +9471,7 @@ class Server {
|
|
|
9460
9471
|
const launchRoot = getTaskLaunchRoot(task.config)
|
|
9461
9472
|
let folderName = folderNameInput
|
|
9462
9473
|
if (!folderName) {
|
|
9463
|
-
if (task.config
|
|
9474
|
+
if (usesWorkspaceTaskPath(task.config)) {
|
|
9464
9475
|
folderName = await generateTerminalWorkspaceFolderName()
|
|
9465
9476
|
} else {
|
|
9466
9477
|
folderName = await suggestTaskFolderName(launchRoot, task.config.title)
|
|
@@ -9508,7 +9519,7 @@ class Server {
|
|
|
9508
9519
|
await persistLauncherPromptContext(targetPath, {
|
|
9509
9520
|
prompt,
|
|
9510
9521
|
includeSpec: true,
|
|
9511
|
-
includeRequest: task.config
|
|
9522
|
+
includeRequest: usesWorkspaceTaskPath(task.config)
|
|
9512
9523
|
})
|
|
9513
9524
|
} catch (error) {
|
|
9514
9525
|
await fs.promises.rm(targetPath, { recursive: true, force: true }).catch(() => {})
|
|
@@ -9841,7 +9852,7 @@ class Server {
|
|
|
9841
9852
|
|
|
9842
9853
|
if (workspaceMode === "reuse") {
|
|
9843
9854
|
const links = await taskWorkspaceLinks.listTaskWorkspaces(task.id, {
|
|
9844
|
-
root: task.config
|
|
9855
|
+
root: getTaskLaunchPath(task.config),
|
|
9845
9856
|
pruneMissing: true
|
|
9846
9857
|
})
|
|
9847
9858
|
workspaceRef = requestedWorkspaceRef
|
|
@@ -9882,7 +9893,7 @@ class Server {
|
|
|
9882
9893
|
const folderName = requestedWorkspaceName || await suggestTaskFolderName(launchRoot, task.config.title)
|
|
9883
9894
|
targetPath = await createLauncherTargetFolder(launchRoot, folderName)
|
|
9884
9895
|
createdTarget = true
|
|
9885
|
-
workspaceRef = taskWorkspaceLinks.createWorkspaceRef(task.config
|
|
9896
|
+
workspaceRef = taskWorkspaceLinks.createWorkspaceRef(getTaskLaunchPath(task.config), targetPath)
|
|
9886
9897
|
if (!workspaceRef) {
|
|
9887
9898
|
throw new Error("Failed to create workspace link.")
|
|
9888
9899
|
}
|
package/server/public/common.js
CHANGED
|
@@ -4418,4 +4418,109 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
4418
4418
|
}
|
|
4419
4419
|
}
|
|
4420
4420
|
|
|
4421
|
+
function getTaskPendingCopyByAction(action) {
|
|
4422
|
+
if (action === '/task/install') {
|
|
4423
|
+
return {
|
|
4424
|
+
button: 'Installing...',
|
|
4425
|
+
status: 'Installing the task and reopening this page.'
|
|
4426
|
+
};
|
|
4427
|
+
}
|
|
4428
|
+
if (action === '/task/start') {
|
|
4429
|
+
return {
|
|
4430
|
+
button: 'Launching...',
|
|
4431
|
+
status: 'Preparing the workspace and opening your selected tool.'
|
|
4432
|
+
};
|
|
4433
|
+
}
|
|
4434
|
+
return {
|
|
4435
|
+
button: 'Working...',
|
|
4436
|
+
status: 'Finishing your request.'
|
|
4437
|
+
};
|
|
4438
|
+
}
|
|
4439
|
+
|
|
4440
|
+
function ensureTaskSubmitFeedback(form) {
|
|
4441
|
+
let feedback = form.querySelector('[data-task-submit-feedback]');
|
|
4442
|
+
if (feedback) {
|
|
4443
|
+
return feedback;
|
|
4444
|
+
}
|
|
4445
|
+
feedback = document.createElement('p');
|
|
4446
|
+
feedback.className = 'task-submit-feedback';
|
|
4447
|
+
feedback.setAttribute('data-task-submit-feedback', '');
|
|
4448
|
+
feedback.setAttribute('aria-live', 'polite');
|
|
4449
|
+
feedback.setAttribute('aria-hidden', 'true');
|
|
4450
|
+
|
|
4451
|
+
const feedbackText = document.createElement('span');
|
|
4452
|
+
feedbackText.setAttribute('data-task-submit-feedback-text', '');
|
|
4453
|
+
feedback.appendChild(feedbackText);
|
|
4454
|
+
form.appendChild(feedback);
|
|
4455
|
+
return feedback;
|
|
4456
|
+
}
|
|
4457
|
+
|
|
4458
|
+
function initTaskPendingSubmitFallback() {
|
|
4459
|
+
const forms = Array.from(document.querySelectorAll('form[action="/task/install"], form[action="/task/start"]'));
|
|
4460
|
+
forms.forEach((form) => {
|
|
4461
|
+
if (form.matches('[data-task-pending-form]') || form.dataset.taskPendingBound === 'true') {
|
|
4462
|
+
return;
|
|
4463
|
+
}
|
|
4464
|
+
|
|
4465
|
+
const action = form.getAttribute('action') || '';
|
|
4466
|
+
form.dataset.taskPendingBound = 'true';
|
|
4467
|
+
|
|
4468
|
+
form.addEventListener('submit', (event) => {
|
|
4469
|
+
if (form.dataset.taskSubmitting === 'true') {
|
|
4470
|
+
event.preventDefault();
|
|
4471
|
+
return;
|
|
4472
|
+
}
|
|
4473
|
+
|
|
4474
|
+
const copy = getTaskPendingCopyByAction(action);
|
|
4475
|
+
const submitter = event.submitter && event.submitter.form === form
|
|
4476
|
+
? event.submitter
|
|
4477
|
+
: form.querySelector('button[type="submit"], input[type="submit"]');
|
|
4478
|
+
const feedback = ensureTaskSubmitFeedback(form);
|
|
4479
|
+
const feedbackText = feedback.querySelector('[data-task-submit-feedback-text]') || feedback;
|
|
4480
|
+
|
|
4481
|
+
event.preventDefault();
|
|
4482
|
+
form.dataset.taskSubmitting = 'true';
|
|
4483
|
+
form.classList.add('is-submitting');
|
|
4484
|
+
form.setAttribute('aria-busy', 'true');
|
|
4485
|
+
document.body.classList.add('task-page-busy');
|
|
4486
|
+
|
|
4487
|
+
if (submitter) {
|
|
4488
|
+
submitter.classList.add('is-busy');
|
|
4489
|
+
submitter.setAttribute('aria-disabled', 'true');
|
|
4490
|
+
if (submitter.tagName === 'BUTTON') {
|
|
4491
|
+
const label = submitter.querySelector('span');
|
|
4492
|
+
if (label) {
|
|
4493
|
+
label.textContent = copy.button;
|
|
4494
|
+
} else {
|
|
4495
|
+
submitter.textContent = copy.button;
|
|
4496
|
+
}
|
|
4497
|
+
} else if (submitter.tagName === 'INPUT') {
|
|
4498
|
+
submitter.value = copy.button;
|
|
4499
|
+
}
|
|
4500
|
+
submitter.disabled = true;
|
|
4501
|
+
}
|
|
4502
|
+
|
|
4503
|
+
Array.from(form.querySelectorAll('button[type="submit"], input[type="submit"]')).forEach((button) => {
|
|
4504
|
+
if (button === submitter) {
|
|
4505
|
+
return;
|
|
4506
|
+
}
|
|
4507
|
+
button.disabled = true;
|
|
4508
|
+
button.setAttribute('aria-disabled', 'true');
|
|
4509
|
+
});
|
|
4510
|
+
|
|
4511
|
+
feedbackText.textContent = copy.status;
|
|
4512
|
+
feedback.classList.add('is-visible');
|
|
4513
|
+
feedback.setAttribute('aria-hidden', 'false');
|
|
4514
|
+
|
|
4515
|
+
window.requestAnimationFrame(() => {
|
|
4516
|
+
window.setTimeout(() => {
|
|
4517
|
+
form.submit();
|
|
4518
|
+
}, 0);
|
|
4519
|
+
});
|
|
4520
|
+
});
|
|
4521
|
+
});
|
|
4522
|
+
}
|
|
4523
|
+
|
|
4524
|
+
initTaskPendingSubmitFallback();
|
|
4525
|
+
|
|
4421
4526
|
})
|
|
@@ -1439,6 +1439,28 @@ body.dark .task-badge-warning {
|
|
|
1439
1439
|
transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
|
|
1440
1440
|
}
|
|
1441
1441
|
|
|
1442
|
+
.task-button.is-busy,
|
|
1443
|
+
.task-link-button.is-busy {
|
|
1444
|
+
pointer-events: none;
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
.task-button.is-busy > i,
|
|
1448
|
+
.task-link-button.is-busy > i {
|
|
1449
|
+
display: none;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
.task-button.is-busy::before,
|
|
1453
|
+
.task-link-button.is-busy::before {
|
|
1454
|
+
content: "";
|
|
1455
|
+
width: 11px;
|
|
1456
|
+
height: 11px;
|
|
1457
|
+
flex: 0 0 auto;
|
|
1458
|
+
border-radius: 999px;
|
|
1459
|
+
border: 1.5px solid currentColor;
|
|
1460
|
+
border-right-color: transparent;
|
|
1461
|
+
animation: task-button-spin 720ms linear infinite;
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1442
1464
|
.task-button:hover,
|
|
1443
1465
|
.task-link-button:hover {
|
|
1444
1466
|
background: var(--task-soft);
|
|
@@ -1539,6 +1561,29 @@ body.dark .task-link-button.danger {
|
|
|
1539
1561
|
margin: 0;
|
|
1540
1562
|
}
|
|
1541
1563
|
|
|
1564
|
+
.task-submit-feedback {
|
|
1565
|
+
margin: 0;
|
|
1566
|
+
display: grid;
|
|
1567
|
+
grid-template-rows: 0fr;
|
|
1568
|
+
opacity: 0;
|
|
1569
|
+
color: var(--task-muted);
|
|
1570
|
+
font-size: 12px;
|
|
1571
|
+
line-height: 1.45;
|
|
1572
|
+
transition:
|
|
1573
|
+
grid-template-rows 220ms cubic-bezier(0.25, 1, 0.5, 1),
|
|
1574
|
+
opacity 180ms cubic-bezier(0.25, 1, 0.5, 1);
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
.task-submit-feedback > span {
|
|
1578
|
+
overflow: hidden;
|
|
1579
|
+
min-height: 0;
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
.task-submit-feedback.is-visible {
|
|
1583
|
+
grid-template-rows: 1fr;
|
|
1584
|
+
opacity: 1;
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1542
1587
|
.task-button.subtle {
|
|
1543
1588
|
color: var(--task-muted);
|
|
1544
1589
|
}
|
|
@@ -1569,6 +1614,23 @@ body.dark .task-link-button.danger {
|
|
|
1569
1614
|
margin-top: 18px;
|
|
1570
1615
|
}
|
|
1571
1616
|
|
|
1617
|
+
.task-install-actions .task-submit-feedback {
|
|
1618
|
+
flex-basis: 100%;
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
.task-install-actions.is-submitting .task-link-button {
|
|
1622
|
+
pointer-events: none;
|
|
1623
|
+
opacity: 0.55;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
.task-prompt-actions .task-submit-feedback {
|
|
1627
|
+
margin-top: 2px;
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
.task-run-form.is-submitting .task-prompt-code {
|
|
1631
|
+
opacity: 0.82;
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1572
1634
|
.task-section-inline {
|
|
1573
1635
|
padding-top: 12px;
|
|
1574
1636
|
padding-bottom: 12px;
|
|
@@ -1673,6 +1735,21 @@ body.dark .task-status.error {
|
|
|
1673
1735
|
opacity: 0.5;
|
|
1674
1736
|
}
|
|
1675
1737
|
|
|
1738
|
+
body.task-page-busy {
|
|
1739
|
+
cursor: progress;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
body.task-page-busy .task-button,
|
|
1743
|
+
body.task-page-busy .task-link-button {
|
|
1744
|
+
cursor: progress;
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
@keyframes task-button-spin {
|
|
1748
|
+
to {
|
|
1749
|
+
transform: rotate(360deg);
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1676
1753
|
.task-share-section {
|
|
1677
1754
|
display: grid;
|
|
1678
1755
|
gap: 8px;
|
|
@@ -2783,3 +2860,18 @@ body.dark .plugin-option .option-icon {
|
|
|
2783
2860
|
justify-self: end;
|
|
2784
2861
|
}
|
|
2785
2862
|
}
|
|
2863
|
+
|
|
2864
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2865
|
+
.task-button,
|
|
2866
|
+
.task-link-button,
|
|
2867
|
+
.task-submit-feedback {
|
|
2868
|
+
transition: none;
|
|
2869
|
+
}
|
|
2870
|
+
|
|
2871
|
+
.task-button.is-busy::before,
|
|
2872
|
+
.task-link-button.is-busy::before {
|
|
2873
|
+
animation: none;
|
|
2874
|
+
border-right-color: currentColor;
|
|
2875
|
+
opacity: 0.72;
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
@@ -748,6 +748,97 @@
|
|
|
748
748
|
});
|
|
749
749
|
}
|
|
750
750
|
|
|
751
|
+
function getTaskPendingCopy(kind) {
|
|
752
|
+
if (kind === "install") {
|
|
753
|
+
return {
|
|
754
|
+
button: "Installing...",
|
|
755
|
+
status: "Installing the task and reopening this page."
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
if (kind === "run") {
|
|
759
|
+
return {
|
|
760
|
+
button: "Launching...",
|
|
761
|
+
status: "Preparing the workspace and opening your selected tool."
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
return {
|
|
765
|
+
button: "Working...",
|
|
766
|
+
status: "Finishing your request."
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
function setTaskPendingState(form, submitter, kind) {
|
|
771
|
+
const copy = getTaskPendingCopy(kind);
|
|
772
|
+
const primarySubmitter = submitter && submitter.form === form
|
|
773
|
+
? submitter
|
|
774
|
+
: form.querySelector("button[type='submit'], input[type='submit']");
|
|
775
|
+
const feedback = form.querySelector("[data-task-submit-feedback]");
|
|
776
|
+
const feedbackText = feedback
|
|
777
|
+
? (feedback.querySelector("[data-task-submit-feedback-text]") || feedback)
|
|
778
|
+
: null;
|
|
779
|
+
|
|
780
|
+
form.classList.add("is-submitting");
|
|
781
|
+
form.setAttribute("aria-busy", "true");
|
|
782
|
+
document.body.classList.add("task-page-busy");
|
|
783
|
+
|
|
784
|
+
if (primarySubmitter) {
|
|
785
|
+
primarySubmitter.classList.add("is-busy");
|
|
786
|
+
primarySubmitter.setAttribute("aria-disabled", "true");
|
|
787
|
+
if (primarySubmitter.tagName === "BUTTON") {
|
|
788
|
+
const label = primarySubmitter.querySelector("span");
|
|
789
|
+
if (label) {
|
|
790
|
+
label.textContent = copy.button;
|
|
791
|
+
} else {
|
|
792
|
+
primarySubmitter.textContent = copy.button;
|
|
793
|
+
}
|
|
794
|
+
} else if (primarySubmitter.tagName === "INPUT") {
|
|
795
|
+
primarySubmitter.value = copy.button;
|
|
796
|
+
}
|
|
797
|
+
primarySubmitter.disabled = true;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
Array.from(form.querySelectorAll("button[type='submit'], input[type='submit']")).forEach((button) => {
|
|
801
|
+
if (button === primarySubmitter) {
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
button.disabled = true;
|
|
805
|
+
button.setAttribute("aria-disabled", "true");
|
|
806
|
+
});
|
|
807
|
+
|
|
808
|
+
if (feedback && feedbackText) {
|
|
809
|
+
feedbackText.textContent = copy.status;
|
|
810
|
+
feedback.classList.add("is-visible");
|
|
811
|
+
feedback.setAttribute("aria-hidden", "false");
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
function initTaskPendingForms() {
|
|
816
|
+
const forms = Array.from(document.querySelectorAll("form[data-task-pending-form]"));
|
|
817
|
+
forms.forEach((form) => {
|
|
818
|
+
form.addEventListener("submit", (event) => {
|
|
819
|
+
if (form.dataset.taskSubmitting === "true") {
|
|
820
|
+
event.preventDefault();
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
const kind = form.getAttribute("data-task-pending-form") || "";
|
|
825
|
+
const submitter = event.submitter && event.submitter.form === form
|
|
826
|
+
? event.submitter
|
|
827
|
+
: form.querySelector("button[type='submit'], input[type='submit']");
|
|
828
|
+
|
|
829
|
+
event.preventDefault();
|
|
830
|
+
form.dataset.taskSubmitting = "true";
|
|
831
|
+
setTaskPendingState(form, submitter, kind);
|
|
832
|
+
|
|
833
|
+
window.requestAnimationFrame(() => {
|
|
834
|
+
window.setTimeout(() => {
|
|
835
|
+
form.submit();
|
|
836
|
+
}, 0);
|
|
837
|
+
});
|
|
838
|
+
});
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
|
|
751
842
|
let taskLauncherBooted = false;
|
|
752
843
|
|
|
753
844
|
function bootTaskLauncher() {
|
|
@@ -759,6 +850,7 @@
|
|
|
759
850
|
initTaskBuilder();
|
|
760
851
|
initTaskLibraryPage();
|
|
761
852
|
initTaskConfirmForms();
|
|
853
|
+
initTaskPendingForms();
|
|
762
854
|
}
|
|
763
855
|
|
|
764
856
|
if (document.readyState === "loading") {
|
|
@@ -391,6 +391,17 @@
|
|
|
391
391
|
return 'workspaces';
|
|
392
392
|
}
|
|
393
393
|
|
|
394
|
+
function normalizeTaskSelectionPath(taskPath) {
|
|
395
|
+
return taskPath === 'tasks' ? 'workspaces' : taskPath;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function taskMatchesSelectionPath(task, currentPath) {
|
|
399
|
+
if (!task) {
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
return normalizeTaskSelectionPath(task.path || '') === (currentPath || '');
|
|
403
|
+
}
|
|
404
|
+
|
|
394
405
|
function getIntentNameRelativePath(intent) {
|
|
395
406
|
const normalizedIntent = normalizeIntent(intent);
|
|
396
407
|
if (normalizedIntent === 'create_app') return 'api';
|
|
@@ -2108,7 +2119,7 @@
|
|
|
2108
2119
|
function getVisibleTasks() {
|
|
2109
2120
|
const query = state.query.toLowerCase();
|
|
2110
2121
|
return state.allTasks.filter((task) => {
|
|
2111
|
-
if (!task
|
|
2122
|
+
if (!taskMatchesSelectionPath(task, state.currentPath)) {
|
|
2112
2123
|
return false;
|
|
2113
2124
|
}
|
|
2114
2125
|
if (!query) {
|
|
@@ -2177,7 +2188,7 @@
|
|
|
2177
2188
|
function render() {
|
|
2178
2189
|
const visibleTasks = getVisibleTasks();
|
|
2179
2190
|
const selectedTask = getSelectedTask();
|
|
2180
|
-
const hasAvailableTasks = state.allTasks.some((task) => task
|
|
2191
|
+
const hasAvailableTasks = state.allTasks.some((task) => taskMatchesSelectionPath(task, state.currentPath));
|
|
2181
2192
|
const showingDetails = Boolean(selectedTask);
|
|
2182
2193
|
const hasVisibleTasks = visibleTasks.length > 0;
|
|
2183
2194
|
toggle.disabled = false;
|
|
@@ -2366,7 +2377,7 @@
|
|
|
2366
2377
|
setTasks(tasks) {
|
|
2367
2378
|
state.allTasks = Array.isArray(tasks) ? tasks.slice() : [];
|
|
2368
2379
|
const selectedTask = getSelectedTask();
|
|
2369
|
-
if (selectedTask
|
|
2380
|
+
if (!taskMatchesSelectionPath(selectedTask, state.currentPath)) {
|
|
2370
2381
|
state.selectedTaskId = '';
|
|
2371
2382
|
}
|
|
2372
2383
|
render();
|
|
@@ -2374,7 +2385,7 @@
|
|
|
2374
2385
|
setPath(taskPath) {
|
|
2375
2386
|
state.currentPath = taskPath || 'workspaces';
|
|
2376
2387
|
const selectedTask = getSelectedTask();
|
|
2377
|
-
if (selectedTask
|
|
2388
|
+
if (!taskMatchesSelectionPath(selectedTask, state.currentPath)) {
|
|
2378
2389
|
state.selectedTaskId = '';
|
|
2379
2390
|
}
|
|
2380
2391
|
state.query = '';
|
|
@@ -2547,7 +2558,7 @@
|
|
|
2547
2558
|
|
|
2548
2559
|
function getTaskSource() {
|
|
2549
2560
|
return state.tasks
|
|
2550
|
-
.filter((task) => task
|
|
2561
|
+
.filter((task) => taskMatchesSelectionPath(task, state.currentPath))
|
|
2551
2562
|
.slice()
|
|
2552
2563
|
.sort(compareTasksByBrowseOrder);
|
|
2553
2564
|
}
|
|
@@ -3373,7 +3384,7 @@
|
|
|
3373
3384
|
setPath(taskPath) {
|
|
3374
3385
|
const nextPath = taskPath || 'workspaces';
|
|
3375
3386
|
const task = getSelectedTask();
|
|
3376
|
-
const selectedTaskInvalid = Boolean(task && task
|
|
3387
|
+
const selectedTaskInvalid = Boolean(task && !taskMatchesSelectionPath(task, nextPath));
|
|
3377
3388
|
if (state.currentPath === nextPath && !selectedTaskInvalid) {
|
|
3378
3389
|
return;
|
|
3379
3390
|
}
|
|
@@ -3386,7 +3397,7 @@
|
|
|
3386
3397
|
setTasks(tasks) {
|
|
3387
3398
|
state.tasks = Array.isArray(tasks) ? tasks.slice() : [];
|
|
3388
3399
|
const task = getSelectedTask();
|
|
3389
|
-
if (task
|
|
3400
|
+
if (!taskMatchesSelectionPath(task, state.currentPath)) {
|
|
3390
3401
|
state.selectedTaskId = '';
|
|
3391
3402
|
}
|
|
3392
3403
|
render();
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
<% if (agent === "electron") { %>
|
|
14
14
|
<link href="/electron.css" rel="stylesheet"/>
|
|
15
15
|
<% } %>
|
|
16
|
+
<script src="/task-launcher.js" defer></script>
|
|
16
17
|
</head>
|
|
17
18
|
<body class="<%= theme %> task-launcher-page task-page task-install-page" data-agent="<%= agent %>">
|
|
18
19
|
<%- include('partials/app_navheader', { agent }) %>
|
|
@@ -63,7 +64,7 @@
|
|
|
63
64
|
</section>
|
|
64
65
|
<% } %>
|
|
65
66
|
|
|
66
|
-
<form class="task-install-actions" method="post" action="/task/install">
|
|
67
|
+
<form class="task-install-actions" method="post" action="/task/install" data-task-pending-form="install">
|
|
67
68
|
<input type="hidden" name="ref" value="<%= ref %>">
|
|
68
69
|
<input type="hidden" name="returnTo" value="<%= returnTo %>">
|
|
69
70
|
<button class="task-button primary" type="submit">
|
|
@@ -71,6 +72,9 @@
|
|
|
71
72
|
<span>Install and continue</span>
|
|
72
73
|
</button>
|
|
73
74
|
<a class="task-link-button" href="/tasks">Cancel</a>
|
|
75
|
+
<p class="task-submit-feedback" data-task-submit-feedback aria-live="polite" aria-hidden="true">
|
|
76
|
+
<span data-task-submit-feedback-text></span>
|
|
77
|
+
</p>
|
|
74
78
|
</form>
|
|
75
79
|
</div>
|
|
76
80
|
</section>
|
|
@@ -17,12 +17,13 @@
|
|
|
17
17
|
<script src="/task-share.js" defer></script>
|
|
18
18
|
</head>
|
|
19
19
|
<%
|
|
20
|
-
const
|
|
20
|
+
const effectiveTaskPath = task.config.path === 'tasks' ? 'workspaces' : task.config.path
|
|
21
|
+
const runRootCopy = effectiveTaskPath === 'api'
|
|
21
22
|
? 'Creates a new app.'
|
|
22
|
-
:
|
|
23
|
+
: effectiveTaskPath === 'plugin'
|
|
23
24
|
? 'Creates a new plugin.'
|
|
24
25
|
: 'Runs in a new workspace.'
|
|
25
|
-
const folderMeta =
|
|
26
|
+
const folderMeta = effectiveTaskPath === 'workspaces' ? 'Optional' : ''
|
|
26
27
|
const headerDescription = task.config.description && !/{{/.test(task.config.description)
|
|
27
28
|
? task.config.description
|
|
28
29
|
: ''
|
|
@@ -114,7 +115,7 @@
|
|
|
114
115
|
<div class="task-status error"><%= error %></div>
|
|
115
116
|
<% } %>
|
|
116
117
|
|
|
117
|
-
<form class="task-run-form task-detail-layout" method="post" action="/task/start">
|
|
118
|
+
<form class="task-run-form task-detail-layout" method="post" action="/task/start" data-task-pending-form="run">
|
|
118
119
|
<input type="hidden" name="id" value="<%= task.id %>">
|
|
119
120
|
|
|
120
121
|
<div class="task-detail-main">
|
|
@@ -126,6 +127,9 @@
|
|
|
126
127
|
<span>Run</span>
|
|
127
128
|
</button>
|
|
128
129
|
<p class="task-inline-help">Tool and folder stay local. The permalink tracks only the task inputs.</p>
|
|
130
|
+
<p class="task-submit-feedback" data-task-submit-feedback aria-live="polite" aria-hidden="true">
|
|
131
|
+
<span data-task-submit-feedback-text></span>
|
|
132
|
+
</p>
|
|
129
133
|
</div>
|
|
130
134
|
</section>
|
|
131
135
|
</div>
|