From 697c8bd2b7a95d3b2e6f484f05581f8a67659b94 Mon Sep 17 00:00:00 2001 From: Rinat Arsaev <11846445+A77AY@users.noreply.github.com> Date: Wed, 11 Mar 2026 18:31:52 +0600 Subject: [PATCH 1/5] bump protos --- package-lock.json | 16 ++++++++-------- package.json | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9b52ccff4..e3b434a95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,10 +22,10 @@ "@angular/router": "^20.1.0", "@ngneat/input-mask": "^6.1.0", "@tailwindcss/postcss": "^4.1.11", - "@vality/domain-proto": "^2.0.1-7a97267.0", + "@vality/domain-proto": "^2.0.1-5c25c2e.0", "@vality/fistful-proto": "^2.0.1-7c61ac5.0", "@vality/machinegun-proto": "^1.0.1-cc2c27c.0", - "@vality/magista-proto": "^2.0.2-2de1ebf.0", + "@vality/magista-proto": "^2.0.2-6cafe01.0", "@vality/ng-monaco-editor": "^20.0.0", "@vality/repairer-proto": "^2.0.2-1a48729.0", "@vality/scrooge-proto": "^0.1.1-42aba67.0", @@ -5955,9 +5955,9 @@ } }, "node_modules/@vality/domain-proto": { - "version": "2.0.1-7a97267.0", - "resolved": "https://registry.npmjs.org/@vality/domain-proto/-/domain-proto-2.0.1-7a97267.0.tgz", - "integrity": "sha512-77vfl9TEjn2ZTSWLNAQNsgDSWhr6oWr5gLze98HPMUGgCC2Sg886e0VWe7KXZcluZ+mgy7G6cSChvE7D925v8g==", + "version": "2.0.1-5c25c2e.0", + "resolved": "https://registry.npmjs.org/@vality/domain-proto/-/domain-proto-2.0.1-5c25c2e.0.tgz", + "integrity": "sha512-sqlfDYQbIu7kJX45JOEVrO6RwtkP7E/9M9AbYkYZ/n77yZTJQr4ZPQFyttGXiIyr4QjgkKBU/sW+W1IzeIZDaw==", "license": "Apache-2.0" }, "node_modules/@vality/fistful-proto": { @@ -5973,9 +5973,9 @@ "license": "Apache-2.0" }, "node_modules/@vality/magista-proto": { - "version": "2.0.2-2de1ebf.0", - "resolved": "https://registry.npmjs.org/@vality/magista-proto/-/magista-proto-2.0.2-2de1ebf.0.tgz", - "integrity": "sha512-kldv1gnEysjiBs1EnDG67wG3TcXrL9tRMT0/qgwmh9iPumtOW6BkXibc/VrcexeAsNRiM6R718YgYOJFF1+Rsw==", + "version": "2.0.2-6cafe01.0", + "resolved": "https://registry.npmjs.org/@vality/magista-proto/-/magista-proto-2.0.2-6cafe01.0.tgz", + "integrity": "sha512-/r8bjvRBBqkMJ8rrbtcgj8NdNZ1SJfYqHPMrUTUp5B2MVAq6wW923O5v1Q4slPjJ5q6dTEeBH+mJwSeBiVecDA==", "license": "Apache-2.0" }, "node_modules/@vality/matez": { diff --git a/package.json b/package.json index 88f7bc18a..d27bf2bca 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,10 @@ "@angular/router": "^20.1.0", "@ngneat/input-mask": "^6.1.0", "@tailwindcss/postcss": "^4.1.11", - "@vality/domain-proto": "^2.0.1-7a97267.0", + "@vality/domain-proto": "^2.0.1-5c25c2e.0", "@vality/fistful-proto": "^2.0.1-7c61ac5.0", "@vality/machinegun-proto": "^1.0.1-cc2c27c.0", - "@vality/magista-proto": "^2.0.2-2de1ebf.0", + "@vality/magista-proto": "^2.0.2-6cafe01.0", "@vality/ng-monaco-editor": "^20.0.0", "@vality/repairer-proto": "^2.0.2-1a48729.0", "@vality/scrooge-proto": "^0.1.1-42aba67.0", From 4b4d258c25cfe85cb14999a3653fabcc1f3ff880 Mon Sep 17 00:00:00 2001 From: Rinat Arsaev <11846445+A77AY@users.noreply.github.com> Date: Thu, 12 Mar 2026 18:40:41 +0600 Subject: [PATCH 2/5] add party name --- src/app/parties/parties.component.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/app/parties/parties.component.ts b/src/app/parties/parties.component.ts index 551d303c9..9e2a826c8 100644 --- a/src/app/parties/parties.component.ts +++ b/src/app/parties/parties.component.ts @@ -42,6 +42,14 @@ export class PartiesComponent implements OnInit { field: 'id', cell: (party) => ({ value: party.ref.id }), }, + { + field: 'name', + cell: (party) => ({ + value: party.data.name, + description: party.data.description, + link: () => `/parties/${party.ref.id}`, + }), + }, { field: 'email', cell: (party) => ({ @@ -49,7 +57,6 @@ export class PartiesComponent implements OnInit { description: (party.data.contact_info.manager_contact_emails || []) .filter(Boolean) .join(', '), - link: () => `/parties/${party.ref.id}`, }), }, { From 83317dbc32806d5b97415c2a126267bb803e3c04 Mon Sep 17 00:00:00 2001 From: Rinat Arsaev <11846445+A77AY@users.noreply.github.com> Date: Thu, 12 Mar 2026 22:31:51 +0600 Subject: [PATCH 3/5] fix weight input --- .../candidates/candidates.component.ts | 5 +- .../edit-candidate-dialog.component.html | 24 +++- .../edit-candidate-dialog.component.ts | 108 ++++++++++-------- 3 files changed, 83 insertions(+), 54 deletions(-) diff --git a/src/app/parties/party/routing-rules/candidates/candidates.component.ts b/src/app/parties/party/routing-rules/candidates/candidates.component.ts index 94a3b25e1..ca1d3d968 100644 --- a/src/app/parties/party/routing-rules/candidates/candidates.component.ts +++ b/src/app/parties/party/routing-rules/candidates/candidates.component.ts @@ -439,7 +439,10 @@ export class CandidatesComponent { first(), switchCombineWith(([_, candidate, candidates]) => { const others = candidates.filter( - (c) => c !== candidate && c.priority === candidate.priority && c.allowed, + (c, idx) => + idx !== candidateIdx && + c.priority === candidate.priority && + getPredicateBoolean(c.allowed), ); const ids = others.map((c) => candidates.findIndex((cd) => cd === c)); return [ diff --git a/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.html b/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.html index 81bfae796..a2131bb44 100644 --- a/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.html +++ b/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.html @@ -9,12 +9,26 @@ label="Weight" type="number" > - + label="Type" + > + +
+
+ @for (item of weightsPreview$ | async; track $index; let isFirst = $first) { +
+ {{ item.percent | number: '1.0-2' }}% +
+ } +
- implements OnInit -{ +export class EditCandidateDialogComponent extends DialogSuperclass< + EditCandidateDialogComponent, + { candidate: RoutingCandidate; others: RoutingCandidate[] }, + { candidate: RoutingCandidate; others: RoutingCandidate[] } +> { private fb = inject(FormBuilder); - private dr = inject(DestroyRef); private othersWeight = this.dialogData.others.reduce((acc, c) => acc + (c.weight || 0), 0); form = this.fb.nonNullable.group({ @@ -50,54 +51,65 @@ export class EditCandidateDialogComponent weight: this.dialogData.candidate.weight, allowed: this.dialogData.candidate.allowed, }); - weightPercentControl = this.fb.nonNullable.control(null); + weightTypeControl = this.fb.nonNullable.control('weight_percent'); + weightOptions = [ + { label: 'Weight', value: 'weight' }, + { label: 'Percent', value: 'weight_percent' }, + ]; - ngOnInit() { - getValueChanges(this.weightPercentControl) - .pipe(takeUntilDestroyed(this.dr)) - .subscribe(() => { - this.form.controls.weight.setValue(null, { - emitEvent: false, - }); - }); - getValueChanges(this.form.controls.weight) - .pipe(takeUntilDestroyed(this.dr)) - .subscribe(() => { - this.weightPercentControl.setValue(null, { - emitEvent: false, - }); - }); - } + weightsPreview$ = getValueChanges(this.form).pipe( + map(() => [ + { + description: 'Current', + percent: this.normalizeWeight(), + }, + ...this.getNewOthers().map((c) => ({ + description: c.terminal.id, + percent: c.weight, + })), + ]), + shareReplay({ refCount: true, bufferSize: 1 }), + ); confirm() { const { terminal, weight, ...value } = getValue(this.form); - const percent = getValue(this.weightPercentControl); - const isPercent = !!percent; - const weightNum = isPercent ? Number(percent) : Number(weight || 0); + const weightNum = this.normalizeWeight(weight); this.closeWithSuccess({ candidate: { ...this.dialogData.candidate, - terminal: { id: terminal }, ...value, + terminal: { id: terminal }, weight: weightNum, }, - others: isPercent - ? this.dialogData.others.map((c) => ({ - ...c, - weight: - c.weight && this.othersWeight - ? Math.round( - (c.weight / this.othersWeight) * - (this.othersWeight - - (weight || 0) + - (percent - ? Math.round((percent / 100) * this.othersWeight) - : 0)), - ) - : 0, - })) - : this.dialogData.others, + others: this.getNewOthers(), }); } + + private getNewOthers(): RoutingCandidate[] { + if (this.weightTypeControl.value === 'weight') { + return this.dialogData.others; + } + + const weight = this.normalizeWeight(); + const othersWeight = Math.min(this.othersWeight - weight, 0); + const othersCount = this.dialogData.others.length; + const availableWeight = MAX_PERCENT_WEIGHT - weight; + + if (othersWeight === 0) { + return this.dialogData.others.map((c) => ({ + ...c, + weight: Math.round(availableWeight / othersCount), + })); + } + + return this.dialogData.others.map((c) => ({ + ...c, + weight: Math.round((c.weight / othersWeight) * availableWeight), + })); + } + + private normalizeWeight(weight: unknown = this.form.value.weight): number { + return Math.max(Math.min(Number(weight || '0'), 100), 0); + } } From 05893b51e3739619cfab3d8f763766c98111a165 Mon Sep 17 00:00:00 2001 From: Rinat Arsaev <11846445+A77AY@users.noreply.github.com> Date: Sun, 15 Mar 2026 23:42:26 +0600 Subject: [PATCH 4/5] new edit --- .../candidates/candidates.component.html | 2 +- .../candidates/candidates.component.ts | 99 ++++++---------- .../edit-candidate-dialog.component.ts | 110 +++++++++++------- 3 files changed, 101 insertions(+), 110 deletions(-) diff --git a/src/app/parties/party/routing-rules/candidates/candidates.component.html b/src/app/parties/party/routing-rules/candidates/candidates.component.html index ff74ef072..565b29d5b 100644 --- a/src/app/parties/party/routing-rules/candidates/candidates.component.html +++ b/src/app/parties/party/routing-rules/candidates/candidates.component.html @@ -76,7 +76,7 @@ - diff --git a/src/app/parties/party/routing-rules/candidates/candidates.component.ts b/src/app/parties/party/routing-rules/candidates/candidates.component.ts index ca1d3d968..7d59a5ef7 100644 --- a/src/app/parties/party/routing-rules/candidates/candidates.component.ts +++ b/src/app/parties/party/routing-rules/candidates/candidates.component.ts @@ -123,7 +123,7 @@ export class CandidatesComponent { private log = inject(NotifyLogService); private route = inject(ActivatedRoute); private sidenavInfoService = inject(SidenavInfoService); - private destroyRef = inject(DestroyRef); + private dr = inject(DestroyRef); protected appMode = inject(AppModeService); protected domainObjectsStoreService = inject(DomainObjectsStoreService); private injector = inject(Injector); @@ -188,24 +188,10 @@ export class CandidatesComponent { }, new Map()); return Array.from(groups.values()) .map((group) => { - const sum = group.reduce( - (acc, item) => - acc + (item.candidate.allowed ? item.candidate.weight || 0 : 0), - 0, - ); - const allowedCount = group.filter((item) => item.allowed).length; + const sum = group.reduce((acc, item) => acc + (item.candidate.weight || 0), 0); return group.map((item) => { const weight = item.candidate.weight || 0; - let weightPercent = 0; - if (item.allowed === false) { - weightPercent = 0; - } else if (allowedCount === 1) { - weightPercent = 100; - } else if (sum > 0) { - weightPercent = Math.round((weight / sum) * 100); - } else { - weightPercent = 0; - } + const weightPercent = sum ? Math.round((weight / sum) * 100) : 0; return { value: { ...item, weightPercent }, width: weightPercent, @@ -269,7 +255,7 @@ export class CandidatesComponent { predicate: d.allowed, toggle: () => { this.getCandidateIdx(d) - .pipe(takeUntilDestroyed(this.destroyRef)) + .pipe(takeUntilDestroyed(this.dr)) .subscribe((idx) => { void this.toggleAllow(idx); }); @@ -293,9 +279,9 @@ export class CandidatesComponent { label: 'Edit', click: () => { this.getCandidateIdx(d) - .pipe(takeUntilDestroyed(this.destroyRef)) + .pipe(takeUntilDestroyed(this.dr)) .subscribe((idx) => { - this.editRule(idx); + this.advancedEdit(idx); }); }, }, @@ -303,7 +289,7 @@ export class CandidatesComponent { label: 'Duplicate', click: () => { this.getCandidateIdx(d) - .pipe(takeUntilDestroyed(this.destroyRef)) + .pipe(takeUntilDestroyed(this.dr)) .subscribe((idx) => { void this.duplicateRule(idx); }); @@ -313,7 +299,7 @@ export class CandidatesComponent { label: getPredicateBoolean(d.allowed) ? 'Deny' : 'Allow', click: () => { this.getCandidateIdx(d) - .pipe(takeUntilDestroyed(this.destroyRef)) + .pipe(takeUntilDestroyed(this.dr)) .subscribe((idx) => { void this.toggleAllow(idx); }); @@ -323,7 +309,7 @@ export class CandidatesComponent { label: 'Remove', click: () => { this.getCandidateIdx(d) - .pipe(takeUntilDestroyed(this.destroyRef)) + .pipe(takeUntilDestroyed(this.dr)) .subscribe((idx) => { void this.removeRule(idx); }); @@ -349,7 +335,7 @@ export class CandidatesComponent { .afterClosed(), ), ) - .pipe(takeUntilDestroyed(this.destroyRef)) + .pipe(takeUntilDestroyed(this.dr)) .subscribe({ next: (res) => { if (res.status === DialogResponseStatus.Success) { @@ -363,7 +349,7 @@ export class CandidatesComponent { }); } - editRule(idx: number) { + advancedEdit(idx: number) { this.routingRulesetService.refID$ .pipe( first(), @@ -383,7 +369,7 @@ export class CandidatesComponent { .afterClosed(), ), ) - .pipe(takeUntilDestroyed(this.destroyRef)) + .pipe(takeUntilDestroyed(this.dr)) .subscribe({ next: (res) => { if (res.status === DialogResponseStatus.Success) { @@ -415,7 +401,7 @@ export class CandidatesComponent { .afterClosed(), ), ) - .pipe(takeUntilDestroyed(this.destroyRef)) + .pipe(takeUntilDestroyed(this.dr)) .subscribe({ next: (res) => { if (res.status === DialogResponseStatus.Success) { @@ -430,49 +416,34 @@ export class CandidatesComponent { } edit(candidateIdx: number) { - this.routingRulesetService.refID$ + combineLatest([this.routingRulesetService.refID$, this.candidates$]) .pipe( - switchCombineWith((refId) => [ - this.routingRulesService.getCandidate(refId, candidateIdx), - this.candidates$, - ]), first(), - switchCombineWith(([_, candidate, candidates]) => { - const others = candidates.filter( - (c, idx) => - idx !== candidateIdx && - c.priority === candidate.priority && - getPredicateBoolean(c.allowed), - ); - const ids = others.map((c) => candidates.findIndex((cd) => cd === c)); - return [ - this.dialog - .open(EditCandidateDialogComponent, { - candidate, - others, - }) - .afterClosed(), - ids, - others, - ]; - }), - switchMap(([[refId], res, ids]) => + switchCombineWith(([_, candidates]) => [ + this.dialog + .open(EditCandidateDialogComponent, { + candidates: candidates + .map((candidate, idx) => ({ idx, candidate })) + .filter( + (c) => + c.candidate.priority === candidates[candidateIdx].priority, + ), + idx: candidateIdx, + }) + .afterClosed(), + ]), + switchMap(([[refId], res]) => res.status === DialogResponseStatus.Success - ? this.routingRulesService.updateRules([ - { - refId, - candidateIdx: candidateIdx, - newCandidate: res.data.candidate, - }, - ...res.data.others.map((newCandidate, idx) => ({ + ? this.routingRulesService.updateRules( + res.data.candidates.map((c) => ({ refId, - candidateIdx: ids[idx], - newCandidate, + candidateIdx: c.idx, + newCandidate: c.candidate, })), - ]) + ) : of(null), ), - takeUntilDestroyed(this.destroyRef), + takeUntilDestroyed(this.dr), ) .subscribe({ next: (res) => { @@ -490,7 +461,7 @@ export class CandidatesComponent { toggleAllow(candidateIdx: number) { runInInjectionContext(this.injector, () => this.routingRulesetService.refID$ - .pipe(first(), takeUntilDestroyed(this.destroyRef)) + .pipe(first(), takeUntilDestroyed(this.dr)) .subscribe((refId) => { changeCandidatesAllowed([{ refId, candidateIdx }]); }), diff --git a/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.ts b/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.ts index 7263659ff..0cb9f74f5 100644 --- a/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.ts +++ b/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.ts @@ -11,7 +11,6 @@ import { DialogSuperclass, InputFieldModule, SelectFieldModule, - getValue, getValueChanges, } from '@vality/matez'; @@ -22,6 +21,16 @@ import { const MAX_PERCENT_WEIGHT = 100; +interface CandidateWithIdx { + candidate: RoutingCandidate; + idx: number; +} + +function normalizePercent(weight: unknown = 0): number { + const parsed = Number(weight); + return Math.max(Math.min(Math.round(isNaN(parsed) ? 0 : parsed), 100), 0); +} + @Component({ selector: 'cc-edit-candidate-dialog', templateUrl: 'edit-candidate-dialog.component.html', @@ -39,17 +48,22 @@ const MAX_PERCENT_WEIGHT = 100; }) export class EditCandidateDialogComponent extends DialogSuperclass< EditCandidateDialogComponent, - { candidate: RoutingCandidate; others: RoutingCandidate[] }, - { candidate: RoutingCandidate; others: RoutingCandidate[] } + { candidates: CandidateWithIdx[]; idx: number }, + { candidates: CandidateWithIdx[]; idx: number } > { private fb = inject(FormBuilder); - private othersWeight = this.dialogData.others.reduce((acc, c) => acc + (c.weight || 0), 0); + private currentCandidate = this.dialogData.candidates.find((c) => c.idx === this.dialogData.idx) + .candidate; + private otherCandidates = this.dialogData.candidates.filter( + (c) => c.idx !== this.dialogData.idx, + ); + private othersWeight = this.otherCandidates.reduce((acc, c) => acc + c.candidate.weight, 0); form = this.fb.nonNullable.group({ - terminal: this.dialogData.candidate.terminal.id, - description: this.dialogData.candidate.description, - weight: this.dialogData.candidate.weight, - allowed: this.dialogData.candidate.allowed, + terminal: this.currentCandidate.terminal.id, + description: this.currentCandidate.description, + weight: this.getPercentWeight(this.currentCandidate.weight), + allowed: this.currentCandidate.allowed, }); weightTypeControl = this.fb.nonNullable.control('weight_percent'); weightOptions = [ @@ -58,58 +72,64 @@ export class EditCandidateDialogComponent extends DialogSuperclass< ]; weightsPreview$ = getValueChanges(this.form).pipe( - map(() => [ - { - description: 'Current', - percent: this.normalizeWeight(), - }, - ...this.getNewOthers().map((c) => ({ - description: c.terminal.id, - percent: c.weight, - })), - ]), + map(() => + this.getNewCandidates() + .sort((a, b) => + a.idx === this.dialogData.idx + ? -1 + : b.idx === this.dialogData.idx + ? 1 + : b.candidate.weight - a.candidate.weight, + ) + .map((c) => ({ + description: c.candidate.terminal.id, + percent: c.candidate.weight, + })), + ), shareReplay({ refCount: true, bufferSize: 1 }), ); confirm() { - const { terminal, weight, ...value } = getValue(this.form); - const weightNum = this.normalizeWeight(weight); - this.closeWithSuccess({ - candidate: { - ...this.dialogData.candidate, - ...value, - terminal: { id: terminal }, - weight: weightNum, - }, - others: this.getNewOthers(), + ...this.dialogData, + candidates: this.getNewCandidates(), }); } - private getNewOthers(): RoutingCandidate[] { + private getNewCandidates(): CandidateWithIdx[] { if (this.weightTypeControl.value === 'weight') { - return this.dialogData.others; + return this.otherCandidates; } - - const weight = this.normalizeWeight(); - const othersWeight = Math.min(this.othersWeight - weight, 0); - const othersCount = this.dialogData.others.length; + const weight = normalizePercent(this.form.value.weight); const availableWeight = MAX_PERCENT_WEIGHT - weight; - if (othersWeight === 0) { - return this.dialogData.others.map((c) => ({ - ...c, - weight: Math.round(availableWeight / othersCount), - })); - } - - return this.dialogData.others.map((c) => ({ + return this.dialogData.candidates.map((c) => ({ ...c, - weight: Math.round((c.weight / othersWeight) * availableWeight), + candidate: { + ...c.candidate, + weight: + c.idx === this.dialogData.idx + ? weight + : normalizePercent( + this.othersWeight === 0 + ? normalizePercent(availableWeight / this.otherCandidates.length) + : (c.candidate.weight / this.othersWeight) * availableWeight, + ), + }, })); } - private normalizeWeight(weight: unknown = this.form.value.weight): number { - return Math.max(Math.min(Number(weight || '0'), 100), 0); + private getPercentWeight( + weight: number = 0, + othersWeight: number = this.othersWeight || 0, + count: number = this.otherCandidates.length + 1, + ): number { + if (othersWeight === 0) { + if (weight === 0) return normalizePercent(MAX_PERCENT_WEIGHT / count); + return 100; + } + if (weight === 0) return 0; + const allWeight = weight + othersWeight; + return normalizePercent((weight / allWeight) * MAX_PERCENT_WEIGHT); } } From 7a0c6cfc6304d90a2b93bd12067a095aceca1e05 Mon Sep 17 00:00:00 2001 From: Rinat Arsaev <11846445+A77AY@users.noreply.github.com> Date: Mon, 16 Mar 2026 02:31:23 +0600 Subject: [PATCH 5/5] support weight type --- .../edit-candidate-dialog.component.html | 4 +- .../edit-candidate-dialog.component.ts | 57 ++++++++++++------- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.html b/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.html index a2131bb44..314968616 100644 --- a/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.html +++ b/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.html @@ -4,9 +4,9 @@
- {{ item.percent | number: '1.0-2' }}% + {{ item.percent }}
} diff --git a/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.ts b/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.ts index 0cb9f74f5..b23933171 100644 --- a/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.ts +++ b/src/app/parties/party/routing-rules/candidates/components/edit-candidate-dialog/edit-candidate-dialog.component.ts @@ -1,4 +1,4 @@ -import { map, shareReplay } from 'rxjs'; +import { combineLatest, map, shareReplay } from 'rxjs'; import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; @@ -71,21 +71,33 @@ export class EditCandidateDialogComponent extends DialogSuperclass< { label: 'Percent', value: 'weight_percent' }, ]; - weightsPreview$ = getValueChanges(this.form).pipe( - map(() => - this.getNewCandidates() - .sort((a, b) => - a.idx === this.dialogData.idx - ? -1 - : b.idx === this.dialogData.idx - ? 1 - : b.candidate.weight - a.candidate.weight, - ) - .map((c) => ({ + weightsPreview$ = combineLatest([ + getValueChanges(this.weightTypeControl), + getValueChanges(this.form), + ]).pipe( + map(([weightType]) => { + const newCandidates = this.getNewCandidates().sort((a, b) => + a.idx === this.dialogData.idx + ? -1 + : b.idx === this.dialogData.idx + ? 1 + : b.candidate.weight - a.candidate.weight, + ); + return newCandidates.map((c) => { + if (weightType === 'weight_percent') + return { + description: c.candidate.terminal.id, + percent: c.candidate.weight + '%', + }; + const allWeight = newCandidates.reduce((acc, c) => acc + c.candidate.weight, 0); + return { description: c.candidate.terminal.id, - percent: c.candidate.weight, - })), - ), + percent: + normalizePercent((c.candidate.weight / allWeight) * 100) + + `% (${c.candidate.weight})`, + }; + }); + }), shareReplay({ refCount: true, bufferSize: 1 }), ); @@ -98,10 +110,17 @@ export class EditCandidateDialogComponent extends DialogSuperclass< private getNewCandidates(): CandidateWithIdx[] { if (this.weightTypeControl.value === 'weight') { - return this.otherCandidates; + const weight = Number(this.form.value.weight) || 0; + return this.dialogData.candidates.map((c) => ({ + ...c, + candidate: { + ...c.candidate, + weight: c.idx === this.dialogData.idx ? weight : c.candidate.weight, + }, + })); } - const weight = normalizePercent(this.form.value.weight); - const availableWeight = MAX_PERCENT_WEIGHT - weight; + const percentWeight = normalizePercent(this.form.value.weight); + const availableWeight = MAX_PERCENT_WEIGHT - percentWeight; return this.dialogData.candidates.map((c) => ({ ...c, @@ -109,7 +128,7 @@ export class EditCandidateDialogComponent extends DialogSuperclass< ...c.candidate, weight: c.idx === this.dialogData.idx - ? weight + ? percentWeight : normalizePercent( this.othersWeight === 0 ? normalizePercent(availableWeight / this.otherCandidates.length)