Skip to content

Commit 3dd0c8b

Browse files
committed
Tag Management: UX Improvements #2198
1 parent f91ec01 commit 3dd0c8b

File tree

13 files changed

+189
-41
lines changed

13 files changed

+189
-41
lines changed

Console/BExIS.Web.Shell/Areas/DDM/BExIS.Modules.Ddm.UI.Svelte/src/routes/taginfo/+page.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
</script>
1717

1818
<Page
19-
title="Tag Overview"
20-
note="Manage and view tags of the dataset."
19+
title="Release Tag Management"
20+
note="Manage and view release tags of the dataset."
2121
contentLayoutType={pageContentLayoutType.center}
2222
{links}
2323
>

Console/BExIS.Web.Shell/Areas/DDM/BExIS.Modules.Ddm.UI.Svelte/src/routes/taginfo/TagInfoEdit.svelte

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,29 @@
88
} from '@bexis2/bexis2-core-ui';
99
import { add, get, save, updateSearch } from './services';
1010
11-
import { tagInfoModelStore, withMinorStore } from './stores.js';
11+
import { tagInfoModelStore, withMinorStore, originalTagInfoModelStore } from './stores.js';
1212
import TablePublish from './table/tablePublish.svelte';
1313
import TableShow from './table/tableShow.svelte';
1414
import TableNr from './table/tableNr.svelte';
1515
import TableText from './table/tableText.svelte';
16+
import TableTextType from './table/tableTextType.svelte';
17+
import TableTextAuthor from './table/tableTextAuthor.svelte';
1618
import TableOptions from './table/tableOptions.svelte';
1719
import TableDate from './table/tableDate.svelte';
20+
import TableVersionNumber from './table/tableVersionNumber.svelte';
1821
import { type TagInfoEditModel, TagType } from './types';
1922
import TableReleaseNote from './table/tableReleaseNote.svelte';
2023
import { createEventDispatcher, onMount } from 'svelte';
24+
import { Tab } from '@skeletonlabs/skeleton';
25+
import TableDateCreate from './table/tableDateCreate.svelte';
2126
2227
let container;
2328
let id: number = 0;
2429
let withMinor: boolean = false;
2530
let rows: number = 3;
2631
2732
let promise: Promise<TagInfoEditModel[]>;
33+
let originalRows: TagInfoEditModel[] = [];
2834
2935
const dispatch = createEventDispatcher();
3036
@@ -36,6 +42,9 @@
3642
promise = get(id);
3743
const tagInfos = await promise;
3844
rows = tagInfos.length;
45+
// deep copy
46+
originalRows = JSON.parse(JSON.stringify(tagInfos));
47+
originalTagInfoModelStore.update(() => originalRows);
3948
tagInfoModelStore.set(tagInfos);
4049
withMinorStore.set(withMinor);
4150
@@ -75,14 +84,16 @@
7584
7685
notificationStore.showNotification({
7786
notificationType: notificationType.success,
78-
message: 'Tag is saved.'
87+
message: 'Release tag changes are saved.'
7988
});
80-
89+
originalTagInfoModelStore.update((arr) =>
90+
arr.map((x) => (x.versionId === tagInfo.versionId ? { ...x, ...tagInfo } : x))
91+
);
8192
dispatch('reload');
8293
} else {
8394
notificationStore.showNotification({
8495
notificationType: notificationType.error,
85-
message: 'Tag is not saved.'
96+
message: 'Release tag changes are not saved.'
8697
});
8798
}
8899
}
@@ -113,7 +124,7 @@
113124
<TablePlaceholder cols={7} {rows} />
114125
</div>
115126
{:then model}
116-
<h2 class="h2">Tag Management</h2>
127+
<h2 class="h2">Release Tag Management</h2>
117128
<div class="table table-compact w-full">
118129
<Table
119130
on:action={tableActions}
@@ -135,16 +146,20 @@
135146
fixedWidth: 10,
136147
header: 'Internal version',
137148
disableFiltering: true,
138-
disableSorting: true
149+
disableSorting: true,
150+
instructions: {
151+
renderComponent: TableVersionNumber
152+
}
139153
},
140154
tagNr: {
141155
fixedWidth: 80,
142-
header: 'Tag',
156+
header: 'Release Tag',
143157
disableFiltering: true,
144158
disableSorting: true,
145159
instructions: {
146160
renderComponent: TableNr
147-
}
161+
},
162+
label: 'Tag'
148163
},
149164
releaseNote: {
150165
header: 'Release Note',
@@ -166,23 +181,29 @@
166181
systemDescription: {
167182
header: 'System Description',
168183
disableFiltering: true,
169-
disableSorting: true
184+
disableSorting: true,
185+
instructions: {
186+
renderComponent: TableTextType
187+
}
170188
},
171189
systemAuthor: {
172-
header: 'System Author',
190+
header: 'Author',
173191
disableFiltering: true,
174-
disableSorting: true
192+
disableSorting: true,
193+
instructions: {
194+
renderComponent: TableTextAuthor
195+
}
175196
},
176197
systemDate: {
177-
header: 'System Date',
198+
header: 'Creation Date',
178199
instructions: {
179-
renderComponent: TableDate
200+
renderComponent: TableDateCreate
180201
},
181202
disableFiltering: true,
182203
disableSorting: true
183204
},
184205
show: {
185-
header: 'Show history',
206+
header: 'Show Note',
186207
fixedWidth: 10,
187208
instructions: {
188209
renderComponent: TableShow

Console/BExIS.Web.Shell/Areas/DDM/BExIS.Modules.Ddm.UI.Svelte/src/routes/taginfo/stores.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ import type { TagInfoEditModel } from './types';
22
import { writable } from 'svelte/store';
33

44
export const tagInfoModelStore = writable<TagInfoEditModel[]>([]);
5+
export const originalTagInfoModelStore = writable<TagInfoEditModel[]>([]);
56
export const withMinorStore = writable<boolean>();

Console/BExIS.Web.Shell/Areas/DDM/BExIS.Modules.Ddm.UI.Svelte/src/routes/taginfo/table/tableDate.svelte

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
}
1717
</script>
1818

19-
{#if !emtpy}
20-
{new Date(value).toLocaleString('de-DE')}
21-
{/if}
19+
<span title="Date of creation of the release tag">
20+
{#if !emtpy}
21+
{new Date(value).toLocaleString('de-DE')}
22+
{/if}
23+
</span>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<script lang="ts">
2+
import type { TagInfoModel } from '../types';
3+
4+
export let value: string;
5+
export let row: TagInfoModel;
6+
let emtpy: boolean = true;
7+
8+
emtpy = isEmpty(value);
9+
10+
function isEmpty(value: string): boolean {
11+
if (value === null || value === undefined || value === '' || value === '0001-01-01T00:00:00') {
12+
return true;
13+
}
14+
15+
return false;
16+
}
17+
</script>
18+
19+
<span title="Creation date of this version">
20+
{#if !emtpy}
21+
{new Date(value).toLocaleString('de-DE')}
22+
{/if}
23+
</span>

Console/BExIS.Web.Shell/Areas/DDM/BExIS.Modules.Ddm.UI.Svelte/src/routes/taginfo/table/tableNr.svelte

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
</script>
55

66
<div>
7-
{#if value > 0}
8-
{value.toFixed(1)}
9-
{/if}
7+
<span title="Release Tag">
8+
{#if value > 0}
9+
{value.toFixed(1)}
10+
{/if}
11+
</span>
1012
</div>

Console/BExIS.Web.Shell/Areas/DDM/BExIS.Modules.Ddm.UI.Svelte/src/routes/taginfo/table/tableOptions.svelte

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
<script lang="ts">
22
import Fa from 'svelte-fa';
33
import { faSave } from '@fortawesome/free-solid-svg-icons';
4-
import { withMinorStore } from '../stores';
5-
import { get } from 'svelte/store';
4+
import { withMinorStore, tagInfoModelStore, originalTagInfoModelStore } from '../stores';
65
import type { TagInfoEditModel } from '../types';
76
87
export let row: TagInfoEditModel;
98
export let dispatchFn;
109
1110
let noTag: boolean = hasNoTag();
12-
let withMinor = get(withMinorStore);
11+
// use auto-subscription so changes to the store re-run reactive statements
12+
let withMinor: boolean;
13+
14+
$: withMinor = $withMinorStore;
1315
1416
function hasNoTag() {
1517
return row.tagId == 0;
@@ -36,25 +38,47 @@
3638
type: 'MAJOR'
3739
}
3840
];
41+
42+
// Check if there are changes compared to the original rows
43+
$: hasChanges = (() => {
44+
const originalRows = $originalTagInfoModelStore;
45+
const currentRow = $tagInfoModelStore.find((x) => x.versionId == row.versionId);
46+
console.log('🚀 ~ hasChanges ~ currentRow:', currentRow);
47+
if (!currentRow) return false;
48+
49+
const originalRow = originalRows.find((x) => x.versionId == row.versionId);
50+
if (!originalRow) return true; // New row
51+
52+
return (
53+
currentRow.releaseNote !== originalRow.releaseNote ||
54+
currentRow.publish !== originalRow.publish ||
55+
currentRow.show !== originalRow.show
56+
);
57+
})();
3958
</script>
4059

4160
<div class="flex gap-2 w-min p-2">
42-
<button
43-
class="btn btn-sm variant-filled-primary"
44-
on:click|preventDefault={() => eventDispatchFn('SAVE')}
45-
>
46-
<Fa icon={faSave} />
47-
</button>
61+
{#if hasChanges}
62+
<button
63+
class="btn btn-sm variant-filled-primary"
64+
title="Save changes"
65+
on:click|preventDefault={() => eventDispatchFn('SAVE')}
66+
>
67+
<Fa icon={faSave} />
68+
</button>
69+
{/if}
4870

4971
{#if noTag}
5072
{#if withMinor}
5173
<button
5274
class="btn btn-sm variant-filled-primary"
75+
title="Create new minor version"
5376
on:click|preventDefault={() => eventDispatchFn('MINOR')}>minor</button
5477
>
5578
{/if}
5679
<button
5780
class="btn btn-sm variant-filled-primary"
81+
title="Create new major version"
5882
on:click|preventDefault={() => eventDispatchFn('MAJOR')}>major</button
5983
>
6084
{/if}

Console/BExIS.Web.Shell/Areas/DDM/BExIS.Modules.Ddm.UI.Svelte/src/routes/taginfo/table/tablePublish.svelte

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,30 @@
22
import { SlideToggle } from '@skeletonlabs/skeleton';
33
import { tagInfoModelStore } from '../stores';
44
import type { TagInfoEditModel } from '../types';
5-
import { get } from 'svelte/store';
65
76
export let value: boolean;
87
export let row: any;
98
let currentRow: TagInfoEditModel;
109
11-
$: currentRow = get(tagInfoModelStore).find((x) => x.versionId == row.original.versionId);
10+
$: currentRow = $tagInfoModelStore.find((x) => x.versionId == row.original.versionId);
11+
12+
function togglePublish(versionId: number, value: boolean) {
13+
tagInfoModelStore.update((arr) =>
14+
arr.map((x) => (x.versionId === versionId ? { ...x, publish: !!value } : x))
15+
);
16+
}
1217
</script>
1318

1419
<div class="flex h-full items-center justify-center">
15-
{#if currentRow.tagId > 0}
16-
<SlideToggle name={currentRow.versionId} class="" bind:checked={currentRow.publish} size="sm" />
17-
{/if}
20+
<div title="Make this release tag visible; Click save to apply">
21+
{#if currentRow.tagId > 0}
22+
<SlideToggle
23+
name={currentRow.versionId}
24+
class=""
25+
checked={currentRow.publish}
26+
size="sm"
27+
on:change={(e) => togglePublish(currentRow.versionId, !!(e.detail ?? e.target?.checked))}
28+
/>
29+
{/if}
30+
</div>
1831
</div>
Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,33 @@
11
<script lang="ts">
22
import { TextArea } from '@bexis2/bexis2-core-ui';
3+
import { tagInfoModelStore } from '../stores';
34
45
export let value: string;
56
export let row: any;
67
export let dispatchFn;
78
89
let currentRow = row.original;
10+
11+
// tagInfoModelStore.update((arr) =>
12+
// arr.map((x) => (x.versionId === currentRow.versionId ? { ...x, releaseNote: value } : x))
13+
// );
14+
15+
// update the tagModelStore when the value changes
16+
$: if (currentRow.releaseNote !== value) {
17+
tagInfoModelStore.update((arr) =>
18+
arr.map((x) => (x.versionId === currentRow.versionId ? { ...x, releaseNote: value } : x))
19+
);
20+
}
921
</script>
1022

11-
<TextArea bind:value={currentRow.releaseNote}></TextArea>
23+
<span title="Release Note; Click save to apply">
24+
<TextArea
25+
bind:value={currentRow.releaseNote}
26+
on:input={() =>
27+
tagInfoModelStore.update((arr) =>
28+
arr.map((x) =>
29+
x.versionId === currentRow.versionId ? { ...x, releaseNote: currentRow.releaseNote } : x
30+
)
31+
)}
32+
></TextArea>
33+
</span>

Console/BExIS.Web.Shell/Areas/DDM/BExIS.Modules.Ddm.UI.Svelte/src/routes/taginfo/table/tableShow.svelte

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,36 @@
22
import { SlideToggle } from '@skeletonlabs/skeleton';
33
import { tagInfoModelStore } from '../stores';
44
import type { TagInfoEditModel } from '../types';
5-
import { get } from 'svelte/store';
65
76
export let value: boolean;
87
export let row: any;
98
109
let currentRow: TagInfoEditModel;
1110
12-
$: currentRow = get(tagInfoModelStore).find((x) => x.versionId == row.original.versionId);
11+
$: currentRow =
12+
$tagInfoModelStore.find((x) => x.versionId == row.original.versionId) ??
13+
({
14+
versionId: row.original.versionId,
15+
tagId: 0,
16+
show: false
17+
} as TagInfoEditModel);
18+
19+
function toggleShow(versionId: number, value: boolean) {
20+
tagInfoModelStore.update((arr) =>
21+
arr.map((x) => (x.versionId === versionId ? { ...x, show: !!value } : x))
22+
);
23+
}
1324
</script>
1425

1526
<div class="flex h-full items-center justify-center">
16-
<div>
27+
<div title="Show the release note of this version; Click save to apply">
1728
{#if currentRow && currentRow.tagId > 0}
1829
<SlideToggle
1930
name={'' + currentRow.versionId}
2031
class=""
21-
bind:checked={currentRow.show}
32+
checked={currentRow.show}
2233
size="sm"
34+
on:change={(e) => toggleShow(currentRow.versionId, !!(e.detail ?? e.target?.checked))}
2335
/>
2436
{/if}
2537
</div>

0 commit comments

Comments
 (0)