Skip to content

Commit cc6aaec

Browse files
committed
Merge branch 'rc' of https://github.com/bexis2/core into rc
2 parents fbade95 + 3404ef9 commit cc6aaec

File tree

7 files changed

+188
-146
lines changed

7 files changed

+188
-146
lines changed

Console/BExIS.Web.Shell/Areas/DDM/BExIS.Modules.Ddm.UI/Views/Data/_tagsView.cshtml

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
<div>
3535
<table>
3636
<tbody>
37+
<th>Release Tag</th>
38+
<th>Release Notes</th>
39+
<th>Release Date</th>
40+
<th>Show Version</th>
3741
@foreach (var tag in Model)
3842
{
3943
<tr id="@tag.Version">
@@ -44,8 +48,12 @@
4448
<div>@note</div>
4549
}
4650
</td>
51+
<td>@tag.ReleaseDate.ToString("dd.MM.yyyy")</td>
52+
<td><a href="@url&[email protected]">Show Version</a></td>
53+
4754
</tr>
4855
}
56+
<tr>
4957
</tbody>
5058
</table>
5159
</div>
@@ -54,34 +62,33 @@
5462

5563
<div id="tagview">
5664
<div>
57-
58-
59-
<table>
60-
<tbody>
61-
@{
62-
var singletag = Model.FirstOrDefault(t => t.Version == tagNr);
63-
64-
65-
<tr id="@singletag.Version" class="selected">
66-
<td><a href="@url&[email protected]"> @singletag.Version</a></td>
67-
<td>
68-
@foreach (var note in singletag.ReleaseNotes)
69-
{
70-
<div>@note</div>
71-
}
72-
</td>
73-
</tr>
74-
}
75-
</tbody>
76-
</table>
77-
65+
@{
66+
var singletag = Model.FirstOrDefault(t => t.Version == tagNr);
67+
68+
<div><b>Release Tag:</b> @singletag.Version (@singletag.ReleaseDate.ToString("dd.MM.yyyy"))</div>
69+
<div></div>
70+
<div><b>Release Notes:</b></div>
71+
<ul>
72+
@if (singletag.ReleaseNotes != null && singletag.ReleaseNotes.Any())
73+
{
74+
foreach (var note in singletag.ReleaseNotes)
75+
{
76+
77+
<li>@note</li>
78+
79+
80+
}
81+
}
82+
</ul>
83+
}
7884

7985
</div>
8086

8187
</div>
8288

8389
<div>
84-
<button id="showTags" class="bx bx-function fa-arrow-down small" onclick="onClickFn()"></button>
90+
<button id="showTags" class="bx bx-function fa-arrow-down small" onclick="onClickFn()"> Show History</button>
91+
8592
@if (hasEditRigths)
8693
{
8794
<button id="editTags" class="bx bx-function fa-tag small"></button>
@@ -140,6 +147,7 @@
140147
const element = document.getElementById("showTags");
141148
element.classList.toggle("fa-arrow-up");
142149
element.classList.toggle("fa-arrow-down");
143-
150+
element.innerText = element.innerText === " Show History" ? " Hide History" : " Show History";
151+
144152
}
145153
</script>

Console/BExIS.Web.Shell/Areas/RPM/BExIS.Modules.Rpm.UI.Svelte/src/lib/components/meaning/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export class MeaningModel {
3535
export class meaningEntryType {
3636
mappingRelation: listItemType;
3737
mappedLinks: listItemType[];
38+
isValid: boolean = true;
3839

3940
public constructor() {
4041
this.mappingRelation = { id: -1, text: '', group: '', description: '' };

Console/BExIS.Web.Shell/Areas/RPM/BExIS.Modules.Rpm.UI.Svelte/src/routes/externallink/ExternalLink.svelte

Lines changed: 84 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import Fa from 'svelte-fa';
44
import { faXmark, faSave } from '@fortawesome/free-solid-svg-icons';
55
6-
import { createEventDispatcher, onMount } from 'svelte';
6+
import { createEventDispatcher, onMount, tick } from 'svelte';
77
88
import suite from './externalLink';
99
import {
@@ -22,12 +22,21 @@
2222
export let link: externalLinkType;
2323
$: link;
2424
25+
// local editable copy to guarantee reactivity on nested property changes
26+
let localLink: externalLinkType = link ? { ...link } : ({} as externalLinkType);
27+
// keep local copy in sync when parent provides a new object
28+
$: if (link && link.id !== localLink.id) localLink = { ...link };
29+
30+
2531
let help: boolean = true;
2632
let loaded = false;
2733
2834
// validation
2935
let res = suite.get();
30-
$: isValid = res.isValid();
36+
37+
$: isValid = res.isValid()
38+
$: isChanged = false
39+
3140
3241
// data
3342
import { helpInfoList } from './help';
@@ -42,33 +51,49 @@
4251
const dispatch = createEventDispatcher();
4352
4453
onMount(() => {
45-
console.log('🚀 ~ file: ExternalLink.svelte:28 ~ linksList:', linksList);
46-
helpStore.setHelpItemList(helpInfoList);
54+
console.log('🚀 ~ file: ExternalLink.svelte:28 ~ linksList:', linksList);
55+
helpStore.setHelpItemList(helpInfoList);
4756
48-
// reset & reload validation
49-
suite.reset();
57+
// reset & reload validation
58+
suite.reset();
5059
51-
// set types =
60+
console.log('🚀 ~ file: ExternalLink.svelte:45 ~ onMount ~ types:', types);
5261
53-
console.log('🚀 ~ file: ExternalLink.svelte:45 ~ onMount ~ types:', types);
62+
if (link.id == 0) {
63+
suite.reset();
64+
} else {
65+
(async () => {
66+
await tick();
67+
// full validation: DO NOT pass an empty string as fieldName
68+
res = suite({ name: localLink.name, uri: localLink.uri, type: localLink.type, id: localLink.id }, undefined);
69+
console.log('Validation result init:', res.isValid(), res.getErrors(), res.getState && res.getState());
70+
})();
71+
}
72+
73+
//updateAutoCompleteList();
74+
75+
loaded = true;
76+
});
5477
55-
setTimeout(async () => {
56-
if (link.id > 0) {
57-
res = suite(link, '');
58-
} // run validation only if start with an existing
59-
}, 10);
78+
function onChangeFn(e: Event) {
79+
// wait for DOM / bindings to update, then validate
80+
const target = e.target as EventTarget & { id?: string } | null;
81+
const id = target?.id ?? '';
82+
// ensure Svelte notices nested changes
83+
localLink = { ...localLink };
84+
console.log('onChangeFn ', id);
85+
console.log('localLink ', localLink);
86+
const uri = localLink.uri;
87+
88+
(async () => {
89+
await tick();
90+
//res = suite({ name: localLink.name, uri: localLink.uri, type: localLink.type, id: localLink.id });
91+
res = suite({ name: localLink.name, uri: localLink.uri, type: localLink.type, id: localLink.id }, id || undefined);
92+
93+
})();
94+
console.log('Changed ', e);
95+
console.log('Validation result:', res.isValid(), res.getErrors());
6096
61-
//updateAutoCompleteList();
62-
63-
loaded = true;
64-
});
65-
66-
function onChangeFn(e) {
67-
// add some delay so the entityTemplate is updated
68-
// otherwise the values are old
69-
setTimeout(async () => {
70-
res = suite(link, e.target.id);
71-
}, 100);
7297
}
7398
7499
function cancel() {
@@ -77,10 +102,12 @@
77102
}
78103
79104
async function submit() {
80-
var s = (await (link.id == 0)) ? create(link) : update(link);
105+
// use localLink for create/update
106+
var s = (await (localLink.id == 0)) ? create(localLink) : update(localLink);
81107
82108
if ((await s).status === 200) {
83-
dispatch('success');
109+
// sync back to parent prop via event
110+
dispatch('success', { link: localLink });
84111
} else {
85112
dispatch('fail');
86113
}
@@ -90,17 +117,18 @@
90117
91118
//change event: if select change check also validation only on the field
92119
// *** is the id of the input component
93-
function onSelectHandler(e, id) {
120+
function onSelectHandler(e: CustomEvent<any>, id: string) {
94121
// // set prefix = null if type = prefix
95122
// // type id for prefix == 1
96123
console.log(id, e);
97124
if (id == 'type' && e.detail.text == 'prefix') {
98-
// if type and prefix
99-
console.log('reset prefix');
100-
link.prefix = undefined;
125+
localLink.prefix = undefined;
101126
}
102-
103-
res = suite(link, id);
127+
(async () => {
128+
await tick();
129+
res = suite({ name: localLink.name, uri: localLink.uri, type: localLink.type, id: localLink.id }, id || undefined);
130+
localLink = { ...localLink };
131+
})();
104132
}
105133
</script>
106134

@@ -111,8 +139,10 @@
111139
<div class="w-1/2">
112140
<TextInput
113141
id="name"
114-
bind:value={link.name}
115-
on:change
142+
label="Name"
143+
required={true}
144+
bind:value={localLink.name}
145+
on:change={() => isChanged = true}
116146
on:input={onChangeFn}
117147
placeholder="Name"
118148
valid={res.isValid('name')}
@@ -136,17 +166,19 @@
136166
complexTarget={true}
137167
isMulti={false}
138168
clearable={false}
139-
bind:target={link.type}
169+
required={true}
170+
bind:target={localLink.type}
140171
placeholder="-- Please select --"
141172
invalid={res.hasErrors('type')}
142173
feedback={res.getErrors('type')}
143174
on:change={(e) => onSelectHandler(e, 'type')}
175+
on:change={() => isChanged = true}
144176
{help}
145177
/>
146178
</div>
147179

148180
<div class="w-1/4">
149-
{#if link.type?.id === externalLinkTypeEnum.prefix}
181+
{#if localLink.type?.id === externalLinkTypeEnum.prefix}
150182
<MultiSelect
151183
id="prefixCategory"
152184
title="Prefix Category"
@@ -158,18 +190,19 @@
158190
complexTarget={true}
159191
isMulti={false}
160192
clearable={true}
161-
bind:target={link.prefixCategory}
193+
bind:target={localLink.prefixCategory}
162194
placeholder="-- Please select --"
163-
invalid={res.hasErrors('type')}
164-
feedback={res.getErrors('type')}
165-
on:change={(e) => onSelectHandler(e, 'type')}
195+
invalid={res.hasErrors('prefixCategory')}
196+
feedback={res.getErrors('prefixCategory')}
197+
on:change={(e) => onSelectHandler(e, 'prefixCategory')}
198+
on:change={() => isChanged = true}
166199
{help}
167200
/>
168201
{/if}
169202
</div>
170203
</div>
171204
<div class="flex gap-5">
172-
{#if link.type?.id !== externalLinkTypeEnum.prefix}
205+
{#if localLink.type?.id !== externalLinkTypeEnum.prefix}
173206
<div class="w-1/4">
174207
<MultiSelect
175208
id="prefix"
@@ -182,11 +215,12 @@
182215
complexTarget={true}
183216
isMulti={false}
184217
clearable={true}
185-
bind:target={link.prefix}
218+
bind:target={localLink.prefix}
186219
placeholder="-- Please select --"
187-
invalid={res.hasErrors('type')}
188-
feedback={res.getErrors('type')}
189-
on:change={(e) => onSelectHandler(e, 'type')}
220+
invalid={res.hasErrors('prefix')}
221+
feedback={res.getErrors('prefix')}
222+
on:change={(e) => onSelectHandler(e, 'prefix')}
223+
on:change={() => isChanged = true}
190224
{help}
191225
/>
192226
</div>
@@ -195,19 +229,20 @@
195229
<TextInput
196230
id="uri"
197231
label="Uri"
198-
bind:value={link.uri}
199-
on:change
232+
bind:value={localLink.uri}
233+
on:change={() => isChanged = true}
200234
on:input={onChangeFn}
201235
placeholder="Uri"
202236
valid={res.isValid('uri')}
203237
invalid={res.hasErrors('uri')}
204238
feedback={res.getErrors('uri')}
239+
required={true}
205240
{help}
206241
/>
207242
</div>
208243
</div>
209244

210-
<UrlPreview bind:link />
245+
<UrlPreview bind:link={localLink} />
211246

212247
<div class="py-5 text-right col-span-2">
213248
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
@@ -224,7 +259,7 @@
224259
class="btn variant-filled-primary h-9 w-16 shadow-md"
225260
title="Save external link, {link.name}"
226261
id="save"
227-
disabled={!isValid}
262+
disabled={!(isChanged && isValid)}
228263
>
229264
<Fa icon={faSave} /></button
230265
>

Console/BExIS.Web.Shell/Areas/RPM/BExIS.Modules.Rpm.UI.Svelte/src/routes/externallink/externalLink.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const suite = create((data = {}, fieldName) => {
99
enforce(data.name).isNotBlank();
1010
});
1111

12-
test('name', 'name allready exist.', () => {
12+
test('name', 'name already exist.', () => {
1313
const existingLinks = get(externalLinksStore).map((e) => e.name);
1414
// if the form is in edit mode, find the selected one by id
1515
const editedObj =
@@ -22,6 +22,16 @@ const suite = create((data = {}, fieldName) => {
2222
enforce(data.name).notInside(list);
2323
});
2424

25+
test('type', 'type is required', () => {
26+
let value = data.type;
27+
if (Array.isArray(value)) value = value[0];
28+
// tolerate object shapes from MultiSelect (e.g. { id, text } or { value } etc.)
29+
if (value && typeof value === 'object') {
30+
value = value.id ?? value.value ?? value.text ?? value.name ?? '';
31+
}
32+
enforce(value).isNotBlank();
33+
});
34+
2535
test('uri', 'uri is required', () => {
2636
enforce(data.uri).isNotBlank();
2737
});

Console/BExIS.Web.Shell/Areas/RPM/BExIS.Modules.Rpm.UI.Svelte/src/routes/meaning/Meaning.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
let res = suite.get();
3232
$: isValid = res.isValid();
3333
34-
let linksValid: boolean = true;
34+
$: linksValid = meaning.externalLinks.every((entry) => entry.isValid);
3535
3636
const dispatch = createEventDispatcher();
3737

0 commit comments

Comments
 (0)