codexmate 0.1.18 → 0.1.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/package.json +1 -1
- package/web-ui/modules/app.methods.pi-config.mjs +10 -1
- package/web-ui/modules/i18n/locales/en.mjs +2 -1
- package/web-ui/modules/i18n/locales/ja.mjs +2 -1
- package/web-ui/modules/i18n/locales/vi.mjs +2 -1
- package/web-ui/modules/i18n/locales/zh-tw.mjs +2 -1
- package/web-ui/modules/i18n/locales/zh.mjs +2 -1
- package/web-ui/partials/index/panel-config-pi.html +23 -15
- package/web-ui/partials/index/panel-dashboard.html +51 -44
- package/web-ui/res/web-ui-render.precompiled.js +127 -112
- package/web-ui/styles/controls-forms.css +7 -0
- package/web-ui/styles/dashboard.css +52 -158
package/package.json
CHANGED
|
@@ -55,6 +55,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
55
55
|
: '';
|
|
56
56
|
const updates = { defaultProvider: providerId };
|
|
57
57
|
if (firstModel) updates.defaultModel = firstModel;
|
|
58
|
+
else updates.defaultModel = '';
|
|
58
59
|
try {
|
|
59
60
|
const result = await apiClient('write-pi-settings', updates);
|
|
60
61
|
if (result && result.error) throw new Error(result.error);
|
|
@@ -126,6 +127,11 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
126
127
|
this.messageType = 'error';
|
|
127
128
|
return;
|
|
128
129
|
}
|
|
130
|
+
if (!Array.isArray(merged.models) || merged.models.length === 0) {
|
|
131
|
+
this.message = '请至少导入或输入一个模型';
|
|
132
|
+
this.messageType = 'error';
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
129
135
|
const providerId = isNew ? this.derivePiProviderId(baseUrl) : editor.id;
|
|
130
136
|
if (isNew) {
|
|
131
137
|
merged.id = providerId;
|
|
@@ -207,6 +213,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
207
213
|
startPiProviderDraft(tpl) {
|
|
208
214
|
const template = isPiPlainObject(tpl) ? tpl : {};
|
|
209
215
|
this.resetPiEditorTransientState();
|
|
216
|
+
this.showAddPiProviderModal = false;
|
|
210
217
|
this.editingPiProvider = {
|
|
211
218
|
id: '',
|
|
212
219
|
isNew: true,
|
|
@@ -350,6 +357,8 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
350
357
|
const wasNew = !!editor.isNew;
|
|
351
358
|
this.resetPiProviderEditing();
|
|
352
359
|
if (wasNew) this.piSelectedProviderTemplate = '';
|
|
360
|
+
this.showAddPiProviderModal = false;
|
|
361
|
+
this.piProviderPickerQuery = '';
|
|
353
362
|
},
|
|
354
363
|
removePiProviderModel(index) {
|
|
355
364
|
if (!this.editingPiProvider) return;
|
|
@@ -544,7 +553,7 @@ export function createPiConfigMethods({ api: apiClient }) {
|
|
|
544
553
|
if (merged.baseUrl === undefined) merged.baseUrl = values.baseUrl || '';
|
|
545
554
|
if (merged.api === undefined) merged.api = values.api || '';
|
|
546
555
|
if (merged.apiKey === undefined) merged.apiKey = values.apiKey || '';
|
|
547
|
-
|
|
556
|
+
merged.models = mapModels(merged.models !== undefined ? merged.models : values.models);
|
|
548
557
|
if (isPiPlainObject(orig.headers)) merged.headers = orig.headers;
|
|
549
558
|
if (typeof orig.title === 'string') merged.title = orig.title;
|
|
550
559
|
else if (typeof orig.name === 'string') merged.name = orig.name;
|
|
@@ -268,6 +268,7 @@ const en = Object.freeze({
|
|
|
268
268
|
'dashboard.doctor.export.json': 'Export JSON',
|
|
269
269
|
'dashboard.doctor.export.md': 'Export Markdown',
|
|
270
270
|
'dashboard.doctor.open': 'Open',
|
|
271
|
+
'dashboard.doctor.empty': 'No checks have been run yet. Run checks to diagnose the current setup.',
|
|
271
272
|
'doctor.action.openConfig': 'Open Config',
|
|
272
273
|
'doctor.action.checkProvider': 'Check provider config',
|
|
273
274
|
'doctor.action.openUsage': 'Open Usage',
|
|
@@ -1361,9 +1362,9 @@ const en = Object.freeze({
|
|
|
1361
1362
|
'pi.providers.json.previewTitle': 'Preview',
|
|
1362
1363
|
'pi.providers.json.editTitle': 'Edit JSON',
|
|
1363
1364
|
'pi.files.title': 'File JSON',
|
|
1364
|
-
'pi.files.desc': 'View and edit Pi settings.json and models.json in full; JSON validity is checked before saving and invalid content is never written.',
|
|
1365
1365
|
'pi.files.settingsTitle': 'settings.json (active settings)',
|
|
1366
1366
|
'pi.files.modelsTitle': 'models.json (providers and models)',
|
|
1367
|
+
'pi.files.modelsHint': 'Merged automatically from the provider management above; prefer editing providers there instead.',
|
|
1367
1368
|
'pi.history.apply': 'Apply this record',
|
|
1368
1369
|
'pi.history.applied': 'History record applied',
|
|
1369
1370
|
'pi.history.applyFailed': 'Failed to apply history record',
|
|
@@ -270,6 +270,7 @@ const ja = Object.freeze({
|
|
|
270
270
|
'dashboard.doctor.export.json': 'JSON エクスポート',
|
|
271
271
|
'dashboard.doctor.export.md': 'Markdown エクスポート',
|
|
272
272
|
'dashboard.doctor.open': '開く',
|
|
273
|
+
'dashboard.doctor.empty': 'まだチェックは実行されていません。「チェックを実行」で現在のセットアップを診断します。',
|
|
273
274
|
'doctor.action.openConfig': 'Config を開く',
|
|
274
275
|
'doctor.action.checkProvider': 'Provider 設定をチェック',
|
|
275
276
|
'doctor.action.openUsage': 'Usage を開く',
|
|
@@ -1362,9 +1363,9 @@ const ja = Object.freeze({
|
|
|
1362
1363
|
'pi.providers.json.previewTitle': 'プレビュー',
|
|
1363
1364
|
'pi.providers.json.editTitle': 'JSON を編集',
|
|
1364
1365
|
'pi.files.title': 'ファイル JSON',
|
|
1365
|
-
'pi.files.desc': 'Pi の settings.json と models.json を全文表示して直接編集します。保存前に JSON の正当性を検証し、不正な内容は書き込みません。',
|
|
1366
1366
|
'pi.files.settingsTitle': 'settings.json(有効な設定)',
|
|
1367
1367
|
'pi.files.modelsTitle': 'models.json(プロバイダーとモデル)',
|
|
1368
|
+
'pi.files.modelsHint': '上のプロバイダー管理から自動的にマージされます。プロバイダーの変更は上の管理画面を優先してください。',
|
|
1368
1369
|
'pi.history.apply': 'この履歴を適用',
|
|
1369
1370
|
'pi.history.applied': '履歴を適用しました',
|
|
1370
1371
|
'pi.history.applyFailed': '履歴の適用に失敗しました',
|
|
@@ -539,6 +539,7 @@ const vi = Object.freeze({
|
|
|
539
539
|
'dashboard.doctor.export.json': 'Xuất JSON',
|
|
540
540
|
'dashboard.doctor.export.md': 'Xuất Markdown',
|
|
541
541
|
'dashboard.doctor.open': 'Mở',
|
|
542
|
+
'dashboard.doctor.empty': 'Chưa chạy lần kiểm tra nào. Nhấn "Chạy kiểm tra" để chẩn đoán cấu hình hiện tại.',
|
|
542
543
|
'doctor.action.openConfig': 'Mở cấu hình',
|
|
543
544
|
'doctor.action.checkProvider': 'Kiểm tra cấu hình nhà cung cấp',
|
|
544
545
|
'doctor.action.openUsage': 'Mở thống kê',
|
|
@@ -1330,9 +1331,9 @@ const vi = Object.freeze({
|
|
|
1330
1331
|
'pi.providers.json.previewTitle': 'Xem trước',
|
|
1331
1332
|
'pi.providers.json.editTitle': 'Chỉnh sửa JSON',
|
|
1332
1333
|
'pi.files.title': 'JSON tập tin',
|
|
1333
|
-
'pi.files.desc': 'Hiển thị đầy đủ và chỉnh sửa trực tiếp settings.json và models.json của Pi; kiểm tra tính hợp lệ của JSON trước khi lưu, nội dung không hợp lệ sẽ không được ghi.',
|
|
1334
1334
|
'pi.files.settingsTitle': 'settings.json (cài đặt đang dùng)',
|
|
1335
1335
|
'pi.files.modelsTitle': 'models.json (nhà cung cấp và mô hình)',
|
|
1336
|
+
'pi.files.modelsHint': 'Được hợp nhất tự động từ phần quản lý nhà cung cấp phía trên; hãy ưu tiên chỉnh sửa ở đó.',
|
|
1336
1337
|
'pi.history.apply': 'Áp dụng bản ghi này',
|
|
1337
1338
|
'pi.history.applied': 'Đã áp dụng lịch sử',
|
|
1338
1339
|
'pi.history.applyFailed': 'Áp dụng lịch sử thất bại',
|
|
@@ -268,6 +268,7 @@ const zhTw = Object.freeze({
|
|
|
268
268
|
'dashboard.doctor.export.json': '匯出 JSON',
|
|
269
269
|
'dashboard.doctor.export.md': '匯出 Markdown',
|
|
270
270
|
'dashboard.doctor.open': '打開',
|
|
271
|
+
'dashboard.doctor.empty': '尚未執行檢查。點擊「運行檢查」診斷目前設定。',
|
|
271
272
|
'doctor.action.openConfig': '打開 Config',
|
|
272
273
|
'doctor.action.checkProvider': '檢查 Provider 設定',
|
|
273
274
|
'doctor.action.openUsage': '打開 Usage',
|
|
@@ -1359,9 +1360,9 @@ const zhTw = Object.freeze({
|
|
|
1359
1360
|
'pi.providers.json.previewTitle': '預覽',
|
|
1360
1361
|
'pi.providers.json.editTitle': '編輯 JSON',
|
|
1361
1362
|
'pi.files.title': '檔案 JSON',
|
|
1362
|
-
'pi.files.desc': '完整展示並直接編輯 Pi 的 settings.json 與 models.json;儲存前校驗 JSON 合法性,非法內容不會寫入。',
|
|
1363
1363
|
'pi.files.settingsTitle': 'settings.json(生效設定)',
|
|
1364
1364
|
'pi.files.modelsTitle': 'models.json(供應商與模型)',
|
|
1365
|
+
'pi.files.modelsHint': '由上方供應商管理自動合併生成;調整供應商請優先使用上方的供應商管理。',
|
|
1365
1366
|
'pi.history.apply': '套用此紀錄',
|
|
1366
1367
|
'pi.history.applied': '已套用歷史紀錄',
|
|
1367
1368
|
'pi.history.applyFailed': '套用歷史紀錄失敗',
|
|
@@ -268,6 +268,7 @@ const zh = Object.freeze({
|
|
|
268
268
|
'dashboard.doctor.export.json': '导出 JSON',
|
|
269
269
|
'dashboard.doctor.export.md': '导出 Markdown',
|
|
270
270
|
'dashboard.doctor.open': '打开',
|
|
271
|
+
'dashboard.doctor.empty': '尚未运行检查。点击上方“运行检查”诊断当前配置。',
|
|
271
272
|
'doctor.action.openConfig': '打开 Config',
|
|
272
273
|
'doctor.action.checkProvider': '检查 Provider 配置',
|
|
273
274
|
'doctor.action.openUsage': '打开 Usage',
|
|
@@ -1359,9 +1360,9 @@ const zh = Object.freeze({
|
|
|
1359
1360
|
'pi.providers.json.previewTitle': '预览',
|
|
1360
1361
|
'pi.providers.json.editTitle': '编辑 JSON',
|
|
1361
1362
|
'pi.files.title': '文件 JSON',
|
|
1362
|
-
'pi.files.desc': '完整展示并直接编辑 Pi 的 settings.json 与 models.json;保存前校验 JSON 合法性,非法内容不会写入。',
|
|
1363
1363
|
'pi.files.settingsTitle': 'settings.json(生效设置)',
|
|
1364
1364
|
'pi.files.modelsTitle': 'models.json(供应商与模型)',
|
|
1365
|
+
'pi.files.modelsHint': '由上方供应商管理自动合并生成;调整供应商请优先使用上方的供应商管理。',
|
|
1365
1366
|
'pi.history.apply': '应用此记录',
|
|
1366
1367
|
'pi.history.applied': '已应用历史记录',
|
|
1367
1368
|
'pi.history.applyFailed': '应用历史记录失败',
|
|
@@ -49,19 +49,24 @@
|
|
|
49
49
|
</div>
|
|
50
50
|
<div class="card-trailing">
|
|
51
51
|
<span v-if="piActiveProvider === providerId" class="pill configured">{{ t('pi.providers.active') }}</span>
|
|
52
|
-
<button v-else type="button" class="btn-tool" @click.stop="switchPiActiveProvider(providerId)" :disabled="!isToolConfigWriteAllowed('pi') || piSaving">{{ t('pi.providers.setActive') }}</button>
|
|
52
|
+
<button v-else type="button" class="btn-tool btn-tool-compact" @click.stop="switchPiActiveProvider(providerId)" :disabled="!isToolConfigWriteAllowed('pi') || piSaving">{{ t('pi.providers.setActive') }}</button>
|
|
53
53
|
</div>
|
|
54
54
|
</div>
|
|
55
55
|
</div>
|
|
56
|
-
<div v-if="!piProviderIds.length" class="
|
|
56
|
+
<div v-if="!piProviderIds.length" class="empty-state">
|
|
57
|
+
<div class="empty-state-title">{{ t('pi.providers.empty') }}</div>
|
|
58
|
+
</div>
|
|
57
59
|
</section>
|
|
58
60
|
|
|
59
|
-
<section class="selector-section">
|
|
61
|
+
<section class="selector-section pi-file-section">
|
|
60
62
|
<div class="selector-header">
|
|
61
|
-
<span class="selector-title">{{ t('pi.files.
|
|
63
|
+
<span class="selector-title">{{ t('pi.files.settingsTitle') }}</span>
|
|
64
|
+
<div class="selector-actions">
|
|
65
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="openPiConfigHistory('settings')" :disabled="piHistoryLoading">{{ t('common.history') }}</button>
|
|
66
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="savePiSettingsJson" :disabled="!isToolConfigWriteAllowed('pi') || piSaving || piFileJsonSaving || !!piSettingsJsonError">{{ t('common.save') }}</button>
|
|
67
|
+
</div>
|
|
62
68
|
</div>
|
|
63
|
-
<div class="config-template-hint">{{ t('pi.
|
|
64
|
-
<label class="form-label">{{ t('pi.files.settingsTitle') }}</label>
|
|
69
|
+
<div class="config-template-hint">{{ t('pi.providers.targetFile', { path: '~/.pi/agent/settings.json' }) }}</div>
|
|
65
70
|
<textarea
|
|
66
71
|
class="template-textarea config-json-editor"
|
|
67
72
|
v-model="piSettingsJsonDraft"
|
|
@@ -71,10 +76,6 @@
|
|
|
71
76
|
@input="piSettingsJsonInput"
|
|
72
77
|
placeholder="{}"></textarea>
|
|
73
78
|
<p v-if="piSettingsJsonError" class="config-template-hint error-text">{{ piSettingsJsonError }}</p>
|
|
74
|
-
<div class="settings-tab-actions">
|
|
75
|
-
<button type="button" class="btn-tool" @click="savePiSettingsJson" :disabled="!isToolConfigWriteAllowed('pi') || piSaving || piFileJsonSaving || !!piSettingsJsonError">{{ t('common.save') }}</button>
|
|
76
|
-
<button type="button" class="btn-mini" @click="openPiConfigHistory('settings')" :disabled="piHistoryLoading">{{ t('common.history') }}</button>
|
|
77
|
-
</div>
|
|
78
79
|
<details v-if="piHistoryTarget === 'settings'" class="prompt-history-panel" open>
|
|
79
80
|
<summary class="prompt-history-summary">
|
|
80
81
|
<span>{{ t('common.history') }}</span>
|
|
@@ -96,7 +97,18 @@
|
|
|
96
97
|
</div>
|
|
97
98
|
</div>
|
|
98
99
|
</details>
|
|
99
|
-
|
|
100
|
+
</section>
|
|
101
|
+
|
|
102
|
+
<section class="selector-section pi-file-section">
|
|
103
|
+
<div class="selector-header">
|
|
104
|
+
<span class="selector-title">{{ t('pi.files.modelsTitle') }}</span>
|
|
105
|
+
<div class="selector-actions">
|
|
106
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="openPiConfigHistory('models')" :disabled="piHistoryLoading">{{ t('common.history') }}</button>
|
|
107
|
+
<button type="button" class="btn-tool btn-tool-compact" @click="savePiModelsJson" :disabled="!isToolConfigWriteAllowed('pi') || piSaving || piFileJsonSaving || !!piModelsJsonError">{{ t('common.save') }}</button>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="config-template-hint">{{ t('pi.files.modelsHint') }}</div>
|
|
111
|
+
<div class="config-template-hint">{{ t('pi.providers.targetFile', { path: '~/.pi/agent/models.json' }) }}</div>
|
|
100
112
|
<textarea
|
|
101
113
|
class="template-textarea config-json-editor"
|
|
102
114
|
v-model="piModelsJsonDraft"
|
|
@@ -106,10 +118,6 @@
|
|
|
106
118
|
@input="piModelsJsonInput"
|
|
107
119
|
placeholder="{}"></textarea>
|
|
108
120
|
<p v-if="piModelsJsonError" class="config-template-hint error-text">{{ piModelsJsonError }}</p>
|
|
109
|
-
<div class="settings-tab-actions">
|
|
110
|
-
<button type="button" class="btn-tool" @click="savePiModelsJson" :disabled="!isToolConfigWriteAllowed('pi') || piSaving || piFileJsonSaving || !!piModelsJsonError">{{ t('common.save') }}</button>
|
|
111
|
-
<button type="button" class="btn-mini" @click="openPiConfigHistory('models')" :disabled="piHistoryLoading">{{ t('common.history') }}</button>
|
|
112
|
-
</div>
|
|
113
121
|
<details v-if="piHistoryTarget === 'models'" class="prompt-history-panel" open>
|
|
114
122
|
<summary class="prompt-history-summary">
|
|
115
123
|
<span>{{ t('common.history') }}</span>
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
role="tabpanel"
|
|
6
6
|
:aria-labelledby="'tab-dashboard'">
|
|
7
7
|
<div class="selector-section doctor-hero">
|
|
8
|
-
<div class="selector-header">
|
|
8
|
+
<div class="selector-header doctor-header">
|
|
9
9
|
<span class="selector-title">{{ t('dashboard.doctor.title') }}</span>
|
|
10
10
|
<div class="selector-actions">
|
|
11
11
|
<button
|
|
12
|
-
class="btn-tool btn-tool-compact"
|
|
12
|
+
class="btn-tool btn-tool-compact doctor-run-btn"
|
|
13
13
|
@click="runHealthCheck"
|
|
14
14
|
:disabled="loading || !!initError || healthCheckLoading">
|
|
15
15
|
{{ healthCheckLoading ? t('dashboard.doctor.checking') : t('dashboard.doctor.runChecks') }}
|
|
@@ -30,52 +30,59 @@
|
|
|
30
30
|
<strong>{{ inspectorModelLoadStatus }}</strong>
|
|
31
31
|
</div>
|
|
32
32
|
</div>
|
|
33
|
-
<div
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<div v-if="healthCheckResult && healthCheckResult.report" class="doctor-action-list">
|
|
40
|
-
<template v-if="healthCheckResult.report.issues && healthCheckResult.report.issues.length">
|
|
41
|
-
<div v-for="issue in healthCheckResult.report.issues" :key="issue.id" class="doctor-action-card">
|
|
42
|
-
<div class="doctor-action-head">
|
|
43
|
-
<div class="doctor-action-title">{{ issue.problem || (issue.problemKey ? t(issue.problemKey, issue.problemParams) : '') }}</div>
|
|
44
|
-
<div :class="['doctor-action-severity', issue.severity]">{{ issue.severityLabel || issue.severity }}</div>
|
|
33
|
+
<div class="doctor-result-section">
|
|
34
|
+
<template v-if="healthCheckResult">
|
|
35
|
+
<div class="doctor-health-result" :class="healthCheckResult.ok ? 'ok' : 'error'">
|
|
36
|
+
<div class="doctor-health-title">
|
|
37
|
+
{{ healthCheckResult.ok ? t('dashboard.health.ok') : t('dashboard.health.fail') }}
|
|
38
|
+
<span v-if="healthCheckResult.issues && healthCheckResult.issues.length">({{ t('dashboard.health.issues', { count: healthCheckResult.issues.length }) }})</span>
|
|
45
39
|
</div>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class="doctor-action-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
40
|
+
</div>
|
|
41
|
+
<div v-if="healthCheckResult.report" class="doctor-action-list">
|
|
42
|
+
<template v-if="healthCheckResult.report.issues && healthCheckResult.report.issues.length">
|
|
43
|
+
<div v-for="issue in healthCheckResult.report.issues" :key="issue.id" class="doctor-action-card">
|
|
44
|
+
<div class="doctor-action-head">
|
|
45
|
+
<div class="doctor-action-title">{{ issue.problem || (issue.problemKey ? t(issue.problemKey, issue.problemParams) : '') }}</div>
|
|
46
|
+
<div :class="['doctor-action-severity', issue.severity]">{{ issue.severityLabel || issue.severity }}</div>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="doctor-action-impact">{{ issue.impact || (issue.impactKey ? t(issue.impactKey, issue.impactParams) : '') }}</div>
|
|
49
|
+
<div
|
|
50
|
+
v-if="issue.actions && issue.actions.some(action => action && action.type === 'navigate' && action.target)"
|
|
51
|
+
class="doctor-action-buttons">
|
|
52
|
+
<template v-for="(action, index) in issue.actions" :key="issue.id + '-action-' + index">
|
|
53
|
+
<button
|
|
54
|
+
v-if="action.type === 'navigate' && action.target"
|
|
55
|
+
type="button"
|
|
56
|
+
class="btn-tool btn-tool-compact"
|
|
57
|
+
@click="action.target ? switchMainTab(action.target) : null">
|
|
58
|
+
{{ action.label || (action.labelKey ? t(action.labelKey, action.labelParams) : t('dashboard.doctor.open')) }}
|
|
59
|
+
</button>
|
|
60
|
+
</template>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</template>
|
|
64
|
+
<div class="doctor-action-footer">
|
|
65
|
+
<button
|
|
66
|
+
type="button"
|
|
67
|
+
class="btn-tool btn-tool-compact"
|
|
68
|
+
@click="healthCheckResult && healthCheckResult.report
|
|
69
|
+
? downloadTextFile('codexmate-doctor.json', JSON.stringify(healthCheckResult.report, null, 2), 'application/json;charset=utf-8')
|
|
70
|
+
: null">
|
|
71
|
+
{{ t('dashboard.doctor.export.json') }}
|
|
72
|
+
</button>
|
|
73
|
+
<button
|
|
74
|
+
type="button"
|
|
75
|
+
class="btn-tool btn-tool-compact"
|
|
76
|
+
@click="healthCheckResult && healthCheckResult.report
|
|
77
|
+
? downloadTextFile('codexmate-doctor.md', String(healthCheckResult.markdown || ''), 'text/markdown;charset=utf-8')
|
|
78
|
+
: null">
|
|
79
|
+
{{ t('dashboard.doctor.export.md') }}
|
|
80
|
+
</button>
|
|
59
81
|
</div>
|
|
60
82
|
</div>
|
|
61
83
|
</template>
|
|
62
|
-
<div class="doctor-
|
|
63
|
-
<
|
|
64
|
-
type="button"
|
|
65
|
-
class="btn-tool btn-tool-compact"
|
|
66
|
-
@click="healthCheckResult && healthCheckResult.report
|
|
67
|
-
? downloadTextFile('codexmate-doctor.json', JSON.stringify(healthCheckResult.report, null, 2), 'application/json;charset=utf-8')
|
|
68
|
-
: null">
|
|
69
|
-
{{ t('dashboard.doctor.export.json') }}
|
|
70
|
-
</button>
|
|
71
|
-
<button
|
|
72
|
-
type="button"
|
|
73
|
-
class="btn-tool btn-tool-compact"
|
|
74
|
-
@click="healthCheckResult && healthCheckResult.report
|
|
75
|
-
? downloadTextFile('codexmate-doctor.md', String(healthCheckResult.markdown || ''), 'text/markdown;charset=utf-8')
|
|
76
|
-
: null">
|
|
77
|
-
{{ t('dashboard.doctor.export.md') }}
|
|
78
|
-
</button>
|
|
84
|
+
<div v-else class="doctor-result-empty">
|
|
85
|
+
<span class="doctor-result-empty-text">{{ t('dashboard.doctor.empty') }}</span>
|
|
79
86
|
</div>
|
|
80
87
|
</div>
|
|
81
88
|
<div class="doctor-grid">
|
|
@@ -819,11 +819,11 @@ return function render(_ctx, _cache) {
|
|
|
819
819
|
"aria-labelledby": 'tab-dashboard'
|
|
820
820
|
}, [
|
|
821
821
|
_createElementVNode("div", { class: "selector-section doctor-hero" }, [
|
|
822
|
-
_createElementVNode("div", { class: "selector-header" }, [
|
|
822
|
+
_createElementVNode("div", { class: "selector-header doctor-header" }, [
|
|
823
823
|
_createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('dashboard.doctor.title')), 1 /* TEXT */),
|
|
824
824
|
_createElementVNode("div", { class: "selector-actions" }, [
|
|
825
825
|
_createElementVNode("button", {
|
|
826
|
-
class: "btn-tool btn-tool-compact",
|
|
826
|
+
class: "btn-tool btn-tool-compact doctor-run-btn",
|
|
827
827
|
onClick: _ctx.runHealthCheck,
|
|
828
828
|
disabled: _ctx.loading || !!_ctx.initError || _ctx.healthCheckLoading
|
|
829
829
|
}, _toDisplayString(_ctx.healthCheckLoading ? _ctx.t('dashboard.doctor.checking') : _ctx.t('dashboard.doctor.runChecks')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
@@ -845,79 +845,87 @@ return function render(_ctx, _cache) {
|
|
|
845
845
|
_createElementVNode("strong", null, _toDisplayString(_ctx.inspectorModelLoadStatus), 1 /* TEXT */)
|
|
846
846
|
])
|
|
847
847
|
]),
|
|
848
|
-
(
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
}, [
|
|
866
|
-
(_ctx.healthCheckResult.report.issues && _ctx.healthCheckResult.report.issues.length)
|
|
867
|
-
? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(_ctx.healthCheckResult.report.issues, (issue) => {
|
|
868
|
-
return (_openBlock(), _createElementBlock("div", {
|
|
869
|
-
key: issue.id,
|
|
870
|
-
class: "doctor-action-card"
|
|
848
|
+
_createElementVNode("div", { class: "doctor-result-section" }, [
|
|
849
|
+
(_ctx.healthCheckResult)
|
|
850
|
+
? (_openBlock(), _createElementBlock(_Fragment, { key: 0 }, [
|
|
851
|
+
_createElementVNode("div", {
|
|
852
|
+
class: _normalizeClass(["doctor-health-result", _ctx.healthCheckResult.ok ? 'ok' : 'error'])
|
|
853
|
+
}, [
|
|
854
|
+
_createElementVNode("div", { class: "doctor-health-title" }, [
|
|
855
|
+
_createTextVNode(_toDisplayString(_ctx.healthCheckResult.ok ? _ctx.t('dashboard.health.ok') : _ctx.t('dashboard.health.fail')) + " ", 1 /* TEXT */),
|
|
856
|
+
(_ctx.healthCheckResult.issues && _ctx.healthCheckResult.issues.length)
|
|
857
|
+
? (_openBlock(), _createElementBlock("span", { key: 0 }, "(" + _toDisplayString(_ctx.t('dashboard.health.issues', { count: _ctx.healthCheckResult.issues.length })) + ")", 1 /* TEXT */))
|
|
858
|
+
: _createCommentVNode("v-if", true)
|
|
859
|
+
])
|
|
860
|
+
], 2 /* CLASS */),
|
|
861
|
+
(_ctx.healthCheckResult.report)
|
|
862
|
+
? (_openBlock(), _createElementBlock("div", {
|
|
863
|
+
key: 0,
|
|
864
|
+
class: "doctor-action-list"
|
|
871
865
|
}, [
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
866
|
+
(_ctx.healthCheckResult.report.issues && _ctx.healthCheckResult.report.issues.length)
|
|
867
|
+
? (_openBlock(true), _createElementBlock(_Fragment, { key: 0 }, _renderList(_ctx.healthCheckResult.report.issues, (issue) => {
|
|
868
|
+
return (_openBlock(), _createElementBlock("div", {
|
|
869
|
+
key: issue.id,
|
|
870
|
+
class: "doctor-action-card"
|
|
871
|
+
}, [
|
|
872
|
+
_createElementVNode("div", { class: "doctor-action-head" }, [
|
|
873
|
+
_createElementVNode("div", { class: "doctor-action-title" }, _toDisplayString(issue.problem || (issue.problemKey ? _ctx.t(issue.problemKey, issue.problemParams) : '')), 1 /* TEXT */),
|
|
874
|
+
_createElementVNode("div", {
|
|
875
|
+
class: _normalizeClass(['doctor-action-severity', issue.severity])
|
|
876
|
+
}, _toDisplayString(issue.severityLabel || issue.severity), 3 /* TEXT, CLASS */)
|
|
877
|
+
]),
|
|
878
|
+
_createElementVNode("div", { class: "doctor-action-impact" }, _toDisplayString(issue.impact || (issue.impactKey ? _ctx.t(issue.impactKey, issue.impactParams) : '')), 1 /* TEXT */),
|
|
879
|
+
(issue.actions && issue.actions.some(action => action && action.type === 'navigate' && action.target))
|
|
880
|
+
? (_openBlock(), _createElementBlock("div", {
|
|
881
|
+
key: 0,
|
|
882
|
+
class: "doctor-action-buttons"
|
|
883
|
+
}, [
|
|
884
|
+
(_openBlock(true), _createElementBlock(_Fragment, null, _renderList(issue.actions, (action, index) => {
|
|
885
|
+
return (_openBlock(), _createElementBlock(_Fragment, {
|
|
886
|
+
key: issue.id + '-action-' + index
|
|
887
|
+
}, [
|
|
888
|
+
(action.type === 'navigate' && action.target)
|
|
889
|
+
? (_openBlock(), _createElementBlock("button", {
|
|
890
|
+
key: 0,
|
|
891
|
+
type: "button",
|
|
892
|
+
class: "btn-tool btn-tool-compact",
|
|
893
|
+
onClick: $event => (action.target ? _ctx.switchMainTab(action.target) : null)
|
|
894
|
+
}, _toDisplayString(action.label || (action.labelKey ? _ctx.t(action.labelKey, action.labelParams) : _ctx.t('dashboard.doctor.open'))), 9 /* TEXT, PROPS */, ["onClick"]))
|
|
895
|
+
: _createCommentVNode("v-if", true)
|
|
896
|
+
], 64 /* STABLE_FRAGMENT */))
|
|
897
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
898
|
+
]))
|
|
899
|
+
: _createCommentVNode("v-if", true)
|
|
900
|
+
]))
|
|
901
|
+
}), 128 /* KEYED_FRAGMENT */))
|
|
902
|
+
: _createCommentVNode("v-if", true),
|
|
903
|
+
_createElementVNode("div", { class: "doctor-action-footer" }, [
|
|
904
|
+
_createElementVNode("button", {
|
|
905
|
+
type: "button",
|
|
906
|
+
class: "btn-tool btn-tool-compact",
|
|
907
|
+
onClick: $event => {_ctx.healthCheckResult && _ctx.healthCheckResult.report
|
|
908
|
+
? _ctx.downloadTextFile('codexmate-doctor.json', JSON.stringify(_ctx.healthCheckResult.report, null, 2), 'application/json;charset=utf-8')
|
|
909
|
+
: null}
|
|
910
|
+
}, _toDisplayString(_ctx.t('dashboard.doctor.export.json')), 9 /* TEXT, PROPS */, ["onClick"]),
|
|
911
|
+
_createElementVNode("button", {
|
|
912
|
+
type: "button",
|
|
913
|
+
class: "btn-tool btn-tool-compact",
|
|
914
|
+
onClick: $event => {_ctx.healthCheckResult && _ctx.healthCheckResult.report
|
|
915
|
+
? _ctx.downloadTextFile('codexmate-doctor.md', String(_ctx.healthCheckResult.markdown || ''), 'text/markdown;charset=utf-8')
|
|
916
|
+
: null}
|
|
917
|
+
}, _toDisplayString(_ctx.t('dashboard.doctor.export.md')), 9 /* TEXT, PROPS */, ["onClick"])
|
|
918
|
+
])
|
|
900
919
|
]))
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
}, _toDisplayString(_ctx.t('dashboard.doctor.export.json')), 9 /* TEXT, PROPS */, ["onClick"]),
|
|
911
|
-
_createElementVNode("button", {
|
|
912
|
-
type: "button",
|
|
913
|
-
class: "btn-tool btn-tool-compact",
|
|
914
|
-
onClick: $event => {_ctx.healthCheckResult && _ctx.healthCheckResult.report
|
|
915
|
-
? _ctx.downloadTextFile('codexmate-doctor.md', String(_ctx.healthCheckResult.markdown || ''), 'text/markdown;charset=utf-8')
|
|
916
|
-
: null}
|
|
917
|
-
}, _toDisplayString(_ctx.t('dashboard.doctor.export.md')), 9 /* TEXT, PROPS */, ["onClick"])
|
|
918
|
-
])
|
|
919
|
-
]))
|
|
920
|
-
: _createCommentVNode("v-if", true),
|
|
920
|
+
: _createCommentVNode("v-if", true)
|
|
921
|
+
], 64 /* STABLE_FRAGMENT */))
|
|
922
|
+
: (_openBlock(), _createElementBlock("div", {
|
|
923
|
+
key: 1,
|
|
924
|
+
class: "doctor-result-empty"
|
|
925
|
+
}, [
|
|
926
|
+
_createElementVNode("span", { class: "doctor-result-empty-text" }, _toDisplayString(_ctx.t('dashboard.doctor.empty')), 1 /* TEXT */)
|
|
927
|
+
]))
|
|
928
|
+
]),
|
|
921
929
|
_createElementVNode("div", { class: "doctor-grid" }, [
|
|
922
930
|
_createElementVNode("button", {
|
|
923
931
|
type: "button",
|
|
@@ -3260,7 +3268,7 @@ return function render(_ctx, _cache) {
|
|
|
3260
3268
|
: (_openBlock(), _createElementBlock("button", {
|
|
3261
3269
|
key: 1,
|
|
3262
3270
|
type: "button",
|
|
3263
|
-
class: "btn-tool",
|
|
3271
|
+
class: "btn-tool btn-tool-compact",
|
|
3264
3272
|
onClick: _withModifiers($event => (_ctx.switchPiActiveProvider(providerId)), ["stop"]),
|
|
3265
3273
|
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving
|
|
3266
3274
|
}, _toDisplayString(_ctx.t('pi.providers.setActive')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]))
|
|
@@ -3272,16 +3280,31 @@ return function render(_ctx, _cache) {
|
|
|
3272
3280
|
(!_ctx.piProviderIds.length)
|
|
3273
3281
|
? (_openBlock(), _createElementBlock("div", {
|
|
3274
3282
|
key: 1,
|
|
3275
|
-
class: "
|
|
3276
|
-
},
|
|
3283
|
+
class: "empty-state"
|
|
3284
|
+
}, [
|
|
3285
|
+
_createElementVNode("div", { class: "empty-state-title" }, _toDisplayString(_ctx.t('pi.providers.empty')), 1 /* TEXT */)
|
|
3286
|
+
]))
|
|
3277
3287
|
: _createCommentVNode("v-if", true)
|
|
3278
3288
|
]),
|
|
3279
|
-
_createElementVNode("section", { class: "selector-section" }, [
|
|
3289
|
+
_createElementVNode("section", { class: "selector-section pi-file-section" }, [
|
|
3280
3290
|
_createElementVNode("div", { class: "selector-header" }, [
|
|
3281
|
-
_createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('pi.files.
|
|
3291
|
+
_createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('pi.files.settingsTitle')), 1 /* TEXT */),
|
|
3292
|
+
_createElementVNode("div", { class: "selector-actions" }, [
|
|
3293
|
+
_createElementVNode("button", {
|
|
3294
|
+
type: "button",
|
|
3295
|
+
class: "btn-tool btn-tool-compact",
|
|
3296
|
+
onClick: $event => (_ctx.openPiConfigHistory('settings')),
|
|
3297
|
+
disabled: _ctx.piHistoryLoading
|
|
3298
|
+
}, _toDisplayString(_ctx.t('common.history')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
|
|
3299
|
+
_createElementVNode("button", {
|
|
3300
|
+
type: "button",
|
|
3301
|
+
class: "btn-tool btn-tool-compact",
|
|
3302
|
+
onClick: _ctx.savePiSettingsJson,
|
|
3303
|
+
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving || _ctx.piFileJsonSaving || !!_ctx.piSettingsJsonError
|
|
3304
|
+
}, _toDisplayString(_ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3305
|
+
])
|
|
3282
3306
|
]),
|
|
3283
|
-
_createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('pi.
|
|
3284
|
-
_createElementVNode("label", { class: "form-label" }, _toDisplayString(_ctx.t('pi.files.settingsTitle')), 1 /* TEXT */),
|
|
3307
|
+
_createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('pi.providers.targetFile', { path: '~/.pi/agent/settings.json' })), 1 /* TEXT */),
|
|
3285
3308
|
_withDirectives(_createElementVNode("textarea", {
|
|
3286
3309
|
class: "template-textarea config-json-editor",
|
|
3287
3310
|
"onUpdate:modelValue": $event => ((_ctx.piSettingsJsonDraft) = $event),
|
|
@@ -3299,20 +3322,6 @@ return function render(_ctx, _cache) {
|
|
|
3299
3322
|
class: "config-template-hint error-text"
|
|
3300
3323
|
}, _toDisplayString(_ctx.piSettingsJsonError), 1 /* TEXT */))
|
|
3301
3324
|
: _createCommentVNode("v-if", true),
|
|
3302
|
-
_createElementVNode("div", { class: "settings-tab-actions" }, [
|
|
3303
|
-
_createElementVNode("button", {
|
|
3304
|
-
type: "button",
|
|
3305
|
-
class: "btn-tool",
|
|
3306
|
-
onClick: _ctx.savePiSettingsJson,
|
|
3307
|
-
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving || _ctx.piFileJsonSaving || !!_ctx.piSettingsJsonError
|
|
3308
|
-
}, _toDisplayString(_ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
|
|
3309
|
-
_createElementVNode("button", {
|
|
3310
|
-
type: "button",
|
|
3311
|
-
class: "btn-mini",
|
|
3312
|
-
onClick: $event => (_ctx.openPiConfigHistory('settings')),
|
|
3313
|
-
disabled: _ctx.piHistoryLoading
|
|
3314
|
-
}, _toDisplayString(_ctx.t('common.history')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3315
|
-
]),
|
|
3316
3325
|
(_ctx.piHistoryTarget === 'settings')
|
|
3317
3326
|
? (_openBlock(), _createElementBlock("details", {
|
|
3318
3327
|
key: 1,
|
|
@@ -3378,8 +3387,28 @@ return function render(_ctx, _cache) {
|
|
|
3378
3387
|
: _createCommentVNode("v-if", true)
|
|
3379
3388
|
])
|
|
3380
3389
|
]))
|
|
3381
|
-
: _createCommentVNode("v-if", true)
|
|
3382
|
-
|
|
3390
|
+
: _createCommentVNode("v-if", true)
|
|
3391
|
+
]),
|
|
3392
|
+
_createElementVNode("section", { class: "selector-section pi-file-section" }, [
|
|
3393
|
+
_createElementVNode("div", { class: "selector-header" }, [
|
|
3394
|
+
_createElementVNode("span", { class: "selector-title" }, _toDisplayString(_ctx.t('pi.files.modelsTitle')), 1 /* TEXT */),
|
|
3395
|
+
_createElementVNode("div", { class: "selector-actions" }, [
|
|
3396
|
+
_createElementVNode("button", {
|
|
3397
|
+
type: "button",
|
|
3398
|
+
class: "btn-tool btn-tool-compact",
|
|
3399
|
+
onClick: $event => (_ctx.openPiConfigHistory('models')),
|
|
3400
|
+
disabled: _ctx.piHistoryLoading
|
|
3401
|
+
}, _toDisplayString(_ctx.t('common.history')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
|
|
3402
|
+
_createElementVNode("button", {
|
|
3403
|
+
type: "button",
|
|
3404
|
+
class: "btn-tool btn-tool-compact",
|
|
3405
|
+
onClick: _ctx.savePiModelsJson,
|
|
3406
|
+
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving || _ctx.piFileJsonSaving || !!_ctx.piModelsJsonError
|
|
3407
|
+
}, _toDisplayString(_ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3408
|
+
])
|
|
3409
|
+
]),
|
|
3410
|
+
_createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('pi.files.modelsHint')), 1 /* TEXT */),
|
|
3411
|
+
_createElementVNode("div", { class: "config-template-hint" }, _toDisplayString(_ctx.t('pi.providers.targetFile', { path: '~/.pi/agent/models.json' })), 1 /* TEXT */),
|
|
3383
3412
|
_withDirectives(_createElementVNode("textarea", {
|
|
3384
3413
|
class: "template-textarea config-json-editor",
|
|
3385
3414
|
"onUpdate:modelValue": $event => ((_ctx.piModelsJsonDraft) = $event),
|
|
@@ -3393,27 +3422,13 @@ return function render(_ctx, _cache) {
|
|
|
3393
3422
|
]),
|
|
3394
3423
|
(_ctx.piModelsJsonError)
|
|
3395
3424
|
? (_openBlock(), _createElementBlock("p", {
|
|
3396
|
-
key:
|
|
3425
|
+
key: 0,
|
|
3397
3426
|
class: "config-template-hint error-text"
|
|
3398
3427
|
}, _toDisplayString(_ctx.piModelsJsonError), 1 /* TEXT */))
|
|
3399
3428
|
: _createCommentVNode("v-if", true),
|
|
3400
|
-
_createElementVNode("div", { class: "settings-tab-actions" }, [
|
|
3401
|
-
_createElementVNode("button", {
|
|
3402
|
-
type: "button",
|
|
3403
|
-
class: "btn-tool",
|
|
3404
|
-
onClick: _ctx.savePiModelsJson,
|
|
3405
|
-
disabled: !_ctx.isToolConfigWriteAllowed('pi') || _ctx.piSaving || _ctx.piFileJsonSaving || !!_ctx.piModelsJsonError
|
|
3406
|
-
}, _toDisplayString(_ctx.t('common.save')), 9 /* TEXT, PROPS */, ["onClick", "disabled"]),
|
|
3407
|
-
_createElementVNode("button", {
|
|
3408
|
-
type: "button",
|
|
3409
|
-
class: "btn-mini",
|
|
3410
|
-
onClick: $event => (_ctx.openPiConfigHistory('models')),
|
|
3411
|
-
disabled: _ctx.piHistoryLoading
|
|
3412
|
-
}, _toDisplayString(_ctx.t('common.history')), 9 /* TEXT, PROPS */, ["onClick", "disabled"])
|
|
3413
|
-
]),
|
|
3414
3429
|
(_ctx.piHistoryTarget === 'models')
|
|
3415
3430
|
? (_openBlock(), _createElementBlock("details", {
|
|
3416
|
-
key:
|
|
3431
|
+
key: 1,
|
|
3417
3432
|
class: "prompt-history-panel",
|
|
3418
3433
|
open: ""
|
|
3419
3434
|
}, [
|
|
@@ -104,6 +104,13 @@
|
|
|
104
104
|
flex: 0 0 auto;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
.selector-header .selector-actions > .btn-tool + .btn-tool,
|
|
108
|
+
.selector-header .selector-actions > .btn-tool-compact + .btn-tool,
|
|
109
|
+
.selector-header .selector-actions > .btn-tool + .btn-tool-compact,
|
|
110
|
+
.selector-header .selector-actions > .btn-tool-compact + .btn-tool-compact {
|
|
111
|
+
margin-top: 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
107
114
|
.selector-actions.opencode-provider-actions {
|
|
108
115
|
display: inline-flex;
|
|
109
116
|
align-items: stretch;
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
.doctor-grid {
|
|
6
6
|
display: grid;
|
|
7
|
-
grid-template-columns: repeat(
|
|
7
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
8
8
|
gap: 12px;
|
|
9
9
|
margin-top: 12px;
|
|
10
|
+
align-items: stretch;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
.doctor-card {
|
|
@@ -102,14 +103,16 @@
|
|
|
102
103
|
display: inline-flex;
|
|
103
104
|
align-items: center;
|
|
104
105
|
gap: 8px;
|
|
105
|
-
|
|
106
|
+
min-width: 150px;
|
|
107
|
+
padding: 8px 12px;
|
|
106
108
|
border-radius: 999px;
|
|
107
109
|
border: 1px solid var(--color-border-soft);
|
|
108
110
|
background: rgba(255, 255, 255, 0.78);
|
|
109
111
|
font-size: var(--font-size-caption);
|
|
110
112
|
color: var(--color-text-secondary);
|
|
111
|
-
justify-content:
|
|
112
|
-
text-align:
|
|
113
|
+
justify-content: space-between;
|
|
114
|
+
text-align: left;
|
|
115
|
+
font-variant-numeric: tabular-nums;
|
|
113
116
|
}
|
|
114
117
|
|
|
115
118
|
.doctor-status-chip strong {
|
|
@@ -162,27 +165,6 @@
|
|
|
162
165
|
text-align: left;
|
|
163
166
|
}
|
|
164
167
|
|
|
165
|
-
.doctor-health-issues {
|
|
166
|
-
display: flex;
|
|
167
|
-
flex-direction: column;
|
|
168
|
-
gap: 6px;
|
|
169
|
-
font-size: var(--font-size-caption);
|
|
170
|
-
align-items: center;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.doctor-health-issue {
|
|
174
|
-
padding: 8px 10px;
|
|
175
|
-
border-radius: 12px;
|
|
176
|
-
border: 1px solid rgba(220, 95, 108, 0.2);
|
|
177
|
-
background: rgba(255, 255, 255, 0.75);
|
|
178
|
-
color: var(--color-text-secondary);
|
|
179
|
-
overflow-wrap: anywhere;
|
|
180
|
-
word-break: break-word;
|
|
181
|
-
text-align: center;
|
|
182
|
-
width: 100%;
|
|
183
|
-
max-width: 720px;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
168
|
.doctor-action-list {
|
|
187
169
|
margin-top: 14px;
|
|
188
170
|
display: grid;
|
|
@@ -212,8 +194,11 @@
|
|
|
212
194
|
color: var(--color-text-primary);
|
|
213
195
|
min-width: 0;
|
|
214
196
|
overflow: hidden;
|
|
215
|
-
|
|
216
|
-
|
|
197
|
+
display: -webkit-box;
|
|
198
|
+
-webkit-box-orient: vertical;
|
|
199
|
+
-webkit-line-clamp: 2;
|
|
200
|
+
overflow-wrap: anywhere;
|
|
201
|
+
word-break: break-word;
|
|
217
202
|
max-width: 100%;
|
|
218
203
|
flex: 1 1 220px;
|
|
219
204
|
}
|
|
@@ -271,6 +256,46 @@
|
|
|
271
256
|
margin-top: 2px;
|
|
272
257
|
}
|
|
273
258
|
|
|
259
|
+
.doctor-result-section {
|
|
260
|
+
margin-top: 14px;
|
|
261
|
+
display: flex;
|
|
262
|
+
flex-direction: column;
|
|
263
|
+
gap: 12px;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.doctor-result-section > .doctor-health-result,
|
|
267
|
+
.doctor-result-section > .doctor-action-list {
|
|
268
|
+
margin-top: 0;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.doctor-result-empty {
|
|
272
|
+
border: 1px dashed var(--color-border-soft);
|
|
273
|
+
border-radius: var(--radius-lg);
|
|
274
|
+
background: rgba(255, 255, 255, 0.5);
|
|
275
|
+
padding: 16px;
|
|
276
|
+
text-align: center;
|
|
277
|
+
font-size: var(--font-size-caption);
|
|
278
|
+
color: var(--color-text-tertiary);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.doctor-header .selector-actions > .doctor-run-btn {
|
|
282
|
+
background: linear-gradient(135deg, var(--color-brand) 0%, var(--color-brand-dark) 100%);
|
|
283
|
+
border-color: var(--color-brand-dark);
|
|
284
|
+
color: #fff;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.doctor-header .selector-actions > .doctor-run-btn:not(:disabled):hover {
|
|
288
|
+
border-color: var(--color-brand-dark);
|
|
289
|
+
color: #fff;
|
|
290
|
+
filter: brightness(1.05);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
@media (max-width: 1280px) {
|
|
294
|
+
.doctor-grid {
|
|
295
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
274
299
|
@media (max-width: 520px) {
|
|
275
300
|
.doctor-grid {
|
|
276
301
|
grid-template-columns: 1fr;
|
|
@@ -305,134 +330,3 @@
|
|
|
305
330
|
}
|
|
306
331
|
}
|
|
307
332
|
|
|
308
|
-
.doctor-providers-health {
|
|
309
|
-
margin-top: 12px;
|
|
310
|
-
padding: 12px;
|
|
311
|
-
border-radius: var(--radius-lg);
|
|
312
|
-
border: 1px solid var(--color-border-soft);
|
|
313
|
-
background: rgba(255, 255, 255, 0.78);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
.doctor-providers-health-title {
|
|
317
|
-
font-size: var(--font-size-body);
|
|
318
|
-
font-weight: var(--font-weight-title);
|
|
319
|
-
color: var(--color-text-primary);
|
|
320
|
-
margin-bottom: 10px;
|
|
321
|
-
display: flex;
|
|
322
|
-
align-items: center;
|
|
323
|
-
gap: 8px;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
.doctor-providers-health-summary {
|
|
327
|
-
font-size: var(--font-size-caption);
|
|
328
|
-
font-weight: var(--font-weight-primary);
|
|
329
|
-
color: var(--color-text-tertiary);
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
.doctor-providers-grid {
|
|
333
|
-
display: flex;
|
|
334
|
-
flex-wrap: wrap;
|
|
335
|
-
gap: 8px;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
.doctor-provider-chip {
|
|
339
|
-
display: inline-flex;
|
|
340
|
-
align-items: center;
|
|
341
|
-
gap: 6px;
|
|
342
|
-
padding: 6px 12px;
|
|
343
|
-
border-radius: 999px;
|
|
344
|
-
border: 1px solid var(--color-border-soft);
|
|
345
|
-
background: rgba(255, 255, 255, 0.85);
|
|
346
|
-
font-size: var(--font-size-caption);
|
|
347
|
-
color: var(--color-text-secondary);
|
|
348
|
-
max-width: 100%;
|
|
349
|
-
overflow: hidden;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
.doctor-provider-chip.green {
|
|
353
|
-
border-color: rgba(57, 181, 97, 0.25);
|
|
354
|
-
background: rgba(57, 181, 97, 0.08);
|
|
355
|
-
color: #2b6a3b;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
.doctor-provider-chip.yellow {
|
|
359
|
-
border-color: rgba(246, 211, 106, 0.45);
|
|
360
|
-
background: rgba(246, 211, 106, 0.16);
|
|
361
|
-
color: #6f4b00;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.doctor-provider-chip.red {
|
|
365
|
-
border-color: rgba(220, 95, 108, 0.28);
|
|
366
|
-
background: rgba(220, 95, 108, 0.08);
|
|
367
|
-
color: #8a2f36;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
.doctor-provider-name {
|
|
371
|
-
overflow: hidden;
|
|
372
|
-
text-overflow: ellipsis;
|
|
373
|
-
white-space: nowrap;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
.doctor-provider-current {
|
|
377
|
-
font-size: 0.85em;
|
|
378
|
-
opacity: 0.7;
|
|
379
|
-
margin-left: 2px;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
.doctor-provider-status-dot {
|
|
383
|
-
width: 8px;
|
|
384
|
-
height: 8px;
|
|
385
|
-
border-radius: 50%;
|
|
386
|
-
flex-shrink: 0;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
.doctor-provider-chip.green .doctor-provider-status-dot {
|
|
390
|
-
background: rgba(57, 181, 97, 0.7);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
.doctor-provider-chip.yellow .doctor-provider-status-dot {
|
|
394
|
-
background: rgba(246, 211, 106, 0.85);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
.doctor-provider-chip.red .doctor-provider-status-dot {
|
|
398
|
-
background: rgba(220, 95, 108, 0.7);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
.doctor-provider-issues {
|
|
402
|
-
margin-top: 10px;
|
|
403
|
-
display: flex;
|
|
404
|
-
flex-direction: column;
|
|
405
|
-
gap: 6px;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
.doctor-provider-issue-card {
|
|
409
|
-
padding: 8px 10px;
|
|
410
|
-
border-radius: 10px;
|
|
411
|
-
border: 1px solid rgba(220, 95, 108, 0.15);
|
|
412
|
-
background: rgba(255, 255, 255, 0.7);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
.doctor-provider-issue-name {
|
|
416
|
-
font-weight: var(--font-weight-secondary);
|
|
417
|
-
color: var(--color-text-primary);
|
|
418
|
-
margin-bottom: 4px;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
.doctor-provider-issue-row {
|
|
422
|
-
font-size: var(--font-size-caption);
|
|
423
|
-
color: var(--color-text-secondary);
|
|
424
|
-
display: flex;
|
|
425
|
-
flex-direction: column;
|
|
426
|
-
gap: 2px;
|
|
427
|
-
padding-left: 8px;
|
|
428
|
-
margin-top: 4px;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
.doctor-provider-issue-text {
|
|
432
|
-
color: #8a2f36;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
.doctor-provider-issue-fix {
|
|
436
|
-
color: var(--color-text-tertiary);
|
|
437
|
-
font-style: italic;
|
|
438
|
-
}
|