lula2 0.3.3 → 0.3.4
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/dist/_app/immutable/assets/0.D6CB7gA7.css +1 -0
- package/dist/_app/immutable/chunks/{C9p1zaS8.js → BhjtS45v.js} +1 -1
- package/dist/_app/immutable/chunks/{cvagBx-i.js → BkFSJLu9.js} +1 -1
- package/dist/_app/immutable/chunks/C1qIqlSh.js +65 -0
- package/dist/_app/immutable/chunks/ClX_MmzV.js +3 -0
- package/dist/_app/immutable/chunks/{ZLxiKtk1.js → CzIDw1HQ.js} +1 -1
- package/dist/_app/immutable/chunks/{DkTmghUd.js → DknPZycG.js} +1 -1
- package/dist/_app/immutable/chunks/{C2RwV308.js → DwdPeWTx.js} +1 -1
- package/dist/_app/immutable/chunks/WK3R0vY-.js +1 -0
- package/dist/_app/immutable/chunks/{EhHGBAhB.js → vNis_B2V.js} +1 -1
- package/dist/_app/immutable/entry/{app.DlQKiOqI.js → app.8CEusWR7.js} +2 -2
- package/dist/_app/immutable/entry/start.D8vrR3Zv.js +1 -0
- package/dist/_app/immutable/nodes/{0.BebGxk-A.js → 0.LShgzT5d.js} +1 -1
- package/dist/_app/immutable/nodes/{1.DfUs1HjM.js → 1.BsTJP2AO.js} +1 -1
- package/dist/_app/immutable/nodes/{2.CrOeZTVE.js → 2.Dr3oL5Ok.js} +1 -1
- package/dist/_app/immutable/nodes/{3.D6SgInYh.js → 3.B0kbkkIQ.js} +1 -1
- package/dist/_app/immutable/nodes/4.UmTgWYf1.js +11 -0
- package/dist/_app/version.json +1 -1
- package/dist/cli/commands/ui.js +10 -10
- package/dist/cli/server/index.js +10 -10
- package/dist/cli/server/server.js +10 -10
- package/dist/cli/server/websocketServer.js +10 -10
- package/dist/index.html +10 -10
- package/dist/index.js +10 -10
- package/package.json +1 -1
- package/src/lib/components/control-sets/ControlSetSelector.svelte +1 -1
- package/src/lib/components/controls/ControlDetailsPanel.svelte +1 -1
- package/src/lib/components/controls/ControlsList.svelte +4 -48
- package/src/lib/components/controls/DynamicControlEditor.svelte +2 -2
- package/src/lib/components/controls/MappingCard.svelte +1 -1
- package/src/lib/components/controls/MappingForm.svelte +1 -1
- package/src/lib/components/controls/renderers/EditableFieldRenderer.svelte +1 -1
- package/src/lib/components/controls/renderers/FieldRenderer.svelte +2 -2
- package/src/lib/components/controls/tabs/CustomFieldsTab.svelte +2 -2
- package/src/lib/components/controls/tabs/ImplementationTab.svelte +3 -3
- package/src/lib/components/controls/tabs/MappingsTab.svelte +1 -1
- package/src/lib/components/controls/tabs/OverviewTab.svelte +4 -4
- package/src/lib/components/controls/tabs/TimelineTab.svelte +2 -3
- package/src/lib/components/controls/utils/ProcessedTextRenderer.svelte +4 -4
- package/src/lib/components/forms/DynamicControlForm.svelte +10 -10
- package/src/lib/components/forms/DynamicField.svelte +4 -4
- package/src/lib/components/forms/FormField.svelte +1 -1
- package/src/lib/components/setup/ExistingControlSets.svelte +1 -1
- package/src/lib/components/setup/SpreadsheetImport.svelte +8 -10
- package/src/lib/components/ui/CustomDropdown.svelte +1 -1
- package/src/lib/components/ui/FilterBuilder.svelte +4 -4
- package/src/lib/components/ui/TabNavigation.svelte +1 -1
- package/src/lib/components/version-control/DiffViewer.svelte +1 -1
- package/src/lib/components/version-control/YamlDiffViewer.svelte +2 -2
- package/src/stores/compliance.ts +2 -69
- package/dist/_app/immutable/assets/0.BeyRWDYp.css +0 -1
- package/dist/_app/immutable/chunks/BTTmO90G.js +0 -65
- package/dist/_app/immutable/chunks/Dz_3mPpR.js +0 -1
- package/dist/_app/immutable/chunks/z5X83jua.js +0 -3
- package/dist/_app/immutable/entry/start.CuPBZjFh.js +0 -1
- package/dist/_app/immutable/nodes/4.Be0URtGy.js +0 -11
|
@@ -4657,6 +4657,7 @@ var WebSocketManager = class {
|
|
|
4657
4657
|
`${control.id}.yaml`,
|
|
4658
4658
|
`${control.id.replace(/\./g, "_")}.yaml`,
|
|
4659
4659
|
// AC-1.1 -> AC-1_1.yaml
|
|
4660
|
+
// eslint-disable-next-line no-useless-escape
|
|
4660
4661
|
`${control.id.replace(/[^\w\-]/g, "_")}.yaml`
|
|
4661
4662
|
// General sanitization
|
|
4662
4663
|
];
|
|
@@ -4878,17 +4879,15 @@ var WebSocketManager = class {
|
|
|
4878
4879
|
id: control.id,
|
|
4879
4880
|
family: control.family
|
|
4880
4881
|
};
|
|
4881
|
-
const fieldSchema = controlSetData.fieldSchema?.fields || {};
|
|
4882
|
-
for (const [fieldName
|
|
4883
|
-
if (
|
|
4882
|
+
const fieldSchema = controlSetData.fieldSchema?.fields || controlSetData.field_schema?.fields || {};
|
|
4883
|
+
for (const [fieldName] of Object.entries(fieldSchema)) {
|
|
4884
|
+
if (control[fieldName] !== void 0) {
|
|
4884
4885
|
metadata[fieldName] = control[fieldName];
|
|
4885
4886
|
}
|
|
4886
4887
|
}
|
|
4887
|
-
if (
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
if (control.compliance_status !== void 0)
|
|
4891
|
-
metadata.compliance_status = control.compliance_status;
|
|
4888
|
+
if (Object.keys(fieldSchema).length === 0) {
|
|
4889
|
+
Object.assign(metadata, control);
|
|
4890
|
+
}
|
|
4892
4891
|
return metadata;
|
|
4893
4892
|
});
|
|
4894
4893
|
return {
|
|
@@ -4945,8 +4944,9 @@ var WebSocketManager = class {
|
|
|
4945
4944
|
id: controlId,
|
|
4946
4945
|
family: control.family || control["control-acronym"]?.toString().split("-")[0] || ""
|
|
4947
4946
|
};
|
|
4948
|
-
|
|
4949
|
-
|
|
4947
|
+
const schemaFields = controlSetData.field_schema?.fields || controlSetData.fieldSchema?.fields;
|
|
4948
|
+
if (schemaFields) {
|
|
4949
|
+
for (const [fieldName] of Object.entries(schemaFields)) {
|
|
4950
4950
|
if (control[fieldName] !== void 0) {
|
|
4951
4951
|
summary[fieldName] = control[fieldName];
|
|
4952
4952
|
}
|
|
@@ -2237,6 +2237,7 @@ var WebSocketManager = class {
|
|
|
2237
2237
|
`${control.id}.yaml`,
|
|
2238
2238
|
`${control.id.replace(/\./g, "_")}.yaml`,
|
|
2239
2239
|
// AC-1.1 -> AC-1_1.yaml
|
|
2240
|
+
// eslint-disable-next-line no-useless-escape
|
|
2240
2241
|
`${control.id.replace(/[^\w\-]/g, "_")}.yaml`
|
|
2241
2242
|
// General sanitization
|
|
2242
2243
|
];
|
|
@@ -2458,17 +2459,15 @@ var WebSocketManager = class {
|
|
|
2458
2459
|
id: control.id,
|
|
2459
2460
|
family: control.family
|
|
2460
2461
|
};
|
|
2461
|
-
const fieldSchema = controlSetData.fieldSchema?.fields || {};
|
|
2462
|
-
for (const [fieldName
|
|
2463
|
-
if (
|
|
2462
|
+
const fieldSchema = controlSetData.fieldSchema?.fields || controlSetData.field_schema?.fields || {};
|
|
2463
|
+
for (const [fieldName] of Object.entries(fieldSchema)) {
|
|
2464
|
+
if (control[fieldName] !== void 0) {
|
|
2464
2465
|
metadata[fieldName] = control[fieldName];
|
|
2465
2466
|
}
|
|
2466
2467
|
}
|
|
2467
|
-
if (
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
if (control.compliance_status !== void 0)
|
|
2471
|
-
metadata.compliance_status = control.compliance_status;
|
|
2468
|
+
if (Object.keys(fieldSchema).length === 0) {
|
|
2469
|
+
Object.assign(metadata, control);
|
|
2470
|
+
}
|
|
2472
2471
|
return metadata;
|
|
2473
2472
|
});
|
|
2474
2473
|
return {
|
|
@@ -2525,8 +2524,9 @@ var WebSocketManager = class {
|
|
|
2525
2524
|
id: controlId,
|
|
2526
2525
|
family: control.family || control["control-acronym"]?.toString().split("-")[0] || ""
|
|
2527
2526
|
};
|
|
2528
|
-
|
|
2529
|
-
|
|
2527
|
+
const schemaFields = controlSetData.field_schema?.fields || controlSetData.fieldSchema?.fields;
|
|
2528
|
+
if (schemaFields) {
|
|
2529
|
+
for (const [fieldName] of Object.entries(schemaFields)) {
|
|
2530
2530
|
if (control[fieldName] !== void 0) {
|
|
2531
2531
|
summary[fieldName] = control[fieldName];
|
|
2532
2532
|
}
|
package/dist/index.html
CHANGED
|
@@ -6,28 +6,28 @@
|
|
|
6
6
|
<link rel="icon" href="/lula.png" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
8
8
|
|
|
9
|
-
<link rel="modulepreload" href="/_app/immutable/entry/start.
|
|
10
|
-
<link rel="modulepreload" href="/_app/immutable/chunks/
|
|
11
|
-
<link rel="modulepreload" href="/_app/immutable/chunks/
|
|
12
|
-
<link rel="modulepreload" href="/_app/immutable/entry/app.
|
|
9
|
+
<link rel="modulepreload" href="/_app/immutable/entry/start.D8vrR3Zv.js">
|
|
10
|
+
<link rel="modulepreload" href="/_app/immutable/chunks/ClX_MmzV.js">
|
|
11
|
+
<link rel="modulepreload" href="/_app/immutable/chunks/BhjtS45v.js">
|
|
12
|
+
<link rel="modulepreload" href="/_app/immutable/entry/app.8CEusWR7.js">
|
|
13
13
|
<link rel="modulepreload" href="/_app/immutable/chunks/DsnmJJEf.js">
|
|
14
|
-
<link rel="modulepreload" href="/_app/immutable/chunks/
|
|
15
|
-
<link rel="modulepreload" href="/_app/immutable/chunks/
|
|
16
|
-
<link rel="modulepreload" href="/_app/immutable/chunks/
|
|
14
|
+
<link rel="modulepreload" href="/_app/immutable/chunks/DwdPeWTx.js">
|
|
15
|
+
<link rel="modulepreload" href="/_app/immutable/chunks/vNis_B2V.js">
|
|
16
|
+
<link rel="modulepreload" href="/_app/immutable/chunks/BkFSJLu9.js">
|
|
17
17
|
</head>
|
|
18
18
|
<body data-sveltekit-preload-data="hover">
|
|
19
19
|
<div style="display: contents">
|
|
20
20
|
<script>
|
|
21
21
|
{
|
|
22
|
-
|
|
22
|
+
__sveltekit_12i3es4 = {
|
|
23
23
|
base: ""
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
const element = document.currentScript.parentElement;
|
|
27
27
|
|
|
28
28
|
Promise.all([
|
|
29
|
-
import("/_app/immutable/entry/start.
|
|
30
|
-
import("/_app/immutable/entry/app.
|
|
29
|
+
import("/_app/immutable/entry/start.D8vrR3Zv.js"),
|
|
30
|
+
import("/_app/immutable/entry/app.8CEusWR7.js")
|
|
31
31
|
]).then(([kit, app]) => {
|
|
32
32
|
kit.start(app, element);
|
|
33
33
|
});
|
package/dist/index.js
CHANGED
|
@@ -4684,6 +4684,7 @@ var WebSocketManager = class {
|
|
|
4684
4684
|
`${control.id}.yaml`,
|
|
4685
4685
|
`${control.id.replace(/\./g, "_")}.yaml`,
|
|
4686
4686
|
// AC-1.1 -> AC-1_1.yaml
|
|
4687
|
+
// eslint-disable-next-line no-useless-escape
|
|
4687
4688
|
`${control.id.replace(/[^\w\-]/g, "_")}.yaml`
|
|
4688
4689
|
// General sanitization
|
|
4689
4690
|
];
|
|
@@ -4905,17 +4906,15 @@ var WebSocketManager = class {
|
|
|
4905
4906
|
id: control.id,
|
|
4906
4907
|
family: control.family
|
|
4907
4908
|
};
|
|
4908
|
-
const fieldSchema = controlSetData.fieldSchema?.fields || {};
|
|
4909
|
-
for (const [fieldName
|
|
4910
|
-
if (
|
|
4909
|
+
const fieldSchema = controlSetData.fieldSchema?.fields || controlSetData.field_schema?.fields || {};
|
|
4910
|
+
for (const [fieldName] of Object.entries(fieldSchema)) {
|
|
4911
|
+
if (control[fieldName] !== void 0) {
|
|
4911
4912
|
metadata[fieldName] = control[fieldName];
|
|
4912
4913
|
}
|
|
4913
4914
|
}
|
|
4914
|
-
if (
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
if (control.compliance_status !== void 0)
|
|
4918
|
-
metadata.compliance_status = control.compliance_status;
|
|
4915
|
+
if (Object.keys(fieldSchema).length === 0) {
|
|
4916
|
+
Object.assign(metadata, control);
|
|
4917
|
+
}
|
|
4919
4918
|
return metadata;
|
|
4920
4919
|
});
|
|
4921
4920
|
return {
|
|
@@ -4972,8 +4971,9 @@ var WebSocketManager = class {
|
|
|
4972
4971
|
id: controlId,
|
|
4973
4972
|
family: control.family || control["control-acronym"]?.toString().split("-")[0] || ""
|
|
4974
4973
|
};
|
|
4975
|
-
|
|
4976
|
-
|
|
4974
|
+
const schemaFields = controlSetData.field_schema?.fields || controlSetData.fieldSchema?.fields;
|
|
4975
|
+
if (schemaFields) {
|
|
4976
|
+
for (const [fieldName] of Object.entries(schemaFields)) {
|
|
4977
4977
|
if (control[fieldName] !== void 0) {
|
|
4978
4978
|
summary[fieldName] = control[fieldName];
|
|
4979
4979
|
}
|
package/package.json
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
onchange={handleChange}
|
|
31
31
|
class="block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-800 dark:text-white"
|
|
32
32
|
>
|
|
33
|
-
{#each availableSets as set}
|
|
33
|
+
{#each availableSets as set (set.id)}
|
|
34
34
|
<option value={set.id}>{set.name} {set.version}</option>
|
|
35
35
|
{/each}
|
|
36
36
|
</select>
|
|
@@ -170,32 +170,6 @@
|
|
|
170
170
|
goto(`/control/${encodeURIComponent(control.id)}`);
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
function getStatusBadgeClass(status: string) {
|
|
174
|
-
switch (status) {
|
|
175
|
-
case 'Implemented':
|
|
176
|
-
return 'bg-green-100 dark:bg-green-900/30 text-green-800 dark:text-green-300';
|
|
177
|
-
case 'Planned':
|
|
178
|
-
return 'bg-amber-100 dark:bg-amber-900/30 text-amber-800 dark:text-amber-300';
|
|
179
|
-
case 'Not Implemented':
|
|
180
|
-
return 'bg-red-100 dark:bg-red-900/30 text-red-800 dark:text-red-300';
|
|
181
|
-
default:
|
|
182
|
-
return 'bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-300';
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function getComplianceBadgeClass(status: string) {
|
|
187
|
-
switch (status) {
|
|
188
|
-
case 'Compliant':
|
|
189
|
-
return 'bg-emerald-100 dark:bg-emerald-900/30 text-emerald-800 dark:text-emerald-300';
|
|
190
|
-
case 'Non-Compliant':
|
|
191
|
-
return 'bg-red-100 dark:bg-red-900/30 text-red-800 dark:text-red-300';
|
|
192
|
-
case 'Not Assessed':
|
|
193
|
-
return 'bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-300';
|
|
194
|
-
default:
|
|
195
|
-
return 'bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-300';
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
173
|
function extractDescriptionFromNested(data: any): string {
|
|
200
174
|
if (typeof data === 'string') {
|
|
201
175
|
return data;
|
|
@@ -224,24 +198,6 @@
|
|
|
224
198
|
return 'No description available';
|
|
225
199
|
}
|
|
226
200
|
|
|
227
|
-
// Helper to determine if a field should be truncated and show tooltip
|
|
228
|
-
function shouldTruncateField(field: FieldSchema | undefined, value: string): boolean {
|
|
229
|
-
if (!value) return false;
|
|
230
|
-
|
|
231
|
-
// Always show tooltip for textarea fields if content is long
|
|
232
|
-
if (field?.ui_type === 'textarea' || field?.ui_type === 'long_text') {
|
|
233
|
-
return value.length > 100; // Lower threshold for long text fields
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// For short_text fields, only show if really long
|
|
237
|
-
if (field?.ui_type === 'short_text') {
|
|
238
|
-
return value.length > 200;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Default for unknown field types
|
|
242
|
-
return value.length > 150;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
201
|
// Get truncation length based on field type
|
|
246
202
|
function getTruncationLength(field: FieldSchema | undefined): number {
|
|
247
203
|
if (field?.ui_type === 'textarea' || field?.ui_type === 'long_text') {
|
|
@@ -296,7 +252,7 @@
|
|
|
296
252
|
<!-- Active Filters Summary -->
|
|
297
253
|
{#if $activeFilters.length > 0}
|
|
298
254
|
<div class="mt-2 flex flex-wrap gap-2">
|
|
299
|
-
{#each $activeFilters as filter, index}
|
|
255
|
+
{#each $activeFilters as filter, index (index)}
|
|
300
256
|
<div class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 dark:bg-blue-900/30 text-blue-800 dark:text-blue-300">
|
|
301
257
|
<span>{filter.fieldName}: </span>
|
|
302
258
|
{#if filter.operator === 'exists' || filter.operator === 'not_exists'}
|
|
@@ -342,7 +298,7 @@
|
|
|
342
298
|
class="grid gap-4 px-6 py-3"
|
|
343
299
|
style="grid-template-columns: repeat({tableColumns.length + 1}, minmax(0, 1fr)); max-width: 100%;"
|
|
344
300
|
>
|
|
345
|
-
{#each tableColumns as { fieldName, field }}
|
|
301
|
+
{#each tableColumns as { fieldName, field }, index (index)}
|
|
346
302
|
<div
|
|
347
303
|
class="text-left text-xs font-semibold text-gray-700 dark:text-gray-300 uppercase tracking-wider"
|
|
348
304
|
>
|
|
@@ -391,7 +347,7 @@
|
|
|
391
347
|
<!-- Scrollable Table Body -->
|
|
392
348
|
<div class="flex-1 overflow-auto">
|
|
393
349
|
<div class="divide-y divide-gray-200 dark:divide-gray-700">
|
|
394
|
-
{#each $filteredControlsWithMappings as control}
|
|
350
|
+
{#each $filteredControlsWithMappings as control, index (index)}
|
|
395
351
|
{@const rawDescription = (() => {
|
|
396
352
|
// Cast control to any to allow dynamic field access
|
|
397
353
|
const anyControl = control as any;
|
|
@@ -434,7 +390,7 @@
|
|
|
434
390
|
tabindex="0"
|
|
435
391
|
aria-label="Select control {control.id}"
|
|
436
392
|
>
|
|
437
|
-
{#each tableColumns as { fieldName, field }}
|
|
393
|
+
{#each tableColumns as { fieldName, field }, index (index)}
|
|
438
394
|
{@const value = (control as any)[fieldName]}
|
|
439
395
|
<div class="flex flex-col justify-center">
|
|
440
396
|
{#if field.ui_type === 'select' && value}
|
|
@@ -193,7 +193,7 @@
|
|
|
193
193
|
CCIs Found in Narrative
|
|
194
194
|
</div>
|
|
195
195
|
<div class="flex flex-wrap gap-2">
|
|
196
|
-
{#each ccisInNarrative as cci}
|
|
196
|
+
{#each ccisInNarrative as cci (cci)}
|
|
197
197
|
<span
|
|
198
198
|
class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 dark:bg-blue-800 text-blue-800 dark:text-blue-200"
|
|
199
199
|
>
|
|
@@ -215,7 +215,7 @@
|
|
|
215
215
|
{:else if activeTab === 'mappings'}
|
|
216
216
|
<div class="space-y-4">
|
|
217
217
|
{#if associatedMappings.length > 0}
|
|
218
|
-
{#each associatedMappings as mapping}
|
|
218
|
+
{#each associatedMappings as mapping (mapping.uuid)}
|
|
219
219
|
<div
|
|
220
220
|
class="border border-gray-200 dark:border-gray-600 rounded-lg p-4 bg-gray-50 dark:bg-gray-800"
|
|
221
221
|
>
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
<div class="mb-4">
|
|
81
81
|
<h4 class="text-xs font-semibold text-gray-600 dark:text-gray-400 uppercase tracking-wider mb-2">Source References</h4>
|
|
82
82
|
<div class="space-y-2">
|
|
83
|
-
{#each mapping.source_entries as entry}
|
|
83
|
+
{#each mapping.source_entries as entry (entry)}
|
|
84
84
|
<div class="bg-gray-50 dark:bg-gray-800 rounded-lg p-3 border border-gray-200 dark:border-gray-700">
|
|
85
85
|
<div class="flex items-start justify-between">
|
|
86
86
|
<span class="text-xs font-mono text-blue-600 dark:text-blue-400 break-all">
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
<!-- Existing entries -->
|
|
111
111
|
{#if formData.source_entries.length > 0}
|
|
112
112
|
<div class="space-y-3">
|
|
113
|
-
{#each formData.source_entries as entry, index}
|
|
113
|
+
{#each formData.source_entries as entry, index (index)}
|
|
114
114
|
<div class="flex items-center gap-3 p-4 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm">
|
|
115
115
|
<div class="flex-1 min-w-0">
|
|
116
116
|
<div class="text-sm font-mono text-gray-900 dark:text-white break-all">
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
class="w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-900 text-gray-900 dark:text-white disabled:opacity-50 disabled:cursor-not-allowed focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:focus:ring-blue-400"
|
|
39
39
|
>
|
|
40
40
|
<option value="">-- Select --</option>
|
|
41
|
-
{#each field.options as option}
|
|
41
|
+
{#each field.options as option (option)}
|
|
42
42
|
<option value={option}>{option}</option>
|
|
43
43
|
{/each}
|
|
44
44
|
</select>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
readonly?: boolean;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
let { fieldName, field, value
|
|
15
|
+
let { fieldName, field, value }: Props = $props();
|
|
16
16
|
|
|
17
17
|
const displayName = $derived(
|
|
18
18
|
field?.original_name || fieldName.replace(/_/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase())
|
|
@@ -46,4 +46,4 @@
|
|
|
46
46
|
<span class="whitespace-pre-line">{value}</span>
|
|
47
47
|
{/if}
|
|
48
48
|
</div>
|
|
49
|
-
</div>
|
|
49
|
+
</div>
|
|
@@ -105,9 +105,9 @@
|
|
|
105
105
|
Additional fields specific to your organization
|
|
106
106
|
</div>
|
|
107
107
|
<div class="space-y-8">
|
|
108
|
-
{#each fieldGroups as fieldGroup}
|
|
108
|
+
{#each fieldGroups as fieldGroup, index (index)}
|
|
109
109
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
110
|
-
{#each fieldGroup as [fieldName, field]}
|
|
110
|
+
{#each fieldGroup as [fieldName, field], index (index)}
|
|
111
111
|
<div class={getFieldLayoutClass(field)}>
|
|
112
112
|
<EditableFieldRenderer
|
|
113
113
|
{fieldName}
|
|
@@ -102,9 +102,9 @@
|
|
|
102
102
|
<div class="space-y-4">
|
|
103
103
|
<div class="bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl shadow-sm hover:shadow-md transition-all duration-200 p-6">
|
|
104
104
|
<div class="space-y-8">
|
|
105
|
-
{#each fieldGroups as fieldGroup}
|
|
105
|
+
{#each fieldGroups as fieldGroup, index (index)}
|
|
106
106
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
107
|
-
{#each fieldGroup as [fieldName, field]}
|
|
107
|
+
{#each fieldGroup as [fieldName, field], index (index)}
|
|
108
108
|
<div class={getFieldLayoutClass(field)}>
|
|
109
109
|
<FieldRenderer
|
|
110
110
|
{fieldName}
|
|
@@ -124,4 +124,4 @@
|
|
|
124
124
|
<p class="text-gray-500 dark:text-gray-400">No implementation fields available</p>
|
|
125
125
|
</div>
|
|
126
126
|
{/if}
|
|
127
|
-
</div>
|
|
127
|
+
</div>
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
<!-- Existing Mappings -->
|
|
100
100
|
{#if mappings.length > 0}
|
|
101
101
|
<div class="space-y-4">
|
|
102
|
-
{#each mappings as mapping}
|
|
102
|
+
{#each mappings as mapping (mapping.uuid)}
|
|
103
103
|
{#if editingMapping && editingMapping.uuid === mapping.uuid}
|
|
104
104
|
<!-- Edit Form in place of the mapping being edited -->
|
|
105
105
|
<div
|
|
@@ -107,9 +107,9 @@
|
|
|
107
107
|
<div class="space-y-4">
|
|
108
108
|
<div class="bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl shadow-sm hover:shadow-md transition-all duration-200 p-6">
|
|
109
109
|
<div class="space-y-8">
|
|
110
|
-
{#each fieldGroups as fieldGroup}
|
|
110
|
+
{#each fieldGroups as fieldGroup, index (index)}
|
|
111
111
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
|
112
|
-
{#each fieldGroup as [fieldName, field]}
|
|
112
|
+
{#each fieldGroup as [fieldName, field], index (index)}
|
|
113
113
|
<div class={getFieldLayoutClass(field)}>
|
|
114
114
|
<FieldRenderer
|
|
115
115
|
{fieldName}
|
|
@@ -136,7 +136,7 @@
|
|
|
136
136
|
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Control Properties</h3>
|
|
137
137
|
<div class="bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl shadow-sm hover:shadow-md transition-all duration-200 p-6">
|
|
138
138
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
139
|
-
{#each Object.entries(control.properties) as [key, value]}
|
|
139
|
+
{#each Object.entries(control.properties) as [key, value], index (index)}
|
|
140
140
|
<FieldRenderer
|
|
141
141
|
fieldName={key.replace(/_/g, ' ')}
|
|
142
142
|
field={null}
|
|
@@ -148,4 +148,4 @@
|
|
|
148
148
|
</div>
|
|
149
149
|
</div>
|
|
150
150
|
{/if}
|
|
151
|
-
</div>
|
|
151
|
+
</div>
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
<script lang="ts">
|
|
5
5
|
import { TimelineItem } from '$components/version-control';
|
|
6
|
-
import type { Control } from '$lib/types';
|
|
7
6
|
import { EmptyState } from '../../ui';
|
|
8
7
|
|
|
9
8
|
interface Props {
|
|
10
|
-
control: Control;
|
|
9
|
+
// control: Control;
|
|
11
10
|
timeline?: any; // Timeline type from control.timeline
|
|
12
11
|
}
|
|
13
12
|
|
|
@@ -26,7 +25,7 @@
|
|
|
26
25
|
{:else if commits.length > 0}
|
|
27
26
|
<div class="mb-4">
|
|
28
27
|
<div class="space-y-6">
|
|
29
|
-
{#each commits as commit, index}
|
|
28
|
+
{#each commits as commit, index (index)}
|
|
30
29
|
<TimelineItem {commit} showConnector={index < commits.length - 1} />
|
|
31
30
|
{/each}
|
|
32
31
|
</div>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
16
|
<div class="space-y-3">
|
|
17
|
-
{#each sections as section}
|
|
17
|
+
{#each sections as section, index (index)}
|
|
18
18
|
{#if section.type === 'header'}
|
|
19
19
|
<h4 class="font-semibold text-gray-900 dark:text-gray-100 mt-4 first:mt-0">
|
|
20
20
|
{section.content}
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
<div class="overflow-x-auto">
|
|
24
24
|
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
|
25
25
|
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
|
26
|
-
{#each section.data.rows as row,
|
|
26
|
+
{#each section.data.rows as row, index (index)}
|
|
27
27
|
<tr class="hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors">
|
|
28
|
-
{#each row.columns as column, j}
|
|
28
|
+
{#each row.columns as column, j (j)}
|
|
29
29
|
<td class="px-3 py-2 text-sm {j === 0 ? 'font-medium text-gray-900 dark:text-gray-100' : 'text-gray-600 dark:text-gray-400'}">
|
|
30
30
|
{#if column.startsWith('CCI-')}
|
|
31
31
|
<code class="px-1.5 py-0.5 text-xs bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200 rounded">
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
</div>
|
|
48
48
|
{:else if section.type === 'list' && section.data?.items}
|
|
49
49
|
<ul class="space-y-1 ml-4">
|
|
50
|
-
{#each section.data.items as item}
|
|
50
|
+
{#each section.data.items as item, index (index)}
|
|
51
51
|
<li class="flex items-start">
|
|
52
52
|
<span class="text-gray-400 dark:text-gray-500 mr-2 flex-shrink-0">•</span>
|
|
53
53
|
<span class="text-gray-600 dark:text-gray-400 text-sm">{item}</span>
|
|
@@ -128,8 +128,8 @@
|
|
|
128
128
|
{#if readonly}
|
|
129
129
|
<!-- View Mode: Clean minimal layout -->
|
|
130
130
|
<div class="space-y-6">
|
|
131
|
-
{#each Object.entries(fieldGroups) as [_groupName, fields]}
|
|
132
|
-
{#each [fields] as fieldList}
|
|
131
|
+
{#each Object.entries(fieldGroups) as [_groupName, fields], index (index)}
|
|
132
|
+
{#each [fields] as fieldList, a (a)}
|
|
133
133
|
{@const importantFields = fieldList.filter((f) =>
|
|
134
134
|
['id', 'title', 'priority', 'status'].includes(f.id)
|
|
135
135
|
)}
|
|
@@ -147,7 +147,7 @@
|
|
|
147
147
|
{#if importantFields.length > 0}
|
|
148
148
|
<div class="pb-4 border-b border-gray-200 dark:border-gray-700">
|
|
149
149
|
<div class="flex flex-wrap items-center gap-6">
|
|
150
|
-
{#each importantFields as field}
|
|
150
|
+
{#each importantFields as field, index (index)}
|
|
151
151
|
{@const value = control[field.id]}
|
|
152
152
|
{#if value !== undefined && value !== null && value !== ''}
|
|
153
153
|
<div class="flex items-center space-x-3">
|
|
@@ -181,7 +181,7 @@
|
|
|
181
181
|
{/if}
|
|
182
182
|
|
|
183
183
|
<!-- Content sections -->
|
|
184
|
-
{#each contentFields as field}
|
|
184
|
+
{#each contentFields as field, index (index)}
|
|
185
185
|
{@const value = control[field.id]}
|
|
186
186
|
|
|
187
187
|
{#if field.type === 'textarea'}
|
|
@@ -206,7 +206,7 @@
|
|
|
206
206
|
</span>
|
|
207
207
|
</h3>
|
|
208
208
|
<div class="space-y-2">
|
|
209
|
-
{#each value as item}
|
|
209
|
+
{#each value as item, index (index)}
|
|
210
210
|
<div class="flex items-start space-x-3 py-2">
|
|
211
211
|
<div class="flex-shrink-0 w-1.5 h-1.5 bg-blue-600 rounded-full mt-2"></div>
|
|
212
212
|
<div class="text-gray-900 dark:text-white leading-relaxed">
|
|
@@ -226,13 +226,13 @@
|
|
|
226
226
|
</span>
|
|
227
227
|
</h3>
|
|
228
228
|
<div class="space-y-3">
|
|
229
|
-
{#each value as item,
|
|
229
|
+
{#each value as item, index (index)}
|
|
230
230
|
<div
|
|
231
231
|
class="bg-gray-50 dark:bg-gray-800 rounded-lg p-4 border border-gray-200 dark:border-gray-700"
|
|
232
232
|
>
|
|
233
233
|
{#if field.arraySchema}
|
|
234
234
|
<dl class="space-y-2">
|
|
235
|
-
{#each Object.entries(field.arraySchema) as [key, schema]}
|
|
235
|
+
{#each Object.entries(field.arraySchema) as [key, schema], index (index)}
|
|
236
236
|
{@const schemaObj = schema as any}
|
|
237
237
|
{#if item[key]}
|
|
238
238
|
<div class="flex justify-between">
|
|
@@ -281,7 +281,7 @@
|
|
|
281
281
|
{:else}
|
|
282
282
|
<!-- Edit Mode: Enhanced form layout -->
|
|
283
283
|
<div class="space-y-10">
|
|
284
|
-
{#each Object.entries(fieldGroups) as [groupName, fields]}
|
|
284
|
+
{#each Object.entries(fieldGroups) as [groupName, fields], index (index)}
|
|
285
285
|
<section
|
|
286
286
|
class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl shadow-sm overflow-hidden"
|
|
287
287
|
>
|
|
@@ -300,7 +300,7 @@
|
|
|
300
300
|
<div class="p-8">
|
|
301
301
|
<!-- Improved grid layout for simple fields -->
|
|
302
302
|
<div class="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-8 mb-10">
|
|
303
|
-
{#each fields as field}
|
|
303
|
+
{#each fields as field, index (index)}
|
|
304
304
|
{#if !['textarea', 'string-array', 'object-array'].includes(field.type)}
|
|
305
305
|
<div class="space-y-2">
|
|
306
306
|
<DynamicField
|
|
@@ -317,7 +317,7 @@
|
|
|
317
317
|
|
|
318
318
|
<!-- Enhanced full-width fields with better spacing -->
|
|
319
319
|
<div class="space-y-10">
|
|
320
|
-
{#each fields as field}
|
|
320
|
+
{#each fields as field, index (index)}
|
|
321
321
|
{#if ['textarea', 'string-array', 'object-array'].includes(field.type)}
|
|
322
322
|
<div
|
|
323
323
|
class="bg-gray-50 dark:bg-gray-800 rounded-xl p-6 border border-gray-200 dark:border-gray-700"
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
{#if !field.required}
|
|
141
141
|
<option value="">-- Select an option --</option>
|
|
142
142
|
{/if}
|
|
143
|
-
{#each field.options as option}
|
|
143
|
+
{#each field.options as option (option)}
|
|
144
144
|
<option value={option}>{option}</option>
|
|
145
145
|
{/each}
|
|
146
146
|
</select>
|
|
@@ -221,7 +221,7 @@
|
|
|
221
221
|
</button>
|
|
222
222
|
</div>
|
|
223
223
|
{:else}
|
|
224
|
-
{#each ensureArray() as item, index}
|
|
224
|
+
{#each ensureArray() as item, index (index)}
|
|
225
225
|
<div
|
|
226
226
|
class="group relative p-4 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm hover:shadow-md transition-shadow"
|
|
227
227
|
>
|
|
@@ -349,7 +349,7 @@
|
|
|
349
349
|
</button>
|
|
350
350
|
</div>
|
|
351
351
|
{:else}
|
|
352
|
-
{#each ensureArray() as item, index}
|
|
352
|
+
{#each ensureArray() as item, index (index)}
|
|
353
353
|
<div
|
|
354
354
|
class="group relative bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl shadow-sm hover:shadow-md transition-all duration-200"
|
|
355
355
|
>
|
|
@@ -409,7 +409,7 @@
|
|
|
409
409
|
<div class="p-4">
|
|
410
410
|
{#if field.arraySchema}
|
|
411
411
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
412
|
-
{#each Object.entries(field.arraySchema) as [key, schemaObj]}
|
|
412
|
+
{#each Object.entries(field.arraySchema) as [key, schemaObj], index (index)}
|
|
413
413
|
{@const schema = schemaObj as any}
|
|
414
414
|
<div class="space-y-2">
|
|
415
415
|
<label
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
</div>
|
|
166
166
|
{:else if controlSets.length > 0}
|
|
167
167
|
<div class="space-y-3">
|
|
168
|
-
{#each controlSets as controlSet}
|
|
168
|
+
{#each controlSets as controlSet, index (index)}
|
|
169
169
|
{@const isCurrent = isCurrentControlSet(controlSet)}
|
|
170
170
|
<div
|
|
171
171
|
on:click={() => !isCurrent && selectControlSet(controlSet)}
|