@nocobase/cli 2.1.0-beta.2 → 2.1.0-beta.20
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/LICENSE.txt +107 -0
- package/README.md +367 -19
- package/README.zh-CN.md +336 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +116 -0
- package/dist/commands/api/resource/create.js +15 -0
- package/dist/commands/api/resource/destroy.js +15 -0
- package/dist/commands/api/resource/get.js +15 -0
- package/dist/commands/api/resource/index.js +20 -0
- package/dist/commands/api/resource/list.js +16 -0
- package/dist/commands/api/resource/query.js +15 -0
- package/dist/commands/api/resource/update.js +15 -0
- package/dist/commands/build.js +57 -0
- package/dist/commands/db/logs.js +85 -0
- package/dist/commands/db/ps.js +60 -0
- package/dist/commands/db/shared.js +81 -0
- package/dist/commands/db/start.js +70 -0
- package/dist/commands/db/stop.js +70 -0
- package/dist/commands/dev.js +149 -0
- package/dist/commands/down.js +193 -0
- package/dist/commands/download.js +865 -0
- package/dist/commands/env/add.js +327 -0
- package/dist/commands/env/auth.js +62 -0
- package/dist/commands/env/list.js +41 -0
- package/dist/commands/env/remove.js +65 -0
- package/dist/commands/env/update.js +73 -0
- package/dist/commands/env/use.js +36 -0
- package/dist/commands/init.js +822 -0
- package/dist/commands/install.js +1888 -0
- package/dist/commands/logs.js +90 -0
- package/dist/commands/pm/disable.js +63 -0
- package/dist/commands/pm/enable.js +63 -0
- package/dist/commands/pm/list.js +54 -0
- package/dist/commands/prompts-stages.js +150 -0
- package/dist/commands/prompts-test.js +181 -0
- package/dist/commands/ps.js +116 -0
- package/dist/commands/restart.js +74 -0
- package/dist/commands/scaffold/migration.js +38 -0
- package/dist/commands/scaffold/plugin.js +37 -0
- package/dist/commands/self/check.js +71 -0
- package/dist/commands/self/index.js +20 -0
- package/dist/commands/self/update.js +76 -0
- package/dist/commands/skills/check.js +63 -0
- package/dist/commands/skills/index.js +20 -0
- package/dist/commands/skills/install.js +58 -0
- package/dist/commands/skills/update.js +58 -0
- package/dist/commands/start.js +211 -0
- package/dist/commands/stop.js +90 -0
- package/dist/commands/test.js +466 -0
- package/dist/commands/upgrade.js +583 -0
- package/dist/generated/command-registry.js +133 -0
- package/dist/help/runtime-help.js +20 -0
- package/dist/lib/api-client.js +243 -0
- package/dist/lib/app-runtime.js +142 -0
- package/dist/lib/auth-store.js +241 -0
- package/dist/lib/bootstrap.js +387 -0
- package/dist/lib/build-config.js +10 -0
- package/dist/lib/cli-home.js +30 -0
- package/dist/lib/cli-locale.js +115 -0
- package/dist/lib/command-discovery.js +39 -0
- package/dist/lib/env-auth.js +872 -0
- package/dist/lib/generated-command.js +142 -0
- package/dist/lib/naming.js +70 -0
- package/dist/lib/openapi.js +62 -0
- package/dist/lib/post-processors.js +23 -0
- package/dist/lib/prompt-catalog.js +581 -0
- package/dist/lib/prompt-validators.js +185 -0
- package/dist/lib/prompt-web-ui.js +2096 -0
- package/dist/lib/resource-command.js +335 -0
- package/dist/lib/resource-request.js +104 -0
- package/dist/lib/run-npm.js +197 -0
- package/dist/lib/runtime-generator.js +419 -0
- package/dist/lib/runtime-store.js +56 -0
- package/dist/lib/self-manager.js +246 -0
- package/dist/lib/skills-manager.js +202 -0
- package/dist/lib/ui.js +175 -0
- package/dist/locale/en-US.json +333 -0
- package/dist/locale/zh-CN.json +333 -0
- package/dist/post-processors/data-modeling.js +66 -0
- package/dist/post-processors/data-source-manager.js +114 -0
- package/dist/post-processors/index.js +19 -0
- package/nocobase-ctl.config.json +287 -0
- package/package.json +60 -26
- package/LICENSE +0 -661
- package/bin/index.js +0 -39
- package/nocobase.conf.tpl +0 -95
- package/src/cli.js +0 -19
- package/src/commands/benchmark.js +0 -73
- package/src/commands/build.js +0 -49
- package/src/commands/clean.js +0 -30
- package/src/commands/client.js +0 -166
- package/src/commands/create-nginx-conf.js +0 -37
- package/src/commands/create-plugin.js +0 -33
- package/src/commands/dev.js +0 -200
- package/src/commands/doc.js +0 -76
- package/src/commands/e2e.js +0 -265
- package/src/commands/global.js +0 -43
- package/src/commands/index.js +0 -45
- package/src/commands/instance-id.js +0 -47
- package/src/commands/locale/cronstrue.js +0 -122
- package/src/commands/locale/react-js-cron/en-US.json +0 -75
- package/src/commands/locale/react-js-cron/index.js +0 -17
- package/src/commands/locale/react-js-cron/zh-CN.json +0 -33
- package/src/commands/locale/react-js-cron/zh-TW.json +0 -33
- package/src/commands/locale.js +0 -81
- package/src/commands/p-test.js +0 -88
- package/src/commands/perf.js +0 -63
- package/src/commands/pkg.js +0 -321
- package/src/commands/pm2.js +0 -37
- package/src/commands/postinstall.js +0 -88
- package/src/commands/start.js +0 -148
- package/src/commands/tar.js +0 -36
- package/src/commands/test-coverage.js +0 -55
- package/src/commands/test.js +0 -107
- package/src/commands/umi.js +0 -33
- package/src/commands/update-deps.js +0 -72
- package/src/commands/upgrade.js +0 -47
- package/src/commands/view-license-key.js +0 -44
- package/src/index.js +0 -14
- package/src/license.js +0 -76
- package/src/logger.js +0 -75
- package/src/plugin-generator.js +0 -80
- package/src/util.js +0 -517
- package/templates/bundle-status.html +0 -338
- package/templates/create-app-package.json +0 -39
- package/templates/plugin/.npmignore.tpl +0 -2
- package/templates/plugin/README.md.tpl +0 -1
- package/templates/plugin/client.d.ts +0 -2
- package/templates/plugin/client.js +0 -1
- package/templates/plugin/package.json.tpl +0 -11
- package/templates/plugin/server.d.ts +0 -2
- package/templates/plugin/server.js +0 -1
- package/templates/plugin/src/client/client.d.ts +0 -249
- package/templates/plugin/src/client/index.tsx.tpl +0 -1
- package/templates/plugin/src/client/locale.ts +0 -21
- package/templates/plugin/src/client/models/index.ts +0 -12
- package/templates/plugin/src/client/plugin.tsx.tpl +0 -10
- package/templates/plugin/src/index.ts +0 -2
- package/templates/plugin/src/locale/en-US.json +0 -1
- package/templates/plugin/src/locale/zh-CN.json +0 -1
- package/templates/plugin/src/server/collections/.gitkeep +0 -0
- package/templates/plugin/src/server/index.ts.tpl +0 -1
- package/templates/plugin/src/server/plugin.ts.tpl +0 -19
|
@@ -0,0 +1,2096 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from 'node:child_process';
|
|
10
|
+
import { createServer } from 'node:http';
|
|
11
|
+
import { createCliTranslate, resolveCliLocale, resolveLocalizedText, } from "./cli-locale.js";
|
|
12
|
+
import { isPromptBlockSkipped, runPromptFieldValidate, } from "./prompt-catalog.js";
|
|
13
|
+
const DEFAULT_SUBMIT = '/__pwc_ui_submit';
|
|
14
|
+
const DEFAULT_REFLOW = '/__pwc_ui_reflow';
|
|
15
|
+
const DEFAULT_VALIDATE_STEP = '/__pwc_ui_validate_step';
|
|
16
|
+
const DEFAULT_VALIDATE_FIELD = '/__pwc_ui_validate_field';
|
|
17
|
+
/** Form POST JSON meta field: current wizard step index when validating "Next" (not a prompt key). */
|
|
18
|
+
export const PWC_FORM_META_STEP = '_pwcStep';
|
|
19
|
+
/** Form POST JSON meta field: current field key when validating a single field. */
|
|
20
|
+
export const PWC_FORM_META_FIELD = '_pwcField';
|
|
21
|
+
const DEFAULT_TIMEOUT_MS = 30 * 60 * 1000;
|
|
22
|
+
const DEFAULT_HOST = '127.0.0.1';
|
|
23
|
+
function resolveUiText(text, locale, fallback = '') {
|
|
24
|
+
return resolveLocalizedText(text, { locale, fallback });
|
|
25
|
+
}
|
|
26
|
+
function hasValueKey(iv, key) {
|
|
27
|
+
return (Object.prototype.hasOwnProperty.call(iv, key) && iv[key] !== undefined && iv[key] !== null);
|
|
28
|
+
}
|
|
29
|
+
function resolveTextDefault(def, out) {
|
|
30
|
+
const iv = def.initialValue;
|
|
31
|
+
if (typeof iv === 'function') {
|
|
32
|
+
return String(iv(out) ?? '');
|
|
33
|
+
}
|
|
34
|
+
return String(iv ?? '');
|
|
35
|
+
}
|
|
36
|
+
function isInputBlock(def) {
|
|
37
|
+
return (def.type === 'text' ||
|
|
38
|
+
def.type === 'boolean' ||
|
|
39
|
+
def.type === 'select' ||
|
|
40
|
+
def.type === 'password' ||
|
|
41
|
+
def.type === 'integer');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Merges CLI/env **`userPreset`** with catalog block defaults, in the same key order and with the
|
|
45
|
+
* same `hidden` / `run` semantics as {@link isPromptBlockSkipped}, so the web form can prefill
|
|
46
|
+
* and reflow `hidden` fields (e.g. `integer` when `select` changes).
|
|
47
|
+
*/
|
|
48
|
+
export function buildWebFormValuesFromCatalog(catalog, userPreset = {}) {
|
|
49
|
+
const out = {};
|
|
50
|
+
for (const [key, def] of Object.entries(catalog)) {
|
|
51
|
+
if (def.type === 'intro' || def.type === 'outro') {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (def.type === 'run') {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (!isInputBlock(def)) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (isPromptBlockSkipped(def, out)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (hasValueKey(userPreset, key)) {
|
|
64
|
+
out[key] = userPreset[key];
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
out[key] = defaultValueForInput(key, def, out);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
function defaultValueForInput(key, def, out) {
|
|
73
|
+
switch (def.type) {
|
|
74
|
+
case 'text':
|
|
75
|
+
return resolveTextDefault(def, out);
|
|
76
|
+
case 'boolean':
|
|
77
|
+
return def.initialValue !== undefined ? Boolean(def.initialValue) : true;
|
|
78
|
+
case 'select': {
|
|
79
|
+
const first = def.options
|
|
80
|
+
.find((o) => typeof o === 'string' || o.disabled !== true);
|
|
81
|
+
const firstValue = typeof first === 'string' ? first : first?.value;
|
|
82
|
+
const i = def.initialValue;
|
|
83
|
+
const enabledValues = def.options
|
|
84
|
+
.filter((o) => typeof o === 'string' || o.disabled !== true)
|
|
85
|
+
.map((o) => (typeof o === 'string' ? o : o.value));
|
|
86
|
+
if (i !== undefined && enabledValues.includes(i)) {
|
|
87
|
+
return i;
|
|
88
|
+
}
|
|
89
|
+
return firstValue ?? '';
|
|
90
|
+
}
|
|
91
|
+
case 'password':
|
|
92
|
+
return def.initialValue ?? '';
|
|
93
|
+
case 'integer':
|
|
94
|
+
return def.initialValue !== undefined && Number.isFinite(def.initialValue) ? def.initialValue : 0;
|
|
95
|
+
default:
|
|
96
|
+
return '';
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Recomputes per-field visibility and the cumulative `out` used to evaluate `hidden` / `run`,
|
|
101
|
+
* from current raw form data (e.g. after changing `select`). Matches how {@link isPromptBlockSkipped} uses `out` while iterating the catalog.
|
|
102
|
+
*/
|
|
103
|
+
export function reflowWebFormState(catalog, raw, userSeed = {}) {
|
|
104
|
+
const out = {};
|
|
105
|
+
const show = {};
|
|
106
|
+
for (const [key, def] of Object.entries(catalog)) {
|
|
107
|
+
if (def.type === 'intro' || def.type === 'outro') {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (def.type === 'run') {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (!isInputBlock(def)) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (isPromptBlockSkipped(def, out)) {
|
|
117
|
+
show[key] = false;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
show[key] = true;
|
|
121
|
+
let val;
|
|
122
|
+
if (rawBodyHasValueForKey(raw, key)) {
|
|
123
|
+
val = normalizeWebRawForBlock(def, raw[key], key);
|
|
124
|
+
}
|
|
125
|
+
else if (hasValueKey(userSeed, key)) {
|
|
126
|
+
val = userSeed[key];
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
val = defaultValueForInput(key, def, out);
|
|
130
|
+
}
|
|
131
|
+
out[key] = val;
|
|
132
|
+
}
|
|
133
|
+
return { show, values: out };
|
|
134
|
+
}
|
|
135
|
+
/** `false` and `0` are valid; only `null` / `undefined` (or missing key) are treated as absent. */
|
|
136
|
+
function rawBodyHasValueForKey(raw, key) {
|
|
137
|
+
if (!Object.prototype.hasOwnProperty.call(raw, key)) {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
const v = raw[key];
|
|
141
|
+
return v !== undefined && v !== null;
|
|
142
|
+
}
|
|
143
|
+
function normalizeWebRawForBlock(def, raw, key) {
|
|
144
|
+
switch (def.type) {
|
|
145
|
+
case 'text':
|
|
146
|
+
return String(raw ?? '');
|
|
147
|
+
case 'boolean': {
|
|
148
|
+
if (raw === false || raw === 'false' || raw === 0) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
return raw === true || raw === 'true' || raw === 1 || raw === '1';
|
|
152
|
+
}
|
|
153
|
+
case 'select': {
|
|
154
|
+
const s = String(raw ?? '');
|
|
155
|
+
const list = def.options
|
|
156
|
+
.filter((o) => typeof o === 'string' || o.disabled !== true)
|
|
157
|
+
.map((o) => (typeof o === 'string' ? o : o.value));
|
|
158
|
+
if (list.includes(s)) {
|
|
159
|
+
return s;
|
|
160
|
+
}
|
|
161
|
+
return list[0] ?? s;
|
|
162
|
+
}
|
|
163
|
+
case 'password':
|
|
164
|
+
return String(raw ?? '');
|
|
165
|
+
case 'integer': {
|
|
166
|
+
if (typeof raw === 'number' && Number.isFinite(raw)) {
|
|
167
|
+
return Math.trunc(raw);
|
|
168
|
+
}
|
|
169
|
+
const t = String(raw ?? '').trim();
|
|
170
|
+
if (t === '' || !/^-?\d+$/.test(t)) {
|
|
171
|
+
return def.initialValue !== undefined && Number.isFinite(def.initialValue) ? def.initialValue : 0;
|
|
172
|
+
}
|
|
173
|
+
return Number.parseInt(t, 10);
|
|
174
|
+
}
|
|
175
|
+
default:
|
|
176
|
+
return String(raw);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Final preset `values` for {@link import('./prompt-catalog.ts').runPromptCatalog} from HTTP JSON body
|
|
181
|
+
* (same keys and semantics as a filled web form: hidden fields omitted from the result when skipped).
|
|
182
|
+
* Runs per-field **`validate`** (including async) from the catalog (honoring {@link BuildWebPresetFromBodyOptions}).
|
|
183
|
+
*/
|
|
184
|
+
export async function buildWebPresetFromBody(catalog, raw, userSeed = {}, buildOpts = {}) {
|
|
185
|
+
const locale = resolveCliLocale(buildOpts.locale);
|
|
186
|
+
const t = createCliTranslate(locale);
|
|
187
|
+
const scope = buildOpts.scopeKeys ?? null;
|
|
188
|
+
const inScope = (k) => scope === null || scope.has(k);
|
|
189
|
+
const preset = {};
|
|
190
|
+
for (const [key, def] of Object.entries(catalog)) {
|
|
191
|
+
if (def.type === 'intro' || def.type === 'outro') {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (def.type === 'run') {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (!isInputBlock(def)) {
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (isPromptBlockSkipped(def, preset)) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
let val;
|
|
204
|
+
if (rawBodyHasValueForKey(raw, key)) {
|
|
205
|
+
val = normalizeWebRawForBlock(def, raw[key], key);
|
|
206
|
+
}
|
|
207
|
+
else if (hasValueKey(userSeed, key)) {
|
|
208
|
+
val = userSeed[key];
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
val = defaultValueForInput(key, def, preset);
|
|
212
|
+
}
|
|
213
|
+
if (def.type === 'text' && def.required && val === '' && inScope(key)) {
|
|
214
|
+
return { preset: {}, error: t('promptCatalog.web.fieldRequired', { key }), fieldKey: key };
|
|
215
|
+
}
|
|
216
|
+
if (def.type === 'password' && def.required && val === '' && inScope(key)) {
|
|
217
|
+
return { preset: {}, error: t('promptCatalog.web.fieldRequired', { key }), fieldKey: key };
|
|
218
|
+
}
|
|
219
|
+
if (def.type === 'integer' && def.required && inScope(key)) {
|
|
220
|
+
const trimmed = String(raw[key] ?? '').trim();
|
|
221
|
+
if (trimmed === '') {
|
|
222
|
+
return { preset: {}, error: t('promptCatalog.web.fieldRequired', { key }), fieldKey: key };
|
|
223
|
+
}
|
|
224
|
+
if (!/^-?\d+$/.test(trimmed)) {
|
|
225
|
+
return { preset: {}, error: t('promptCatalog.web.fieldMustBeInteger', { key }), fieldKey: key };
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
preset[key] = val;
|
|
229
|
+
if (inScope(key)) {
|
|
230
|
+
const errCustom = await runPromptFieldValidate(def, val, preset);
|
|
231
|
+
if (errCustom) {
|
|
232
|
+
return { preset: {}, error: errCustom, fieldKey: key };
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return { preset };
|
|
237
|
+
}
|
|
238
|
+
function escapeHtml(s) {
|
|
239
|
+
return s
|
|
240
|
+
.replace(/&/g, '&')
|
|
241
|
+
.replace(/</g, '<')
|
|
242
|
+
.replace(/"/g, '"')
|
|
243
|
+
.replace(/'/g, ''');
|
|
244
|
+
}
|
|
245
|
+
function computePwcWizardSteps(options, merged, locale) {
|
|
246
|
+
const t = createCliTranslate(locale);
|
|
247
|
+
if (options.stages && options.stages.length > 0) {
|
|
248
|
+
if (options.stages.length === 1) {
|
|
249
|
+
const st0 = options.stages[0];
|
|
250
|
+
const allKeys = [];
|
|
251
|
+
for (const [key, def] of Object.entries(merged)) {
|
|
252
|
+
if (isInputBlock(def)) {
|
|
253
|
+
allKeys.push(key);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const title = resolveUiText(st0.sectionTitle, locale).trim();
|
|
257
|
+
const description = resolveUiText(st0.sectionDescription, locale).trim();
|
|
258
|
+
return [
|
|
259
|
+
{
|
|
260
|
+
title: title && title.length > 0 ? title : t('promptCatalog.web.defaultFormTitle'),
|
|
261
|
+
...(description && description.length > 0 ? { description } : {}),
|
|
262
|
+
keys: allKeys,
|
|
263
|
+
},
|
|
264
|
+
];
|
|
265
|
+
}
|
|
266
|
+
return options.stages.map((st, i) => {
|
|
267
|
+
const keys = [];
|
|
268
|
+
for (const [key, def] of Object.entries(st.catalog)) {
|
|
269
|
+
if (isInputBlock(def)) {
|
|
270
|
+
keys.push(key);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const title = resolveUiText(st.sectionTitle, locale).trim();
|
|
274
|
+
const description = resolveUiText(st.sectionDescription, locale).trim();
|
|
275
|
+
return {
|
|
276
|
+
title: title && title.length > 0 ? title : t('promptCatalog.web.defaultStepTitle', { index: i + 1 }),
|
|
277
|
+
...(description && description.length > 0 ? { description } : {}),
|
|
278
|
+
keys,
|
|
279
|
+
};
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
const allKeys = [];
|
|
283
|
+
for (const [key, def] of Object.entries(merged)) {
|
|
284
|
+
if (isInputBlock(def)) {
|
|
285
|
+
allKeys.push(key);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
if (allKeys.length === 0) {
|
|
289
|
+
return [];
|
|
290
|
+
}
|
|
291
|
+
/* Single `catalog` (no `stages`): one page, no side Steps nav — use `stages` for multi-page UI. */
|
|
292
|
+
return [{ title: t('promptCatalog.web.defaultFormTitle'), keys: allKeys }];
|
|
293
|
+
}
|
|
294
|
+
/** antd Form.Item-style explain line (per-field error / help). */
|
|
295
|
+
const PWC_FORM_ITEM_EXPLAIN = '<div class="pwc-form-item-explain" data-pwc-explain="1" role="alert" hidden></div>';
|
|
296
|
+
/** Suffix slot for status icon (e.g. fail) — filled by client script. */
|
|
297
|
+
const PWC_FORM_ITEM_SUFFIX = '<span class="pwc-form-item-suffix" data-pwc-suffix="1" aria-hidden="true"></span>';
|
|
298
|
+
function renderPwcRadioOptions(key, def, defaults, hidden, locale) {
|
|
299
|
+
return def.options
|
|
300
|
+
.map((o, index) => {
|
|
301
|
+
const val = typeof o === 'string' ? o : o.value;
|
|
302
|
+
const lab = typeof o === 'string' ? o : resolveUiText(o.label, locale, o.value);
|
|
303
|
+
const hint = typeof o === 'string'
|
|
304
|
+
? ''
|
|
305
|
+
: o.hint
|
|
306
|
+
? `<div class="pwc-radio-option-hint">${escapeHtml(resolveUiText(o.hint, locale))}</div>`
|
|
307
|
+
: '';
|
|
308
|
+
const optionDisabled = typeof o !== 'string' && o.disabled === true;
|
|
309
|
+
const checked = String(defaults[key] ?? '') === val ? ' checked' : '';
|
|
310
|
+
const required = def.required && index === 0 ? ' required' : '';
|
|
311
|
+
const disabled = hidden || optionDisabled ? ' disabled' : '';
|
|
312
|
+
const optionClass = optionDisabled ? 'pwc-radio-option pwc-radio-option--disabled' : 'pwc-radio-option';
|
|
313
|
+
const ariaDisabled = optionDisabled ? ' aria-disabled="true"' : '';
|
|
314
|
+
const staticDisabled = optionDisabled ? ' data-pwc-static-disabled="1"' : '';
|
|
315
|
+
return (`<label class="${optionClass}"${ariaDisabled}>` +
|
|
316
|
+
`<input class="pwc-radio-input" name="${escapeHtml(key)}" type="radio" value="${escapeHtml(String(val))}"${checked}${required}${disabled}${staticDisabled} />` +
|
|
317
|
+
`<span class="pwc-radio-option-body">` +
|
|
318
|
+
`<span class="pwc-radio-option-label">${escapeHtml(String(lab))}</span>` +
|
|
319
|
+
hint +
|
|
320
|
+
`</span>` +
|
|
321
|
+
`</label>`);
|
|
322
|
+
})
|
|
323
|
+
.join('');
|
|
324
|
+
}
|
|
325
|
+
function renderPwcFieldRow(key, def, defaults, show, locale) {
|
|
326
|
+
if (!isInputBlock(def)) {
|
|
327
|
+
return '';
|
|
328
|
+
}
|
|
329
|
+
const labelText = 'message' in def ? resolveUiText(def.message, locale, key) : key;
|
|
330
|
+
const hidden = show[key] === false;
|
|
331
|
+
const display = hidden ? 'none' : 'block';
|
|
332
|
+
const itemOpen = (extraClass) => `<div class="pwc-form-item${extraClass ? ` ${extraClass}` : ''}" data-pwc-wrap="${escapeHtml(key)}" data-pwc-field="${escapeHtml(key)}" style="display:${display}">`;
|
|
333
|
+
if (def.type === 'text') {
|
|
334
|
+
const req = def.required ? ' required' : '';
|
|
335
|
+
const disabled = hidden ? ' disabled' : '';
|
|
336
|
+
const ph = def.placeholder ? ` placeholder="${escapeHtml(resolveUiText(def.placeholder, locale))}"` : '';
|
|
337
|
+
const v = escapeHtml(String(defaults[key] ?? ''));
|
|
338
|
+
return (itemOpen('') +
|
|
339
|
+
`<div class="pwc-form-item-label"><span class="pwc-l">${escapeHtml(labelText)}</span></div>` +
|
|
340
|
+
`<div class="pwc-form-item-control">` +
|
|
341
|
+
`<div class="pwc-form-item-control-input">` +
|
|
342
|
+
`<div class="pwc-input-affix-wrapper">` +
|
|
343
|
+
`<input class="pwc-form-input" name="${escapeHtml(key)}" type="text" value="${v}"${ph}${req}${disabled} autocomplete="off" />` +
|
|
344
|
+
PWC_FORM_ITEM_SUFFIX +
|
|
345
|
+
`</div></div>` +
|
|
346
|
+
PWC_FORM_ITEM_EXPLAIN +
|
|
347
|
+
`</div></div>`);
|
|
348
|
+
}
|
|
349
|
+
if (def.type === 'boolean') {
|
|
350
|
+
const checked = defaults[key] === true ? ' checked' : '';
|
|
351
|
+
const disabled = hidden ? ' disabled' : '';
|
|
352
|
+
return (itemOpen('pwc-form-item--bool') +
|
|
353
|
+
`<div class="pwc-bool-wrap"><label><input class="pwc-bool-input" name="${escapeHtml(key)}" type="checkbox" value="1"${checked}${disabled} /> <span class="pwc-l">${escapeHtml(labelText)}</span></label></div>` +
|
|
354
|
+
PWC_FORM_ITEM_EXPLAIN +
|
|
355
|
+
`</div>`);
|
|
356
|
+
}
|
|
357
|
+
if (def.type === 'select') {
|
|
358
|
+
if (def.variant === 'radio') {
|
|
359
|
+
const opts = renderPwcRadioOptions(key, def, defaults, hidden, locale);
|
|
360
|
+
return (itemOpen('') +
|
|
361
|
+
`<div class="pwc-form-item-label"><span class="pwc-l">${escapeHtml(labelText)}</span></div>` +
|
|
362
|
+
`<div class="pwc-form-item-control">` +
|
|
363
|
+
`<div class="pwc-form-item-control-input">` +
|
|
364
|
+
`<div class="pwc-radio-group" role="radiogroup" aria-label="${escapeHtml(labelText)}">` +
|
|
365
|
+
opts +
|
|
366
|
+
`</div></div>` +
|
|
367
|
+
PWC_FORM_ITEM_EXPLAIN +
|
|
368
|
+
`</div></div>`);
|
|
369
|
+
}
|
|
370
|
+
const opts = def.options
|
|
371
|
+
.map((o) => {
|
|
372
|
+
const val = typeof o === 'string' ? o : o.value;
|
|
373
|
+
const lab = typeof o === 'string' ? o : resolveUiText(o.label, locale, o.value);
|
|
374
|
+
const sel = String(defaults[key] ?? '') === val ? ' selected' : '';
|
|
375
|
+
const disabledOpt = typeof o !== 'string' && o.disabled === true ? ' disabled' : '';
|
|
376
|
+
return `<option value="${escapeHtml(String(val))}"${sel}${disabledOpt}>${escapeHtml(String(lab))}</option>`;
|
|
377
|
+
})
|
|
378
|
+
.join('');
|
|
379
|
+
const req = def.required ? ' required' : '';
|
|
380
|
+
const disabled = hidden ? ' disabled' : '';
|
|
381
|
+
return (itemOpen('') +
|
|
382
|
+
`<div class="pwc-form-item-label"><span class="pwc-l">${escapeHtml(labelText)}</span></div>` +
|
|
383
|
+
`<div class="pwc-form-item-control">` +
|
|
384
|
+
`<div class="pwc-form-item-control-input">` +
|
|
385
|
+
`<div class="pwc-input-affix-wrapper pwc-input-affix-wrapper--select">` +
|
|
386
|
+
`<select class="pwc-form-input" name="${escapeHtml(key)}"${req}${disabled}>${opts}</select>` +
|
|
387
|
+
PWC_FORM_ITEM_SUFFIX +
|
|
388
|
+
`</div></div>` +
|
|
389
|
+
PWC_FORM_ITEM_EXPLAIN +
|
|
390
|
+
`</div></div>`);
|
|
391
|
+
}
|
|
392
|
+
if (def.type === 'password') {
|
|
393
|
+
const req = def.required ? ' required' : '';
|
|
394
|
+
const disabled = hidden ? ' disabled' : '';
|
|
395
|
+
const v = escapeHtml(String(defaults[key] ?? ''));
|
|
396
|
+
return (itemOpen('') +
|
|
397
|
+
`<div class="pwc-form-item-label"><span class="pwc-l">${escapeHtml(labelText)}</span></div>` +
|
|
398
|
+
`<div class="pwc-form-item-control">` +
|
|
399
|
+
`<div class="pwc-form-item-control-input">` +
|
|
400
|
+
`<div class="pwc-input-affix-wrapper">` +
|
|
401
|
+
`<input class="pwc-form-input" name="${escapeHtml(key)}" type="password" value="${v}"${req}${disabled} autocomplete="new-password" />` +
|
|
402
|
+
PWC_FORM_ITEM_SUFFIX +
|
|
403
|
+
`</div></div>` +
|
|
404
|
+
PWC_FORM_ITEM_EXPLAIN +
|
|
405
|
+
`</div></div>`);
|
|
406
|
+
}
|
|
407
|
+
if (def.type === 'integer') {
|
|
408
|
+
const ph = def.placeholder ? ` placeholder="${escapeHtml(resolveUiText(def.placeholder, locale))}"` : '';
|
|
409
|
+
const req = def.required ? ' required' : '';
|
|
410
|
+
const disabled = hidden ? ' disabled' : '';
|
|
411
|
+
const v = String(defaults[key] ?? 0);
|
|
412
|
+
return (itemOpen('') +
|
|
413
|
+
`<div class="pwc-form-item-label"><span class="pwc-l">${escapeHtml(labelText)}</span></div>` +
|
|
414
|
+
`<div class="pwc-form-item-control">` +
|
|
415
|
+
`<div class="pwc-form-item-control-input">` +
|
|
416
|
+
`<div class="pwc-input-affix-wrapper">` +
|
|
417
|
+
`<input class="pwc-form-input" name="${escapeHtml(key)}" type="number" inputmode="numeric" step="1" value="${escapeHtml(v)}"${ph}${req}${disabled} />` +
|
|
418
|
+
PWC_FORM_ITEM_SUFFIX +
|
|
419
|
+
`</div></div>` +
|
|
420
|
+
PWC_FORM_ITEM_EXPLAIN +
|
|
421
|
+
`</div></div>`);
|
|
422
|
+
}
|
|
423
|
+
return '';
|
|
424
|
+
}
|
|
425
|
+
/* Ant Design Steps icon: ~14px inside 32px container (iconFontSize token) */
|
|
426
|
+
const PWC_AD_CHECK_SVG = `<svg class="pwc-ad-icon-check-svg" viewBox="0 0 12 12" width="14" height="14" focusable="false" aria-hidden="true"><path fill="currentColor" d="M10.28 1.5L4.4 7.4 1.7 4.7 0.5 5.9l3.2 3.2 1.1 1.1L11.4 2.6z"/></svg>`;
|
|
427
|
+
/** antd Alert `type="error"`-style leading icon (14px) — @see https://ant.design/components/alert */
|
|
428
|
+
const PWC_AD_ALERT_ERROR_ICON_SVG = `<svg class="pwc-ad-alert__svg" viewBox="0 0 14 14" width="14" height="14" focusable="false" aria-hidden="true"><path fill="currentColor" d="M7 0.5a6.5 6.5 0 1 0 0 13a6.5 6.5 0 0 0 0-13zm0 1.2a5.3 5.3 0 1 1 0 10.6A5.3 5.3 0 0 1 7 1.7zM6.4 3.4h1.2v3.6H6.4V3.4zm0 4.5h1.2v1.1H6.4V7.9z"/></svg>`;
|
|
429
|
+
/** antd Alert `type="success"`-style leading icon (14px) — @see https://ant.design/components/alert */
|
|
430
|
+
const PWC_AD_ALERT_SUCCESS_ICON_SVG = `<svg class="pwc-ad-alert__svg" viewBox="0 0 14 14" width="14" height="14" focusable="false" aria-hidden="true"><path fill="currentColor" d="M7 0.5a6.5 6.5 0 1 0 0 13a6.5 6.5 0 0 0 0-13zm-1 8.45L3.65 6.1l-.85.85L6 10.15l5.2-5.2-.85-.85L6.5 7.95z"/></svg>`;
|
|
431
|
+
/** Suffix “fail” icon (antd Form validation) — @see https://ant.design/components/form */
|
|
432
|
+
const PWC_FORM_FAIL_ICON_SVG = `<svg class="pwc-form-fail__svg" viewBox="0 0 14 14" width="14" height="14" focusable="false" aria-hidden="true"><circle cx="7" cy="7" r="6.5" fill="currentColor"/><path fill="none" stroke="#fff" stroke-width="1.2" stroke-linecap="round" d="M4.2 4.2l5.6 5.6M9.8 4.2l-5.6 5.6"/></svg>`;
|
|
433
|
+
/**
|
|
434
|
+
* **Vertical** {@link https://ant.design/components/steps-cn | Steps} (`orientation="vertical"`),
|
|
435
|
+
* with CSS aligned to antd tokens (icon 32px, 14px title, `colorSplit` rail, `wait` / `process` / `finish`).
|
|
436
|
+
* Primary in steps uses antd default blue in light / `#1668dc` in dark; form primary buttons still use the page accent.
|
|
437
|
+
*/
|
|
438
|
+
function buildPwcAntdStyleStepsHeader(stepDefs, currentIndex, total, visibleStepIndices, uiText) {
|
|
439
|
+
const parts = [];
|
|
440
|
+
for (let i = 0; i < total; i += 1) {
|
|
441
|
+
const st = i < stepDefs.length ? stepDefs[i] : { title: `Step ${i + 1}`, keys: [] };
|
|
442
|
+
const t = st.title;
|
|
443
|
+
const rawDesc = st.description?.trim() ?? '';
|
|
444
|
+
const descHtml = rawDesc.length > 0
|
|
445
|
+
? `<div class="pwc-ad-steps-item-description">${escapeHtml(rawDesc)}</div>`
|
|
446
|
+
: '';
|
|
447
|
+
const visiblePos = visibleStepIndices.indexOf(i);
|
|
448
|
+
const currentVisiblePos = visibleStepIndices.indexOf(currentIndex);
|
|
449
|
+
const state = visiblePos < currentVisiblePos ? 'finish' : i === currentIndex ? 'process' : 'wait';
|
|
450
|
+
const num = visiblePos + 1;
|
|
451
|
+
const hiddenAttr = visiblePos === -1 ? ' hidden' : '';
|
|
452
|
+
const iconHtml = state === 'finish'
|
|
453
|
+
? `<span class="pwc-ad-icon pwc-ad-icon--finish" aria-label="${escapeHtml(uiText.doneAriaLabel)}">${PWC_AD_CHECK_SVG}</span>`
|
|
454
|
+
: `<span class="pwc-ad-icon" aria-label="${num}"><span class="pwc-ad-icon-num">${num}</span></span>`;
|
|
455
|
+
const ariaCurrent = state === 'process' ? 'step' : 'false';
|
|
456
|
+
const nextVisible = visibleStepIndices.indexOf(i + 1) !== -1;
|
|
457
|
+
const tailDone = visiblePos !== -1 && currentVisiblePos !== -1 && visiblePos < currentVisiblePos;
|
|
458
|
+
const tailHtml = i < total - 1
|
|
459
|
+
? `<div class="pwc-ad-vert__tail" data-pwc-vtail="${i}" data-pwc-conn="${tailDone ? 'done' : 'todo'}" aria-hidden="true"${nextVisible && visiblePos !== -1 ? '' : ' hidden'}></div>`
|
|
460
|
+
: '';
|
|
461
|
+
parts.push(`<li class="pwc-ad-steps-item pwc-ad-steps-item--${state}" data-pwc-step-idx="${i}" data-pwc-state="${state}" role="listitem" aria-current="${ariaCurrent}"${hiddenAttr}>` +
|
|
462
|
+
`<div class="pwc-ad-steps-item-row">` +
|
|
463
|
+
`<div class="pwc-ad-vert">` +
|
|
464
|
+
`<div class="pwc-ad-vert__icon" aria-hidden="true">${iconHtml}</div>` +
|
|
465
|
+
tailHtml +
|
|
466
|
+
`</div>` +
|
|
467
|
+
`<div class="pwc-ad-vert__main">` +
|
|
468
|
+
`<div class="pwc-ad-steps-item-title" title="${escapeHtml(t)}">${escapeHtml(t)}</div>` +
|
|
469
|
+
descHtml +
|
|
470
|
+
`</div>` +
|
|
471
|
+
`</div></li>`);
|
|
472
|
+
}
|
|
473
|
+
return (`<nav class="pwc-ad-steps pwc-ad-steps--vertical" id="pwcAntSteps" aria-label="${escapeHtml(uiText.stepsAriaLabel)}" style="--pwc-ad-n:${total}">` +
|
|
474
|
+
`<ol class="pwc-ad-steps-list pwc-ad-steps-list--vertical">${parts.join('')}</ol></nav>`);
|
|
475
|
+
}
|
|
476
|
+
function computeInitialVisibleStepIndices(catalog, stepDefs, show) {
|
|
477
|
+
const visible = [];
|
|
478
|
+
for (let i = 0; i < stepDefs.length; i += 1) {
|
|
479
|
+
if (i === 0) {
|
|
480
|
+
visible.push(i);
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
483
|
+
const hasVisibleField = stepDefs[i].keys.some((key) => {
|
|
484
|
+
const def = catalog[key];
|
|
485
|
+
return Boolean(def && isInputBlock(def) && show[key] !== false);
|
|
486
|
+
});
|
|
487
|
+
if (hasVisibleField) {
|
|
488
|
+
visible.push(i);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return visible.length > 0 ? visible : [0];
|
|
492
|
+
}
|
|
493
|
+
function buildPwcFormHtml(catalog, defaults, show, stepDefs, initialStepIndex, totalSteps, locale, uiText) {
|
|
494
|
+
if (stepDefs.length === 0) {
|
|
495
|
+
return '';
|
|
496
|
+
}
|
|
497
|
+
const oneStep = stepDefs.length === 1;
|
|
498
|
+
const visibleStepIndices = computeInitialVisibleStepIndices(catalog, stepDefs, show);
|
|
499
|
+
const out = [];
|
|
500
|
+
if (!oneStep) {
|
|
501
|
+
out.push('<div class="pwc-wizard pwc-wizard--with-sidebar" id="pwcWizard">');
|
|
502
|
+
out.push(`<aside class="pwc-wizard-sidenav" id="pwcWizardSidenav" aria-label="${escapeHtml(uiText.stepsSidebarAriaLabel)}">`);
|
|
503
|
+
out.push(buildPwcAntdStyleStepsHeader(stepDefs, initialStepIndex, totalSteps, visibleStepIndices, uiText));
|
|
504
|
+
out.push('</aside><div class="pwc-wizard-main">');
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
out.push('<div class="pwc-wizard" id="pwcWizard">');
|
|
508
|
+
}
|
|
509
|
+
for (let i = 0; i < stepDefs.length; i += 1) {
|
|
510
|
+
const sd = stepDefs[i];
|
|
511
|
+
const active = i === initialStepIndex;
|
|
512
|
+
const hiddenAttr = active ? '' : ' hidden';
|
|
513
|
+
out.push(`<section class="pwc-step${active ? ' pwc-step--active' : ''}" data-pwc-step="${i}"${hiddenAttr} aria-label="${escapeHtml(sd.title)}">`);
|
|
514
|
+
if (!oneStep) {
|
|
515
|
+
out.push(`<h2 class="pwc-step-title">${escapeHtml(sd.title)}</h2>`);
|
|
516
|
+
}
|
|
517
|
+
for (const key of sd.keys) {
|
|
518
|
+
const def = catalog[key];
|
|
519
|
+
if (def) {
|
|
520
|
+
out.push(renderPwcFieldRow(key, def, defaults, show, locale));
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
out.push('</section>');
|
|
524
|
+
}
|
|
525
|
+
if (!oneStep) {
|
|
526
|
+
out.push(`<div class="pwc-wizard-ctl" id="pwcWizardCtl" role="group" aria-label="${escapeHtml(uiText.stepNavigationAriaLabel)}">` +
|
|
527
|
+
`<button type="button" class="pwc-btn-pager" id="pwcBack" ${initialStepIndex === 0 ? 'hidden' : ''}>${escapeHtml(uiText.back)}</button>` +
|
|
528
|
+
`<div class="pwc-wizard-ctl-spacer" aria-hidden="true"></div>` +
|
|
529
|
+
`<button type="button" class="pwc-btn-pager pwc-btn-pager--primary" id="pwcNext" ${initialStepIndex >= totalSteps - 1 ? 'hidden' : ''}>${escapeHtml(uiText.next)}</button>` +
|
|
530
|
+
`<button type="submit" class="pwc-btn-submit pwc-wizard-ctl__submit" id="pwcFormSubmit" ${initialStepIndex < totalSteps - 1 ? 'hidden' : ''}>${escapeHtml(uiText.submit)}</button>` +
|
|
531
|
+
`</div>`);
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
out.push(`<div class="pwc-wizard-ctl" id="pwcWizardCtl" role="group" aria-label="${escapeHtml(uiText.submitAriaLabel)}">` +
|
|
535
|
+
`<div class="pwc-wizard-ctl-spacer" aria-hidden="true"></div>` +
|
|
536
|
+
`<button type="submit" class="pwc-btn-submit pwc-wizard-ctl__submit" id="pwcFormSubmit">${escapeHtml(uiText.submit)}</button>` +
|
|
537
|
+
`</div>`);
|
|
538
|
+
}
|
|
539
|
+
/* Status / error Alert: under main form column only, not full-width under the side Steps. */
|
|
540
|
+
out.push('<div id="pwcStatus" class="pwc-ad-status pwc-ad-status--empty" role="status" aria-live="polite"></div>');
|
|
541
|
+
if (!oneStep) {
|
|
542
|
+
out.push('</div></div>');
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
out.push('</div>');
|
|
546
|
+
}
|
|
547
|
+
return out.join('\n');
|
|
548
|
+
}
|
|
549
|
+
function readFormFromClient(body) {
|
|
550
|
+
if (body === null || body === undefined || typeof body !== 'object') {
|
|
551
|
+
return {};
|
|
552
|
+
}
|
|
553
|
+
return { ...body };
|
|
554
|
+
}
|
|
555
|
+
function readFormFromClientStrippingPwcMeta(o) {
|
|
556
|
+
if (!Object.prototype.hasOwnProperty.call(o, PWC_FORM_META_STEP)) {
|
|
557
|
+
return { ...o };
|
|
558
|
+
}
|
|
559
|
+
const { [PWC_FORM_META_STEP]: _meta, ...rest } = o;
|
|
560
|
+
return rest;
|
|
561
|
+
}
|
|
562
|
+
function openUrlInDefaultBrowser(url) {
|
|
563
|
+
const platform = process.platform;
|
|
564
|
+
if (platform === 'darwin') {
|
|
565
|
+
spawn('open', [url], { stdio: 'ignore', detached: true }).unref();
|
|
566
|
+
}
|
|
567
|
+
else if (platform === 'win32') {
|
|
568
|
+
spawn('cmd', ['/c', 'start', '', url], { stdio: 'ignore', detached: true, windowsHide: true }).unref();
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
spawn('xdg-open', [url], { stdio: 'ignore', detached: true }).unref();
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
function closePromptWebUiServer(server, done) {
|
|
575
|
+
server.close(done);
|
|
576
|
+
server.closeIdleConnections?.();
|
|
577
|
+
server.closeAllConnections?.();
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Merge multiple `stages` into one `PromptsCatalog` in order; duplicate keys throw.
|
|
581
|
+
* `sectionBeforeKey` maps the **first input** key in each stage (if `sectionTitle` is set) to a heading.
|
|
582
|
+
*/
|
|
583
|
+
export function mergeWebUICatalogsFromStages(stages) {
|
|
584
|
+
if (!stages.length) {
|
|
585
|
+
throw new Error('mergeWebUICatalogsFromStages: `stages` must be non-empty.');
|
|
586
|
+
}
|
|
587
|
+
const merged = {};
|
|
588
|
+
const sectionBeforeKey = new Map();
|
|
589
|
+
const used = new Set();
|
|
590
|
+
for (const stage of stages) {
|
|
591
|
+
const title = typeof stage.sectionTitle === 'string' ? stage.sectionTitle.trim() : '';
|
|
592
|
+
let needTitle = Boolean(title);
|
|
593
|
+
for (const [key, def] of Object.entries(stage.catalog)) {
|
|
594
|
+
if (isInputBlock(def) && needTitle && title) {
|
|
595
|
+
sectionBeforeKey.set(key, title);
|
|
596
|
+
needTitle = false;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
for (const [key, def] of Object.entries(stage.catalog)) {
|
|
600
|
+
if (used.has(key)) {
|
|
601
|
+
throw new Error(`runPromptCatalogWebUI: duplicate prompt key "${key}" across stages; use unique keys in each \`PromptsCatalog\`.`);
|
|
602
|
+
}
|
|
603
|
+
used.add(key);
|
|
604
|
+
merged[key] = def;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
return { merged, sectionBeforeKey };
|
|
608
|
+
}
|
|
609
|
+
function resolveMergedCatalog(options) {
|
|
610
|
+
if (options.stages !== undefined && options.stages.length > 0) {
|
|
611
|
+
if (options.catalog !== undefined) {
|
|
612
|
+
throw new Error('runPromptCatalogWebUI: set only one of `catalog` or `stages`, not both.');
|
|
613
|
+
}
|
|
614
|
+
return mergeWebUICatalogsFromStages(options.stages);
|
|
615
|
+
}
|
|
616
|
+
if (options.catalog !== undefined) {
|
|
617
|
+
return { merged: options.catalog, sectionBeforeKey: new Map() };
|
|
618
|
+
}
|
|
619
|
+
throw new Error('runPromptCatalogWebUI: set `options.catalog` or a non-empty `options.stages`.');
|
|
620
|
+
}
|
|
621
|
+
function mergeValueSeedsFromOptions(options) {
|
|
622
|
+
let s = { ...(options.values ?? {}) };
|
|
623
|
+
if (options.stages) {
|
|
624
|
+
for (const st of options.stages) {
|
|
625
|
+
if (st.values) {
|
|
626
|
+
s = { ...s, ...st.values };
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
return s;
|
|
631
|
+
}
|
|
632
|
+
const PROMPT_BLOCK_TYPE_MARKERS = new Set([
|
|
633
|
+
'intro',
|
|
634
|
+
'outro',
|
|
635
|
+
'text',
|
|
636
|
+
'boolean',
|
|
637
|
+
'select',
|
|
638
|
+
'password',
|
|
639
|
+
'integer',
|
|
640
|
+
'run',
|
|
641
|
+
]);
|
|
642
|
+
/**
|
|
643
|
+
* `PromptsCatalog` is a record of block defs (each with a `type`). Used to disambiguate
|
|
644
|
+
* `runPromptCatalogWebUI(maybeCatalog)` from `runPromptCatalogWebUI({ pageTitle, values, … })`.
|
|
645
|
+
*/
|
|
646
|
+
function looksLikeOnlyPromptsCatalog(o) {
|
|
647
|
+
const values = Object.values(o);
|
|
648
|
+
if (values.length === 0) {
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
651
|
+
for (const v of values) {
|
|
652
|
+
if (typeof v !== 'object' || v === null || !('type' in v)) {
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
const t = v.type;
|
|
656
|
+
if (typeof t !== 'string' || !PROMPT_BLOCK_TYPE_MARKERS.has(t)) {
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return true;
|
|
661
|
+
}
|
|
662
|
+
export function runPromptCatalogWebUI(catalogOrOptions, options) {
|
|
663
|
+
if (options !== undefined) {
|
|
664
|
+
return runPromptCatalogWebUIImpl({ ...options, catalog: catalogOrOptions });
|
|
665
|
+
}
|
|
666
|
+
if (typeof catalogOrOptions === 'object' && catalogOrOptions !== null) {
|
|
667
|
+
if ('stages' in catalogOrOptions || 'catalog' in catalogOrOptions) {
|
|
668
|
+
return runPromptCatalogWebUIImpl(catalogOrOptions);
|
|
669
|
+
}
|
|
670
|
+
if (looksLikeOnlyPromptsCatalog(catalogOrOptions)) {
|
|
671
|
+
return runPromptCatalogWebUIImpl({ catalog: catalogOrOptions });
|
|
672
|
+
}
|
|
673
|
+
return runPromptCatalogWebUIImpl(catalogOrOptions);
|
|
674
|
+
}
|
|
675
|
+
return runPromptCatalogWebUIImpl({ catalog: catalogOrOptions });
|
|
676
|
+
}
|
|
677
|
+
function runPromptCatalogWebUIImpl(options) {
|
|
678
|
+
const locale = resolveCliLocale(options.locale);
|
|
679
|
+
const t = createCliTranslate(locale);
|
|
680
|
+
const { merged } = resolveMergedCatalog(options);
|
|
681
|
+
const userSeed = mergeValueSeedsFromOptions(options);
|
|
682
|
+
const formDefaults = buildWebFormValuesFromCatalog(merged, userSeed);
|
|
683
|
+
const initialShow = reflowWebFormState(merged, Object.fromEntries(Object.entries(formDefaults).map(([k, v]) => [k, v])), userSeed).show;
|
|
684
|
+
const submitPath = options.submitPath ?? DEFAULT_SUBMIT;
|
|
685
|
+
const reflowPath = options.reflowPath ?? DEFAULT_REFLOW;
|
|
686
|
+
const host = options.host ?? DEFAULT_HOST;
|
|
687
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
688
|
+
const pageTitle = resolveUiText(options.pageTitle, locale, t('promptCatalog.web.pageTitle'));
|
|
689
|
+
const h1 = resolveUiText(options.documentHeading, locale, t('promptCatalog.web.documentHeading'));
|
|
690
|
+
const documentHint = resolveUiText(options.documentHint, locale, t('promptCatalog.web.documentHint'));
|
|
691
|
+
const catalog = merged;
|
|
692
|
+
const pwcStepDefs = computePwcWizardSteps(options, catalog, locale);
|
|
693
|
+
const pwcNSteps = Math.max(1, pwcStepDefs.length);
|
|
694
|
+
const resolveValidateStepPath = options.validateStepPath ?? DEFAULT_VALIDATE_STEP;
|
|
695
|
+
const resolveValidateFieldPath = options.validateFieldPath ?? DEFAULT_VALIDATE_FIELD;
|
|
696
|
+
const uiText = {
|
|
697
|
+
stepsAriaLabel: t('promptCatalog.web.stepsAriaLabel'),
|
|
698
|
+
stepsSidebarAriaLabel: t('promptCatalog.web.stepsSidebarAriaLabel'),
|
|
699
|
+
stepNavigationAriaLabel: t('promptCatalog.web.stepNavigationAriaLabel'),
|
|
700
|
+
submitAriaLabel: t('promptCatalog.web.submitAriaLabel'),
|
|
701
|
+
back: t('promptCatalog.web.back'),
|
|
702
|
+
next: t('promptCatalog.web.next'),
|
|
703
|
+
submit: t('promptCatalog.web.submit'),
|
|
704
|
+
checking: t('promptCatalog.web.checking'),
|
|
705
|
+
sending: t('promptCatalog.web.sending'),
|
|
706
|
+
successTitle: t('promptCatalog.web.successTitle'),
|
|
707
|
+
errorTitle: t('promptCatalog.web.errorTitle'),
|
|
708
|
+
savedAndClosing: t('promptCatalog.web.savedAndClosing'),
|
|
709
|
+
savedCloseBlocked: t('promptCatalog.web.savedCloseBlocked'),
|
|
710
|
+
invalidValue: t('promptCatalog.web.invalidValue'),
|
|
711
|
+
invalidRequest: t('promptCatalog.web.invalidRequest'),
|
|
712
|
+
invalidStep: t('promptCatalog.web.invalidStep'),
|
|
713
|
+
invalidField: t('promptCatalog.web.invalidField'),
|
|
714
|
+
doneAriaLabel: 'done',
|
|
715
|
+
};
|
|
716
|
+
let server;
|
|
717
|
+
let timeoutId;
|
|
718
|
+
return new Promise((resolve, reject) => {
|
|
719
|
+
const rejectAndClose = (err) => {
|
|
720
|
+
if (timeoutId !== undefined) {
|
|
721
|
+
clearTimeout(timeoutId);
|
|
722
|
+
timeoutId = undefined;
|
|
723
|
+
}
|
|
724
|
+
if (server) {
|
|
725
|
+
closePromptWebUiServer(server, () => reject(err));
|
|
726
|
+
}
|
|
727
|
+
else {
|
|
728
|
+
reject(err);
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
const servePage = (port) => {
|
|
732
|
+
const base = `http://${host}:${port}`;
|
|
733
|
+
const formInner = buildPwcFormHtml(catalog, formDefaults, initialShow, pwcStepDefs, 0, pwcNSteps, locale, uiText);
|
|
734
|
+
const wizardClientJson = JSON.stringify({ n: pwcNSteps, stepDefs: pwcStepDefs });
|
|
735
|
+
const pwcValStepUrl = pwcNSteps > 1 ? JSON.stringify(base + resolveValidateStepPath) : 'null';
|
|
736
|
+
const pwcValFieldUrl = JSON.stringify(base + resolveValidateFieldPath);
|
|
737
|
+
const uiTextJson = JSON.stringify(uiText);
|
|
738
|
+
const pwcShellClass = options.stages && options.stages.length > 0
|
|
739
|
+
? 'pwc-shell pwc-shell--stages'
|
|
740
|
+
: 'pwc-shell';
|
|
741
|
+
const page = `<!doctype html>
|
|
742
|
+
<html lang="${escapeHtml(locale)}">
|
|
743
|
+
<head>
|
|
744
|
+
<meta charset="utf-8" />
|
|
745
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
746
|
+
<meta name="color-scheme" content="light dark" />
|
|
747
|
+
<title>${escapeHtml(pageTitle)}</title>
|
|
748
|
+
<style>
|
|
749
|
+
:root {
|
|
750
|
+
--pwc-bg: #f5f5f5;
|
|
751
|
+
--pwc-bg-grad: radial-gradient(1200px 560px at 100% 0%, rgba(22, 119, 255, 0.08) 0%, transparent 46%),
|
|
752
|
+
radial-gradient(900px 420px at 0% 100%, rgba(114, 46, 209, 0.05) 0%, transparent 52%);
|
|
753
|
+
--pwc-surface: #ffffff;
|
|
754
|
+
--pwc-surface-raise: #fafafa;
|
|
755
|
+
--pwc-text: rgba(0, 0, 0, 0.88);
|
|
756
|
+
--pwc-text-muted: rgba(0, 0, 0, 0.45);
|
|
757
|
+
--pwc-border: #f0f0f0;
|
|
758
|
+
--pwc-border-strong: #d9d9d9;
|
|
759
|
+
--pwc-accent: #1677ff;
|
|
760
|
+
--pwc-accent-hover: #4096ff;
|
|
761
|
+
--pwc-focus: 0 0 0 2px rgba(5, 145, 255, 0.12);
|
|
762
|
+
--pwc-radius: 8px;
|
|
763
|
+
--pwc-radius-sm: 8px;
|
|
764
|
+
--pwc-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
|
|
765
|
+
--pwc-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, monospace;
|
|
766
|
+
}
|
|
767
|
+
@media (prefers-color-scheme: dark) {
|
|
768
|
+
:root {
|
|
769
|
+
--pwc-bg: #141414;
|
|
770
|
+
--pwc-bg-grad: radial-gradient(920px 500px at 100% 0%, rgba(22, 119, 255, 0.12) 0%, transparent 48%),
|
|
771
|
+
radial-gradient(720px 360px at 0% 100%, rgba(114, 46, 209, 0.09) 0%, transparent 54%);
|
|
772
|
+
--pwc-surface: #1f1f1f;
|
|
773
|
+
--pwc-surface-raise: #262626;
|
|
774
|
+
--pwc-text: rgba(255, 255, 255, 0.85);
|
|
775
|
+
--pwc-text-muted: rgba(255, 255, 255, 0.45);
|
|
776
|
+
--pwc-border: #303030;
|
|
777
|
+
--pwc-border-strong: #434343;
|
|
778
|
+
--pwc-accent: #1668dc;
|
|
779
|
+
--pwc-accent-hover: #3c89e8;
|
|
780
|
+
--pwc-focus: 0 0 0 2px rgba(22, 104, 220, 0.2);
|
|
781
|
+
--pwc-shadow: 0 1px 2px rgba(0, 0, 0, 0.16);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
785
|
+
body {
|
|
786
|
+
margin: 0;
|
|
787
|
+
min-height: 100vh;
|
|
788
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif;
|
|
789
|
+
font-size: 14px;
|
|
790
|
+
line-height: 1.5715;
|
|
791
|
+
color: var(--pwc-text);
|
|
792
|
+
background: var(--pwc-bg);
|
|
793
|
+
background-image: var(--pwc-bg-grad);
|
|
794
|
+
}
|
|
795
|
+
.pwc-shell { max-width: 48rem; margin: 0 auto; padding: 24px 20px 32px; }
|
|
796
|
+
/* Wider when using the stages option (side Steps + main column) */
|
|
797
|
+
.pwc-shell--stages { max-width: 64rem; }
|
|
798
|
+
.pwc-card {
|
|
799
|
+
background: var(--pwc-surface);
|
|
800
|
+
border: 1px solid var(--pwc-border);
|
|
801
|
+
border-radius: var(--pwc-radius);
|
|
802
|
+
box-shadow: var(--pwc-shadow);
|
|
803
|
+
padding: 0;
|
|
804
|
+
overflow: hidden;
|
|
805
|
+
}
|
|
806
|
+
/* Sidebar: like antd layout — no extra card box, only a split line + air */
|
|
807
|
+
.pwc-wizard--with-sidebar {
|
|
808
|
+
display: flex;
|
|
809
|
+
flex-direction: row;
|
|
810
|
+
align-items: flex-start;
|
|
811
|
+
width: 100%;
|
|
812
|
+
gap: 0 24px;
|
|
813
|
+
}
|
|
814
|
+
.pwc-wizard-sidenav {
|
|
815
|
+
flex: 0 0 auto;
|
|
816
|
+
width: 16.5rem;
|
|
817
|
+
min-width: 12rem;
|
|
818
|
+
max-width: 19rem;
|
|
819
|
+
padding: 4px 16px 4px 0;
|
|
820
|
+
background: transparent;
|
|
821
|
+
border: none;
|
|
822
|
+
border-radius: 0;
|
|
823
|
+
border-right: 1px solid var(--pwc-ad-color-split);
|
|
824
|
+
position: sticky;
|
|
825
|
+
top: 4px;
|
|
826
|
+
align-self: flex-start;
|
|
827
|
+
max-height: min(70vh, 30rem);
|
|
828
|
+
overflow-y: auto;
|
|
829
|
+
}
|
|
830
|
+
.pwc-wizard-sidenav .pwc-ad-steps { margin: 0; padding: 0; }
|
|
831
|
+
.pwc-wizard-sidenav .pwc-ad-steps--vertical { margin: 0; }
|
|
832
|
+
.pwc-wizard-sidenav .pwc-ad-steps--vertical .pwc-ad-steps-item { padding: 0 0 10px; }
|
|
833
|
+
.pwc-wizard-sidenav .pwc-ad-vert { width: var(--pwc-ad-icon-size); min-width: var(--pwc-ad-icon-size); }
|
|
834
|
+
.pwc-wizard-sidenav .pwc-ad-steps--vertical .pwc-ad-steps-item-title {
|
|
835
|
+
-webkit-line-clamp: 2;
|
|
836
|
+
}
|
|
837
|
+
.pwc-wizard-sidenav .pwc-ad-steps-item--process .pwc-ad-steps-item-title { font-weight: 500; }
|
|
838
|
+
.pwc-wizard-main {
|
|
839
|
+
flex: 1;
|
|
840
|
+
min-width: 0;
|
|
841
|
+
}
|
|
842
|
+
@media (max-width: 34rem) {
|
|
843
|
+
.pwc-shell { padding: 16px 14px 24px; }
|
|
844
|
+
.pwc-card { padding: 0; }
|
|
845
|
+
.pwc-wizard--with-sidebar { flex-direction: column; gap: 16px; }
|
|
846
|
+
.pwc-wizard-sidenav {
|
|
847
|
+
position: static;
|
|
848
|
+
max-height: none;
|
|
849
|
+
width: 100%;
|
|
850
|
+
max-width: none;
|
|
851
|
+
padding: 0 0 12px 0;
|
|
852
|
+
border-right: none;
|
|
853
|
+
border-bottom: 1px solid var(--pwc-ad-color-split);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
.pwc-header {
|
|
857
|
+
padding: 20px 24px 16px;
|
|
858
|
+
border-bottom: 1px solid var(--pwc-border);
|
|
859
|
+
background: var(--pwc-surface);
|
|
860
|
+
}
|
|
861
|
+
.pwc-header h1 {
|
|
862
|
+
font-size: 30px;
|
|
863
|
+
font-weight: 600;
|
|
864
|
+
letter-spacing: -0.02em;
|
|
865
|
+
line-height: 1.2666666667;
|
|
866
|
+
margin: 0 0 8px 0;
|
|
867
|
+
}
|
|
868
|
+
.pwc-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
|
|
869
|
+
.pwc-pill {
|
|
870
|
+
display: inline-flex;
|
|
871
|
+
align-items: center;
|
|
872
|
+
min-height: 28px;
|
|
873
|
+
font-size: 12px;
|
|
874
|
+
font-weight: 600;
|
|
875
|
+
letter-spacing: 0.02em;
|
|
876
|
+
text-transform: uppercase;
|
|
877
|
+
color: var(--pwc-accent);
|
|
878
|
+
background: color-mix(in srgb, var(--pwc-accent) 12%, var(--pwc-surface));
|
|
879
|
+
border: 1px solid color-mix(in srgb, var(--pwc-accent) 25%, var(--pwc-border));
|
|
880
|
+
padding: 0 12px;
|
|
881
|
+
border-radius: 999px;
|
|
882
|
+
}
|
|
883
|
+
.hint { font-size: 14px; line-height: 1.5715; color: var(--pwc-text-muted); margin: 0; }
|
|
884
|
+
.hint code { font-family: var(--pwc-mono); font-size: 0.8em; padding: 0.1em 0.3em; border-radius: 4px; background: var(--pwc-surface-raise); border: 1px solid var(--pwc-border); }
|
|
885
|
+
#pwcForm {
|
|
886
|
+
margin-top: 0;
|
|
887
|
+
padding: 24px 24px 20px;
|
|
888
|
+
}
|
|
889
|
+
@media (max-width: 34rem) {
|
|
890
|
+
.pwc-header {
|
|
891
|
+
padding: 16px 16px 14px;
|
|
892
|
+
}
|
|
893
|
+
#pwcForm {
|
|
894
|
+
padding: 18px 16px 16px;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
.pwc-wizard { width: 100%; }
|
|
898
|
+
/*
|
|
899
|
+
* Steps visual alignment with Ant Design 5/6
|
|
900
|
+
* @see https://ant.design/components/steps-cn
|
|
901
|
+
* (iconSize 32, iconFontSize 14, colorText / colorTextDescription, colorSplit rail, colorBorder, etc.)
|
|
902
|
+
*/
|
|
903
|
+
:root {
|
|
904
|
+
/* Primary + hover/active (antd defaultAlgorithm: colorPrimaryHover / colorPrimaryActive) */
|
|
905
|
+
--pwc-ad-color-primary: #1677ff;
|
|
906
|
+
--pwc-ad-color-primary-hover: #4096ff;
|
|
907
|
+
--pwc-ad-color-primary-active: #0958d9;
|
|
908
|
+
--pwc-ad-color-text: rgba(0, 0, 0, 0.88);
|
|
909
|
+
--pwc-ad-color-text-description: rgba(0, 0, 0, 0.45);
|
|
910
|
+
--pwc-ad-color-wait: rgba(0, 0, 0, 0.25);
|
|
911
|
+
--pwc-ad-color-border: #d9d9d9;
|
|
912
|
+
--pwc-ad-color-split: #f0f0f0;
|
|
913
|
+
--pwc-ad-color-container: #ffffff;
|
|
914
|
+
--pwc-ad-color-fill-alter: #fafafa;
|
|
915
|
+
--pwc-ad-wait-icon-bg: rgba(0, 0, 0, 0.04);
|
|
916
|
+
--pwc-ad-icon-size: 32px;
|
|
917
|
+
--pwc-ad-icon-font-size: 14px;
|
|
918
|
+
--pwc-ad-title-font-size: 14px;
|
|
919
|
+
--pwc-ad-line-height: 1.5715;
|
|
920
|
+
/* antd Alert type=error (colorErrorBg / colorErrorBorder / colorError) */
|
|
921
|
+
--pwc-ad-alert-error-bg: #fff2f0;
|
|
922
|
+
--pwc-ad-alert-error-border: #ffccc7;
|
|
923
|
+
--pwc-ad-alert-error-text: rgba(0, 0, 0, 0.88);
|
|
924
|
+
--pwc-ad-alert-error-icon: #ff4d4f;
|
|
925
|
+
/* antd Alert type=success (colorSuccessBg / colorSuccessBorder / colorSuccess) */
|
|
926
|
+
--pwc-ad-alert-success-bg: #f6ffed;
|
|
927
|
+
--pwc-ad-alert-success-border: #b7eb8f;
|
|
928
|
+
--pwc-ad-alert-success-text: rgba(0, 0, 0, 0.88);
|
|
929
|
+
--pwc-ad-alert-success-icon: #52c41a;
|
|
930
|
+
/* antd Form validation (colorError) */
|
|
931
|
+
--pwc-form-color-error: #ff4d4f;
|
|
932
|
+
}
|
|
933
|
+
@media (prefers-color-scheme: dark) {
|
|
934
|
+
:root {
|
|
935
|
+
--pwc-ad-color-text: rgba(255, 255, 255, 0.85);
|
|
936
|
+
--pwc-ad-color-text-description: rgba(255, 255, 255, 0.45);
|
|
937
|
+
--pwc-ad-color-wait: rgba(255, 255, 255, 0.3);
|
|
938
|
+
--pwc-ad-color-border: #424242;
|
|
939
|
+
--pwc-ad-color-split: #303030;
|
|
940
|
+
--pwc-ad-color-container: #1f1f1f;
|
|
941
|
+
--pwc-ad-color-fill-alter: #1a1a1a;
|
|
942
|
+
--pwc-ad-color-primary: #1668dc;
|
|
943
|
+
--pwc-ad-color-primary-hover: #3c89e8;
|
|
944
|
+
--pwc-ad-color-primary-active: #124699;
|
|
945
|
+
--pwc-ad-wait-icon-bg: rgba(255, 255, 255, 0.08);
|
|
946
|
+
--pwc-ad-alert-error-bg: #2a1215;
|
|
947
|
+
--pwc-ad-alert-error-border: #58181c;
|
|
948
|
+
--pwc-ad-alert-error-text: rgba(255, 255, 255, 0.85);
|
|
949
|
+
--pwc-ad-alert-error-icon: #d32029;
|
|
950
|
+
--pwc-ad-alert-success-bg: #162312;
|
|
951
|
+
--pwc-ad-alert-success-border: #274916;
|
|
952
|
+
--pwc-ad-alert-success-text: rgba(255, 255, 255, 0.85);
|
|
953
|
+
--pwc-ad-alert-success-icon: #49aa19;
|
|
954
|
+
--pwc-form-color-error: #d32029;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
/* antd Alert type=error — @see https://ant.design/components/alert */
|
|
958
|
+
.pwc-ad-status { margin: 16px 0 0; min-height: 0; }
|
|
959
|
+
.pwc-ad-status--empty:empty { margin-top: 8px; }
|
|
960
|
+
.pwc-ad-alert {
|
|
961
|
+
display: flex;
|
|
962
|
+
align-items: flex-start;
|
|
963
|
+
gap: 10px;
|
|
964
|
+
margin: 16px 0 0;
|
|
965
|
+
padding: 9px 12px;
|
|
966
|
+
font-size: 14px;
|
|
967
|
+
line-height: 1.5715;
|
|
968
|
+
border-radius: 6px;
|
|
969
|
+
box-sizing: border-box;
|
|
970
|
+
}
|
|
971
|
+
.pwc-ad-alert--error {
|
|
972
|
+
color: var(--pwc-ad-alert-error-text);
|
|
973
|
+
background: var(--pwc-ad-alert-error-bg);
|
|
974
|
+
border: 1px solid var(--pwc-ad-alert-error-border);
|
|
975
|
+
}
|
|
976
|
+
.pwc-ad-alert--success {
|
|
977
|
+
color: var(--pwc-ad-alert-success-text);
|
|
978
|
+
background: var(--pwc-ad-alert-success-bg);
|
|
979
|
+
border: 1px solid var(--pwc-ad-alert-success-border);
|
|
980
|
+
}
|
|
981
|
+
.pwc-ad-alert .pwc-ad-alert__icon {
|
|
982
|
+
display: inline-flex;
|
|
983
|
+
line-height: 0;
|
|
984
|
+
flex-shrink: 0;
|
|
985
|
+
margin-top: 1px;
|
|
986
|
+
}
|
|
987
|
+
.pwc-ad-alert--error .pwc-ad-alert__icon { color: var(--pwc-ad-alert-error-icon); }
|
|
988
|
+
.pwc-ad-alert--success .pwc-ad-alert__icon { color: var(--pwc-ad-alert-success-icon); }
|
|
989
|
+
.pwc-ad-alert .pwc-ad-alert__inner { flex: 1; min-width: 0; }
|
|
990
|
+
.pwc-ad-alert .pwc-ad-alert__title {
|
|
991
|
+
font-size: 14px;
|
|
992
|
+
font-weight: 500;
|
|
993
|
+
margin: 0 0 4px 0;
|
|
994
|
+
}
|
|
995
|
+
.pwc-ad-alert--error .pwc-ad-alert__title { color: var(--pwc-ad-alert-error-text); }
|
|
996
|
+
.pwc-ad-alert--success .pwc-ad-alert__title { color: var(--pwc-ad-alert-success-text); }
|
|
997
|
+
.pwc-ad-alert .pwc-ad-alert__desc {
|
|
998
|
+
font-size: 14px;
|
|
999
|
+
font-weight: 400;
|
|
1000
|
+
margin: 0;
|
|
1001
|
+
}
|
|
1002
|
+
.pwc-ad-alert--error .pwc-ad-alert__desc { color: var(--pwc-ad-color-text-description); }
|
|
1003
|
+
.pwc-ad-alert--success .pwc-ad-alert__desc { color: var(--pwc-ad-color-text-description); }
|
|
1004
|
+
.pwc-ad-hint--plain {
|
|
1005
|
+
font-size: 12px;
|
|
1006
|
+
color: var(--pwc-text-muted);
|
|
1007
|
+
margin: 16px 0 0;
|
|
1008
|
+
}
|
|
1009
|
+
.pwc-ad-steps { width: 100%; margin: 0; padding: 0; }
|
|
1010
|
+
.pwc-ad-steps--vertical { max-width: 100%; }
|
|
1011
|
+
.pwc-ad-steps-list--vertical {
|
|
1012
|
+
list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; width: 100%;
|
|
1013
|
+
gap: 0; align-items: stretch;
|
|
1014
|
+
}
|
|
1015
|
+
.pwc-ad-steps--vertical .pwc-ad-steps-item {
|
|
1016
|
+
margin: 0; text-align: left; box-sizing: border-box; padding: 0 0 12px;
|
|
1017
|
+
}
|
|
1018
|
+
.pwc-ad-steps--vertical .pwc-ad-steps-item:last-child { padding-bottom: 0; }
|
|
1019
|
+
.pwc-ad-steps--vertical .pwc-ad-steps-item-row {
|
|
1020
|
+
display: flex; flex-direction: row; align-items: flex-start; gap: 12px; width: 100%;
|
|
1021
|
+
}
|
|
1022
|
+
.pwc-ad-vert {
|
|
1023
|
+
display: flex; flex-direction: column; align-items: center; width: var(--pwc-ad-icon-size);
|
|
1024
|
+
flex-shrink: 0; min-width: var(--pwc-ad-icon-size);
|
|
1025
|
+
}
|
|
1026
|
+
.pwc-ad-vert__icon { width: var(--pwc-ad-icon-size); height: var(--pwc-ad-icon-size); flex-shrink: 0; line-height: 0; }
|
|
1027
|
+
.pwc-ad-vert__tail {
|
|
1028
|
+
flex: 1 1 auto; width: 1px; min-height: 8px; margin-top: 4px; align-self: center;
|
|
1029
|
+
background: var(--pwc-ad-color-split); border-radius: 0; transition: background 0.2s;
|
|
1030
|
+
}
|
|
1031
|
+
.pwc-ad-vert__tail[data-pwc-conn="done"] { background: var(--pwc-ad-color-primary); }
|
|
1032
|
+
.pwc-ad-vert__main {
|
|
1033
|
+
flex: 1; min-width: 0; padding-top: 0; text-align: left; align-self: flex-start;
|
|
1034
|
+
}
|
|
1035
|
+
.pwc-ad-icon {
|
|
1036
|
+
display: inline-flex; align-items: center; justify-content: center; box-sizing: border-box;
|
|
1037
|
+
width: var(--pwc-ad-icon-size); height: var(--pwc-ad-icon-size); border-radius: 50%;
|
|
1038
|
+
border: 1px solid transparent; background-clip: padding-box;
|
|
1039
|
+
background: var(--pwc-ad-color-container);
|
|
1040
|
+
color: var(--pwc-ad-color-wait);
|
|
1041
|
+
font-size: var(--pwc-ad-icon-font-size);
|
|
1042
|
+
font-weight: 500;
|
|
1043
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif;
|
|
1044
|
+
line-height: 1;
|
|
1045
|
+
transition: background 0.2s, border-color 0.2s, color 0.2s;
|
|
1046
|
+
}
|
|
1047
|
+
.pwc-ad-icon-num { line-height: 1; }
|
|
1048
|
+
.pwc-ad-steps-item--wait .pwc-ad-icon {
|
|
1049
|
+
background: var(--pwc-ad-wait-icon-bg);
|
|
1050
|
+
border: 1px solid transparent;
|
|
1051
|
+
color: var(--pwc-ad-color-text-description);
|
|
1052
|
+
}
|
|
1053
|
+
@media (prefers-color-scheme: dark) {
|
|
1054
|
+
.pwc-ad-steps-item--wait .pwc-ad-icon { color: var(--pwc-ad-color-text-description); }
|
|
1055
|
+
}
|
|
1056
|
+
/* antd process: solid primary, white number (not outline) */
|
|
1057
|
+
.pwc-ad-steps-item--process .pwc-ad-icon {
|
|
1058
|
+
background: var(--pwc-ad-color-primary);
|
|
1059
|
+
border: 1px solid var(--pwc-ad-color-primary);
|
|
1060
|
+
color: #fff;
|
|
1061
|
+
}
|
|
1062
|
+
.pwc-ad-icon--finish {
|
|
1063
|
+
border: 1px solid var(--pwc-ad-color-primary) !important;
|
|
1064
|
+
background: var(--pwc-ad-color-primary) !important; color: #fff !important;
|
|
1065
|
+
}
|
|
1066
|
+
.pwc-ad-icon-check-svg { display: block; margin: 0 auto; }
|
|
1067
|
+
.pwc-ad-steps--vertical .pwc-ad-steps-item-title {
|
|
1068
|
+
font-size: var(--pwc-ad-title-font-size);
|
|
1069
|
+
line-height: var(--pwc-ad-line-height);
|
|
1070
|
+
color: var(--pwc-ad-color-text-description);
|
|
1071
|
+
margin: 0; padding: 0; max-width: 100%;
|
|
1072
|
+
font-weight: 400;
|
|
1073
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif;
|
|
1074
|
+
overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
|
|
1075
|
+
}
|
|
1076
|
+
.pwc-ad-steps-item--process .pwc-ad-steps-item-title {
|
|
1077
|
+
color: var(--pwc-ad-color-text);
|
|
1078
|
+
font-weight: 500;
|
|
1079
|
+
}
|
|
1080
|
+
.pwc-ad-steps-item--finish .pwc-ad-steps-item-title { color: var(--pwc-ad-color-text-description); font-weight: 400; }
|
|
1081
|
+
.pwc-ad-steps-item--wait .pwc-ad-steps-item-title { color: var(--pwc-ad-color-text-description); }
|
|
1082
|
+
.pwc-ad-steps--vertical .pwc-ad-steps-item-description {
|
|
1083
|
+
font-size: 12px;
|
|
1084
|
+
line-height: 1.5;
|
|
1085
|
+
color: var(--pwc-ad-color-text-description);
|
|
1086
|
+
margin: 4px 0 0 0;
|
|
1087
|
+
max-width: 100%;
|
|
1088
|
+
font-weight: 400;
|
|
1089
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif;
|
|
1090
|
+
overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
|
1091
|
+
}
|
|
1092
|
+
.pwc-ad-steps-item--process .pwc-ad-steps-item-description { color: var(--pwc-ad-color-text-description); }
|
|
1093
|
+
.pwc-ad-steps-item--wait .pwc-ad-steps-item-description { color: var(--pwc-ad-color-text-description); }
|
|
1094
|
+
.pwc-ad-steps-item--finish .pwc-ad-steps-item-description { color: var(--pwc-ad-color-text-description); }
|
|
1095
|
+
.pwc-step[hidden] { display: none !important; }
|
|
1096
|
+
/* antd Form / Typography: section title */
|
|
1097
|
+
.pwc-step h2.pwc-step-title {
|
|
1098
|
+
font-size: 20px;
|
|
1099
|
+
font-weight: 500;
|
|
1100
|
+
line-height: 1.4;
|
|
1101
|
+
letter-spacing: 0;
|
|
1102
|
+
color: var(--pwc-ad-color-text);
|
|
1103
|
+
margin: 0 0 24px 0;
|
|
1104
|
+
}
|
|
1105
|
+
@media (prefers-color-scheme: dark) {
|
|
1106
|
+
.pwc-step h2.pwc-step-title { color: var(--pwc-ad-color-text); }
|
|
1107
|
+
}
|
|
1108
|
+
/* antd Form.Item: no nested cards — spacing + normal labels */
|
|
1109
|
+
.pwc-l {
|
|
1110
|
+
display: block;
|
|
1111
|
+
font-weight: 400;
|
|
1112
|
+
font-size: 14px;
|
|
1113
|
+
line-height: 1.5715;
|
|
1114
|
+
color: var(--pwc-ad-color-text);
|
|
1115
|
+
margin: 0 0 8px 0;
|
|
1116
|
+
}
|
|
1117
|
+
label { display: block; }
|
|
1118
|
+
.pwc-step [data-pwc-wrap] {
|
|
1119
|
+
margin: 0 0 24px 0;
|
|
1120
|
+
padding: 0;
|
|
1121
|
+
background: transparent;
|
|
1122
|
+
border: none;
|
|
1123
|
+
border-radius: 0;
|
|
1124
|
+
}
|
|
1125
|
+
.pwc-step h2 + [data-pwc-wrap] { margin-top: 0; }
|
|
1126
|
+
.pwc-bool-wrap { padding: 0; }
|
|
1127
|
+
.pwc-bool-wrap label { display: flex; flex-direction: row; align-items: center; flex-wrap: nowrap; gap: 10px; }
|
|
1128
|
+
.pwc-bool-wrap .pwc-l { display: inline; margin-bottom: 0; font-weight: 400; }
|
|
1129
|
+
.pwc-bool-wrap input[type=checkbox] { margin: 0; flex-shrink: 0; width: 16px; height: 16px; accent-color: var(--pwc-ad-color-primary); border-radius: 4px; cursor: pointer; }
|
|
1130
|
+
.pwc-radio-group { display: grid; gap: 12px; }
|
|
1131
|
+
.pwc-radio-option {
|
|
1132
|
+
display: flex;
|
|
1133
|
+
align-items: flex-start;
|
|
1134
|
+
gap: 10px;
|
|
1135
|
+
padding: 12px;
|
|
1136
|
+
border: 1px solid var(--pwc-ad-color-border);
|
|
1137
|
+
border-radius: 8px;
|
|
1138
|
+
background: var(--pwc-ad-color-container);
|
|
1139
|
+
cursor: pointer;
|
|
1140
|
+
transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
|
|
1141
|
+
}
|
|
1142
|
+
.pwc-radio-option:hover {
|
|
1143
|
+
border-color: var(--pwc-ad-color-primary);
|
|
1144
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--pwc-ad-color-primary) 8%, transparent);
|
|
1145
|
+
background: color-mix(in srgb, var(--pwc-ad-color-primary) 2%, var(--pwc-ad-color-container));
|
|
1146
|
+
}
|
|
1147
|
+
.pwc-radio-option--disabled {
|
|
1148
|
+
cursor: not-allowed;
|
|
1149
|
+
background: var(--pwc-ad-color-fill-alter);
|
|
1150
|
+
}
|
|
1151
|
+
.pwc-radio-option--disabled:hover {
|
|
1152
|
+
border-color: var(--pwc-ad-color-border);
|
|
1153
|
+
box-shadow: none;
|
|
1154
|
+
background: var(--pwc-ad-color-fill-alter);
|
|
1155
|
+
}
|
|
1156
|
+
.pwc-radio-input {
|
|
1157
|
+
margin: 3px 0 0;
|
|
1158
|
+
width: 16px;
|
|
1159
|
+
height: 16px;
|
|
1160
|
+
flex-shrink: 0;
|
|
1161
|
+
accent-color: var(--pwc-ad-color-primary);
|
|
1162
|
+
cursor: pointer;
|
|
1163
|
+
}
|
|
1164
|
+
.pwc-radio-option--disabled .pwc-radio-input {
|
|
1165
|
+
cursor: not-allowed;
|
|
1166
|
+
}
|
|
1167
|
+
.pwc-radio-option-body { min-width: 0; }
|
|
1168
|
+
.pwc-radio-option-label {
|
|
1169
|
+
display: block;
|
|
1170
|
+
font-size: 14px;
|
|
1171
|
+
line-height: 1.5715;
|
|
1172
|
+
color: var(--pwc-ad-color-text);
|
|
1173
|
+
}
|
|
1174
|
+
.pwc-radio-option--disabled .pwc-radio-option-label {
|
|
1175
|
+
color: color-mix(in srgb, var(--pwc-ad-color-text) 55%, transparent);
|
|
1176
|
+
}
|
|
1177
|
+
.pwc-radio-option-hint {
|
|
1178
|
+
margin-top: 2px;
|
|
1179
|
+
font-size: 12px;
|
|
1180
|
+
line-height: 1.5;
|
|
1181
|
+
color: var(--pwc-ad-color-text-description);
|
|
1182
|
+
}
|
|
1183
|
+
.pwc-radio-option--disabled .pwc-radio-option-hint {
|
|
1184
|
+
color: color-mix(in srgb, var(--pwc-ad-color-text-description) 70%, transparent);
|
|
1185
|
+
}
|
|
1186
|
+
.pwc-radio-input:focus-visible {
|
|
1187
|
+
outline: none;
|
|
1188
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--pwc-ad-color-primary) 20%, transparent);
|
|
1189
|
+
border-radius: 999px;
|
|
1190
|
+
}
|
|
1191
|
+
.pwc-radio-option:has(.pwc-radio-input:checked) {
|
|
1192
|
+
border-color: var(--pwc-ad-color-primary);
|
|
1193
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--pwc-ad-color-primary) 12%, transparent);
|
|
1194
|
+
background: color-mix(in srgb, var(--pwc-ad-color-primary) 5%, var(--pwc-ad-color-container));
|
|
1195
|
+
}
|
|
1196
|
+
.pwc-radio-option--disabled:has(.pwc-radio-input:checked) {
|
|
1197
|
+
border-color: var(--pwc-ad-color-border);
|
|
1198
|
+
box-shadow: none;
|
|
1199
|
+
background: var(--pwc-ad-color-fill-alter);
|
|
1200
|
+
}
|
|
1201
|
+
.pwc-form-item-has-error .pwc-radio-option {
|
|
1202
|
+
border-color: var(--pwc-form-color-error);
|
|
1203
|
+
}
|
|
1204
|
+
.pwc-form-item-has-error .pwc-radio-option:has(.pwc-radio-input:checked) {
|
|
1205
|
+
background: color-mix(in srgb, var(--pwc-form-color-error) 5%, var(--pwc-ad-color-container));
|
|
1206
|
+
}
|
|
1207
|
+
/* antd Form.Item: label + control + explain — @see https://ant.design/components/form */
|
|
1208
|
+
.pwc-form-item { margin: 0 0 24px 0; }
|
|
1209
|
+
.pwc-form-item-label { margin: 0; padding: 0; }
|
|
1210
|
+
.pwc-form-item-control { width: 100%; }
|
|
1211
|
+
.pwc-form-item--bool { margin: 0 0 24px 0; }
|
|
1212
|
+
.pwc-form-item--bool .pwc-bool-wrap { margin: 0; }
|
|
1213
|
+
.pwc-input-affix-wrapper { position: relative; display: block; width: 100%; }
|
|
1214
|
+
.pwc-form-item-suffix:empty { display: none; }
|
|
1215
|
+
.pwc-form-item-suffix {
|
|
1216
|
+
position: absolute; z-index: 1; right: 11px; top: 50%;
|
|
1217
|
+
transform: translateY(-50%);
|
|
1218
|
+
color: var(--pwc-form-color-error);
|
|
1219
|
+
display: flex; align-items: center; line-height: 0;
|
|
1220
|
+
pointer-events: none;
|
|
1221
|
+
}
|
|
1222
|
+
.pwc-input-affix-wrapper .pwc-form-input { padding-right: 32px; }
|
|
1223
|
+
.pwc-input-affix-wrapper--select .pwc-form-input { padding-right: 32px; }
|
|
1224
|
+
.pwc-form-item-explain { font-size: 14px; line-height: 1.5715; margin-top: 4px; clear: both; }
|
|
1225
|
+
.pwc-form-item-explain[hidden] { display: none !important; }
|
|
1226
|
+
.pwc-form-item-explain:not([hidden]) { color: var(--pwc-form-color-error); }
|
|
1227
|
+
.pwc-form-item-has-error .pwc-form-input { border-color: var(--pwc-form-color-error) !important; }
|
|
1228
|
+
.pwc-form-item-has-error .pwc-form-input:hover { border-color: var(--pwc-form-color-error) !important; }
|
|
1229
|
+
.pwc-form-item-has-error .pwc-form-input:focus,
|
|
1230
|
+
.pwc-form-item-has-error .pwc-form-input:focus-visible {
|
|
1231
|
+
border-color: var(--pwc-form-color-error) !important;
|
|
1232
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--pwc-form-color-error) 20%, transparent) !important;
|
|
1233
|
+
}
|
|
1234
|
+
.pwc-form-item--bool.pwc-form-item-has-error .pwc-bool-wrap {
|
|
1235
|
+
display: inline-block; max-width: 100%;
|
|
1236
|
+
padding: 6px 10px; border: 1px solid var(--pwc-form-color-error); border-radius: 6px; box-sizing: border-box;
|
|
1237
|
+
}
|
|
1238
|
+
.pwc-form-fail__svg { display: block; }
|
|
1239
|
+
/* antd Input: single border, 6px radius */
|
|
1240
|
+
input.pwc-form-input, select.pwc-form-input, textarea {
|
|
1241
|
+
width: 100%;
|
|
1242
|
+
margin-top: 0;
|
|
1243
|
+
padding: 6px 11px;
|
|
1244
|
+
min-height: 40px;
|
|
1245
|
+
font: inherit;
|
|
1246
|
+
font-size: 14px;
|
|
1247
|
+
line-height: 1.5715;
|
|
1248
|
+
color: var(--pwc-ad-color-text);
|
|
1249
|
+
background: var(--pwc-ad-color-container);
|
|
1250
|
+
border: 1px solid var(--pwc-ad-color-border);
|
|
1251
|
+
border-radius: 6px;
|
|
1252
|
+
transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
|
|
1253
|
+
}
|
|
1254
|
+
input.pwc-form-input:hover, select.pwc-form-input:hover, textarea:hover {
|
|
1255
|
+
border-color: var(--pwc-ad-color-primary);
|
|
1256
|
+
}
|
|
1257
|
+
input.pwc-form-input:focus, input.pwc-form-input:focus-visible, select.pwc-form-input:focus, textarea:focus {
|
|
1258
|
+
outline: none;
|
|
1259
|
+
border-color: var(--pwc-ad-color-primary);
|
|
1260
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--pwc-ad-color-primary) 16%, transparent);
|
|
1261
|
+
}
|
|
1262
|
+
input.pwc-form-input::placeholder, textarea::placeholder { color: var(--pwc-ad-color-text-description); }
|
|
1263
|
+
input.pwc-form-input:disabled, select.pwc-form-input:disabled, textarea:disabled {
|
|
1264
|
+
color: color-mix(in srgb, var(--pwc-ad-color-text) 55%, transparent);
|
|
1265
|
+
background: var(--pwc-ad-color-fill-alter);
|
|
1266
|
+
cursor: not-allowed;
|
|
1267
|
+
border-color: var(--pwc-ad-color-border);
|
|
1268
|
+
box-shadow: none;
|
|
1269
|
+
}
|
|
1270
|
+
select { cursor: pointer; }
|
|
1271
|
+
.pwc-wizard-ctl {
|
|
1272
|
+
display: flex;
|
|
1273
|
+
flex-wrap: nowrap;
|
|
1274
|
+
align-items: center;
|
|
1275
|
+
gap: 8px;
|
|
1276
|
+
margin-top: 28px;
|
|
1277
|
+
padding-top: 0;
|
|
1278
|
+
}
|
|
1279
|
+
.pwc-wizard-ctl .pwc-btn-pager {
|
|
1280
|
+
min-height: 40px;
|
|
1281
|
+
box-sizing: border-box;
|
|
1282
|
+
}
|
|
1283
|
+
.pwc-wizard-ctl-spacer { flex: 1 1 auto; min-width: 8px; }
|
|
1284
|
+
.pwc-wizard-ctl__submit {
|
|
1285
|
+
flex: 0 0 auto;
|
|
1286
|
+
width: auto !important;
|
|
1287
|
+
min-width: 136px;
|
|
1288
|
+
}
|
|
1289
|
+
.pwc-btn-pager {
|
|
1290
|
+
padding: 4px 15px;
|
|
1291
|
+
font: inherit;
|
|
1292
|
+
font-weight: 400;
|
|
1293
|
+
font-size: 14px;
|
|
1294
|
+
line-height: 1.5715;
|
|
1295
|
+
color: var(--pwc-ad-color-text);
|
|
1296
|
+
background: var(--pwc-ad-color-container);
|
|
1297
|
+
border: 1px solid var(--pwc-ad-color-border);
|
|
1298
|
+
border-radius: 6px;
|
|
1299
|
+
cursor: pointer;
|
|
1300
|
+
transition: all 0.2s;
|
|
1301
|
+
}
|
|
1302
|
+
.pwc-btn-pager:hover {
|
|
1303
|
+
color: var(--pwc-ad-color-primary);
|
|
1304
|
+
border-color: var(--pwc-ad-color-primary);
|
|
1305
|
+
background: var(--pwc-ad-color-container);
|
|
1306
|
+
}
|
|
1307
|
+
.pwc-btn-pager:active {
|
|
1308
|
+
color: var(--pwc-ad-color-primary-active);
|
|
1309
|
+
border-color: var(--pwc-ad-color-primary-active);
|
|
1310
|
+
}
|
|
1311
|
+
.pwc-btn-pager--primary {
|
|
1312
|
+
color: #fff;
|
|
1313
|
+
background: var(--pwc-ad-color-primary);
|
|
1314
|
+
border-color: var(--pwc-ad-color-primary);
|
|
1315
|
+
transition: background 0.2s, border-color 0.2s, color 0.2s;
|
|
1316
|
+
}
|
|
1317
|
+
.pwc-btn-pager--primary:hover {
|
|
1318
|
+
color: #fff;
|
|
1319
|
+
background: var(--pwc-ad-color-primary-hover);
|
|
1320
|
+
border-color: var(--pwc-ad-color-primary-hover);
|
|
1321
|
+
}
|
|
1322
|
+
.pwc-btn-pager--primary:active {
|
|
1323
|
+
color: #fff;
|
|
1324
|
+
background: var(--pwc-ad-color-primary-active);
|
|
1325
|
+
border-color: var(--pwc-ad-color-primary-active);
|
|
1326
|
+
}
|
|
1327
|
+
.pwc-btn-pager:focus-visible { outline: none; box-shadow: var(--pwc-focus); }
|
|
1328
|
+
.pwc-btn-pager--primary:focus-visible {
|
|
1329
|
+
outline: none;
|
|
1330
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--pwc-ad-color-primary) 20%, transparent);
|
|
1331
|
+
}
|
|
1332
|
+
.pwc-wizard-ctl .pwc-btn-submit,
|
|
1333
|
+
.pwc-wizard-ctl button.pwc-btn-submit {
|
|
1334
|
+
margin: 0;
|
|
1335
|
+
height: 40px;
|
|
1336
|
+
padding: 4px 15px;
|
|
1337
|
+
font: inherit;
|
|
1338
|
+
font-weight: 400;
|
|
1339
|
+
font-size: 14px;
|
|
1340
|
+
line-height: 1.5715;
|
|
1341
|
+
color: #fff;
|
|
1342
|
+
background: var(--pwc-ad-color-primary);
|
|
1343
|
+
border: 1px solid var(--pwc-ad-color-primary);
|
|
1344
|
+
border-radius: 6px;
|
|
1345
|
+
cursor: pointer;
|
|
1346
|
+
box-shadow: 0 2px 0 color-mix(in srgb, #000 2%, transparent);
|
|
1347
|
+
transition: background 0.2s, border-color 0.2s, color 0.2s;
|
|
1348
|
+
}
|
|
1349
|
+
.pwc-wizard-ctl .pwc-btn-submit:hover, .pwc-wizard-ctl button.pwc-btn-submit:hover {
|
|
1350
|
+
background: var(--pwc-ad-color-primary-hover);
|
|
1351
|
+
border-color: var(--pwc-ad-color-primary-hover);
|
|
1352
|
+
}
|
|
1353
|
+
.pwc-wizard-ctl .pwc-btn-submit:active, .pwc-wizard-ctl button.pwc-btn-submit:active {
|
|
1354
|
+
background: var(--pwc-ad-color-primary-active);
|
|
1355
|
+
border-color: var(--pwc-ad-color-primary-active);
|
|
1356
|
+
}
|
|
1357
|
+
.pwc-wizard-ctl .pwc-btn-submit:focus-visible, .pwc-wizard-ctl button.pwc-btn-submit:focus-visible {
|
|
1358
|
+
outline: none;
|
|
1359
|
+
box-shadow: 0 0 0 2px color-mix(in srgb, var(--pwc-ad-color-primary) 20%, transparent);
|
|
1360
|
+
}
|
|
1361
|
+
.pwc-btn-pager[hidden], .pwc-btn-submit[hidden] { display: none !important; }
|
|
1362
|
+
@media (max-width: 34rem) {
|
|
1363
|
+
.pwc-wizard-ctl {
|
|
1364
|
+
flex-wrap: wrap;
|
|
1365
|
+
}
|
|
1366
|
+
.pwc-wizard-ctl-spacer {
|
|
1367
|
+
display: none;
|
|
1368
|
+
}
|
|
1369
|
+
.pwc-wizard-ctl .pwc-btn-pager,
|
|
1370
|
+
.pwc-wizard-ctl .pwc-btn-submit {
|
|
1371
|
+
flex: 1 1 100%;
|
|
1372
|
+
width: 100% !important;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
</style>
|
|
1376
|
+
</head>
|
|
1377
|
+
<body>
|
|
1378
|
+
<div class="${pwcShellClass}">
|
|
1379
|
+
<div class="pwc-card">
|
|
1380
|
+
<header class="pwc-header">
|
|
1381
|
+
<h1>${escapeHtml(h1)}</h1>
|
|
1382
|
+
<p class="hint">${escapeHtml(documentHint)}</p>
|
|
1383
|
+
</header>
|
|
1384
|
+
<form id="pwcForm" autocomplete="off">
|
|
1385
|
+
${formInner}
|
|
1386
|
+
</form>
|
|
1387
|
+
</div>
|
|
1388
|
+
</div>
|
|
1389
|
+
<script>
|
|
1390
|
+
(function () {
|
|
1391
|
+
var sub = ${JSON.stringify(base + submitPath)};
|
|
1392
|
+
var ref = ${JSON.stringify(base + reflowPath)};
|
|
1393
|
+
var pwcValStep = ${pwcValStepUrl};
|
|
1394
|
+
var pwcValField = ${pwcValFieldUrl};
|
|
1395
|
+
var pwcStepMeta = ${JSON.stringify(PWC_FORM_META_STEP)};
|
|
1396
|
+
var pwcFieldMeta = ${JSON.stringify(PWC_FORM_META_FIELD)};
|
|
1397
|
+
var s = document.getElementById('pwcStatus');
|
|
1398
|
+
var wcfg = ${wizardClientJson};
|
|
1399
|
+
var uiText = ${uiTextJson};
|
|
1400
|
+
var pwcN = wcfg && typeof wcfg.n === 'number' ? wcfg.n : 1;
|
|
1401
|
+
var pwcSteps = (wcfg && wcfg.stepDefs) || [];
|
|
1402
|
+
var pwcCur = 0;
|
|
1403
|
+
var pwcVisibleSteps = [];
|
|
1404
|
+
var pwcAdCheck = ${JSON.stringify(PWC_AD_CHECK_SVG)};
|
|
1405
|
+
var pwcErrIcon = ${JSON.stringify(PWC_AD_ALERT_ERROR_ICON_SVG)};
|
|
1406
|
+
var pwcOkIcon = ${JSON.stringify(PWC_AD_ALERT_SUCCESS_ICON_SVG)};
|
|
1407
|
+
var pwcFieldFail = ${JSON.stringify(PWC_FORM_FAIL_ICON_SVG)};
|
|
1408
|
+
var pwcCloseTimer = null;
|
|
1409
|
+
var pwcCloseProbeTimer = null;
|
|
1410
|
+
var pwcFieldReqSeq = {};
|
|
1411
|
+
var form = document.getElementById('pwcForm');
|
|
1412
|
+
function pwcEsc(t) {
|
|
1413
|
+
return String(t == null ? '' : t)
|
|
1414
|
+
.replace(/&/g, '&')
|
|
1415
|
+
.replace(/</g, '<')
|
|
1416
|
+
.replace(/>/g, '>')
|
|
1417
|
+
.replace(/"/g, '"');
|
|
1418
|
+
}
|
|
1419
|
+
function pwcSetStatusEmpty() {
|
|
1420
|
+
if (!s) { return; }
|
|
1421
|
+
s.className = 'pwc-ad-status pwc-ad-status--empty';
|
|
1422
|
+
s.setAttribute('role', 'status');
|
|
1423
|
+
s.textContent = '';
|
|
1424
|
+
}
|
|
1425
|
+
function pwcSetStatusHint(msg) {
|
|
1426
|
+
if (!s) { return; }
|
|
1427
|
+
s.className = 'pwc-ad-hint--plain';
|
|
1428
|
+
s.setAttribute('role', 'status');
|
|
1429
|
+
s.textContent = String(msg);
|
|
1430
|
+
}
|
|
1431
|
+
function pwcSetStatusError(message) {
|
|
1432
|
+
if (!s) { return; }
|
|
1433
|
+
var t = String(message == null ? '' : message)
|
|
1434
|
+
.replace(/^\\s*Error:\\s*/i, '');
|
|
1435
|
+
s.className = 'pwc-ad-alert pwc-ad-alert--error';
|
|
1436
|
+
s.setAttribute('role', 'alert');
|
|
1437
|
+
s.innerHTML =
|
|
1438
|
+
'<span class="pwc-ad-alert__icon" aria-hidden="true">' + pwcErrIcon + '</span>' +
|
|
1439
|
+
'<div class="pwc-ad-alert__inner"><div class="pwc-ad-alert__title">' + pwcEsc(uiText.errorTitle) + '</div>' +
|
|
1440
|
+
'<div class="pwc-ad-alert__desc">' + pwcEsc(t) + '</div></div>';
|
|
1441
|
+
}
|
|
1442
|
+
function pwcSetStatusSuccess(message) {
|
|
1443
|
+
if (!s) { return; }
|
|
1444
|
+
var t = String(message == null ? '' : message);
|
|
1445
|
+
s.className = 'pwc-ad-alert pwc-ad-alert--success';
|
|
1446
|
+
s.setAttribute('role', 'status');
|
|
1447
|
+
s.innerHTML =
|
|
1448
|
+
'<span class="pwc-ad-alert__icon" aria-hidden="true">' + pwcOkIcon + '</span>' +
|
|
1449
|
+
'<div class="pwc-ad-alert__inner"><div class="pwc-ad-alert__title">' + pwcEsc(uiText.successTitle) + '</div>' +
|
|
1450
|
+
'<div class="pwc-ad-alert__desc">' + pwcEsc(t) + '</div></div>';
|
|
1451
|
+
}
|
|
1452
|
+
function pwcScheduleWindowClose() {
|
|
1453
|
+
if (pwcCloseTimer != null) { clearTimeout(pwcCloseTimer); }
|
|
1454
|
+
if (pwcCloseProbeTimer != null) { clearTimeout(pwcCloseProbeTimer); }
|
|
1455
|
+
pwcCloseTimer = setTimeout(function () {
|
|
1456
|
+
window.close();
|
|
1457
|
+
pwcCloseProbeTimer = setTimeout(function () {
|
|
1458
|
+
if (!s || document.visibilityState !== 'visible') { return; }
|
|
1459
|
+
pwcSetStatusSuccess(uiText.savedCloseBlocked);
|
|
1460
|
+
}, 600);
|
|
1461
|
+
}, 5000);
|
|
1462
|
+
}
|
|
1463
|
+
function pwcSetFieldError(key, message) {
|
|
1464
|
+
if (!form || !key) { return; }
|
|
1465
|
+
var wrap = form.querySelector('[data-pwc-field=\"' + String(key) + '\"]');
|
|
1466
|
+
if (!wrap) { return; }
|
|
1467
|
+
var ex = wrap.querySelector('[data-pwc-explain]');
|
|
1468
|
+
var suf = wrap.querySelector('[data-pwc-suffix]');
|
|
1469
|
+
if (message) {
|
|
1470
|
+
wrap.classList.add('pwc-form-item-has-error');
|
|
1471
|
+
if (ex) {
|
|
1472
|
+
ex.textContent = String(message);
|
|
1473
|
+
ex.removeAttribute('hidden');
|
|
1474
|
+
}
|
|
1475
|
+
if (suf) { suf.innerHTML = pwcFieldFail; }
|
|
1476
|
+
} else {
|
|
1477
|
+
wrap.classList.remove('pwc-form-item-has-error');
|
|
1478
|
+
if (ex) {
|
|
1479
|
+
ex.textContent = '';
|
|
1480
|
+
ex.setAttribute('hidden', '');
|
|
1481
|
+
}
|
|
1482
|
+
if (suf) { suf.innerHTML = ''; }
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1485
|
+
function pwcClearAllFieldErrors() {
|
|
1486
|
+
if (!form) { return; }
|
|
1487
|
+
var nodes = form.querySelectorAll('[data-pwc-field]');
|
|
1488
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
1489
|
+
var k = nodes[i].getAttribute('data-pwc-field');
|
|
1490
|
+
if (k) { pwcSetFieldError(k, null); }
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
function pwcParseErrorBody(x) {
|
|
1494
|
+
var msg = String(x);
|
|
1495
|
+
var fk = null;
|
|
1496
|
+
try {
|
|
1497
|
+
var j = JSON.parse(x);
|
|
1498
|
+
if (j && j.error) { msg = String(j.error); }
|
|
1499
|
+
if (j && j.fieldKey) { fk = String(j.fieldKey); }
|
|
1500
|
+
} catch (e) {}
|
|
1501
|
+
return { msg: msg, fk: fk };
|
|
1502
|
+
}
|
|
1503
|
+
function pwcSetFieldDirty(key, dirty) {
|
|
1504
|
+
if (!form || !key) { return; }
|
|
1505
|
+
var wrap = form.querySelector('[data-pwc-field=\"' + String(key) + '\"]');
|
|
1506
|
+
if (!wrap) { return; }
|
|
1507
|
+
if (dirty) {
|
|
1508
|
+
wrap.setAttribute('data-pwc-dirty', '1');
|
|
1509
|
+
} else {
|
|
1510
|
+
wrap.removeAttribute('data-pwc-dirty');
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
function pwcIsFieldDirty(key) {
|
|
1514
|
+
if (!form || !key) { return false; }
|
|
1515
|
+
var wrap = form.querySelector('[data-pwc-field=\"' + String(key) + '\"]');
|
|
1516
|
+
return !!(wrap && wrap.getAttribute('data-pwc-dirty') === '1');
|
|
1517
|
+
}
|
|
1518
|
+
function getControl(formEl, k) {
|
|
1519
|
+
if (!formEl || !formEl.elements) { return null; }
|
|
1520
|
+
var el = formEl.elements[k];
|
|
1521
|
+
if (el == null) { return null; }
|
|
1522
|
+
if (typeof RadioNodeList !== 'undefined' && el instanceof RadioNodeList) { return el[0] || null; }
|
|
1523
|
+
return el;
|
|
1524
|
+
}
|
|
1525
|
+
function setControlValue(formEl, k, rawVal) {
|
|
1526
|
+
if (!formEl || !formEl.elements) { return; }
|
|
1527
|
+
var el = formEl.elements[k];
|
|
1528
|
+
if (el == null) { return; }
|
|
1529
|
+
if (typeof RadioNodeList !== 'undefined' && el instanceof RadioNodeList) {
|
|
1530
|
+
var want = rawVal == null ? '' : String(rawVal);
|
|
1531
|
+
for (var i = 0; i < el.length; i++) {
|
|
1532
|
+
if (el[i]) {
|
|
1533
|
+
el[i].checked = el[i].value === want;
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
return;
|
|
1537
|
+
}
|
|
1538
|
+
if (el.type === 'checkbox') {
|
|
1539
|
+
el.checked = Boolean(rawVal);
|
|
1540
|
+
return;
|
|
1541
|
+
}
|
|
1542
|
+
el.value = rawVal == null ? '' : String(rawVal);
|
|
1543
|
+
}
|
|
1544
|
+
function getControlValue(formEl, k) {
|
|
1545
|
+
if (!formEl || !formEl.elements) { return undefined; }
|
|
1546
|
+
var el = formEl.elements[k];
|
|
1547
|
+
if (el == null) { return undefined; }
|
|
1548
|
+
if (typeof RadioNodeList !== 'undefined' && el instanceof RadioNodeList) {
|
|
1549
|
+
for (var i = 0; i < el.length; i++) {
|
|
1550
|
+
if (el[i] && el[i].checked) {
|
|
1551
|
+
return el[i].value;
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
return el.value || undefined;
|
|
1555
|
+
}
|
|
1556
|
+
if (el.type === 'checkbox') {
|
|
1557
|
+
return !!el.checked;
|
|
1558
|
+
}
|
|
1559
|
+
return el.value;
|
|
1560
|
+
}
|
|
1561
|
+
function collect(options) {
|
|
1562
|
+
var dirtyOnly = !!(options && options.dirtyOnly);
|
|
1563
|
+
var o = {};
|
|
1564
|
+
if (!form || !form.elements) { return o; }
|
|
1565
|
+
var nodes = form.querySelectorAll('[data-pwc-wrap]');
|
|
1566
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
1567
|
+
var w = nodes[i];
|
|
1568
|
+
if (w.style.display === 'none') { continue; }
|
|
1569
|
+
var k = w.getAttribute('data-pwc-wrap');
|
|
1570
|
+
if (!k) { continue; }
|
|
1571
|
+
if (dirtyOnly && !pwcIsFieldDirty(k)) { continue; }
|
|
1572
|
+
var inp = getControl(form, k);
|
|
1573
|
+
if (inp == null) { continue; }
|
|
1574
|
+
var rawVal = getControlValue(form, k);
|
|
1575
|
+
if (inp.type === 'checkbox') {
|
|
1576
|
+
o[k] = !!inp.checked;
|
|
1577
|
+
} else if (inp.type === 'radio') {
|
|
1578
|
+
o[k] = rawVal;
|
|
1579
|
+
} else if (inp.type === 'number') {
|
|
1580
|
+
var sv = (rawVal != null && String(rawVal) !== '') ? String(rawVal).trim() : '';
|
|
1581
|
+
if (sv === '' || sv === '-' || sv === '+') {
|
|
1582
|
+
o[k] = 0;
|
|
1583
|
+
} else {
|
|
1584
|
+
var n0 = parseInt(sv, 10);
|
|
1585
|
+
o[k] = (typeof n0 === 'number' && !isNaN(n0)) ? n0 : 0;
|
|
1586
|
+
}
|
|
1587
|
+
} else {
|
|
1588
|
+
o[k] = rawVal;
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
return o;
|
|
1592
|
+
}
|
|
1593
|
+
function reflow() {
|
|
1594
|
+
clearTimeout(t);
|
|
1595
|
+
return fetch(ref, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(collect({ dirtyOnly: true })) })
|
|
1596
|
+
.then(function (r) { return r.json(); })
|
|
1597
|
+
.then(function (d) {
|
|
1598
|
+
var sh = d.show || {};
|
|
1599
|
+
var vals = d.values || {};
|
|
1600
|
+
if (!form) { return; }
|
|
1601
|
+
form.querySelectorAll('[data-pwc-wrap]').forEach(function (w) {
|
|
1602
|
+
var k = w.getAttribute('data-pwc-wrap');
|
|
1603
|
+
var wasHidden = w.style.display === 'none';
|
|
1604
|
+
var hidden = k != null && sh[k] === false;
|
|
1605
|
+
w.style.display = hidden ? 'none' : 'block';
|
|
1606
|
+
var ctrls = w.querySelectorAll('input, select, textarea');
|
|
1607
|
+
for (var i = 0; i < ctrls.length; i++) {
|
|
1608
|
+
ctrls[i].disabled = hidden || ctrls[i].getAttribute('data-pwc-static-disabled') === '1';
|
|
1609
|
+
}
|
|
1610
|
+
if (!hidden && k && !pwcIsFieldDirty(k) && Object.prototype.hasOwnProperty.call(vals, k)) {
|
|
1611
|
+
setControlValue(form, k, vals[k]);
|
|
1612
|
+
}
|
|
1613
|
+
});
|
|
1614
|
+
pwcRefreshVisibleSteps();
|
|
1615
|
+
})
|
|
1616
|
+
.catch(function () {});
|
|
1617
|
+
}
|
|
1618
|
+
var t;
|
|
1619
|
+
function scheduleReflow() { clearTimeout(t); t = setTimeout(reflow, 120); }
|
|
1620
|
+
function pwcStepHasVisibleFields(stepIndex) {
|
|
1621
|
+
if (!form || !pwcSteps || stepIndex < 0 || stepIndex >= pwcSteps.length) {
|
|
1622
|
+
return false;
|
|
1623
|
+
}
|
|
1624
|
+
var st = pwcSteps[stepIndex];
|
|
1625
|
+
if (!st || !st.keys || st.keys.length === 0) {
|
|
1626
|
+
return false;
|
|
1627
|
+
}
|
|
1628
|
+
for (var i = 0; i < st.keys.length; i++) {
|
|
1629
|
+
var key = st.keys[i];
|
|
1630
|
+
var wrap = form.querySelector('[data-pwc-wrap=\"' + String(key) + '\"]');
|
|
1631
|
+
if (wrap && wrap.style.display !== 'none') {
|
|
1632
|
+
return true;
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
return false;
|
|
1636
|
+
}
|
|
1637
|
+
function pwcRefreshVisibleSteps() {
|
|
1638
|
+
var prevCur = pwcCur;
|
|
1639
|
+
pwcVisibleSteps = [];
|
|
1640
|
+
for (var i = 0; i < pwcN; i++) {
|
|
1641
|
+
if (i === 0 || pwcStepHasVisibleFields(i)) {
|
|
1642
|
+
pwcVisibleSteps.push(i);
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
if (pwcVisibleSteps.length === 0) {
|
|
1646
|
+
pwcVisibleSteps = [0];
|
|
1647
|
+
}
|
|
1648
|
+
var items = document.querySelectorAll('.pwc-ad-steps-item[data-pwc-step-idx]');
|
|
1649
|
+
for (var j = 0; j < items.length; j++) {
|
|
1650
|
+
var li = items[j];
|
|
1651
|
+
var idx = parseInt(li.getAttribute('data-pwc-step-idx') || '0', 10);
|
|
1652
|
+
li.hidden = pwcVisibleSteps.indexOf(idx) === -1;
|
|
1653
|
+
}
|
|
1654
|
+
var sections = document.querySelectorAll('.pwc-step');
|
|
1655
|
+
for (var k = 0; k < sections.length; k++) {
|
|
1656
|
+
var el = sections[k];
|
|
1657
|
+
var si = parseInt(el.getAttribute('data-pwc-step') || '0', 10);
|
|
1658
|
+
if (pwcVisibleSteps.indexOf(si) === -1) {
|
|
1659
|
+
el.setAttribute('hidden', '');
|
|
1660
|
+
el.classList.remove('pwc-step--active');
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
if (pwcVisibleSteps.indexOf(pwcCur) === -1) {
|
|
1664
|
+
pwcCur = pwcVisibleSteps[0];
|
|
1665
|
+
}
|
|
1666
|
+
pwcRenderCurrentStep(pwcCur, { preserveErrors: pwcCur === prevCur });
|
|
1667
|
+
}
|
|
1668
|
+
function pwcVisibleStepPosition(stepIndex) {
|
|
1669
|
+
return pwcVisibleSteps.indexOf(stepIndex);
|
|
1670
|
+
}
|
|
1671
|
+
function pwcVisiblePrev(stepIndex) {
|
|
1672
|
+
var pos = pwcVisibleStepPosition(stepIndex);
|
|
1673
|
+
if (pos <= 0) {
|
|
1674
|
+
return stepIndex;
|
|
1675
|
+
}
|
|
1676
|
+
return pwcVisibleSteps[pos - 1];
|
|
1677
|
+
}
|
|
1678
|
+
function pwcVisibleNext(stepIndex) {
|
|
1679
|
+
var pos = pwcVisibleStepPosition(stepIndex);
|
|
1680
|
+
if (pos === -1 || pos >= pwcVisibleSteps.length - 1) {
|
|
1681
|
+
return stepIndex;
|
|
1682
|
+
}
|
|
1683
|
+
return pwcVisibleSteps[pos + 1];
|
|
1684
|
+
}
|
|
1685
|
+
function pwcRenderCurrentStep(n, opts) {
|
|
1686
|
+
pwcCur = n;
|
|
1687
|
+
if (pwcN <= 1) { return; }
|
|
1688
|
+
if (!(opts && opts.preserveErrors)) {
|
|
1689
|
+
pwcClearAllFieldErrors();
|
|
1690
|
+
}
|
|
1691
|
+
var sections = document.querySelectorAll('.pwc-step');
|
|
1692
|
+
for (var i = 0; i < sections.length; i++) {
|
|
1693
|
+
var el = sections[i];
|
|
1694
|
+
var si = parseInt(el.getAttribute('data-pwc-step') || '0', 10);
|
|
1695
|
+
if (pwcVisibleSteps.indexOf(si) === -1) {
|
|
1696
|
+
el.setAttribute('hidden', '');
|
|
1697
|
+
el.classList.remove('pwc-step--active');
|
|
1698
|
+
} else if (si === n) {
|
|
1699
|
+
el.removeAttribute('hidden');
|
|
1700
|
+
el.classList.add('pwc-step--active');
|
|
1701
|
+
} else {
|
|
1702
|
+
el.setAttribute('hidden', '');
|
|
1703
|
+
el.classList.remove('pwc-step--active');
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
pwcSyncAntStepsUI(n);
|
|
1707
|
+
var b = document.getElementById('pwcBack');
|
|
1708
|
+
var nx = document.getElementById('pwcNext');
|
|
1709
|
+
var sm = document.getElementById('pwcFormSubmit');
|
|
1710
|
+
var visiblePos = pwcVisibleStepPosition(n);
|
|
1711
|
+
if (b) { b.hidden = visiblePos <= 0; }
|
|
1712
|
+
if (nx) { nx.hidden = visiblePos >= pwcVisibleSteps.length - 1; }
|
|
1713
|
+
if (sm) { sm.hidden = visiblePos < pwcVisibleSteps.length - 1; }
|
|
1714
|
+
}
|
|
1715
|
+
function pwcSyncAntStepsUI(cur) {
|
|
1716
|
+
if (pwcN <= 1) { return; }
|
|
1717
|
+
var items = document.querySelectorAll('.pwc-ad-steps-item[data-pwc-step-idx]');
|
|
1718
|
+
for (var k = 0; k < items.length; k++) {
|
|
1719
|
+
var li = items[k];
|
|
1720
|
+
var i = parseInt(li.getAttribute('data-pwc-step-idx') || '0', 10);
|
|
1721
|
+
if (pwcVisibleSteps.indexOf(i) === -1) {
|
|
1722
|
+
continue;
|
|
1723
|
+
}
|
|
1724
|
+
var curPos = pwcVisibleStepPosition(cur);
|
|
1725
|
+
var itemPos = pwcVisibleStepPosition(i);
|
|
1726
|
+
var st = itemPos < curPos ? 'finish' : (i === cur ? 'process' : 'wait');
|
|
1727
|
+
li.setAttribute('data-pwc-state', st);
|
|
1728
|
+
li.setAttribute('aria-current', st === 'process' ? 'step' : 'false');
|
|
1729
|
+
li.className = 'pwc-ad-steps-item pwc-ad-steps-item--' + st;
|
|
1730
|
+
var iconWrap = li.querySelector('.pwc-ad-vert__icon');
|
|
1731
|
+
if (iconWrap) {
|
|
1732
|
+
if (st === 'finish') {
|
|
1733
|
+
iconWrap.innerHTML = '<span class="pwc-ad-icon pwc-ad-icon--finish" aria-label="done">' + pwcAdCheck + '</span>';
|
|
1734
|
+
} else {
|
|
1735
|
+
var num = itemPos + 1;
|
|
1736
|
+
iconWrap.innerHTML = '<span class="pwc-ad-icon" aria-label="' + num + '"><span class="pwc-ad-icon-num">' + num + '</span></span>';
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
var vtails = document.querySelectorAll('.pwc-ad-vert__tail[data-pwc-vtail]');
|
|
1741
|
+
for (var v = 0; v < vtails.length; v++) {
|
|
1742
|
+
var vt = vtails[v];
|
|
1743
|
+
var vi = parseInt(vt.getAttribute('data-pwc-vtail') || '0', 10);
|
|
1744
|
+
if (pwcVisibleSteps.indexOf(vi) === -1 || pwcVisibleSteps.indexOf(vi + 1) === -1) {
|
|
1745
|
+
vt.hidden = true;
|
|
1746
|
+
continue;
|
|
1747
|
+
}
|
|
1748
|
+
vt.hidden = false;
|
|
1749
|
+
vt.setAttribute('data-pwc-conn', pwcVisibleStepPosition(vi) < pwcVisibleStepPosition(cur) ? 'done' : 'todo');
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
function pwcSetStep(n) {
|
|
1753
|
+
if (pwcVisibleSteps.indexOf(n) === -1) {
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
pwcRenderCurrentStep(n, { preserveErrors: n === pwcCur });
|
|
1757
|
+
reflow();
|
|
1758
|
+
}
|
|
1759
|
+
function validateCurrentStep() {
|
|
1760
|
+
if (!form || pwcN <= 1) { return true; }
|
|
1761
|
+
var st = pwcSteps[pwcCur];
|
|
1762
|
+
if (!st || !st.keys) { return true; }
|
|
1763
|
+
for (var a = 0; a < st.keys.length; a++) {
|
|
1764
|
+
pwcSetFieldError(st.keys[a], null);
|
|
1765
|
+
}
|
|
1766
|
+
for (var j = 0; j < st.keys.length; j++) {
|
|
1767
|
+
var k = st.keys[j];
|
|
1768
|
+
var w = form.querySelector('[data-pwc-wrap=\"' + k + '\"]');
|
|
1769
|
+
if (!w || w.style.display === 'none') { continue; }
|
|
1770
|
+
var inp = getControl(form, k);
|
|
1771
|
+
if (inp == null) { continue; }
|
|
1772
|
+
if (typeof inp.checkValidity === 'function' && !inp.checkValidity()) {
|
|
1773
|
+
var vm = (typeof inp.validationMessage === 'string' && inp.validationMessage) ? inp.validationMessage : uiText.invalidValue;
|
|
1774
|
+
pwcSetFieldError(k, vm);
|
|
1775
|
+
if (typeof inp.focus === 'function') { inp.focus(); }
|
|
1776
|
+
return false;
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
return true;
|
|
1780
|
+
}
|
|
1781
|
+
function pwcNextPayload() {
|
|
1782
|
+
var o = collect();
|
|
1783
|
+
o[pwcStepMeta] = pwcCur;
|
|
1784
|
+
return o;
|
|
1785
|
+
}
|
|
1786
|
+
function pwcFieldPayload(key) {
|
|
1787
|
+
var o = collect();
|
|
1788
|
+
o[pwcFieldMeta] = key;
|
|
1789
|
+
return o;
|
|
1790
|
+
}
|
|
1791
|
+
function pwcValidateField(key) {
|
|
1792
|
+
if (!form || !key || pwcValField == null) { return Promise.resolve(); }
|
|
1793
|
+
var wrap = form.querySelector('[data-pwc-wrap=\"' + String(key) + '\"]');
|
|
1794
|
+
if (!wrap || wrap.style.display === 'none') { return Promise.resolve(); }
|
|
1795
|
+
var reqSeq = (pwcFieldReqSeq[key] || 0) + 1;
|
|
1796
|
+
pwcFieldReqSeq[key] = reqSeq;
|
|
1797
|
+
return fetch(pwcValField, {
|
|
1798
|
+
method: 'POST',
|
|
1799
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1800
|
+
body: JSON.stringify(pwcFieldPayload(key))
|
|
1801
|
+
})
|
|
1802
|
+
.then(function (r) {
|
|
1803
|
+
if (!r.ok) {
|
|
1804
|
+
return r.text().then(function (x) {
|
|
1805
|
+
var pe = pwcParseErrorBody(x);
|
|
1806
|
+
var e = new Error(pe.msg || String(r.status));
|
|
1807
|
+
e.pwcFieldKey = pe.fk;
|
|
1808
|
+
throw e;
|
|
1809
|
+
});
|
|
1810
|
+
}
|
|
1811
|
+
return r.json();
|
|
1812
|
+
})
|
|
1813
|
+
.then(function () {
|
|
1814
|
+
if (pwcFieldReqSeq[key] !== reqSeq) { return; }
|
|
1815
|
+
pwcSetFieldError(key, null);
|
|
1816
|
+
})
|
|
1817
|
+
.catch(function (err) {
|
|
1818
|
+
if (pwcFieldReqSeq[key] !== reqSeq) { return; }
|
|
1819
|
+
if (err && err.pwcFieldKey) {
|
|
1820
|
+
pwcSetFieldError(err.pwcFieldKey, err.message || String(err));
|
|
1821
|
+
return;
|
|
1822
|
+
}
|
|
1823
|
+
pwcSetStatusError(err && err.message ? err.message : err);
|
|
1824
|
+
});
|
|
1825
|
+
}
|
|
1826
|
+
function pwcTryAdvanceNext() {
|
|
1827
|
+
if (pwcVisibleStepPosition(pwcCur) >= pwcVisibleSteps.length - 1) { return Promise.resolve(); }
|
|
1828
|
+
if (!validateCurrentStep()) { return Promise.resolve(); }
|
|
1829
|
+
if (pwcValStep == null) {
|
|
1830
|
+
return reflow().then(function () { pwcSetStep(pwcVisibleNext(pwcCur)); });
|
|
1831
|
+
}
|
|
1832
|
+
pwcSetStatusHint(uiText.checking);
|
|
1833
|
+
return fetch(pwcValStep, {
|
|
1834
|
+
method: 'POST',
|
|
1835
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1836
|
+
body: JSON.stringify(pwcNextPayload())
|
|
1837
|
+
})
|
|
1838
|
+
.then(function (r) {
|
|
1839
|
+
if (!r.ok) {
|
|
1840
|
+
return r.text().then(function (x) {
|
|
1841
|
+
var pe = pwcParseErrorBody(x);
|
|
1842
|
+
var e = new Error(pe.msg || String(r.status));
|
|
1843
|
+
e.pwcFieldKey = pe.fk;
|
|
1844
|
+
throw e;
|
|
1845
|
+
});
|
|
1846
|
+
}
|
|
1847
|
+
return r.json();
|
|
1848
|
+
})
|
|
1849
|
+
.then(function () {
|
|
1850
|
+
pwcSetStatusEmpty();
|
|
1851
|
+
return reflow().then(function () { pwcSetStep(pwcVisibleNext(pwcCur)); });
|
|
1852
|
+
})
|
|
1853
|
+
.catch(function (err) {
|
|
1854
|
+
if (err && err.pwcFieldKey) {
|
|
1855
|
+
pwcSetFieldError(err.pwcFieldKey, err.message || String(err));
|
|
1856
|
+
pwcSetStatusEmpty();
|
|
1857
|
+
var f0 = getControl(form, err.pwcFieldKey);
|
|
1858
|
+
if (f0 && typeof f0.focus === 'function') { f0.focus(); }
|
|
1859
|
+
return;
|
|
1860
|
+
}
|
|
1861
|
+
pwcSetStatusError(err && err.message ? err.message : err);
|
|
1862
|
+
});
|
|
1863
|
+
}
|
|
1864
|
+
if (form) {
|
|
1865
|
+
function pwcOnFieldTouched(e) {
|
|
1866
|
+
var t = e.target;
|
|
1867
|
+
if (t && t.name) {
|
|
1868
|
+
pwcSetFieldDirty(t.name, true);
|
|
1869
|
+
pwcSetFieldError(t.name, null);
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
form.addEventListener('input', function (e) { pwcOnFieldTouched(e); scheduleReflow(); });
|
|
1873
|
+
form.addEventListener('change', function (e) {
|
|
1874
|
+
pwcOnFieldTouched(e);
|
|
1875
|
+
scheduleReflow();
|
|
1876
|
+
var t = e.target;
|
|
1877
|
+
if (t && t.name) {
|
|
1878
|
+
void pwcValidateField(t.name);
|
|
1879
|
+
}
|
|
1880
|
+
});
|
|
1881
|
+
form.addEventListener('keydown', function (e) {
|
|
1882
|
+
if (e.key !== 'Enter' || pwcN <= 1) { return; }
|
|
1883
|
+
if (e.target && e.target.tagName === 'TEXTAREA') { return; }
|
|
1884
|
+
if (pwcCur < pwcN - 1) {
|
|
1885
|
+
e.preventDefault();
|
|
1886
|
+
void pwcTryAdvanceNext();
|
|
1887
|
+
}
|
|
1888
|
+
});
|
|
1889
|
+
}
|
|
1890
|
+
var pwcBack = document.getElementById('pwcBack');
|
|
1891
|
+
if (pwcBack) { pwcBack.addEventListener('click', function () { if (pwcVisibleStepPosition(pwcCur) > 0) { pwcSetStep(pwcVisiblePrev(pwcCur)); } }); }
|
|
1892
|
+
var pwcNext = document.getElementById('pwcNext');
|
|
1893
|
+
if (pwcNext) { pwcNext.addEventListener('click', function () { void pwcTryAdvanceNext(); }); }
|
|
1894
|
+
pwcRefreshVisibleSteps();
|
|
1895
|
+
if (form) { setTimeout(function () { reflow(); }, 0); }
|
|
1896
|
+
if (form) {
|
|
1897
|
+
form.addEventListener('submit', function (e) {
|
|
1898
|
+
e.preventDefault();
|
|
1899
|
+
if (pwcN > 1 && pwcVisibleStepPosition(pwcCur) < pwcVisibleSteps.length - 1) { return; }
|
|
1900
|
+
pwcSetStatusHint(uiText.sending);
|
|
1901
|
+
pwcClearAllFieldErrors();
|
|
1902
|
+
fetch(sub, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(collect()) })
|
|
1903
|
+
.then(function (r) {
|
|
1904
|
+
if (!r.ok) {
|
|
1905
|
+
return r.text().then(function (x) {
|
|
1906
|
+
var pe = pwcParseErrorBody(x);
|
|
1907
|
+
var e = new Error(pe.msg || String(r.status));
|
|
1908
|
+
e.pwcFieldKey = pe.fk;
|
|
1909
|
+
throw e;
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
return r.json();
|
|
1913
|
+
})
|
|
1914
|
+
.then(function () {
|
|
1915
|
+
pwcSetStatusSuccess(uiText.savedAndClosing);
|
|
1916
|
+
pwcScheduleWindowClose();
|
|
1917
|
+
})
|
|
1918
|
+
.catch(function (err) {
|
|
1919
|
+
if (err && err.pwcFieldKey) {
|
|
1920
|
+
pwcSetFieldError(err.pwcFieldKey, err.message || String(err));
|
|
1921
|
+
pwcSetStatusEmpty();
|
|
1922
|
+
var f1 = getControl(form, err.pwcFieldKey);
|
|
1923
|
+
if (f1 && typeof f1.focus === 'function') { f1.focus(); }
|
|
1924
|
+
return;
|
|
1925
|
+
}
|
|
1926
|
+
pwcSetStatusError(err && err.message ? err.message : err);
|
|
1927
|
+
});
|
|
1928
|
+
});
|
|
1929
|
+
}
|
|
1930
|
+
})();
|
|
1931
|
+
<\/script>
|
|
1932
|
+
</body>
|
|
1933
|
+
</html>`;
|
|
1934
|
+
return page;
|
|
1935
|
+
};
|
|
1936
|
+
server = createServer((req, res) => {
|
|
1937
|
+
if (!req.socket.remoteAddress ||
|
|
1938
|
+
!['127.0.0.1', '::1', '::ffff:127.0.0.1'].includes(req.socket.remoteAddress)) {
|
|
1939
|
+
res.writeHead(403).end();
|
|
1940
|
+
return;
|
|
1941
|
+
}
|
|
1942
|
+
if (req.method === 'GET' && (req.url === '/' || req.url === '')) {
|
|
1943
|
+
const addr = server?.address();
|
|
1944
|
+
const port = typeof addr === 'object' && addr ? Number(addr.port) : 0;
|
|
1945
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
1946
|
+
res.end(servePage(port));
|
|
1947
|
+
return;
|
|
1948
|
+
}
|
|
1949
|
+
if (req.method === 'POST' && req.url === reflowPath) {
|
|
1950
|
+
const chunks = [];
|
|
1951
|
+
req.on('data', (c) => chunks.push(c));
|
|
1952
|
+
req.on('end', () => {
|
|
1953
|
+
try {
|
|
1954
|
+
const raw = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
1955
|
+
const { show, values } = reflowWebFormState(catalog, readFormFromClient(raw), userSeed);
|
|
1956
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1957
|
+
res.end(JSON.stringify({ show, values }));
|
|
1958
|
+
}
|
|
1959
|
+
catch {
|
|
1960
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
1961
|
+
res.end(JSON.stringify({ show: {}, values: {} }));
|
|
1962
|
+
}
|
|
1963
|
+
});
|
|
1964
|
+
return;
|
|
1965
|
+
}
|
|
1966
|
+
if (req.method === 'POST' && req.url === resolveValidateStepPath) {
|
|
1967
|
+
if (pwcNSteps <= 1) {
|
|
1968
|
+
res.writeHead(404).end();
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1971
|
+
const chunks = [];
|
|
1972
|
+
req.on('data', (c) => chunks.push(c));
|
|
1973
|
+
req.on('end', () => {
|
|
1974
|
+
void (async () => {
|
|
1975
|
+
try {
|
|
1976
|
+
const raw = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
1977
|
+
const sidx = raw[PWC_FORM_META_STEP];
|
|
1978
|
+
const step = typeof sidx === 'number' && Number.isFinite(sidx)
|
|
1979
|
+
? sidx
|
|
1980
|
+
: typeof sidx === 'string' && sidx.length > 0
|
|
1981
|
+
? Number.parseInt(sidx, 10)
|
|
1982
|
+
: NaN;
|
|
1983
|
+
if (!Number.isInteger(step) || step < 0 || step >= pwcStepDefs.length) {
|
|
1984
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
1985
|
+
res.end(JSON.stringify({ ok: false, error: t('promptCatalog.web.invalidStep') }));
|
|
1986
|
+
return;
|
|
1987
|
+
}
|
|
1988
|
+
const { error, fieldKey } = await buildWebPresetFromBody(catalog, readFormFromClient(readFormFromClientStrippingPwcMeta(raw)), userSeed, { scopeKeys: new Set(pwcStepDefs[step].keys), locale });
|
|
1989
|
+
if (error) {
|
|
1990
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
1991
|
+
res.end(JSON.stringify(fieldKey ? { ok: false, error, fieldKey } : { ok: false, error }));
|
|
1992
|
+
return;
|
|
1993
|
+
}
|
|
1994
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
1995
|
+
res.end(JSON.stringify({ ok: true }));
|
|
1996
|
+
}
|
|
1997
|
+
catch {
|
|
1998
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
1999
|
+
res.end(JSON.stringify({ ok: false, error: t('promptCatalog.web.invalidRequest') }));
|
|
2000
|
+
}
|
|
2001
|
+
})();
|
|
2002
|
+
});
|
|
2003
|
+
return;
|
|
2004
|
+
}
|
|
2005
|
+
if (req.method === 'POST' && req.url === resolveValidateFieldPath) {
|
|
2006
|
+
const chunks = [];
|
|
2007
|
+
req.on('data', (c) => chunks.push(c));
|
|
2008
|
+
req.on('end', () => {
|
|
2009
|
+
void (async () => {
|
|
2010
|
+
try {
|
|
2011
|
+
const raw = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
2012
|
+
const fieldKeyRaw = raw[PWC_FORM_META_FIELD];
|
|
2013
|
+
const fieldKey = typeof fieldKeyRaw === 'string' && fieldKeyRaw.trim().length > 0
|
|
2014
|
+
? fieldKeyRaw.trim()
|
|
2015
|
+
: '';
|
|
2016
|
+
if (!fieldKey || !Object.prototype.hasOwnProperty.call(catalog, fieldKey)) {
|
|
2017
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
2018
|
+
res.end(JSON.stringify({ ok: false, error: t('promptCatalog.web.invalidField') }));
|
|
2019
|
+
return;
|
|
2020
|
+
}
|
|
2021
|
+
const { error } = await buildWebPresetFromBody(catalog, readFormFromClient(readFormFromClientStrippingPwcMeta(raw)), userSeed, { scopeKeys: new Set([fieldKey]), locale });
|
|
2022
|
+
if (error) {
|
|
2023
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
2024
|
+
res.end(JSON.stringify({ ok: false, error, fieldKey }));
|
|
2025
|
+
return;
|
|
2026
|
+
}
|
|
2027
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2028
|
+
res.end(JSON.stringify({ ok: true }));
|
|
2029
|
+
}
|
|
2030
|
+
catch {
|
|
2031
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
2032
|
+
res.end(JSON.stringify({ ok: false, error: t('promptCatalog.web.invalidRequest') }));
|
|
2033
|
+
}
|
|
2034
|
+
})();
|
|
2035
|
+
});
|
|
2036
|
+
return;
|
|
2037
|
+
}
|
|
2038
|
+
if (req.method === 'POST' && req.url === submitPath) {
|
|
2039
|
+
const chunks = [];
|
|
2040
|
+
req.on('data', (c) => chunks.push(c));
|
|
2041
|
+
req.on('end', () => {
|
|
2042
|
+
void (async () => {
|
|
2043
|
+
try {
|
|
2044
|
+
const raw = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
2045
|
+
const { preset, error, fieldKey } = await buildWebPresetFromBody(catalog, readFormFromClient(raw), userSeed, { locale });
|
|
2046
|
+
if (error) {
|
|
2047
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
2048
|
+
res.end(JSON.stringify(fieldKey ? { ok: false, error, fieldKey } : { ok: false, error }));
|
|
2049
|
+
return;
|
|
2050
|
+
}
|
|
2051
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
2052
|
+
res.end(JSON.stringify({ ok: true }), () => {
|
|
2053
|
+
if (timeoutId !== undefined) {
|
|
2054
|
+
clearTimeout(timeoutId);
|
|
2055
|
+
timeoutId = undefined;
|
|
2056
|
+
}
|
|
2057
|
+
if (server) {
|
|
2058
|
+
closePromptWebUiServer(server, () => resolve(preset));
|
|
2059
|
+
return;
|
|
2060
|
+
}
|
|
2061
|
+
resolve(preset);
|
|
2062
|
+
});
|
|
2063
|
+
}
|
|
2064
|
+
catch (e) {
|
|
2065
|
+
res.writeHead(400, { 'Content-Type': 'text/plain' });
|
|
2066
|
+
res.end(t('promptCatalog.web.invalidRequest'));
|
|
2067
|
+
}
|
|
2068
|
+
})();
|
|
2069
|
+
});
|
|
2070
|
+
return;
|
|
2071
|
+
}
|
|
2072
|
+
if (req.method === 'GET' && req.url === '/favicon.ico') {
|
|
2073
|
+
res.writeHead(204).end();
|
|
2074
|
+
return;
|
|
2075
|
+
}
|
|
2076
|
+
res.writeHead(404).end();
|
|
2077
|
+
});
|
|
2078
|
+
server.listen(options.port ?? 0, host, () => {
|
|
2079
|
+
const addr = server?.address();
|
|
2080
|
+
if (typeof addr !== 'object' || !addr) {
|
|
2081
|
+
rejectAndClose(new Error('Failed to bind HTTP server'));
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2084
|
+
const port = addr.port;
|
|
2085
|
+
const startUrl = `http://${host}:${port}/`;
|
|
2086
|
+
options.onServerStart?.({ host, port, url: startUrl });
|
|
2087
|
+
try {
|
|
2088
|
+
openUrlInDefaultBrowser(startUrl);
|
|
2089
|
+
}
|
|
2090
|
+
catch (e) {
|
|
2091
|
+
(options.onOpenBrowserError ?? ((u, err) => console.warn(String(err), u)))(startUrl, e);
|
|
2092
|
+
}
|
|
2093
|
+
timeoutId = setTimeout(() => rejectAndClose(new Error('Local UI timeout — close the tab and try again, or resubmit within the time limit.')), timeoutMs);
|
|
2094
|
+
});
|
|
2095
|
+
});
|
|
2096
|
+
}
|