diff --git a/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.html b/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.html index b620dcc60..bd616d952 100644 --- a/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.html +++ b/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.html @@ -118,7 +118,7 @@ -
+
+ - +
- - {{ data.tags[0].content }} - - - - {{ data.tags.length - 1 }} - + @if (data.tags.length === 0) { + - + } @else { + + {{ data.tags[0].content }} + + + + {{ data.tags.length - 1 }} + + }
diff --git a/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.scss b/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.scss index f740f45b2..f2fa16085 100644 --- a/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.scss +++ b/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.scss @@ -36,6 +36,14 @@ td:first-child { padding-left: 25px; } +::ng-deep tr:has(> td .locked) { + cursor: not-allowed; + + td { + color: var(--cds-text-on-color-disabled); + } +} + .valtimo-carbon-list { ::ng-deep &__header--hidden thead { display: none; @@ -94,7 +102,3 @@ td:first-child { } } } - -.disabled { - cursor: not-allowed; -} diff --git a/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.ts b/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.ts index 299cdc735..a4b59f8b2 100644 --- a/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.ts +++ b/projects/valtimo/components/src/lib/components/carbon-list/carbon-list.component.ts @@ -395,7 +395,7 @@ export class CarbonListComponent implements OnInit, AfterViewInit, OnDestroy { }); case ViewType.TAGS: return new TableItem({ - data: {tags: item.tags}, + data: {tags: item?.tags ?? []}, template: this.tagTemplate, }); default: diff --git a/projects/valtimo/components/src/lib/components/form-io/form-io.component.ts b/projects/valtimo/components/src/lib/components/form-io/form-io.component.ts index 358a4b8eb..3a70a121a 100644 --- a/projects/valtimo/components/src/lib/components/form-io/form-io.component.ts +++ b/projects/valtimo/components/src/lib/components/form-io/form-io.component.ts @@ -32,10 +32,9 @@ import { Formio, FormioComponent as FormIoSourceComponent, FormioOptions, + FormioRefreshValue, FormioSubmission, - FormioUtils, } from '@formio/angular'; -import {FormioRefreshValue} from '@formio/angular/formio.common'; import {jwtDecode} from 'jwt-decode'; import {NGXLogger} from 'ngx-logger'; import {BehaviorSubject, combineLatest, Observable, Subject, Subscription, timer} from 'rxjs'; @@ -43,6 +42,7 @@ import {distinctUntilChanged, map, switchMap, take, tap} from 'rxjs/operators'; import {FormIoStateService} from './services/form-io-state.service'; import {ActivatedRoute} from '@angular/router'; import {TranslateService} from '@ngx-translate/core'; +import {FormIoLocalStorageService} from './services/form-io-local-storage.service'; import {deepmerge} from 'deepmerge-ts'; import {ConfigService, ValtimoConfig} from '@valtimo/config'; @@ -50,6 +50,7 @@ import {ConfigService, ValtimoConfig} from '@valtimo/config'; selector: 'valtimo-form-io', templateUrl: './form-io.component.html', styleUrls: ['./form-io.component.css'], + providers: [FormIoLocalStorageService], }) export class FormioComponent implements OnInit, OnChanges, OnDestroy { @Input() set options(optionsValue: ValtimoFormioOptions) { @@ -73,7 +74,7 @@ export class FormioComponent implements OnInit, OnChanges, OnDestroy { @HostListener('window:beforeunload', ['$event']) private handleBeforeUnload() { - this.clearTokenFromLocalStorage(); + this.localStorageService.clearTokenFromLocalStorage(); } public refreshForm = new EventEmitter(); @@ -83,7 +84,6 @@ export class FormioComponent implements OnInit, OnChanges, OnDestroy { public readonly options$ = new BehaviorSubject(undefined); public readonly readOnly$ = new BehaviorSubject(false); public readonly errors$ = new BehaviorSubject>([]); - public readonly tokenSetInLocalStorage$ = new BehaviorSubject(false); public readonly currentLanguage$ = this.translateService.stream('key').pipe( map(() => this.translateService.currentLang), @@ -115,19 +115,20 @@ export class FormioComponent implements OnInit, OnChanges, OnDestroy { tap(options => this.logger.debug('Form.IO options used', options)) ); + public readonly tokenSetInLocalStorage$ = this.localStorageService.tokenSetInLocalStorage$; + private _tokenRefreshTimerSubscription!: Subscription; private _formRefreshSubscription!: Subscription; private readonly _subscriptions = new Subscription(); private readonly _tokenTimerSubscription = new Subscription(); - private readonly _FORMIO_TOKEN_LOCAL_STORAGE_KEY = 'formioToken'; - constructor( private readonly userProviderService: UserProviderService, private readonly logger: NGXLogger, private readonly stateService: FormIoStateService, private readonly route: ActivatedRoute, private readonly translateService: TranslateService, + private readonly localStorageService: FormIoLocalStorageService, private readonly modalService: ValtimoModalService, private readonly configService: ConfigService ) { @@ -157,7 +158,7 @@ export class FormioComponent implements OnInit, OnChanges, OnDestroy { this.unsubscribeFormRefresh(); this._tokenRefreshTimerSubscription?.unsubscribe(); this._subscriptions.unsubscribe(); - this.clearTokenFromLocalStorage(); + this.localStorageService.clearTokenFromLocalStorage(); } public showErrors(errors: string[]): void { @@ -218,9 +219,8 @@ export class FormioComponent implements OnInit, OnChanges, OnDestroy { private setToken(token: string): void { Formio.setUser(jwtDecode(token)); Formio.setToken(token); - localStorage.setItem(this._FORMIO_TOKEN_LOCAL_STORAGE_KEY, token); this.setTimerForTokenRefresh(token); - this.tokenSetInLocalStorage$.next(true); + this.localStorageService.setTokenInLocalStorage(token); this.logger.debug('New token set for form.io.'); } @@ -277,10 +277,6 @@ export class FormioComponent implements OnInit, OnChanges, OnDestroy { ); } - private clearTokenFromLocalStorage(): void { - localStorage.removeItem(this._FORMIO_TOKEN_LOCAL_STORAGE_KEY); - } - private setOverrideOptions(config: ValtimoConfig): void { if (!config.formioOptions) return; diff --git a/projects/valtimo/components/src/lib/components/form-io/services/form-io-local-storage.service.ts b/projects/valtimo/components/src/lib/components/form-io/services/form-io-local-storage.service.ts new file mode 100644 index 000000000..43a1afd85 --- /dev/null +++ b/projects/valtimo/components/src/lib/components/form-io/services/form-io-local-storage.service.ts @@ -0,0 +1,68 @@ +/* + * Copyright 2015-2024 Ritense BV, the Netherlands. + * + * Licensed under EUPL, Version 1.2 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {Injectable} from '@angular/core'; +import {BehaviorSubject, Observable} from 'rxjs'; + +@Injectable() +export class FormIoLocalStorageService { + private readonly _FORMIO_TOKEN_LOCAL_STORAGE_KEY = 'formioToken'; + private readonly _tokenSetInLocalStorage$ = new BehaviorSubject(false); + + public get tokenSetInLocalStorage$(): Observable { + return this._tokenSetInLocalStorage$.asObservable(); + } + + public setTokenInLocalStorage(token: string): void { + setTimeout(() => { + localStorage.setItem(this._FORMIO_TOKEN_LOCAL_STORAGE_KEY, token); + this.checkIfTokenExistsInLocalStorage(); + }); + } + + public clearTokenFromLocalStorage(): void { + localStorage.removeItem(this._FORMIO_TOKEN_LOCAL_STORAGE_KEY); + this.checkIfTokenIsRemovedFromLocalStorage(); + } + + private getTokenFromLocalStorage(): string | null { + return localStorage.getItem(this._FORMIO_TOKEN_LOCAL_STORAGE_KEY); + } + + private checkIfTokenExistsInLocalStorage(): void { + const maxChecks = 100; + let checks = 0; + + if (this.getTokenFromLocalStorage()) { + this._tokenSetInLocalStorage$.next(true); + } else if (checks <= maxChecks) { + checks++; + this.checkIfTokenExistsInLocalStorage(); + } + } + + private checkIfTokenIsRemovedFromLocalStorage(): void { + const maxChecks = 100; + let checks = 0; + + if (this.getTokenFromLocalStorage() && checks <= maxChecks) { + checks++; + this.checkIfTokenIsRemovedFromLocalStorage(); + } else { + this._tokenSetInLocalStorage$.next(false); + } + } +} diff --git a/projects/valtimo/components/src/lib/components/right-sidebar/right-sidebar.component.html b/projects/valtimo/components/src/lib/components/right-sidebar/right-sidebar.component.html index 48dc72b65..fa97d44f8 100644 --- a/projects/valtimo/components/src/lib/components/right-sidebar/right-sidebar.component.html +++ b/projects/valtimo/components/src/lib/components/right-sidebar/right-sidebar.component.html @@ -149,7 +149,9 @@ diff --git a/projects/valtimo/dossier-management/src/lib/components/dossier-management-detail-container-actions/dossier-management-detail-container-actions.component.html b/projects/valtimo/dossier-management/src/lib/components/dossier-management-detail-container-actions/dossier-management-detail-container-actions.component.html index c31383583..62634fb3e 100644 --- a/projects/valtimo/dossier-management/src/lib/components/dossier-management-detail-container-actions/dossier-management-detail-container-actions.component.html +++ b/projects/valtimo/dossier-management/src/lib/components/dossier-management-detail-container-actions/dossier-management-detail-container-actions.component.html @@ -56,6 +56,7 @@ class="overflow-button" > {{ @@ -65,6 +66,7 @@ {{ 'Remove document definition' | translate }} {{ 'dossierManagement.statuses.columns.color' | translate }} { @@ -81,18 +81,16 @@ export class DossierManagementStatusModalComponent implements OnInit, OnDestroy @Output() public closeModalEvent = new EventEmitter(); - private readonly _type = new BehaviorSubject(undefined); + private readonly _type$ = new BehaviorSubject(undefined); private readonly _typeAnimationDelay$ = new BehaviorSubject(undefined); private readonly _prefillStatus = new BehaviorSubject(undefined); - public readonly isClosed$ = this._type.pipe(map(type => type === 'closed')); - public readonly statusFormGroup = this.fb.group({ title: this.fb.control('', Validators.required), key: this.fb.control('', [ Validators.required, Validators.minLength(3), - this.uniqueKeyValidator(), + this.uniqueKeyValidator, ]), visibleInCaseListByDefault: this.fb.control(true, Validators.required), color: this.fb.control('', Validators.required), @@ -112,6 +110,8 @@ export class DossierManagementStatusModalComponent implements OnInit, OnDestroy }) ); + public readonly isClosed$ = this._type$.pipe(map(type => type === 'closed')); + public readonly disabled$ = new BehaviorSubject(false); private readonly COLORS: InternalCaseStatusColor[] = [ @@ -345,11 +345,15 @@ export class DossierManagementStatusModalComponent implements OnInit, OnDestroy this.statusFormGroup.patchValue({key: ''}); } - private uniqueKeyValidator(): ValidatorFn { - return (control: AbstractControl): ValidationErrors | null => - this.usedKeys?.every((key: string) => key !== control.value) - ? null - : {uniqueKey: {value: control.value}}; + private uniqueKeyValidator(): AsyncValidatorFn { + return (control: AbstractControl): Observable => + combineLatest([this.isEdit$, control.valueChanges]).pipe( + map(([isEdit, keyValue]) => + this.usedKeys?.every((key: string) => key !== keyValue) || isEdit + ? null + : {uniqueKey: {value: control.value}} + ) + ); } private disable(): void { diff --git a/projects/valtimo/dossier/src/lib/components/dossier-detail/dossier-detail.component.html b/projects/valtimo/dossier/src/lib/components/dossier-detail/dossier-detail.component.html index 5b3b46c13..1dc4e6f0b 100644 --- a/projects/valtimo/dossier/src/lib/components/dossier-detail/dossier-detail.component.html +++ b/projects/valtimo/dossier/src/lib/components/dossier-detail/dossier-detail.component.html @@ -61,7 +61,7 @@ let-document="document" let-canAssign="canAssign" > -
+
@@ -91,10 +91,6 @@ > - -
{{ documentDefinitionNameTitle?.trim() }}
-
- -
- +
+ @if (obs.caseStatus) { + {{ obs.caseStatus.title }} + } + +
+ +
+ +
+
-
- {{ caseStatus.title }} -
diff --git a/projects/valtimo/dossier/src/lib/components/dossier-detail/dossier-detail.component.scss b/projects/valtimo/dossier/src/lib/components/dossier-detail/dossier-detail.component.scss index ea86e913a..2a90375f0 100644 --- a/projects/valtimo/dossier/src/lib/components/dossier-detail/dossier-detail.component.scss +++ b/projects/valtimo/dossier/src/lib/components/dossier-detail/dossier-detail.component.scss @@ -65,9 +65,11 @@ width: 100%; justify-content: space-between; align-items: flex-end; + padding-bottom: 4px; &.--compact { - align-items: center; + padding-bottom: 0; + align-items: flex-start; } ::ng-deep .version-selection { @@ -79,11 +81,17 @@ } } -.dossier-assign-user { - padding-bottom: 4px; - margin-left: -16px; +.dossier-status-assign-custom-title { + display: flex; + gap: 16px; + align-items: flex-end; + + .cds--tag { + margin: 0; + height: var(--cds-layout-size-height-md); + } &.--compact { - margin-left: 0; + align-items: center; } } diff --git a/projects/valtimo/dossier/src/lib/components/dossier-list/dossier-list.component.ts b/projects/valtimo/dossier/src/lib/components/dossier-list/dossier-list.component.ts index e1be4764c..e4c703d0c 100644 --- a/projects/valtimo/dossier/src/lib/components/dossier-list/dossier-list.component.ts +++ b/projects/valtimo/dossier/src/lib/components/dossier-list/dossier-list.component.ts @@ -45,7 +45,6 @@ import { Documents, DocumentService, InternalCaseStatus, - InternalCaseStatusColor, InternalCaseStatusUtils, SpecifiedDocuments, } from '@valtimo/document'; @@ -432,7 +431,8 @@ export class DossierListComponent implements OnInit, OnDestroy { return res.data.map(item => { const status = res.statuses.find( - (status: InternalCaseStatus) => status.key === item.internalStatus + (status: InternalCaseStatus) => + status.key === item.internalStatus || status.key === item.status ); if (!status) return item; diff --git a/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.html b/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.html index 9a19ac8c4..771e358b8 100644 --- a/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.html +++ b/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.html @@ -24,44 +24,53 @@ @if (obs.formDefinition) { -
- - - {{ 'Download' | translate }} - +
+ @if (obs.formDefinition.readOnly) { + {{ 'formManagement.readOnly' | translate }} + } - - {{ 'Upload' | translate }} - +
+ + + {{ 'Download' | translate }} + - - {{ 'interface.delete' | translate }} - + + {{ 'Upload' | translate }} + - - {{ 'formManagement.duplicate' | translate }} - - + + {{ 'interface.delete' | translate }} + - + + +
diff --git a/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.scss b/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.scss index 787d46752..80faa63e6 100644 --- a/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.scss +++ b/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.scss @@ -20,6 +20,25 @@ align-items: center; justify-content: flex-end; gap: 16px; + margin-left: auto; + } + + &__header-container { + width: 100%; + display: flex; + justify-content: space-between; + align-items: flex-end; + padding-bottom: 4px; + + .cds--tag { + margin: 0; + height: var(--cds-layout-size-height-md); + } + + &.--compact { + align-items: flex-start; + padding-bottom: 0; + } } &__output .cds--tab-content { diff --git a/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.ts b/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.ts index c0225ebf8..771f42014 100644 --- a/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.ts +++ b/projects/valtimo/form-management/src/lib/form-management-edit/form-management-edit.component.ts @@ -29,7 +29,6 @@ import { BehaviorSubject, distinctUntilChanged, filter, - first, Subscription, switchMap, take, @@ -60,6 +59,9 @@ export class FormManagementEditComponent public activeTab = EDIT_TABS.BUILDER; private readonly _formDefinition$ = new BehaviorSubject(null); + private get _formDefinition(): FormDefinition { + return this._formDefinition$.getValue(); + } public readonly formDefinition$ = this._formDefinition$.pipe( filter((definition: FormDefinition | null) => !!definition), distinctUntilChanged( @@ -117,7 +119,7 @@ export class FormManagementEditComponent } this._changeActive = true; this.modifiedFormDefinition = event.form; - this._formDefinition$.next(event.form); + this._formDefinition$.next({...this._formDefinition, formDefinition: event.form}); this.jsonFormDefinition$.next({...definition, value: JSON.stringify(event.form)}); this._changeActive = false; } @@ -201,9 +203,13 @@ export class FormManagementEditComponent return; } + const parsedDefinition = JSON.parse(value); + + this.modifiedFormDefinition = parsedDefinition; + this._formDefinition$.next({ ...definition, - formDefinition: JSON.parse(value), + formDefinition: parsedDefinition, }); } diff --git a/projects/valtimo/form-management/src/lib/form-management.module.ts b/projects/valtimo/form-management/src/lib/form-management.module.ts index 42a9ba365..be566d224 100644 --- a/projects/valtimo/form-management/src/lib/form-management.module.ts +++ b/projects/valtimo/form-management/src/lib/form-management.module.ts @@ -18,23 +18,22 @@ import {NgModule} from '@angular/core'; import {FormManagementComponent} from './form-management.component'; import {FormManagementRoutingModule} from './form-management-routing.module'; import { + ButtonModule, + CarbonListModule, + ConfirmationModalModule, DropzoneModule, + EditorModule, FormIoModule, - ListModule, - ModalModule as vcModalModule, - ValtimoCdsModalDirectiveModule, - WidgetModule, - ButtonModule, FormModule, InputModule as vInputModule, - VModalModule, - TitleModule, - CarbonListModule, - PageTitleModule, + ListModule, + ModalModule as vcModalModule, RenderInPageHeaderDirectiveModule, - EditorModule, SpinnerModule, - ConfirmationModalModule, + TitleModule, + ValtimoCdsModalDirectiveModule, + VModalModule, + WidgetModule, } from '@valtimo/components'; import {CommonModule} from '@angular/common'; import {FormsModule, ReactiveFormsModule} from '@angular/forms'; @@ -52,6 +51,7 @@ import { ModalModule, PlaceholderModule, TabsModule, + TagModule, } from 'carbon-components-angular'; @NgModule({ @@ -94,6 +94,7 @@ import { SpinnerModule, IconModule, ConfirmationModalModule, + TagModule, ], exports: [FormManagementComponent], }) diff --git a/projects/valtimo/object/src/lib/components/object-list/object-list.component.ts b/projects/valtimo/object/src/lib/components/object-list/object-list.component.ts index 3135db804..79b1aa161 100644 --- a/projects/valtimo/object/src/lib/components/object-list/object-list.component.ts +++ b/projects/valtimo/object/src/lib/components/object-list/object-list.component.ts @@ -54,8 +54,7 @@ export class ObjectListComponent { readonly objectManagementId$: Observable = this.route.params.pipe( map(params => params.objectManagementId), tap(objectManagementId => { - if (!this._settingPageTitle && objectManagementId) { - this._settingPageTitle = true; + if (objectManagementId) { this.objectManagementService.getObjectById(objectManagementId).subscribe(objectType => { if (objectType.title) { this.pageTitleService.setCustomPageTitle(objectType.title); @@ -234,8 +233,6 @@ export class ObjectListComponent { }) ); - private _settingPageTitle = false; - constructor( private readonly objectService: ObjectService, private readonly objectColumnService: ObjectColumnService, diff --git a/projects/valtimo/task/src/lib/services/task-list-pagination.service.ts b/projects/valtimo/task/src/lib/services/task-list-pagination.service.ts index 2ed1a101b..12eda6ff9 100644 --- a/projects/valtimo/task/src/lib/services/task-list-pagination.service.ts +++ b/projects/valtimo/task/src/lib/services/task-list-pagination.service.ts @@ -40,7 +40,7 @@ export class TaskListPaginationService { public get paginationForCurrentTaskTypeForList$(): Observable { return this._paginationForCurrentTaskType$.pipe( - map(pagination => ({...pagination, page: pagination.page + 1})) + map(pagination => ({...pagination, page: pagination?.page + 1 || 1})) ); } diff --git a/projects/valtimo/zgw/src/lib/zgw.module.ts b/projects/valtimo/zgw/src/lib/zgw.module.ts index a7aaaa8c9..1e40e00c9 100644 --- a/projects/valtimo/zgw/src/lib/zgw.module.ts +++ b/projects/valtimo/zgw/src/lib/zgw.module.ts @@ -26,7 +26,6 @@ import { ZakenApiZaaktypeLinkComponent, } from './modules'; import { - CASE_MANAGEMENT_TAB_TOKEN, ZGW_CASE_CONFIGURATION_EXTENSIONS_TOKEN, ZGW_DOCUMENTEN_API_DOCUMENTS_COMPONENT_TOKEN, ZGW_OBJECT_TYPE_COMPONENT_TOKEN, @@ -38,7 +37,6 @@ import {RouterModule} from '@angular/router'; import {DropzoneModule, FileSizeModule} from '@valtimo/components'; import {DocumentModule} from '@valtimo/document'; import {ResourceModule} from '@valtimo/resource'; -import {DossierManagementZgwComponent} from './components'; @NgModule({ imports: [ @@ -56,14 +54,6 @@ import {DossierManagementZgwComponent} from './components'; declarations: [DocumentenApiUploaderComponent], exports: [DocumentenApiUploaderComponent], providers: [ - { - provide: CASE_MANAGEMENT_TAB_TOKEN, - useValue: { - translationKey: 'zgw.zgwTab', - component: DossierManagementZgwComponent, - }, - multi: true, - }, { provide: ZGW_OBJECT_TYPE_COMPONENT_TOKEN, useValue: DossierDetailTabObjectTypeComponent, diff --git a/scripts/equalize-deps.cjs b/scripts/equalize-deps.cjs index 161b39e0f..302be5643 100644 --- a/scripts/equalize-deps.cjs +++ b/scripts/equalize-deps.cjs @@ -89,7 +89,7 @@ const cleanUp = () => { const fetchDeps = () => http.get( // update link to raw Github content of latest major package.json - 'https://raw.githubusercontent.com/valtimo-platform/valtimo-frontend-libraries/development/12.0.0/package.json', + 'https://raw.githubusercontent.com/valtimo-platform/valtimo-frontend-libraries/rc/12.0.0/package.json', function (response) { response.pipe(file);