Compare commits

...

11 Commits

Author SHA1 Message Date
dependabot[bot]
65f6e8f4de
build(deps-dev): bump vite from 5.4.18 to 5.4.19 (#10851)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.18 to 5.4.19.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.19/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.19/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 5.4.19
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-12 11:36:55 -04:00
Soumyajit Chakraborty
ec47d8eac8
AAE-34869 fixing padding issue (#10850) 2025-05-12 20:19:47 +05:30
dependabot[bot]
ca6e3969d8
build(deps): bump slackapi/slack-github-action from 2.0.0 to 2.1.0 (#10848)
Bumps [slackapi/slack-github-action](https://github.com/slackapi/slack-github-action) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/slackapi/slack-github-action/releases)
- [Commits](485a9d42d3...b0fa283ad8)

---
updated-dependencies:
- dependency-name: slackapi/slack-github-action
  dependency-version: 2.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-12 10:21:28 -04:00
dependabot[bot]
b4e8e4943a
build(deps): bump zgosalvez/github-actions-ensure-sha-pinned-actions (#10849)
Bumps [zgosalvez/github-actions-ensure-sha-pinned-actions](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions) from 3.0.23 to 3.0.24.
- [Release notes](https://github.com/zgosalvez/github-actions-ensure-sha-pinned-actions/releases)
- [Commits](4830be28ce...2d6823da40)

---
updated-dependencies:
- dependency-name: zgosalvez/github-actions-ensure-sha-pinned-actions
  dependency-version: 3.0.24
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-12 10:20:40 -04:00
dependabot[bot]
71b8dae86d
build(deps): bump Alfresco/alfresco-build-tools (#10837)
Bumps [Alfresco/alfresco-build-tools](https://github.com/alfresco/alfresco-build-tools) from 8.18.3 to 8.20.0.
- [Release notes](https://github.com/alfresco/alfresco-build-tools/releases)
- [Commits](247f59bac1...8cd8c3798c)

---
updated-dependencies:
- dependency-name: Alfresco/alfresco-build-tools
  dependency-version: 8.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-12 10:18:33 -04:00
dependabot[bot]
84e5a0fa4b
build(deps): bump github/codeql-action from 3.28.16 to 3.28.17 (#10838)
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.16 to 3.28.17.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](28deaeda66...60168efe1c)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.28.17
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-12 10:18:11 -04:00
Ewelina Dikta
f2845a36c6
[AAE-29434] Adding process with process variables to simpleapp (#10845) 2025-05-12 09:03:50 +02:00
Soumyajit Chakraborty
acf9e3e11c
Improvement/aae 30909 enhance user experience with tab navigation within the form (#10844)
* AAE-30909 tab-header fixed at the top

* AAE-30909 fixing widh and scrolling issues in workspace and studio-hxp
2025-05-08 19:23:30 +05:30
Soumyajit Chakraborty
adeb82c137
AAE-34335 fix for styling discrepancies in form-widgets (#10841) 2025-05-06 18:33:28 +05:30
Wojciech Duda
48defa2b5f
AAE-34594 Remove redundant scroll bar from form renderer (#10840) 2025-05-06 10:19:09 +01:00
Robert Duda
9ee0e5ee3e
AAE-19688 Persist feature flag overrides in session storage (#10832)
* AAE-19688 Persist feature flag overrides in session storage

* unit tests
2025-04-30 16:59:50 +02:00
17 changed files with 226 additions and 138 deletions

View File

@ -26,7 +26,7 @@ runs:
cache-dependency-path: package-lock.json cache-dependency-path: package-lock.json
- name: get latest tag sha - name: get latest tag sha
id: tag-sha id: tag-sha
uses: Alfresco/alfresco-build-tools/.github/actions/git-latest-tag@247f59bac145315d38078f8954c763e0db57d5f1 # v8.18.3 uses: Alfresco/alfresco-build-tools/.github/actions/git-latest-tag@8cd8c3798c79d10540e2876ad7cf2a5311cbd1ae # v8.20.0
# CACHE # CACHE
- name: Node Modules cache - name: Node Modules cache
id: node-modules-cache id: node-modules-cache

View File

@ -30,7 +30,7 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 uses: github/codeql-action/init@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
# Override language selection by uncommenting this and choosing your languages # Override language selection by uncommenting this and choosing your languages
with: with:
languages: javascript languages: javascript
@ -39,7 +39,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 uses: github/codeql-action/autobuild@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@ -53,4 +53,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@28deaeda66b76a05916b6923827895f2b14ab387 # v3.28.16 uses: github/codeql-action/analyze@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17

View File

@ -64,7 +64,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Ensure SHA pinned actions - name: Ensure SHA pinned actions
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@4830be28ce81da52ec70d65c552a7403821d98d4 # v3.0.23 uses: zgosalvez/github-actions-ensure-sha-pinned-actions@2d6823da4039243036c86d76f503c84e2ded2517 # v3.0.24
- name: Check package-lock.json version - name: Check package-lock.json version
run: | run: |
@ -277,7 +277,7 @@ jobs:
uses: ./.github/actions/slack-group-area uses: ./.github/actions/slack-group-area
with: with:
affected: ${{ steps.e2e-result.outputs.result }} affected: ${{ steps.e2e-result.outputs.result }}
- uses: slackapi/slack-github-action@485a9d42d3a73031f12ec201c457e2162c45d02d # v2.0.0 - uses: slackapi/slack-github-action@b0fa283ad8fea605de13dc3f449259339835fc52 # v2.1.0
name: Nofify QA failure name: Nofify QA failure
if: ${{ github.event_name == 'schedule' && contains(needs.*.result, 'failure') }} if: ${{ github.event_name == 'schedule' && contains(needs.*.result, 'failure') }}
env: env:

View File

@ -229,7 +229,7 @@ jobs:
needs: [release-storybook, release-npm, npm-check-bundle] needs: [release-storybook, release-npm, npm-check-bundle]
steps: steps:
- uses: slackapi/slack-github-action@485a9d42d3a73031f12ec201c457e2162c45d02d # v2.0.0 - uses: slackapi/slack-github-action@b0fa283ad8fea605de13dc3f449259339835fc52 # v2.1.0
name: Nofify FE eng-guild-front-end workflow failed name: Nofify FE eng-guild-front-end workflow failed
if: ${{ contains(toJson(needs.*.result), 'failure') }} if: ${{ contains(toJson(needs.*.result), 'failure') }}
env: env:

View File

@ -17,37 +17,37 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { DebugFeaturesService } from './debug-features.service'; import { DebugFeaturesService } from './debug-features.service';
import { StorageService } from '../../../../src/lib/common/services/storage.service'; import { OverridableFeaturesServiceToken, WritableFeaturesServiceConfigToken, WritableFeaturesServiceToken } from '../interfaces/features.interface';
import { OverridableFeaturesServiceToken, WritableFeaturesServiceToken } from '../interfaces/features.interface';
import { DummyFeaturesService } from './dummy-features.service'; import { DummyFeaturesService } from './dummy-features.service';
import { StorageFeaturesService } from './storage-features.service'; import { StorageFeaturesService } from './storage-features.service';
import { take } from 'rxjs/operators'; import { take } from 'rxjs/operators';
describe('DebugFeaturesService', () => { describe('DebugFeaturesService', () => {
let service: DebugFeaturesService; let service: DebugFeaturesService;
const mockStorage = { let mockStorageKey: string;
getItem: () => let mockStorage;
JSON.stringify({
feature1: {
current: true
},
feature2: {
current: false,
fictive: true
}
}),
setItem: () => {}
};
beforeEach(() => { beforeEach(() => {
mockStorageKey = 'storage-key-test';
mockStorage = { [mockStorageKey]: true };
TestBed.configureTestingModule({ TestBed.configureTestingModule({
providers: [ providers: [
DebugFeaturesService, DebugFeaturesService,
{ provide: StorageService, useValue: mockStorage }, {
provide: WritableFeaturesServiceConfigToken,
useValue: { storageKey: mockStorageKey }
},
{ provide: WritableFeaturesServiceToken, useClass: StorageFeaturesService }, { provide: WritableFeaturesServiceToken, useClass: StorageFeaturesService },
{ provide: OverridableFeaturesServiceToken, useClass: DummyFeaturesService } { provide: OverridableFeaturesServiceToken, useClass: DummyFeaturesService }
] ]
}); });
spyOn(sessionStorage, 'getItem').and.callFake((key) => JSON.stringify(mockStorage[key]));
spyOn(sessionStorage, 'setItem').and.callFake((key, value) => {
mockStorage[key] = value;
});
service = TestBed.inject(DebugFeaturesService); service = TestBed.inject(DebugFeaturesService);
}); });

View File

@ -16,8 +16,8 @@
*/ */
import { Inject, Injectable, Optional } from '@angular/core'; import { Inject, Injectable, Optional } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs'; import { BehaviorSubject, Observable, combineLatest } from 'rxjs';
import { skip, switchMap } from 'rxjs/operators'; import { filter, switchMap } from 'rxjs/operators';
import { import {
IDebugFeaturesService, IDebugFeaturesService,
IFeaturesService, IFeaturesService,
@ -29,12 +29,12 @@ import {
FlagSet, FlagSet,
IWritableFeaturesService IWritableFeaturesService
} from '../interfaces/features.interface'; } from '../interfaces/features.interface';
import { StorageService } from '@alfresco/adf-core';
@Injectable() @Injectable()
export class DebugFeaturesService implements IDebugFeaturesService { export class DebugFeaturesService implements IDebugFeaturesService {
private isInDebugMode: BehaviorSubject<boolean>; private readonly isInDebugModeSubject = new BehaviorSubject<boolean>(false);
private isInDebugMode$: Observable<boolean>; private readonly isInDebugMode$ = this.isInDebugModeSubject.asObservable();
private readonly initSubject = new BehaviorSubject<boolean>(false);
get storageKey(): string { get storageKey(): string {
return `${this.config?.storageKey || 'feature-flags'}-override`; return `${this.config?.storageKey || 'feature-flags'}-override`;
@ -43,14 +43,15 @@ export class DebugFeaturesService implements IDebugFeaturesService {
constructor( constructor(
@Inject(OverridableFeaturesServiceToken) private overriddenFeaturesService: IFeaturesService, @Inject(OverridableFeaturesServiceToken) private overriddenFeaturesService: IFeaturesService,
@Inject(WritableFeaturesServiceToken) private writableFeaturesService: IFeaturesService & IWritableFeaturesService, @Inject(WritableFeaturesServiceToken) private writableFeaturesService: IFeaturesService & IWritableFeaturesService,
private storageService: StorageService,
@Optional() @Inject(WritableFeaturesServiceConfigToken) private config?: WritableFeaturesServiceConfig @Optional() @Inject(WritableFeaturesServiceConfigToken) private config?: WritableFeaturesServiceConfig
) { ) {
this.isInDebugMode = new BehaviorSubject<boolean>(JSON.parse(this.storageService.getItem(this.storageKey) || 'false')); this.init();
this.isInDebugMode$ = this.isInDebugMode.asObservable();
this.isInDebugMode.pipe(skip(1)).subscribe((debugMode) => { combineLatest({
this.storageService.setItem(this.storageKey, JSON.stringify(debugMode)); debugMode: this.isInDebugModeSubject,
init: this.waitForInitializationToFinish()
}).subscribe(({ debugMode }) => {
sessionStorage.setItem(this.storageKey, JSON.stringify(debugMode));
}); });
} }
@ -87,10 +88,20 @@ export class DebugFeaturesService implements IDebugFeaturesService {
} }
enable(on: boolean): void { enable(on: boolean): void {
this.isInDebugMode.next(on); this.isInDebugModeSubject.next(on);
} }
isEnabled$(): Observable<boolean> { isEnabled$(): Observable<boolean> {
return this.isInDebugMode$; return this.isInDebugMode$;
} }
private init() {
const storedOverride = JSON.parse(sessionStorage.getItem(this.storageKey) || 'false');
this.isInDebugModeSubject.next(storedOverride);
this.initSubject.next(true);
}
private waitForInitializationToFinish(): Observable<boolean> {
return this.initSubject.pipe(filter((initialized) => !!initialized));
}
} }

View File

@ -17,17 +17,20 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { StorageFeaturesService } from './storage-features.service'; import { StorageFeaturesService } from './storage-features.service';
import { StorageService } from '../../../../src/public-api';
import { FlagSet, WritableFeaturesServiceConfigToken } from '../interfaces/features.interface'; import { FlagSet, WritableFeaturesServiceConfigToken } from '../interfaces/features.interface';
import { skip, take } from 'rxjs/operators'; import { skip, take } from 'rxjs/operators';
describe('StorageFeaturesService', () => { describe('StorageFeaturesService', () => {
let storageFeaturesService: StorageFeaturesService; let storageFeaturesService: StorageFeaturesService;
describe('if flags are present in LocalStorage', () => { describe('if flags are present in sessionStorage', () => {
const mockStorage = { let mockStorageKey: string;
getItem: () => let mockStorage;
JSON.stringify({
beforeEach(() => {
mockStorageKey = 'storage-key-test';
mockStorage = {
[mockStorageKey]: {
feature1: { feature1: {
current: true current: true
}, },
@ -35,23 +38,23 @@ describe('StorageFeaturesService', () => {
current: false, current: false,
fictive: true fictive: true
} }
}), }
setItem: () => {}
}; };
beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
providers: [ providers: [
{ provide: StorageService, useValue: mockStorage },
{ {
provide: WritableFeaturesServiceConfigToken, provide: WritableFeaturesServiceConfigToken,
useValue: { useValue: { storageKey: mockStorageKey }
storageKey: 'storage-key-test'
}
} }
] ]
}); });
spyOn(sessionStorage, 'getItem').and.callFake((key) => JSON.stringify(mockStorage[key]));
spyOn(sessionStorage, 'setItem').and.callFake((key, value) => {
mockStorage[key] = value;
});
storageFeaturesService = TestBed.inject(StorageFeaturesService); storageFeaturesService = TestBed.inject(StorageFeaturesService);
storageFeaturesService.init(); storageFeaturesService.init();
}); });

View File

@ -16,8 +16,8 @@
*/ */
import { Inject, Injectable, Optional } from '@angular/core'; import { Inject, Injectable, Optional } from '@angular/core';
import { BehaviorSubject, Observable, of } from 'rxjs'; import { BehaviorSubject, combineLatest, Observable, of } from 'rxjs';
import { map, skip } from 'rxjs/operators'; import { filter, map } from 'rxjs/operators';
import { import {
FlagChangeset, FlagChangeset,
IFeaturesService, IFeaturesService,
@ -28,21 +28,21 @@ import {
WritableFeaturesServiceConfig WritableFeaturesServiceConfig
} from '../interfaces/features.interface'; } from '../interfaces/features.interface';
import { FlagSetParser } from './flagset.parser'; import { FlagSetParser } from './flagset.parser';
import { StorageService } from '@alfresco/adf-core';
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
export class StorageFeaturesService implements IFeaturesService, IWritableFeaturesService { export class StorageFeaturesService implements IFeaturesService, IWritableFeaturesService {
private currentFlagState: WritableFlagChangeset = {}; private currentFlagState: WritableFlagChangeset = {};
private flags = new BehaviorSubject<WritableFlagChangeset>({}); private readonly flags = new BehaviorSubject<WritableFlagChangeset>({});
private flags$ = this.flags.asObservable(); private readonly flags$ = this.flags.asObservable();
private readonly initSubject = new BehaviorSubject<boolean>(false);
constructor( constructor(@Optional() @Inject(WritableFeaturesServiceConfigToken) private config?: WritableFeaturesServiceConfig) {
private storageService: StorageService, combineLatest({
@Optional() @Inject(WritableFeaturesServiceConfigToken) private config?: WritableFeaturesServiceConfig flags: this.flags,
) { init: this.waitForInitializationToFinish()
this.flags.pipe(skip(1)).subscribe((flags) => { }).subscribe(({ flags }) => {
this.currentFlagState = flags; this.currentFlagState = flags;
this.storageService.setItem(this.storageKey, JSON.stringify(FlagSetParser.serialize(flags))); sessionStorage.setItem(this.storageKey, JSON.stringify(FlagSetParser.serialize(flags)));
}); });
} }
@ -51,9 +51,10 @@ export class StorageFeaturesService implements IFeaturesService, IWritableFeatur
} }
init(): Observable<WritableFlagChangeset> { init(): Observable<WritableFlagChangeset> {
const storedFlags = JSON.parse(this.storageService.getItem(this.storageKey) || '{}'); const storedFlags = JSON.parse(sessionStorage.getItem(this.storageKey) || '{}');
const initialFlagChangeSet = FlagSetParser.deserialize(storedFlags); const initialFlagChangeSet = FlagSetParser.deserialize(storedFlags);
this.flags.next(initialFlagChangeSet); this.flags.next(initialFlagChangeSet);
this.initSubject.next(true);
return of(initialFlagChangeSet); return of(initialFlagChangeSet);
} }
@ -133,4 +134,8 @@ export class StorageFeaturesService implements IFeaturesService, IWritableFeatur
this.flags.next(mergedFlags); this.flags.next(mergedFlags);
} }
private waitForInitializationToFinish(): Observable<boolean> {
return this.initSubject.pipe(filter((initialized) => !!initialized));
}
} }

View File

@ -78,6 +78,7 @@ describe('DateFnsUtils', () => {
it('should parse alternative ISO datetime', () => { it('should parse alternative ISO datetime', () => {
const result = DateFnsUtils.parseDate('1982-03-13T10:00:000Z', `yyyy-MM-dd'T'HH:mm:sssXXX`); const result = DateFnsUtils.parseDate('1982-03-13T10:00:000Z', `yyyy-MM-dd'T'HH:mm:sssXXX`);
expect(result.toISOString()).toBe('1982-03-13T10:00:00.000Z'); expect(result.toISOString()).toBe('1982-03-13T10:00:00.000Z');
}); });

View File

@ -4,7 +4,9 @@
<div *ngIf="hasTabs()" class="alfresco-tabs-widget"> <div *ngIf="hasTabs()" class="alfresco-tabs-widget">
<mat-tab-group> <mat-tab-group>
<mat-tab *ngFor="let tab of visibleTabs()" [label]="tab.title | translate "> <mat-tab *ngFor="let tab of visibleTabs()" [label]="tab.title | translate ">
<div class="adf-form-tab-content">
<ng-template *ngTemplateOutlet="render; context: { fieldToRender: tab.fields }" /> <ng-template *ngTemplateOutlet="render; context: { fieldToRender: tab.fields }" />
</div>
</mat-tab> </mat-tab>
</mat-tab-group> </mat-tab-group>
</div> </div>

View File

@ -13,6 +13,40 @@
height: 100%; height: 100%;
} }
.alfresco-tabs-widget {
width: 100%;
position: absolute;
.adf-form-tab-group {
width: 100%;
z-index: 9999;
}
#{ms.$mat-tab-body} {
margin-bottom: 8em;
}
#{ms.$mat-tab-header} {
z-index: 10;
margin: 0;
background-color: white;
position: sticky;
/* stylelint-disable-next-line value-no-vendor-prefix */
position: -webkit-sticky; /* macOS/iOS Safari */
/* stylelint-disable-next-line declaration-no-important */
margin-left: 0 !important;
top: 0;
}
#{ms.$mat-tab-body-wrapper} {
padding-top: 16px;
}
}
.mat-mdc-card-content:first-child {
padding-top: 1em;
}
.adf-container-widget { .adf-container-widget {
.adf-grid-list { .adf-grid-list {
display: grid; display: grid;
@ -24,6 +58,7 @@
display: flex; display: flex;
margin-right: -1%; margin-right: -1%;
width: 100%;
&-item { &-item {
width: 100%; width: 100%;
@ -115,12 +150,18 @@
overflow: hidden; overflow: hidden;
} }
& #{ms.$mat-tab-header} {
position: fixed;
z-index: 1000;
}
& #{ms.$mat-card-header-text} { & #{ms.$mat-card-header-text} {
margin: 0; margin: 0;
} }
& #{ms.$mat-tab-body-content} { & #{ms.$mat-tab-body-content} {
overflow: hidden; overflow: hidden;
padding-top: 0;
} }
& #{mat-tab-label-text} { & #{mat-tab-label-text} {

View File

@ -6,8 +6,11 @@ $mat-tab-label-active: '.mdc-tab--active';
$mat-tab-label-container: '.mat-mdc-tab-label-container'; $mat-tab-label-container: '.mat-mdc-tab-label-container';
$mat-tab-label-text: '.mdc-tab__text-label'; $mat-tab-label-text: '.mdc-tab__text-label';
$mat-tab-body: '.mat-mdc-tab-body'; $mat-tab-body: '.mat-mdc-tab-body';
$mat-tab-header: '.mat-mdc-tab-header';
$mat-tab-body-content: '.mat-mdc-tab-body-content'; $mat-tab-body-content: '.mat-mdc-tab-body-content';
$mat-tab-ink-bar: '.mdc-tab-indicator'; $mat-tab-ink-bar: '.mdc-tab-indicator';
$mat-tab-body-wrapper: '.mat-mdc-tab-body-wrapper';
$mat-tab-body-content: '.mat-mdc-card-content';
$mat-chip: '.mat-mdc-chip'; $mat-chip: '.mat-mdc-chip';
$mat-chip-list: '.mat-mdc-chip-list'; $mat-chip-list: '.mat-mdc-chip-list';
$mat-checkbox: '.mat-mdc-checkbox'; $mat-checkbox: '.mat-mdc-checkbox';

View File

@ -5,11 +5,9 @@
<div <div
*ngIf="hasForm()" *ngIf="hasForm()"
class="adf-cloud-form-container adf-cloud-form-{{ displayConfiguration?.options?.fullscreen ? 'fullscreen' : 'inline' }}-container" class="adf-cloud-form-container adf-cloud-form-{{ displayConfiguration?.options?.fullscreen ? 'fullscreen' : 'inline' }}-container"
[style]="formStyle"> [style]="formStyle"
<div class="adf-cloud-form-content" >
[cdkTrapFocus]="displayConfiguration?.options?.trapFocus" <div class="adf-cloud-form-content" [cdkTrapFocus]="displayConfiguration?.options?.trapFocus" cdkTrapFocusAutoCapture>
cdkTrapFocusAutoCapture>
<adf-toolbar class="adf-cloud-form-toolbar" *ngIf="displayConfiguration?.options?.displayToolbar"> <adf-toolbar class="adf-cloud-form-toolbar" *ngIf="displayConfiguration?.options?.displayToolbar">
<div class="adf-cloud-form__form-title"> <div class="adf-cloud-form__form-title">
<span class="adf-cloud-form__display-name" [title]="form.taskName"> <span class="adf-cloud-form__display-name" [title]="form.taskName">
@ -30,7 +28,8 @@
[title]="'ADF_VIEWER.ACTIONS.CLOSE' | translate" [title]="'ADF_VIEWER.ACTIONS.CLOSE' | translate"
mat-icon-button mat-icon-button
title="{{ 'ADF_VIEWER.ACTIONS.CLOSE' | translate }}" title="{{ 'ADF_VIEWER.ACTIONS.CLOSE' | translate }}"
(click)="switchToDisplayMode()"> (click)="switchToDisplayMode()"
>
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</adf-toolbar> </adf-toolbar>
@ -45,14 +44,20 @@
<mat-card-title> <mat-card-title>
<h4> <h4>
<div *ngIf="showValidationIcon" class="adf-form-validation-button"> <div *ngIf="showValidationIcon" class="adf-form-validation-button">
<i id="adf-valid-form-icon" class="material-icons" <i id="adf-valid-form-icon" class="material-icons" *ngIf="form.isValid; else no_valid_form">check_circle</i>
*ngIf="form.isValid; else no_valid_form">check_circle</i>
<ng-template #no_valid_form> <ng-template #no_valid_form>
<i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i> <i id="adf-invalid-form-icon" class="material-icons adf-invalid-color">error</i>
</ng-template> </ng-template>
</div> </div>
<div *ngIf="!displayConfiguration?.options?.fullscreen && findDisplayConfiguration('fullScreen')" class="adf-cloud-form-fullscreen-button"> <div
<button mat-icon-button (click)="switchToDisplayMode('fullScreen')" [attr.data-automation-id]="'adf-cloud-form-fullscreen-button'"> *ngIf="!displayConfiguration?.options?.fullscreen && findDisplayConfiguration('fullScreen')"
class="adf-cloud-form-fullscreen-button"
>
<button
mat-icon-button
(click)="switchToDisplayMode('fullScreen')"
[attr.data-automation-id]="'adf-cloud-form-fullscreen-button'"
>
<mat-icon>fullscreen</mat-icon> <mat-icon>fullscreen</mat-icon>
</button> </button>
</div> </div>
@ -73,8 +78,15 @@
<mat-card-content class="adf-form-container-card-content"> <mat-card-content class="adf-form-container-card-content">
<adf-form-renderer [formDefinition]="form" [readOnly]="readOnly" /> <adf-form-renderer [formDefinition]="form" [readOnly]="readOnly" />
</mat-card-content> </mat-card-content>
<div class="adf-cloud-form-content-card-actions">
<mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions" align="end"> <mat-card-actions *ngIf="form.hasOutcomes()" class="adf-form-mat-card-actions" align="end">
<mat-checkbox id="adf-form-open-next-task" *ngIf="showNextTaskCheckbox" [checked]="isNextTaskCheckboxChecked" (change)="onNextTaskCheckboxCheckedChanged($event)">{{'ADF_CLOUD_TASK_FORM.OPEN_NEXT_TASK.LABEL' | translate}}</mat-checkbox> <mat-checkbox
id="adf-form-open-next-task"
*ngIf="showNextTaskCheckbox"
[checked]="isNextTaskCheckboxChecked"
(change)="onNextTaskCheckboxCheckedChanged($event)"
>{{ 'ADF_CLOUD_TASK_FORM.OPEN_NEXT_TASK.LABEL' | translate }}</mat-checkbox
>
<span class="adf-card-actions-spacer"></span> <span class="adf-card-actions-spacer"></span>
<ng-content select="adf-cloud-form-custom-outcomes" /> <ng-content select="adf-cloud-form-custom-outcomes" />
<ng-container *ngFor="let outcome of form.outcomes"> <ng-container *ngFor="let outcome of form.outcomes">
@ -92,6 +104,7 @@
</ng-container> </ng-container>
</mat-card-actions> </mat-card-actions>
</div> </div>
</div>
</mat-card> </mat-card>
</div> </div>
</div> </div>

View File

@ -17,6 +17,7 @@
flex: 1; flex: 1;
flex-direction: column; flex-direction: column;
display: flex; display: flex;
position: relative;
} }
.adf-card-actions-spacer { .adf-card-actions-spacer {
@ -72,13 +73,14 @@
&-content-card { &-content-card {
overflow-y: auto; overflow-y: auto;
position: static;
&-fullscreen { &-fullscreen {
padding: 0; padding: 0;
height: 100%; height: 100%;
width: 100%; width: 100%;
.adf-cloud-form-content-card-container { &-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
@ -89,6 +91,14 @@
} }
} }
} }
&-actions {
position: fixed;
bottom: 0;
width: -webkit-fill-available;
z-index: 1;
background-color: white;
}
} }
&-sidebars { &-sidebars {

View File

@ -1,6 +1,5 @@
<form> <form>
<mat-form-field <mat-form-field
[appearance]="formFieldAppearance"
[subscriptSizing]="formFieldSubscriptSizing" [subscriptSizing]="formFieldSubscriptSizing"
[floatLabel]="'auto'" [floatLabel]="'auto'"
class="adf-people-cloud" class="adf-people-cloud"

6
package-lock.json generated
View File

@ -39976,9 +39976,9 @@
} }
}, },
"node_modules/vite": { "node_modules/vite": {
"version": "5.4.18", "version": "5.4.19",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.18.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz",
"integrity": "sha512-1oDcnEp3lVyHCuQ2YFelM4Alm2o91xNoMncRm1U7S+JdYfYOvbiGZ3/CxGttrOu2M/KcGz7cRC2DoNUA6urmMA==", "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {