@k2b/cloud 0.37.0 → 0.38.0
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/package.json +4 -2
- package/src/_internal/help-catalog.ts +123 -4
- package/src/_internal/help.ts +27 -6
- package/src/account/Avatar.tsx +20 -2
- package/src/account/ui.ts +1 -1
- package/src/ai/browser.ts +1 -0
- package/src/ai/chart-block.ts +44 -13
- package/src/ai/chat/chart-block.tsx +2 -11
- package/src/ai/chat/messages.ts +10 -0
- package/src/ai/chat/web-tools.tsx +23 -6
- package/src/ai/chat-tasks.ts +65 -1
- package/src/ai/default-tool-contracts.ts +30 -13
- package/src/ai/fetch-file-tool.ts +37 -3
- package/src/ai/migrate.ts +19 -2
- package/src/ai/readable-html.ts +1057 -0
- package/src/api/help.ts +23 -4
- package/src/api/mcp.ts +8 -2
- package/src/browser/FileChooser.tsx +11 -3
- package/src/browser/choose-files.browser-harness.tsx +4 -1
- package/src/browser/file-chooser-messages.ts +4 -0
- package/src/browser/file-providers.ts +14 -1
- package/src/browser/provider-folder.tsx +58 -5
- package/src/browser/resource-picker.tsx +5 -1
- package/src/cli/admin/workflows.ts +1 -0
- package/src/config/env.ts +14 -0
- package/src/contracts/file-provider.ts +48 -1
- package/src/contracts/outgoing-mail.ts +8 -1
- package/src/server/help.ts +136 -10
- package/src/server/services/geo.ts +21 -4
- package/src/services/allowed-network-fetch.ts +189 -0
- package/src/services/help/index.ts +46 -5
- package/src/services/help/store.ts +26 -5
- package/src/services/help/types.ts +10 -2
- package/src/services/index.ts +1 -0
- package/src/services/outgoing-mail/dispatcher.ts +7 -2
- package/src/services/outgoing-mail/resolve-host.ts +39 -0
- package/src/services/outgoing-mail/test-send.ts +18 -3
- package/src/services/outgoing-mail/transport.ts +24 -13
- package/src/services/settings/index.ts +48 -26
- package/src/shared/help.ts +41 -0
- package/src/shared/index.ts +9 -1
- package/src/shared/markdown/extensions/guided-help.ts +208 -64
- package/src/shared/markdown/formula.ts +8 -8
- package/src/shared/markdown/index.ts +72 -11
- package/src/ssr/Layout.tsx +20 -2
- package/src/ssr/LayoutHelp.browser-harness.tsx +130 -27
- package/src/ssr/LayoutHelp.tsx +569 -410
- package/src/ssr/ShellRuntime.island.tsx +17 -25
- package/src/ssr/help-messages.ts +60 -38
- package/src/ssr/help.ts +3 -0
- package/src/ssr/layout-help-article.ts +41 -0
- package/src/ssr/layout-help-navigation.ts +0 -12
- package/src/ssr/layout-help-registry.tsx +4 -11
- package/src/ssr/layout-help-search.ts +9 -12
- package/src/ssr/layout-help-start.ts +68 -0
- package/src/ssr/platform-messages.ts +4 -0
- package/src/ssr/shell-data.tsx +7 -0
- package/src/ssr/shell-shortcuts.ts +8 -0
- package/src/styles/effects.css +688 -185
- package/src/styles/resource-search.css +25 -0
- package/src/workflows/store/events.ts +24 -0
- package/src/workflows/store/index.ts +8 -0
- package/src/workflows/store/observability.ts +6 -1
- package/src/workflows/store/retention.ts +157 -0
|
@@ -1,43 +1,146 @@
|
|
|
1
|
-
import { LocaleProvider } from "@k2b/ui";
|
|
1
|
+
import { AppWorkspace, LocaleProvider } from "@k2b/ui";
|
|
2
2
|
import { render } from "solid-js/web";
|
|
3
|
+
import { registerContextAwareCommand } from "../browser/command-bridge";
|
|
3
4
|
import type { HelpDocumentManifest, HelpDocumentPayload } from "../shared/help";
|
|
4
|
-
import { LayoutHelpPage } from "./LayoutHelp";
|
|
5
|
+
import { LayoutHelpPage, openLayoutHelpDialog } from "./LayoutHelp";
|
|
6
|
+
import { registry } from "./layout-help-registry";
|
|
5
7
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
const params = new URL(location.href).searchParams;
|
|
9
|
+
const fixture = (id: string, title: string, order: number, kind?: HelpDocumentManifest["kind"], icon?: string): HelpDocumentManifest => ({
|
|
10
|
+
id,
|
|
11
|
+
title,
|
|
9
12
|
description: "Help browser fixture",
|
|
10
|
-
order
|
|
11
|
-
|
|
13
|
+
order,
|
|
14
|
+
...(kind ? { kind } : {}),
|
|
15
|
+
...(icon ? { icon } : {}),
|
|
16
|
+
url: `/api/help/${id}`,
|
|
12
17
|
searchUrl: "/api/help/search",
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
(
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
});
|
|
19
|
+
// `?start`: an app with every kind and more tasks than the start shows as tiles.
|
|
20
|
+
const startDocuments: HelpDocumentManifest[] = [
|
|
21
|
+
fixture("share-space", "Share a Space", 10, "task", "ti ti-share"),
|
|
22
|
+
fixture("claim-task", "Claim a task", 20, "task", "ti ti-hand-grab"),
|
|
23
|
+
fixture("statuses", "Create and order statuses", 30, "task", "ti ti-arrows-sort"),
|
|
24
|
+
fixture("calendar-feed", "See dates in your own calendar", 40, "task", "ti ti-calendar-share"),
|
|
25
|
+
fixture("templates", "Start from a template", 50, undefined, "ti ti-template"),
|
|
26
|
+
fixture("filters", "Filter and find items", 60, "task", "ti ti-filter"),
|
|
27
|
+
fixture("handoffs", "Hand work over", 70, "task", "ti ti-arrows-exchange"),
|
|
28
|
+
fixture("archive", "Archive a Space", 80, "task", "ti ti-archive"),
|
|
29
|
+
fixture("import", "Import tasks from a spreadsheet with a very long title that wraps", 90, "task", "ti ti-table-import"),
|
|
30
|
+
fixture("recurring", "Repeat a task", 100, "task", "ti ti-repeat"),
|
|
31
|
+
fixture("start", "Start with Spaces", 5, "start", "ti ti-rocket"),
|
|
32
|
+
fixture("access-levels", "Access levels", 110, "reference", "ti ti-key"),
|
|
33
|
+
fixture("troubleshoot", "Fix problems in Spaces", 120, "troubleshoot", "ti ti-lifebuoy"),
|
|
34
|
+
];
|
|
35
|
+
const documents: HelpDocumentManifest[] = params.has("start")
|
|
36
|
+
? startDocuments
|
|
37
|
+
: Array.from({ length: 8 }, (_, index) => fixture(`topic-${index}`, `Topic ${index}`, index));
|
|
38
|
+
// `?commands`: what the shell and an app register on a real page.
|
|
39
|
+
if (params.has("commands")) {
|
|
40
|
+
for (const command of [
|
|
41
|
+
{ id: "cloud.shell.focus", title: "Hide sidebar", description: "", shortcut: "mod+\\" },
|
|
42
|
+
{ id: "cloud.search", title: "Open global search", description: "", shortcut: "mod+k" },
|
|
43
|
+
{ id: "cloud.help", title: "Open shortcut help", description: "", shortcut: "shift+/" },
|
|
44
|
+
{ id: "spaces.new", title: "New task", description: "", shortcut: "n" },
|
|
45
|
+
{ id: "spaces.filter", title: "Filter tasks", description: "", shortcut: "f" },
|
|
46
|
+
{ id: "spaces.complete", title: "Complete selected", description: "", shortcut: "x", scope: "selection" as const },
|
|
47
|
+
])
|
|
48
|
+
registerContextAwareCommand({ ...command, action: () => {} });
|
|
49
|
+
}
|
|
50
|
+
const lead = "<p>Share a Space so that other people can see and change its tasks.</p>";
|
|
51
|
+
const longHtml =
|
|
52
|
+
lead +
|
|
53
|
+
Array.from(
|
|
54
|
+
{ length: 8 },
|
|
55
|
+
(_, index) =>
|
|
56
|
+
`<h2 id="section-${index}" class="help-section-title">Section ${index}</h2>${Array.from({ length: 18 }, () => "<p>Read this guidance to finish the task and understand how the app works.</p>").join("")}`,
|
|
57
|
+
).join("");
|
|
58
|
+
// A short task article: the short answer, one section, four steps.
|
|
59
|
+
const taskHtml = `${lead}<h2 id="invite-people" class="help-section-title">Invite people</h2><div class="help-steps"><ol class="k2b-steps"><li>Open <span class="k2b-label-chip">Space settings</span>.</li><li>Choose <span class="k2b-label-chip">Add person</span>.</li><li>Enter a name or a group.</li><li>Choose the access level.</li></ol></div><p>Spaces saves the change at once.</p><div class="help-compare"><ul><li><strong>Add a person</strong> Gives one named person access to every task in this Space.</li><li><strong>Add a group</strong> Gives everyone in the group access, including people who join later.</li></ul></div>`;
|
|
60
|
+
const link = (id: string, title: string, appId = "spaces", appName = "Spaces") => ({
|
|
61
|
+
appId,
|
|
62
|
+
appName,
|
|
63
|
+
accent: appId === "spaces" ? "#16a34a" : "#2563eb",
|
|
64
|
+
documentId: id,
|
|
65
|
+
title,
|
|
66
|
+
description: "Help browser fixture",
|
|
67
|
+
url: `/help/apps/${appId}/${id}`,
|
|
68
|
+
});
|
|
19
69
|
window.fetch = Object.assign(
|
|
20
70
|
async (input: URL | RequestInfo) => {
|
|
21
71
|
await new Promise((resolve) => setTimeout(resolve, 80));
|
|
22
72
|
const path = String(input);
|
|
23
|
-
if (path.includes("/search"))
|
|
73
|
+
if (path.includes("/search")) {
|
|
74
|
+
const query = new URL(path, location.href).searchParams.get("q") ?? "";
|
|
75
|
+
const ids = params.has("start")
|
|
76
|
+
? documents.filter((document) => document.title.toLocaleLowerCase().includes(query)).map((document) => document.id)
|
|
77
|
+
: ["topic-0", "topic-1"];
|
|
78
|
+
return Response.json({ locale: "en", ids });
|
|
79
|
+
}
|
|
24
80
|
const id = path.split("/").at(-1) ?? "topic-0";
|
|
25
|
-
const payload: HelpDocumentPayload = {
|
|
81
|
+
const payload: HelpDocumentPayload = {
|
|
82
|
+
id,
|
|
83
|
+
locale: "en",
|
|
84
|
+
title: id,
|
|
85
|
+
markdown: "Help",
|
|
86
|
+
html: id === "topic-1" ? taskHtml : longHtml,
|
|
87
|
+
kind: "task",
|
|
88
|
+
needs: "manage",
|
|
89
|
+
next: link("topic-2", "Topic 2"),
|
|
90
|
+
related: [link("topic-3", "Topic 3"), link("mail-share", "Share a mailbox", "mail", "Mail")],
|
|
91
|
+
};
|
|
26
92
|
return Response.json(payload);
|
|
27
93
|
},
|
|
28
94
|
{ preconnect: () => {} },
|
|
29
95
|
);
|
|
30
96
|
const main = document.querySelector<HTMLElement>(".layout-content-main");
|
|
31
97
|
if (!main) throw new Error("Missing Layout main");
|
|
32
|
-
const embedded =
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
98
|
+
const embedded = params.has("embedded");
|
|
99
|
+
const referenceHost = params.get("host");
|
|
100
|
+
if (referenceHost === "grids" || referenceHost === "pulse") {
|
|
101
|
+
// The Grids and Pulse query reference windows: one article beside the reference sidebar, without the Cloud shell.
|
|
102
|
+
const host = document.createElement("div");
|
|
103
|
+
host.className = "h-dvh";
|
|
104
|
+
document.body.replaceChildren(host);
|
|
105
|
+
const reader = () => <LayoutHelpPage documents={documents.slice(0, 1)} initialTopic="topic-0" includeShortcuts={false} embedded />;
|
|
106
|
+
render(
|
|
107
|
+
() => (
|
|
108
|
+
<LocaleProvider locale="en">
|
|
109
|
+
<AppWorkspace>
|
|
110
|
+
<AppWorkspace.Sidebar>
|
|
111
|
+
<AppWorkspace.SidebarDesktop>
|
|
112
|
+
<AppWorkspace.SidebarBody>Reference</AppWorkspace.SidebarBody>
|
|
113
|
+
</AppWorkspace.SidebarDesktop>
|
|
114
|
+
</AppWorkspace.Sidebar>
|
|
115
|
+
<AppWorkspace.Content>
|
|
116
|
+
{referenceHost === "grids" ? (
|
|
117
|
+
<AppWorkspace.Main class="p-[var(--ui-space-shell)]" scroll={false}>
|
|
118
|
+
<div class="flex min-h-0 flex-1 flex-col overflow-auto">{reader()}</div>
|
|
119
|
+
</AppWorkspace.Main>
|
|
120
|
+
) : (
|
|
121
|
+
<AppWorkspace.Main class="overflow-y-auto">{reader()}</AppWorkspace.Main>
|
|
122
|
+
)}
|
|
123
|
+
</AppWorkspace.Content>
|
|
124
|
+
</AppWorkspace>
|
|
125
|
+
</LocaleProvider>
|
|
126
|
+
),
|
|
127
|
+
host,
|
|
128
|
+
);
|
|
129
|
+
} else if (params.has("modal")) {
|
|
130
|
+
// The dialog reads the topics the page registered, as Layout.HelpDocuments does.
|
|
131
|
+
for (const manifest of documents) registry()?.set(manifest.id, manifest);
|
|
132
|
+
window.__cloudLayoutHelpPageBase = "/app/spaces/help";
|
|
133
|
+
openLayoutHelpDialog();
|
|
134
|
+
} else {
|
|
135
|
+
const host = document.createElement("div");
|
|
136
|
+
if (embedded) host.style.cssText = "width:360px;height:700px";
|
|
137
|
+
main.append(host);
|
|
138
|
+
render(
|
|
139
|
+
() => (
|
|
140
|
+
<LocaleProvider locale="en">
|
|
141
|
+
<LayoutHelpPage documents={documents} embedded={embedded} pageBase="/app/spaces/help" />
|
|
142
|
+
</LocaleProvider>
|
|
143
|
+
),
|
|
144
|
+
host,
|
|
145
|
+
);
|
|
146
|
+
}
|