clay-server 5.2.0-beta.9 → 5.2.1-beta.1
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/README.md +0 -4
- package/lib/clay-product-control-tools.js +1 -0
- package/lib/clay-product-control.js +14 -11
- package/lib/clay-vendor-usage.js +44 -0
- package/lib/github-star-count.js +147 -0
- package/lib/notes-checklist.js +43 -1
- package/lib/notes.js +2 -1
- package/lib/project-session-notes.js +33 -8
- package/lib/project-sessions.js +63 -24
- package/lib/project-start-protocol.js +29 -0
- package/lib/project-vendor-login.js +2 -0
- package/lib/project.js +5 -1
- package/lib/public/app.js +30 -18
- package/lib/public/css/command-palette.css +12 -2
- package/lib/public/css/contextual-clay.css +1 -1
- package/lib/public/css/filebrowser.css +4 -5
- package/lib/public/css/mate-loading-scene.css +21 -0
- package/lib/public/css/messages.css +30 -11
- package/lib/public/css/overlays.css +67 -256
- package/lib/public/css/project-mate-creation.css +5 -6
- package/lib/public/css/project-start.css +108 -0
- package/lib/public/css/projects-hub.css +53 -14
- package/lib/public/css/right-workbench.css +28 -0
- package/lib/public/css/settings-shell.css +103 -0
- package/lib/public/css/sidebar.css +7 -0
- package/lib/public/css/title-bar.css +99 -0
- package/lib/public/index.html +54 -66
- package/lib/public/modules/account-transport-settings.js +8 -2
- package/lib/public/modules/admin-settings-email.js +7 -2
- package/lib/public/modules/admin-settings-invitations.js +2 -2
- package/lib/public/modules/admin-settings-projects.js +2 -2
- package/lib/public/modules/admin-settings-ui.js +20 -4
- package/lib/public/modules/admin-settings-users.js +4 -4
- package/lib/public/modules/app-home-hub.js +2 -1
- package/lib/public/modules/app-messages.js +10 -2
- package/lib/public/modules/app-projects.js +1 -407
- package/lib/public/modules/app-rate-limit.js +12 -1
- package/lib/public/modules/clay-tool-presentation.js +1 -0
- package/lib/public/modules/contextual-clay.js +3 -1
- package/lib/public/modules/github-star.js +66 -0
- package/lib/public/modules/home-surface-boot.js +0 -1
- package/lib/public/modules/mate-loading-scene.js +17 -0
- package/lib/public/modules/pair-result-status.js +89 -39
- package/lib/public/modules/pane-appearance-bridge.js +59 -0
- package/lib/public/modules/profile.js +11 -3
- package/lib/public/modules/project-mate-creation-workspace.js +13 -4
- package/lib/public/modules/project-session-visibility-settings.js +19 -16
- package/lib/public/modules/project-settings-environment.js +12 -1
- package/lib/public/modules/project-settings.js +119 -129
- package/lib/public/modules/project-start-dialog.js +130 -0
- package/lib/public/modules/project-start-folder-state.js +78 -0
- package/lib/public/modules/project-start-folder-view.js +190 -0
- package/lib/public/modules/project-start-forms.js +66 -0
- package/lib/public/modules/project-start-path.js +60 -0
- package/lib/public/modules/project-start-state.js +54 -0
- package/lib/public/modules/project-start-submit.js +67 -0
- package/lib/public/modules/projects-hub-view.js +32 -44
- package/lib/public/modules/projects-hub.js +39 -28
- package/lib/public/modules/server-settings.js +36 -91
- package/lib/public/modules/settings-project-target.js +56 -0
- package/lib/public/modules/settings-select.js +1 -1
- package/lib/public/modules/settings-shell-registry.js +88 -0
- package/lib/public/modules/settings-shell-view.js +104 -0
- package/lib/public/modules/settings-shell.js +342 -0
- package/lib/public/modules/sidebar-mobile.js +8 -30
- package/lib/public/modules/sidebar-projects.js +2 -1
- package/lib/public/modules/theme.js +31 -3
- package/lib/public/modules/topbar-workbench-controls.js +102 -0
- package/lib/public/modules/user-settings-integrations.js +2 -1
- package/lib/public/modules/user-settings-layout.js +12 -34
- package/lib/public/modules/user-settings-profile.js +1 -1
- package/lib/public/modules/user-settings.js +18 -85
- package/lib/public/modules/vendor-usage-format.js +93 -0
- package/lib/public/modules/vendor-usage-list.js +45 -0
- package/lib/public/modules/vendor-usage-model.js +215 -0
- package/lib/public/modules/vendor-usage-overview.js +323 -0
- package/lib/public/style.css +13 -10
- package/lib/public/welcome-art/conversation-desk.png +0 -0
- package/lib/public/welcome-art/mate-clay.png +0 -0
- package/lib/public/welcome-art/project-clay.png +0 -0
- package/lib/sdk-bridge.js +6 -1
- package/lib/sdk-message-processor.js +9 -1
- package/lib/sdk-quota-snapshot.js +20 -2
- package/lib/server-github-stars.js +39 -0
- package/lib/server-global-ws.js +21 -17
- package/lib/server.js +11 -0
- package/lib/session-notes-mcp-server.js +26 -4
- package/lib/session-notes-writes.js +88 -0
- package/lib/session-visibility.js +20 -8
- package/lib/sessions.js +12 -2
- package/lib/vendor-usage-acp-readers.js +97 -0
- package/lib/vendor-usage-capabilities.js +88 -0
- package/lib/vendor-usage-http-readers.js +214 -0
- package/lib/vendor-usage-metrics.js +47 -0
- package/lib/vendor-usage-native-readers.js +106 -0
- package/lib/vendor-usage-overview.js +406 -0
- package/lib/vendor-usage-service.js +281 -0
- package/lib/ws-schema.js +4 -2
- package/lib/yoke/adapters/claude.js +12 -0
- package/lib/yoke/adapters/codex-query-contract.js +1 -0
- package/lib/yoke/adapters/codex.js +45 -12
- package/lib/yoke/claude-hook-installer.js +1 -0
- package/lib/yoke/codex-dynamic-tool-names.js +80 -0
- package/lib/yoke/codex-model-catalog.js +37 -3
- package/lib/yoke/muse-services.js +16 -3
- package/lib/yoke/providers/claude-model-descriptions.js +22 -2
- package/lib/yoke/vendor-registry.js +6 -2
- package/package.json +2 -1
- package/lib/public/modules/server-settings-navigation.js +0 -39
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* Unified full-screen settings shell. Personal, Project and Server panes keep
|
|
2
|
+
their ids (so the shared settings-ui primitives still apply) and mount into
|
|
3
|
+
the shell content; their former modal chrome is neutralised here. */
|
|
4
|
+
#settings-shell {
|
|
5
|
+
position: fixed; inset: 0; z-index: 600; display: flex; flex-direction: column;
|
|
6
|
+
background: var(--bg); color: var(--text);
|
|
7
|
+
}
|
|
8
|
+
#settings-shell.hidden { display: none; }
|
|
9
|
+
#settings-shell [hidden], #settings-shell .hidden { display: none !important; }
|
|
10
|
+
#settings-shell :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
11
|
+
|
|
12
|
+
/* --- Header: close and scope tabs --- */
|
|
13
|
+
.settings-shell-header {
|
|
14
|
+
flex: 0 0 auto; display: flex; align-items: center; gap: 12px; min-height: 48px;
|
|
15
|
+
padding: calc(var(--safe-top) + 6px) 16px 6px; border-bottom: 1px solid var(--border-subtle); background: var(--sidebar-bg);
|
|
16
|
+
}
|
|
17
|
+
.settings-shell-close {
|
|
18
|
+
display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 10px 0 8px; border: 1px solid var(--border);
|
|
19
|
+
border-radius: 8px; background: var(--bg); color: var(--text-secondary); font: inherit; font-size: 13px; cursor: pointer;
|
|
20
|
+
}
|
|
21
|
+
.settings-shell-close:hover { color: var(--text); border-color: var(--text-dimmer); }
|
|
22
|
+
.settings-shell-close svg { width: 16px; height: 16px; }
|
|
23
|
+
.settings-shell-close kbd { font: inherit; font-size: 11px; color: var(--text-dimmer); padding-left: 4px; }
|
|
24
|
+
.settings-scope-tabs { display: inline-flex; gap: 2px; padding: 3px; border: 1px solid var(--border); border-radius: 9px; background: var(--bg-alt); }
|
|
25
|
+
.settings-scope-tab {
|
|
26
|
+
min-width: 76px; height: 28px; padding: 0 12px; border: 0; border-radius: 6px; background: none;
|
|
27
|
+
color: var(--text-muted); font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
|
|
28
|
+
}
|
|
29
|
+
.settings-scope-tab:hover { color: var(--text); }
|
|
30
|
+
.settings-scope-tab.active { background: var(--bg); color: var(--text); box-shadow: 0 1px 3px rgba(0, 0, 0, .12); }
|
|
31
|
+
|
|
32
|
+
/* --- Body: navigation + content --- */
|
|
33
|
+
.settings-shell-body { flex: 1 1 auto; min-height: 0; display: flex; }
|
|
34
|
+
.settings-shell-nav { flex: 0 0 240px; width: 240px; overflow-y: auto; background: var(--sidebar-bg); border-right: 1px solid var(--border-subtle); }
|
|
35
|
+
.settings-shell-nav-inner { padding: 20px 12px 32px 14px; }
|
|
36
|
+
.settings-scope-head { display: flex; flex-direction: column; gap: 2px; padding: 0 10px 12px; margin-bottom: 8px; border-bottom: 1px solid var(--border-subtle); }
|
|
37
|
+
.settings-scope-head strong { font-size: 14px; color: var(--text); }
|
|
38
|
+
.settings-scope-head small { font-size: 12px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
39
|
+
.settings-scope-hint { font-size: 12px; line-height: 1.35; color: var(--text-muted); }
|
|
40
|
+
.settings-project-picker { padding: 0 4px 12px; }
|
|
41
|
+
.settings-project-picker .settings-label { display: block; margin: 0 0 6px 6px; font-size: 12px; color: var(--text-muted); }
|
|
42
|
+
.settings-project-picker .settings-picker { display: block; width: 100%; }
|
|
43
|
+
.settings-project-picker .settings-picker-menu { right: auto; left: 0; width: 100%; max-width: none; }
|
|
44
|
+
.settings-project-picker select { width: 100%; }
|
|
45
|
+
.settings-shell-nav .settings-nav-item { min-height: 32px; padding: 6px 10px; font-size: 13px; }
|
|
46
|
+
.settings-shell-nav .settings-nav-item.active { background: rgba(var(--overlay-rgb), .08); color: var(--text); }
|
|
47
|
+
.settings-shell-nav .settings-nav-item:focus-visible { outline-offset: -2px; }
|
|
48
|
+
.settings-shell-nav .settings-nav-dropdown { display: none; }
|
|
49
|
+
.settings-shell-content { flex: 1 1 auto; min-width: 0; overflow-y: auto; padding: 28px 40px calc(var(--safe-bottom) + 56px); }
|
|
50
|
+
.settings-shell-status { max-width: 760px; margin: 0 0 16px; padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-alt); color: var(--text-secondary); font-size: 13px; }
|
|
51
|
+
.settings-shell-status[data-state="error"] { border-color: color-mix(in srgb, var(--error) 40%, var(--border)); color: var(--error); }
|
|
52
|
+
|
|
53
|
+
/* --- Panes: neutralise the former modal/overlay chrome --- */
|
|
54
|
+
#settings-shell .settings-pane { position: static; inset: auto; z-index: auto; display: block; width: 100%; max-width: 760px; margin: 0; padding: 0; background: none; backdrop-filter: none; animation: none; overflow: visible; }
|
|
55
|
+
#settings-shell .settings-pane.hidden { display: none !important; }
|
|
56
|
+
#user-settings .us-modal, #project-settings .ps-modal {
|
|
57
|
+
position: static; display: block; width: auto; height: auto; border: 0; border-radius: 0; background: none; box-shadow: none; animation: none; overflow: visible;
|
|
58
|
+
}
|
|
59
|
+
#user-settings .us-modal-body, #project-settings .project-settings-layout { display: block; height: auto; overflow: visible; background: none; }
|
|
60
|
+
#user-settings .us-modal-content, #project-settings .project-settings-content, #server-settings .server-settings-content {
|
|
61
|
+
max-width: none; padding: 0; background: none; overflow: visible;
|
|
62
|
+
}
|
|
63
|
+
#project-settings .project-settings-content-inner, #server-settings .server-settings-content-inner { padding: 0; }
|
|
64
|
+
#server-settings .server-settings-layout { display: block; height: auto; background: none; }
|
|
65
|
+
#server-settings .server-settings-layout::after { display: none; }
|
|
66
|
+
#project-settings .ps-section h2, #user-settings .us-section h2, #server-settings .server-settings-section h2 { margin-top: 0; }
|
|
67
|
+
#project-settings.ps-no-target .ps-section { display: none; }
|
|
68
|
+
#project-settings .settings-empty { padding: 24px 0; }
|
|
69
|
+
|
|
70
|
+
/* --- Inline subviews (admin editors, avatar crop): replace the page's list in place --- */
|
|
71
|
+
.has-subview > :not(h2):not(.settings-subview) { display: none !important; }
|
|
72
|
+
.admin-subview, .avatar-positioner-inline { display: block; position: static; padding: 0; background: none; }
|
|
73
|
+
.admin-subview .admin-modal {
|
|
74
|
+
position: static; width: auto; max-width: 640px; max-height: none; margin: 0; border: 1px solid var(--border);
|
|
75
|
+
border-radius: 10px; background: var(--bg); box-shadow: none;
|
|
76
|
+
}
|
|
77
|
+
.admin-subview .admin-modal-header { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid var(--border-subtle); }
|
|
78
|
+
.admin-subview .admin-modal-header h3 { margin: 0; font-size: 14px; }
|
|
79
|
+
.admin-subview .admin-modal-body { padding: 14px 16px; overflow: visible; max-height: none; }
|
|
80
|
+
.admin-subview .admin-modal-footer { display: flex; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--border-subtle); }
|
|
81
|
+
.avatar-positioner-inline .avatar-positioner-container { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; max-width: 360px; padding: 16px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg); box-shadow: none; }
|
|
82
|
+
|
|
83
|
+
/* --- Narrow screens: tabs in the header, page select replaces the nav list --- */
|
|
84
|
+
@media (max-width: 800px) {
|
|
85
|
+
.settings-shell-header { padding-left: 10px; padding-right: 10px; gap: 8px; }
|
|
86
|
+
.settings-shell-close span, .settings-shell-close kbd { display: none; }
|
|
87
|
+
.settings-shell-close { width: 32px; padding: 0; justify-content: center; }
|
|
88
|
+
.settings-scope-tabs { flex: 1 1 auto; min-width: 0; }
|
|
89
|
+
.settings-scope-tab { flex: 1 1 0; min-width: 0; padding: 0 6px; }
|
|
90
|
+
.settings-shell-body { flex-direction: column; }
|
|
91
|
+
.settings-shell-nav { flex: 0 0 auto; width: 100%; max-height: 40%; border-right: 0; border-bottom: 1px solid var(--border-subtle); }
|
|
92
|
+
.settings-shell-nav-inner { padding: 10px 12px; display: grid; gap: 8px; }
|
|
93
|
+
.settings-scope-head { display: none; }
|
|
94
|
+
.settings-project-picker { padding: 0; }
|
|
95
|
+
.settings-project-picker .settings-picker { display: none; }
|
|
96
|
+
.settings-project-picker select { height: 36px; }
|
|
97
|
+
.settings-shell-nav-items { display: none; }
|
|
98
|
+
.settings-shell-nav .settings-nav-dropdown { display: block; width: 100%; height: 36px; margin: 0; }
|
|
99
|
+
.settings-shell-content { padding: 18px 14px calc(var(--safe-bottom) + 40px); }
|
|
100
|
+
}
|
|
101
|
+
@media (prefers-reduced-motion: reduce) {
|
|
102
|
+
#settings-shell * { transition: none !important; animation: none !important; }
|
|
103
|
+
}
|
|
@@ -1392,6 +1392,13 @@ body:not(.home-active) #icon-strip-hint-mate { display: none; }
|
|
|
1392
1392
|
.user-island-profile:active { transform: translateY(1px); }
|
|
1393
1393
|
.user-island-profile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
1394
1394
|
|
|
1395
|
+
.user-island-quick-controls {
|
|
1396
|
+
display: flex;
|
|
1397
|
+
align-items: center;
|
|
1398
|
+
justify-content: center;
|
|
1399
|
+
gap: 4px;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1395
1402
|
.cursor-share-toggle {
|
|
1396
1403
|
position: relative;
|
|
1397
1404
|
width: var(--account-rail-cursor-target, 28px);
|
|
@@ -93,6 +93,10 @@
|
|
|
93
93
|
right: 10px;
|
|
94
94
|
top: 50%;
|
|
95
95
|
transform: translateY(-50%);
|
|
96
|
+
/* The transform makes this group its own stacking context, so its popovers
|
|
97
|
+
are ordered by this value. Sit above chat layers but below contextual Clay
|
|
98
|
+
(160), the mobile overlays and modals. */
|
|
99
|
+
z-index: 150;
|
|
96
100
|
display: flex;
|
|
97
101
|
align-items: center;
|
|
98
102
|
gap: 2px;
|
|
@@ -116,6 +120,22 @@
|
|
|
116
120
|
|
|
117
121
|
#server-settings-btn.active { color: var(--text); }
|
|
118
122
|
|
|
123
|
+
/* Browser, Terminal and sticky-note visibility live beside Notifications and
|
|
124
|
+
Settings on desktop. Match those compact top-bar buttons; the same nodes keep
|
|
125
|
+
their own IDs, state and handlers (see topbar-workbench-controls.js). */
|
|
126
|
+
.top-bar-actions :is(#shared-browser-toggle-btn, #terminal-toggle-btn, #sticky-notes-toggle-btn) {
|
|
127
|
+
position: relative;
|
|
128
|
+
padding: 3px;
|
|
129
|
+
border: 0;
|
|
130
|
+
border-radius: 6px;
|
|
131
|
+
}
|
|
132
|
+
.top-bar-actions :is(#shared-browser-toggle-btn, #terminal-toggle-btn, #sticky-notes-toggle-btn) .lucide { width: 14px; height: 14px; }
|
|
133
|
+
.top-bar-actions :is(#shared-browser-toggle-btn, #terminal-toggle-btn, #sticky-notes-toggle-btn):hover { color: var(--text-secondary); background: rgba(var(--overlay-rgb), 0.06); border: 0; }
|
|
134
|
+
.top-bar-actions #shared-browser-toggle-btn:disabled:hover { background: none; }
|
|
135
|
+
/* These controls belong to a session: keep them out of the project-less shell and while the title bar is replaced by another view. */
|
|
136
|
+
body.projects-shell .top-bar-actions :is(#shared-browser-toggle-btn, #terminal-toggle-btn, #sticky-notes-toggle-btn),
|
|
137
|
+
#top-bar.title-bar-hidden .top-bar-actions :is(#shared-browser-toggle-btn, #terminal-toggle-btn, #sticky-notes-toggle-btn) { display: none; }
|
|
138
|
+
|
|
119
139
|
/* --- Theme toggle pill switch (light/dark) --- */
|
|
120
140
|
.theme-toggle {
|
|
121
141
|
display: flex;
|
|
@@ -906,3 +926,82 @@
|
|
|
906
926
|
.rate-limit-popover { font-size: 11px; padding: 6px 10px; }
|
|
907
927
|
.header-context { width: 50px; }
|
|
908
928
|
}
|
|
929
|
+
|
|
930
|
+
/* --- GitHub Star link (desktop only, beside the brand) --- */
|
|
931
|
+
.top-bar-star {
|
|
932
|
+
display: flex;
|
|
933
|
+
align-items: center;
|
|
934
|
+
gap: 6px;
|
|
935
|
+
flex: 0 0 auto;
|
|
936
|
+
white-space: nowrap;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
.top-bar-star-pill {
|
|
940
|
+
display: inline-flex;
|
|
941
|
+
align-items: stretch;
|
|
942
|
+
height: 20px;
|
|
943
|
+
border: 1px solid var(--border-subtle);
|
|
944
|
+
border-radius: 6px;
|
|
945
|
+
background: rgba(var(--overlay-rgb), 0.03);
|
|
946
|
+
color: var(--text-muted);
|
|
947
|
+
font-size: 11px;
|
|
948
|
+
font-weight: 600;
|
|
949
|
+
line-height: 18px;
|
|
950
|
+
text-decoration: none;
|
|
951
|
+
overflow: hidden;
|
|
952
|
+
transition: background 0.15s, border-color 0.15s, color 0.15s;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
.top-bar-star-pill:hover {
|
|
956
|
+
background: rgba(var(--overlay-rgb), 0.08);
|
|
957
|
+
border-color: var(--border);
|
|
958
|
+
color: var(--text-secondary);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
.top-bar-star-pill:active { transform: translateY(1px); }
|
|
962
|
+
|
|
963
|
+
.top-bar-star-pill:focus-visible {
|
|
964
|
+
outline: 2px solid var(--accent);
|
|
965
|
+
outline-offset: 2px;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
.top-bar-star-mark {
|
|
969
|
+
align-self: center;
|
|
970
|
+
width: 12px;
|
|
971
|
+
height: 12px;
|
|
972
|
+
margin: 0 4px 0 6px;
|
|
973
|
+
fill: currentColor;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
.top-bar-star-label { padding-right: 6px; }
|
|
977
|
+
|
|
978
|
+
.top-bar-star-count {
|
|
979
|
+
padding: 0 6px;
|
|
980
|
+
border-left: 1px solid var(--border-subtle);
|
|
981
|
+
font-variant-numeric: tabular-nums;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
.top-bar-star-count.hidden { display: none; }
|
|
985
|
+
|
|
986
|
+
@media (max-width: 790px) {
|
|
987
|
+
.top-bar-star-long { display: none; }
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
/* The CTA yields to functional controls sharing the left group: the install
|
|
991
|
+
pill shortens the label first (and takes the pill when space is tight); a
|
|
992
|
+
visible update notice takes the whole CTA. */
|
|
993
|
+
.top-bar-left-pills:has(.top-bar-install-btn:not(.hidden)) .top-bar-star-long { display: none; }
|
|
994
|
+
.top-bar-left-pills:has(#update-pill-wrap:not(.hidden)) .top-bar-star { display: none; }
|
|
995
|
+
|
|
996
|
+
@media (max-width: 1100px) {
|
|
997
|
+
.top-bar-left-pills:has(.top-bar-install-btn:not(.hidden)) .top-bar-star { display: none; }
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
@media (max-width: 768px) {
|
|
1001
|
+
.top-bar-star { display: none; }
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1005
|
+
.top-bar-star-pill { transition: none; }
|
|
1006
|
+
.top-bar-star-pill:active { transform: none; }
|
|
1007
|
+
}
|
package/lib/public/index.html
CHANGED
|
@@ -60,6 +60,9 @@ body { background: transparent; color: inherit; }
|
|
|
60
60
|
<div id="top-bar">
|
|
61
61
|
<div class="top-bar-left-pills">
|
|
62
62
|
<a class="top-bar-brand-link" href="https://github.com/chadbyte/clay" target="_blank" rel="noopener noreferrer" aria-label="Clay Studio repository"><span class="top-bar-brand-wordmark" aria-hidden="true"></span></a>
|
|
63
|
+
<div class="top-bar-star" id="github-star">
|
|
64
|
+
<a class="top-bar-star-pill" id="github-star-link" href="https://github.com/chadbyte/clay" target="_blank" rel="noopener noreferrer" aria-label="Star Clay on GitHub"><svg class="top-bar-star-mark" viewBox="0 0 16 16" aria-hidden="true" focusable="false"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg><span class="top-bar-star-label">Star<span class="top-bar-star-long"> on GitHub</span></span><span class="top-bar-star-count hidden" id="github-star-count"></span></a>
|
|
65
|
+
</div>
|
|
63
66
|
<button id="pwa-install-pill" class="top-bar-install-btn hidden" title="Open as app"><i data-lucide="download"></i> Open as app</button>
|
|
64
67
|
<div id="update-pill-wrap" class="top-bar-update hidden">
|
|
65
68
|
<button id="update-pill" class="top-bar-update-btn"><i data-lucide="arrow-up-circle"></i> <span id="update-version"></span> is available. Update now</button>
|
|
@@ -74,9 +77,12 @@ body { background: transparent; color: inherit; }
|
|
|
74
77
|
<!-- Pill badges -->
|
|
75
78
|
<div id="skip-perms-pill" class="top-bar-pill pill-error hidden"><i data-lucide="shield-off"></i> <span>Skip perms</span></div>
|
|
76
79
|
<div id="client-count" class="top-bar-pill pill-accent hidden"><i data-lucide="users"></i> <span id="client-count-text"></span></div>
|
|
77
|
-
|
|
80
|
+
<!-- Right workbench controls: same nodes and handlers as before; app JS returns them to the title bar on mobile. -->
|
|
81
|
+
<button type="button" id="shared-browser-toggle-btn" class="hidden" title="Browser" aria-label="Browser" aria-controls="shared-browser-panel" aria-expanded="false" disabled><i data-lucide="globe"></i></button>
|
|
82
|
+
<button id="terminal-toggle-btn" title="Terminal"><i data-lucide="square-terminal"></i><span id="terminal-count" class="hidden"></span></button>
|
|
83
|
+
<button type="button" id="sticky-notes-toggle-btn" aria-label="Hide sticky notes" aria-pressed="false" title="Hide sticky notes"><i data-lucide="eye-off"></i></button>
|
|
78
84
|
<button id="notif-center-btn" title="Notifications"><i data-lucide="bell"></i><span id="notif-center-badge" class="notif-badge hidden">0</span></button>
|
|
79
|
-
<button id="server-settings-btn" title="
|
|
85
|
+
<button id="server-settings-btn" title="Settings" aria-label="Settings" aria-expanded="false"><i data-lucide="settings"></i></button>
|
|
80
86
|
</div>
|
|
81
87
|
</div>
|
|
82
88
|
|
|
@@ -322,9 +328,6 @@ body { background: transparent; color: inherit; }
|
|
|
322
328
|
</button>
|
|
323
329
|
<button id="debate-pdf-btn" class="hidden" title="Export debate as PDF"><i data-lucide="download"></i></button>
|
|
324
330
|
<button id="find-in-session-btn" title="Search in session (Ctrl+F)"><i data-lucide="search"></i></button>
|
|
325
|
-
<button type="button" id="sticky-notes-toggle-btn" aria-label="Hide sticky notes" aria-pressed="false" title="Hide sticky notes"><i data-lucide="eye-off"></i></button>
|
|
326
|
-
<button type="button" id="shared-browser-toggle-btn" class="hidden" title="Browser" aria-label="Browser" aria-controls="shared-browser-panel" aria-expanded="false" disabled><i data-lucide="globe"></i></button>
|
|
327
|
-
<button id="terminal-toggle-btn" title="Terminal"><i data-lucide="square-terminal"></i><span id="terminal-count" class="hidden"></span></button>
|
|
328
331
|
</div>
|
|
329
332
|
</div>
|
|
330
333
|
<div id="main-panels">
|
|
@@ -657,13 +660,10 @@ body { background: transparent; color: inherit; }
|
|
|
657
660
|
</div>
|
|
658
661
|
</div>
|
|
659
662
|
<div id="project-settings" class="hidden">
|
|
660
|
-
<div class="ps-modal"
|
|
661
|
-
<header class="ps-modal-header"><div><h2 id="ps-modal-title">Project settings</h2><span id="ps-nav-title"></span></div><button class="settings-btn-sm" id="project-settings-close" aria-label="Close project settings"><i data-lucide="x"></i></button></header>
|
|
663
|
+
<div class="ps-modal">
|
|
662
664
|
<div class="project-settings-layout">
|
|
663
|
-
<nav class="project-settings-nav" aria-label="Project settings">
|
|
664
|
-
<div class="project-settings-nav-inner"><select id="ps-nav-dropdown" class="settings-nav-dropdown" aria-label="Settings page"></select><div class="server-settings-nav-items"></div></div>
|
|
665
|
-
</nav>
|
|
666
665
|
<div class="project-settings-content"><div class="project-settings-content-inner">
|
|
666
|
+
<div class="settings-empty" id="ps-empty" hidden><h2 tabindex="-1">No project selected</h2><p id="ps-empty-text" class="settings-hint"></p></div>
|
|
667
667
|
<section class="ps-section active" data-section="profile">
|
|
668
668
|
<h2>General</h2><p class="ps-section-desc">Identify this project in your workspace.</p>
|
|
669
669
|
<div class="ps-project-identity">
|
|
@@ -680,8 +680,8 @@ body { background: transparent; color: inherit; }
|
|
|
680
680
|
<div class="settings-field" id="ps-session-visibility-default-field" style="display:none">
|
|
681
681
|
<label class="settings-label" for="ps-session-visibility-default">New session visibility</label>
|
|
682
682
|
<div class="settings-hint">Applies to new project conversations and Issue Start work sessions. Existing sessions, hidden work, and delegated workflows keep their current visibility.</div>
|
|
683
|
+
<div class="settings-hint hidden" id="ps-session-visibility-default-owner-hint">Only the project owner can change this setting. Administrators can view it here but cannot change it.</div>
|
|
683
684
|
<div class="settings-hint hidden" id="ps-session-visibility-default-inherited-hint">This worktree inherits the setting from its parent project. Change it there.</div>
|
|
684
|
-
<div class="settings-hint hidden" id="ps-session-visibility-default-non-current-hint">Open this project to change this setting.</div>
|
|
685
685
|
<select class="ps-select" id="ps-session-visibility-default">
|
|
686
686
|
<option value="private">Private</option>
|
|
687
687
|
<option value="shared">Shared with project members</option>
|
|
@@ -737,11 +737,16 @@ body { background: transparent; color: inherit; }
|
|
|
737
737
|
<span class="user-island-cta hidden">Personalize your name</span>
|
|
738
738
|
</div>
|
|
739
739
|
</button>
|
|
740
|
-
<
|
|
741
|
-
<
|
|
742
|
-
|
|
740
|
+
<div class="user-island-quick-controls">
|
|
741
|
+
<button id="cursor-share-toggle" class="cursor-share-toggle" type="button" aria-pressed="false" aria-label="Cursor sharing unavailable" disabled>
|
|
742
|
+
<i data-lucide="mouse-pointer-2" class="cursor-share-icon" aria-hidden="true"></i>
|
|
743
|
+
</button>
|
|
744
|
+
<button id="appearance-mode-toggle" class="cursor-share-toggle" type="button" aria-label="Switch to light mode" title="Switch to light mode">
|
|
745
|
+
<i data-lucide="sun" class="cursor-share-icon" aria-hidden="true"></i>
|
|
746
|
+
</button>
|
|
747
|
+
</div>
|
|
743
748
|
<div class="user-island-actions">
|
|
744
|
-
<button id="user-settings-btn" title="
|
|
749
|
+
<button id="user-settings-btn" title="Personal settings" aria-label="Personal settings" aria-expanded="false"><i data-lucide="settings"></i></button>
|
|
745
750
|
</div>
|
|
746
751
|
</div>
|
|
747
752
|
|
|
@@ -780,19 +785,31 @@ body { background: transparent; color: inherit; }
|
|
|
780
785
|
</div>
|
|
781
786
|
</div>
|
|
782
787
|
|
|
783
|
-
<!-- ===
|
|
788
|
+
<!-- === Unified settings shell (full screen): Personal, Project and Server panes mount into it === -->
|
|
789
|
+
<div id="settings-shell" class="hidden" role="region" aria-label="Settings">
|
|
790
|
+
<header class="settings-shell-header">
|
|
791
|
+
<button type="button" id="settings-shell-close" class="settings-shell-close" aria-label="Close settings"><i data-lucide="arrow-left" aria-hidden="true"></i><span>Back</span><kbd>Esc</kbd></button>
|
|
792
|
+
<div class="settings-scope-tabs" id="settings-scope-tabs" role="group" aria-label="Settings scope"></div>
|
|
793
|
+
</header>
|
|
794
|
+
<div class="settings-shell-body">
|
|
795
|
+
<nav class="settings-shell-nav" aria-label="Settings navigation">
|
|
796
|
+
<div class="settings-shell-nav-inner">
|
|
797
|
+
<div class="settings-scope-head"><strong id="settings-scope-title">Settings</strong><small id="settings-server-name" hidden></small><span id="settings-scope-hint" class="settings-scope-hint"></span></div>
|
|
798
|
+
<div class="settings-project-picker" id="settings-project-picker" hidden><label class="settings-label" for="settings-project-select">Project</label><select id="settings-project-select" class="ps-select" aria-label="Project"></select></div>
|
|
799
|
+
<select id="settings-page-select" class="settings-nav-dropdown" aria-label="Settings page"></select>
|
|
800
|
+
<div class="settings-shell-nav-items" id="settings-page-nav"></div>
|
|
801
|
+
</div>
|
|
802
|
+
</nav>
|
|
803
|
+
<main class="settings-shell-content" id="settings-shell-content">
|
|
804
|
+
<p id="settings-shell-status" class="settings-shell-status" role="status" hidden></p>
|
|
805
|
+
</main>
|
|
806
|
+
</div>
|
|
807
|
+
</div>
|
|
808
|
+
|
|
809
|
+
<!-- === Personal settings pane === -->
|
|
784
810
|
<div id="user-settings" class="hidden">
|
|
785
|
-
<div class="confirm-backdrop" id="user-settings-backdrop"></div>
|
|
786
811
|
<div class="us-modal">
|
|
787
|
-
<div class="us-modal-header">
|
|
788
|
-
<span class="us-modal-title">User Settings</span>
|
|
789
|
-
<button class="us-modal-close" id="user-settings-close" title="Close"><i data-lucide="x"></i></button>
|
|
790
|
-
</div>
|
|
791
812
|
<div class="us-modal-body">
|
|
792
|
-
<nav class="us-modal-nav">
|
|
793
|
-
<select id="user-settings-nav-dropdown" class="settings-nav-dropdown"></select>
|
|
794
|
-
<div class="us-modal-nav-items"></div>
|
|
795
|
-
</nav>
|
|
796
813
|
<div class="us-modal-content">
|
|
797
814
|
|
|
798
815
|
<div class="us-section" data-section="us-notifications">
|
|
@@ -1031,16 +1048,8 @@ body { background: transparent; color: inherit; }
|
|
|
1031
1048
|
</div>
|
|
1032
1049
|
|
|
1033
1050
|
<!-- === Server Settings (full-screen overlay) === -->
|
|
1034
|
-
<div id="server-settings" class="hidden"
|
|
1051
|
+
<div id="server-settings" class="hidden">
|
|
1035
1052
|
<div class="server-settings-layout">
|
|
1036
|
-
<nav class="server-settings-nav" aria-label="Server settings pages">
|
|
1037
|
-
<div class="server-settings-nav-inner">
|
|
1038
|
-
<div class="server-settings-nav-header">Server settings<small id="settings-server-name"></small></div>
|
|
1039
|
-
<select id="settings-nav-dropdown" class="settings-nav-dropdown" aria-label="Settings page"></select>
|
|
1040
|
-
<div class="server-settings-nav-items" id="settings-page-nav"></div>
|
|
1041
|
-
<button class="settings-nav-item" id="settings-personal-link">Personal notifications ↗</button>
|
|
1042
|
-
</div>
|
|
1043
|
-
</nav>
|
|
1044
1053
|
<div class="server-settings-content"><div class="server-settings-content-inner">
|
|
1045
1054
|
<p id="settings-access-status" role="status">Checking administrator access…</p>
|
|
1046
1055
|
<div class="server-settings-section active" data-section="overview">
|
|
@@ -1248,7 +1257,7 @@ body { background: transparent; color: inherit; }
|
|
|
1248
1257
|
<div class="settings-hint settings-restart-error hidden" id="settings-restart-error" style="margin-top: 8px;"></div>
|
|
1249
1258
|
</div>
|
|
1250
1259
|
</div>
|
|
1251
|
-
</div><section class="settings-operation settings-danger-operation"><div class="settings-danger-entry"><div class="settings-danger-entry-copy"><h3>Danger zone</h3><p>Shut down Clay for everyone. Active work stops; restarting requires access to the host.</p></div><button type="button" class="settings-btn-sm settings-btn-danger" id="settings-shutdown-review" aria-expanded="false" aria-controls="settings-shutdown-flow"><i data-lucide="power" aria-hidden="true"></i>Review shutdown…</button></div><div id="settings-shutdown-flow" hidden role="group" aria-labelledby="settings-shutdown-title"><h4 id="settings-shutdown-title">Shut down server</h4><p class="settings-hint">Stops Clay, interrupts active work and disconnects everyone. You will need shell or service-manager access to start it again.</p><label class="settings-label" for="settings-shutdown-input">Type shutdown to continue</label><div class="settings-shutdown-input-row"><input type="text" id="settings-shutdown-input" autocomplete="off" spellcheck="false"><button class="settings-btn-sm settings-btn-danger" id="settings-shutdown-btn" disabled>Shut down…</button></div><p id="settings-shutdown-error" class="settings-hint hidden" role="status"></p><button type="button" class="settings-btn-sm" id="settings-shutdown-back">Back</button></div></section></div></div></div
|
|
1260
|
+
</div><section class="settings-operation settings-danger-operation"><div class="settings-danger-entry"><div class="settings-danger-entry-copy"><h3>Danger zone</h3><p>Shut down Clay for everyone. Active work stops; restarting requires access to the host.</p></div><button type="button" class="settings-btn-sm settings-btn-danger" id="settings-shutdown-review" aria-expanded="false" aria-controls="settings-shutdown-flow"><i data-lucide="power" aria-hidden="true"></i>Review shutdown…</button></div><div id="settings-shutdown-flow" hidden role="group" aria-labelledby="settings-shutdown-title"><h4 id="settings-shutdown-title">Shut down server</h4><p class="settings-hint">Stops Clay, interrupts active work and disconnects everyone. You will need shell or service-manager access to start it again.</p><label class="settings-label" for="settings-shutdown-input">Type shutdown to continue</label><div class="settings-shutdown-input-row"><input type="text" id="settings-shutdown-input" autocomplete="off" spellcheck="false"><button class="settings-btn-sm settings-btn-danger" id="settings-shutdown-btn" disabled>Shut down…</button></div><p id="settings-shutdown-error" class="settings-hint hidden" role="status"></p><button type="button" class="settings-btn-sm" id="settings-shutdown-back">Back</button></div></section></div></div></div></div></div>
|
|
1252
1261
|
|
|
1253
1262
|
<div id="paste-modal" class="hidden" role="dialog" aria-modal="true" aria-labelledby="paste-modal-title">
|
|
1254
1263
|
<div class="confirm-backdrop"></div>
|
|
@@ -1358,37 +1367,16 @@ body { background: transparent; color: inherit; }
|
|
|
1358
1367
|
</div>
|
|
1359
1368
|
</div>
|
|
1360
1369
|
|
|
1361
|
-
<div id="
|
|
1362
|
-
<div class="
|
|
1363
|
-
<div class="
|
|
1364
|
-
<
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
<button class="
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
<div class="add-project-body">
|
|
1372
|
-
<div class="add-project-panel active" data-panel="existing">
|
|
1373
|
-
<div class="add-project-input-wrap">
|
|
1374
|
-
<span id="add-project-prefix" class="add-project-prefix hidden"></span>
|
|
1375
|
-
<input type="text" id="add-project-input" placeholder="/" autocomplete="off" spellcheck="false">
|
|
1376
|
-
<div id="add-project-suggestions" class="hidden"></div>
|
|
1377
|
-
</div>
|
|
1378
|
-
</div>
|
|
1379
|
-
<div class="add-project-panel" data-panel="create">
|
|
1380
|
-
<input type="text" id="add-project-create-input" placeholder="Project name" autocomplete="off" spellcheck="false">
|
|
1381
|
-
</div>
|
|
1382
|
-
<div class="add-project-panel" data-panel="clone">
|
|
1383
|
-
<input type="text" id="add-project-clone-input" placeholder="https://github.com/user/repo" autocomplete="off" spellcheck="false">
|
|
1384
|
-
<div id="add-project-clone-progress" class="hidden"><span class="clone-spinner"></span><span id="add-project-clone-text">Cloning...</span></div>
|
|
1385
|
-
</div>
|
|
1386
|
-
<div id="add-project-error" class="hidden"></div>
|
|
1387
|
-
</div>
|
|
1388
|
-
<div class="confirm-actions">
|
|
1389
|
-
<button class="confirm-btn confirm-cancel" id="add-project-cancel">Cancel</button>
|
|
1390
|
-
<button class="confirm-btn confirm-ok" id="add-project-ok">Add</button>
|
|
1391
|
-
</div>
|
|
1370
|
+
<div id="project-start-modal" class="hidden">
|
|
1371
|
+
<div class="project-start-backdrop"></div>
|
|
1372
|
+
<div class="project-start-dialog" role="dialog" aria-modal="true" aria-labelledby="project-start-title" aria-describedby="project-start-subtitle" tabindex="-1">
|
|
1373
|
+
<header class="project-start-header">
|
|
1374
|
+
<button type="button" class="project-start-icon-btn" id="project-start-back" aria-label="Back to choices" hidden><i data-lucide="arrow-left"></i></button>
|
|
1375
|
+
<h2 id="project-start-title">Start a project</h2>
|
|
1376
|
+
<button type="button" class="project-start-icon-btn" id="project-start-close" aria-label="Close"><i data-lucide="x"></i></button>
|
|
1377
|
+
</header>
|
|
1378
|
+
<p class="project-start-subtitle" id="project-start-subtitle">Start something new, or pick up where you left off.</p>
|
|
1379
|
+
<div class="project-start-body" id="project-start-body"></div>
|
|
1392
1380
|
</div>
|
|
1393
1381
|
</div>
|
|
1394
1382
|
|
|
@@ -33,8 +33,14 @@ export function initAccountTransportSettings() {
|
|
|
33
33
|
'<div class="settings-form-actions"><button class="settings-btn-sm">Save connection settings</button></div></form><p class="settings-hint" role="status"></p>';
|
|
34
34
|
anchor.after(section);
|
|
35
35
|
section.querySelectorAll('[name=origin],[name=proxies]').forEach(function (input) { input.oninput = function () {
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
// A draft is the form differing from the saved values, so a manual revert clears it.
|
|
37
|
+
var saved = store.get('accountTransport') || {};
|
|
38
|
+
var origin = section.querySelector('[name=origin]').value.trim();
|
|
39
|
+
var proxies = section.querySelector('[name=proxies]').value.split(/\s+/).filter(Boolean);
|
|
40
|
+
var dirty = origin !== (saved.origin || '') || proxies.join('\n') !== (saved.trustedProxies || []).join('\n');
|
|
41
|
+
var state = Object.assign({}, saved, { dirty: dirty, error: '' });
|
|
42
|
+
if (dirty) setSettingsDraft('accountTransport', true); else clearSettingsDraft('accountTransport');
|
|
43
|
+
store.set({ accountTransport: state }); render(state);
|
|
38
44
|
}; });
|
|
39
45
|
section.querySelector('form').onsubmit = async function (event) {
|
|
40
46
|
event.preventDefault(); var password = section.querySelector('[name=password]');
|
|
@@ -96,8 +96,13 @@ function renderSmtpTab(body, cfg) {
|
|
|
96
96
|
|
|
97
97
|
body.innerHTML = html;
|
|
98
98
|
clearSettingsDraft('smtp');
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
// The draft is the form differing from what was rendered, so reverting a field clears it.
|
|
100
|
+
var fields = Array.from(body.querySelectorAll('input, select, textarea'));
|
|
101
|
+
function fieldValue(field) { return field.type === 'checkbox' ? field.checked : field.value; }
|
|
102
|
+
var baseline = fields.map(fieldValue);
|
|
103
|
+
function syncDraft() { setSettingsDraft('smtp', fields.some(function (field, index) { return fieldValue(field) !== baseline[index]; })); }
|
|
104
|
+
body.oninput = syncDraft;
|
|
105
|
+
body.onchange = syncDraft;
|
|
101
106
|
refreshIcons(body);
|
|
102
107
|
|
|
103
108
|
var errorEl = body.querySelector("#smtp-error");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { store } from './store.js';
|
|
2
2
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
3
3
|
import { showToast, copyToClipboard, escapeHtml } from './utils.js';
|
|
4
|
-
import { apiGet, apiPost, apiPut, apiDelete, showConfirmDialog, showConfirmResetPin, prepareAdminModal } from './admin-settings-ui.js';
|
|
4
|
+
import { apiGet, apiPost, apiPut, apiDelete, showConfirmDialog, showConfirmResetPin, prepareAdminModal, mountAdminSubview } from './admin-settings-ui.js';
|
|
5
5
|
// --- Invites ---
|
|
6
6
|
export function loadInvitesTab(body) {
|
|
7
7
|
apiGet("/api/admin/invites").then(function (data) {
|
|
@@ -138,7 +138,7 @@ function showEmailInvitePrompt(body) {
|
|
|
138
138
|
'<button class="admin-modal-cancel">Cancel</button>' +
|
|
139
139
|
'</div></div>';
|
|
140
140
|
modal.innerHTML = html;
|
|
141
|
-
|
|
141
|
+
mountAdminSubview(modal);
|
|
142
142
|
prepareAdminModal(modal);
|
|
143
143
|
refreshIcons(modal);
|
|
144
144
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { store } from './store.js';
|
|
2
2
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
3
3
|
import { showToast, copyToClipboard, escapeHtml } from './utils.js';
|
|
4
|
-
import { apiGet, apiPost, apiPut, apiDelete, showConfirmDialog, showConfirmResetPin, prepareAdminModal } from './admin-settings-ui.js';
|
|
4
|
+
import { apiGet, apiPost, apiPut, apiDelete, showConfirmDialog, showConfirmResetPin, prepareAdminModal, mountAdminSubview } from './admin-settings-ui.js';
|
|
5
5
|
// --- Projects ---
|
|
6
6
|
export function loadProjectsTab(body) {
|
|
7
7
|
var projectList = store.get('projectsHubList') || [];
|
|
@@ -168,7 +168,7 @@ function showProjectUsersModal(slug, parentBody) {
|
|
|
168
168
|
html += '</div>';
|
|
169
169
|
|
|
170
170
|
modal.innerHTML = html;
|
|
171
|
-
|
|
171
|
+
mountAdminSubview(modal);
|
|
172
172
|
prepareAdminModal(modal);
|
|
173
173
|
refreshIcons(modal);
|
|
174
174
|
|
|
@@ -14,13 +14,29 @@ export function apiPost(url, body) { return request(url, 'POST', body || {}); }
|
|
|
14
14
|
export function apiPut(url, body) { return request(url, 'PUT', body); }
|
|
15
15
|
export function apiDelete(url) { return request(url, 'DELETE'); }
|
|
16
16
|
|
|
17
|
+
// Editors open inline in the active Server settings page (a subview with its
|
|
18
|
+
// own Back/Cancel path) instead of over the page. Only destructive
|
|
19
|
+
// confirmations remain overlay dialogs.
|
|
20
|
+
export function mountAdminSubview(modal) {
|
|
21
|
+
var host = document.querySelector('#server-settings .server-settings-section.active');
|
|
22
|
+
if (!host) { document.body.appendChild(modal); return; }
|
|
23
|
+
modal.className = 'admin-subview settings-subview';
|
|
24
|
+
host.classList.add('has-subview');
|
|
25
|
+
host.appendChild(modal);
|
|
26
|
+
var observer = new MutationObserver(function () {
|
|
27
|
+
if (!host.querySelector('.settings-subview')) { host.classList.remove('has-subview'); observer.disconnect(); }
|
|
28
|
+
});
|
|
29
|
+
observer.observe(host, { childList: true });
|
|
30
|
+
}
|
|
31
|
+
|
|
17
32
|
export function prepareAdminModal(modal) {
|
|
18
33
|
if (modal.dataset.prepared) return;
|
|
19
34
|
modal.dataset.prepared = 'true';
|
|
20
35
|
var previous = document.activeElement;
|
|
21
|
-
var
|
|
36
|
+
var inline = modal.classList.contains('settings-subview');
|
|
37
|
+
var restore = inline ? function () {} : isolateSettingsDialog(modal);
|
|
22
38
|
var dialog = modal.querySelector('.admin-modal');
|
|
23
|
-
dialog.setAttribute('role', 'dialog'); dialog.setAttribute('aria-modal', 'true');
|
|
39
|
+
dialog.setAttribute('role', inline ? 'region' : 'dialog'); if (!inline) dialog.setAttribute('aria-modal', 'true');
|
|
24
40
|
var title = dialog.querySelector('h3'); dialog.setAttribute('aria-label', title ? title.textContent : 'Confirm action');
|
|
25
41
|
var dirty = false;
|
|
26
42
|
modal.addEventListener('input', function () { dirty = true; });
|
|
@@ -37,7 +53,7 @@ export function prepareAdminModal(modal) {
|
|
|
37
53
|
modal.addEventListener('keydown', function (event) {
|
|
38
54
|
event.stopPropagation();
|
|
39
55
|
if (event.key === 'Escape') { event.preventDefault(); if (dirty) cancel(event); else modal.remove(); }
|
|
40
|
-
trapSettingsFocus(event, modal);
|
|
56
|
+
if (!inline) trapSettingsFocus(event, modal);
|
|
41
57
|
});
|
|
42
58
|
modal.querySelectorAll('.admin-smtp-row').forEach(function (row) {
|
|
43
59
|
var label = row.querySelector('label'); var input = row.querySelector('input, select');
|
|
@@ -49,7 +65,7 @@ export function prepareAdminModal(modal) {
|
|
|
49
65
|
var closeObserver = new MutationObserver(function () {
|
|
50
66
|
if (!modal.isConnected) { closeObserver.disconnect(); restore(); if (previous && previous.isConnected) previous.focus(); }
|
|
51
67
|
});
|
|
52
|
-
closeObserver.observe(document.body, { childList: true });
|
|
68
|
+
closeObserver.observe(inline ? modal.parentElement : document.body, { childList: true });
|
|
53
69
|
var focus = modal.querySelector('input:not([type=hidden]), .admin-modal-cancel, button');
|
|
54
70
|
if (focus) focus.focus();
|
|
55
71
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { store } from './store.js';
|
|
2
2
|
import { iconHtml, refreshIcons } from './icons.js';
|
|
3
3
|
import { showToast, copyToClipboard, escapeHtml } from './utils.js';
|
|
4
|
-
import { apiGet, apiPost, apiPut, apiDelete, showConfirmDialog, showConfirmResetPin, prepareAdminModal } from './admin-settings-ui.js';
|
|
4
|
+
import { apiGet, apiPost, apiPut, apiDelete, showConfirmDialog, showConfirmResetPin, prepareAdminModal, mountAdminSubview } from './admin-settings-ui.js';
|
|
5
5
|
// --- Users ---
|
|
6
6
|
export function loadUsersTab(body) {
|
|
7
7
|
apiGet("/api/admin/users").then(function (data) {
|
|
@@ -163,7 +163,7 @@ function showPermissionsModal(user, body) {
|
|
|
163
163
|
'</div></div>';
|
|
164
164
|
|
|
165
165
|
modal.innerHTML = html;
|
|
166
|
-
|
|
166
|
+
mountAdminSubview(modal);
|
|
167
167
|
prepareAdminModal(modal);
|
|
168
168
|
refreshIcons(modal);
|
|
169
169
|
|
|
@@ -222,7 +222,7 @@ function showAddUserModal(body) {
|
|
|
222
222
|
'<button class="admin-modal-cancel">Cancel</button>' +
|
|
223
223
|
'</div></div>';
|
|
224
224
|
modal.innerHTML = html;
|
|
225
|
-
|
|
225
|
+
mountAdminSubview(modal);
|
|
226
226
|
prepareAdminModal(modal);
|
|
227
227
|
refreshIcons(modal);
|
|
228
228
|
|
|
@@ -299,7 +299,7 @@ function showTempPinModal(user, tempPin) {
|
|
|
299
299
|
'<button class="admin-modal-cancel">Close</button>' +
|
|
300
300
|
'</div></div>';
|
|
301
301
|
modal.innerHTML = html;
|
|
302
|
-
|
|
302
|
+
mountAdminSubview(modal);
|
|
303
303
|
prepareAdminModal(modal);
|
|
304
304
|
refreshIcons(modal);
|
|
305
305
|
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
import { showProjectsHub, hideProjectsHub } from './projects-hub.js';
|
|
4
4
|
import { store } from './store.js';
|
|
5
5
|
import { getWs } from './ws-ref.js';
|
|
6
|
-
import { getCachedProjects,
|
|
6
|
+
import { getCachedProjects, switchProject } from './app-projects.js';
|
|
7
|
+
import { openAddProjectModal } from './project-start-dialog.js';
|
|
7
8
|
import { chooseProjectActivationTarget, homeProjectCreationState } from './project-activation.js';
|
|
8
9
|
import { mateAvatarUrl } from './avatar.js';
|
|
9
10
|
import { exitDmMode } from './app-dm.js';
|