mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-09-17 14:21:29 +00:00
Ng17 migration (#10295)
* Migrate to NG17 * [ci:force] - fixed deps * [ci:force] - fixed build for testing 1 * Fixed build for all the packages * [ci:force] - fixing lint * [ci:force] - Fixed lint * AAE-26163 Fix infinite loop when authentication error event occured (#10272) * AAE-26163 Logout user after 3 login attempts failed, avoiding infinite loop when an authentication error occured, like when a user machine clock is significantly out of sync * AAE-26163 Wait to discovery document to be loaded and user not authenticated to perform a ssoLogin, logout user if login fails after 3 attempts * AAE-26163 Fix missed id_token_hint invoking logout when a login error occured due to a clock significantly out of sync * AAE-26163 Add fake observable to unit test * AAE-26163 Show oauth event logs if showDebugInformation is enabled, remove auth items if access token is not valid * AAE-26163 Improve tryLogin error message * AAE-26163 Check if token has expired to fix case when user access the application after the token is expired and with a clock significantly out of sync * AAE-26163 Test logout when clock is out of sync * AAE-26163 Create a service to check if local machine time is out of sync * AAE-26163 Update oauthErrorEvent$ and combinedOAuthErrorsStream$ to return errors * AAE-26163 Output error within combined oauth error event subscription * AAE-26163 Fix lint problems * AAE-26163 Logout user when token refresh error happens for the second time, if the token is not refreshed properly after first refresh error * AAE-26163 Logout user once an oauth error event occur due to clock out of sync * AAE-26163 Fix retry login error message if the OAuthErrorEvent doesn t return reason * AAE-26163 Fix the issue where the logout API call is canceled by the authorize call when login fails due to clock synchronization problems, causing an infinite loop. * remove console.log * AAE-26163 Fix retry login error message if the OAuthErrorEvent reason is an empty object * Cherry picked commit from oidc and run fix lint * [MIGRATION] - fixed build and lint * [MIGRATION] - Added injectionContext to avoid error NG0203 for unit tests * [MIGRATION] - Moving mocha to jest * [MIGRATION] - Fixing failing migrated tests * [MIGRATION] - Migrating to Jest - working but some tests fails * Trying to fix js-api unit tests * Removing testing lib to sync with develop * Fixed two excluded unit tests * Removed unused project parts * Removed unused project parts * Reduced tserrors on building storybook * Fixed sonarqube errors * Removing temporarily eslint rule from publishing * [MIGRATION] - Fixed lint * [MIGRATION] - Fixed type * [MIGRATION] - Rebased * [MIGRATION] - Readded removed action * [MIGRATION] - Checking deps * [MIGRATION] - updated lock * [ACS-9052] manage versions close button is too low (#10466) * [ci:force] - Fixed lint * [ACS-9052] Fixed close button in version manager position * [ACS-9052] Reverted unwanted changes --------- Co-authored-by: VitoAlbano <vito.albano.123@gmail.com> * [MIGRATION] - fixed storybook builds * [MIGRATION] - Checking if now eslint is releasable * [MIGRATION] - Changing the building executor for eslint-rules * Readded rule for peer deps * Fixed wrong rule * [ACS-9075] Fixed incorrect buttons labels color (#10489) * Update package.json * Fix ACA pipeline * [ACS-9084] Fixed incorrect color for notification bell icon (#10513) * Change dialog label padding * [AAE-26767] - Fixed lint * [AAE-26767] - Fixed lint * updated dependencies * AAE-30733 Fix incorrect alignment of icons in permission list header * [MIGRATION] - sync package-lock * [MIGRATION] - Fixed package on core lib * [MIGRATION] - Removed unused lock * Fixed licence * [MIGRATION] - sync lock file * [MIGRATION] - fixed lint issues * [ACS-9271][ACA] Login page input labels are cut if the input is not empty (#10637) * AAE-31453 Override card-view-textitem readonly color --------- Co-authored-by: Amedeo Lepore <amedeo.lepore@hyland.com> Co-authored-by: Ehsan Rezaei <ehsan.rezaei@hyland.com> Co-authored-by: AleksanderSklorz <115619721+AleksanderSklorz@users.noreply.github.com> Co-authored-by: DominikIwanek <dominik.iwanek@hyland.com> Co-authored-by: swapnil-verma-gl <92505353+swapnil-verma-gl@users.noreply.github.com> Co-authored-by: Wojciech Duda <69160975+wojd0@users.noreply.github.com> Co-authored-by: dominikiwanekhyland <141320833+dominikiwanekhyland@users.noreply.github.com>
This commit is contained in:
@@ -69,10 +69,7 @@ describe('StoragePrefixFactory', () => {
|
||||
}
|
||||
};
|
||||
|
||||
const prefixFactory = new StoragePrefixFactory(
|
||||
appConfigService as AppConfigService,
|
||||
externalPrefixFactory
|
||||
);
|
||||
const prefixFactory = new StoragePrefixFactory(appConfigService as AppConfigService, externalPrefixFactory);
|
||||
|
||||
prefixFactory.getPrefix().subscribe((prefix) => {
|
||||
expect(prefix).toBe('prefix-from-factory');
|
||||
@@ -95,10 +92,7 @@ describe('StoragePrefixFactory', () => {
|
||||
}
|
||||
};
|
||||
|
||||
const prefixFactory = new StoragePrefixFactory(
|
||||
appConfigService as AppConfigService,
|
||||
externalPrefixFactory
|
||||
);
|
||||
const prefixFactory = new StoragePrefixFactory(appConfigService as AppConfigService, externalPrefixFactory);
|
||||
|
||||
prefixFactory.getPrefix().subscribe((prefix) => {
|
||||
expect(prefix).toBe(appConfigPrefix);
|
||||
|
@@ -33,7 +33,8 @@ export class StoragePrefixFactory {
|
||||
constructor(
|
||||
private appConfigService: AppConfigService,
|
||||
@Optional()
|
||||
@Inject(STORAGE_PREFIX_FACTORY_SERVICE) private storagePrefixFactory?: StoragePrefixFactoryService
|
||||
@Inject(STORAGE_PREFIX_FACTORY_SERVICE)
|
||||
private storagePrefixFactory?: StoragePrefixFactoryService
|
||||
) {}
|
||||
|
||||
getPrefix(): Observable<string | undefined> {
|
||||
@@ -43,9 +44,7 @@ export class StoragePrefixFactory {
|
||||
return of(prefix);
|
||||
}
|
||||
|
||||
return this.storagePrefixFactory ?
|
||||
this.storagePrefixFactory.getPrefix() :
|
||||
of(prefix);
|
||||
return this.storagePrefixFactory ? this.storagePrefixFactory.getPrefix() : of(prefix);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@@ -34,8 +34,7 @@ export function loadAppConfig(
|
||||
storageService: StorageService,
|
||||
adfHttpClient: AdfHttpClient,
|
||||
storagePrefixFactory: StoragePrefixFactory
|
||||
) {
|
||||
|
||||
) {
|
||||
const init = () => {
|
||||
adfHttpClient.disableCsrf = appConfigService.get<boolean>(AppConfigValues.DISABLECSRF, true);
|
||||
storageService.prefix = appConfigService.get<string>(AppConfigValues.STORAGE_PREFIX, '');
|
||||
@@ -45,4 +44,4 @@ export function loadAppConfig(
|
||||
});
|
||||
};
|
||||
return () => appConfigService.load(init);
|
||||
};
|
||||
}
|
||||
|
@@ -23,9 +23,10 @@ import { AuthenticationService } from '../services/authentication.service';
|
||||
import { RedirectAuthService } from '../oidc/redirect-auth.service';
|
||||
|
||||
const mockNext: HttpHandler = {
|
||||
handle: () => new Observable(subscriber => {
|
||||
subscriber.complete();
|
||||
})
|
||||
handle: () =>
|
||||
new Observable((subscriber) => {
|
||||
subscriber.complete();
|
||||
})
|
||||
};
|
||||
|
||||
const mockRequest = (url) => new HttpRequest('GET', url);
|
||||
|
@@ -18,8 +18,15 @@
|
||||
import { throwError as observableThrowError, Observable } from 'rxjs';
|
||||
import { Injectable } from '@angular/core';
|
||||
import {
|
||||
HttpHandler, HttpInterceptor, HttpRequest,
|
||||
HttpSentEvent, HttpHeaderResponse, HttpProgressEvent, HttpResponse, HttpUserEvent, HttpHeaders
|
||||
HttpHandler,
|
||||
HttpInterceptor,
|
||||
HttpRequest,
|
||||
HttpSentEvent,
|
||||
HttpHeaderResponse,
|
||||
HttpProgressEvent,
|
||||
HttpResponse,
|
||||
HttpUserEvent,
|
||||
HttpHeaders
|
||||
} from '@angular/common/http';
|
||||
import { catchError, mergeMap } from 'rxjs/operators';
|
||||
import { AuthenticationService } from '../services/authentication.service';
|
||||
@@ -30,61 +37,52 @@ export class AuthBearerInterceptor implements HttpInterceptor {
|
||||
|
||||
private excludedUrlsRegex: RegExp[];
|
||||
|
||||
constructor(private authenticationService: AuthenticationService) { }
|
||||
constructor(private authenticationService: AuthenticationService) {}
|
||||
|
||||
private loadExcludedUrlsRegex() {
|
||||
const excludedUrls = this.bearerExcludedUrls;
|
||||
this.excludedUrlsRegex = excludedUrls.map((urlPattern) => new RegExp(`^https?://[^/]+/${urlPattern}`, 'i')) || [];
|
||||
}
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler):
|
||||
Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
|
||||
|
||||
|
||||
if (!this.excludedUrlsRegex) {
|
||||
this.loadExcludedUrlsRegex();
|
||||
private loadExcludedUrlsRegex() {
|
||||
const excludedUrls = this.bearerExcludedUrls;
|
||||
this.excludedUrlsRegex = excludedUrls.map((urlPattern) => new RegExp(`^https?://[^/]+/${urlPattern}`, 'i')) || [];
|
||||
}
|
||||
|
||||
const requestUrl = req.url;
|
||||
const shallPass: boolean = this.excludedUrlsRegex.some((regex) => regex.test(requestUrl));
|
||||
if (shallPass) {
|
||||
return next.handle(req)
|
||||
.pipe(
|
||||
catchError((error) => observableThrowError(error))
|
||||
intercept(
|
||||
req: HttpRequest<any>,
|
||||
next: HttpHandler
|
||||
): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
|
||||
if (!this.excludedUrlsRegex) {
|
||||
this.loadExcludedUrlsRegex();
|
||||
}
|
||||
|
||||
const requestUrl = req.url;
|
||||
const shallPass: boolean = this.excludedUrlsRegex.some((regex) => regex.test(requestUrl));
|
||||
if (shallPass) {
|
||||
return next.handle(req).pipe(catchError((error) => observableThrowError(error)));
|
||||
}
|
||||
|
||||
return this.authenticationService.addTokenToHeader(requestUrl, req.headers).pipe(
|
||||
mergeMap((headersWithBearer) => {
|
||||
const headerWithContentType = this.appendJsonContentType(headersWithBearer, req.body);
|
||||
const kcReq = req.clone({ headers: headerWithContentType });
|
||||
return next.handle(kcReq).pipe(catchError((error) => observableThrowError(error)));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return this.authenticationService.addTokenToHeader(requestUrl, req.headers)
|
||||
.pipe(
|
||||
mergeMap((headersWithBearer) => {
|
||||
const headerWithContentType = this.appendJsonContentType(headersWithBearer, req.body);
|
||||
const kcReq = req.clone({ headers: headerWithContentType});
|
||||
return next.handle(kcReq)
|
||||
.pipe(
|
||||
catchError((error) => observableThrowError(error))
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
private appendJsonContentType(headers: HttpHeaders, reqBody: any): HttpHeaders {
|
||||
// prevent adding any content type, to properly handle formData with boundary browser generated value,
|
||||
// as adding any Content-Type its going to break the upload functionality
|
||||
|
||||
private appendJsonContentType(headers: HttpHeaders, reqBody: any): HttpHeaders {
|
||||
if (headers.get('Content-Type') === 'multipart/form-data' && !(reqBody instanceof FormData)) {
|
||||
return headers.delete('Content-Type');
|
||||
}
|
||||
|
||||
// prevent adding any content type, to properly handle formData with boundary browser generated value,
|
||||
// as adding any Content-Type its going to break the upload functionality
|
||||
if (!headers.get('Content-Type') && !(reqBody instanceof FormData)) {
|
||||
return headers.set('Content-Type', 'application/json;charset=UTF-8');
|
||||
}
|
||||
|
||||
if (headers.get('Content-Type') === 'multipart/form-data' && !(reqBody instanceof FormData)) {
|
||||
return headers.delete('Content-Type');
|
||||
return headers;
|
||||
}
|
||||
|
||||
if (!headers.get('Content-Type') && !(reqBody instanceof FormData)) {
|
||||
return headers.set('Content-Type', 'application/json;charset=UTF-8');
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
protected get bearerExcludedUrls(): readonly string[] {
|
||||
return this._bearerExcludedUrls;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -38,7 +38,6 @@ export interface TicketEntry {
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ContentAuth {
|
||||
|
||||
onLogin = new ReplaySubject<any>(1);
|
||||
onLogout = new ReplaySubject<any>(1);
|
||||
onError = new Subject<any>();
|
||||
@@ -60,9 +59,7 @@ export class ContentAuth {
|
||||
return this.appConfigService.get<string>(AppConfigValues.ECMHOST) + '/' + contextRootEcm + '/api/-default-/public/authentication/versions/1';
|
||||
}
|
||||
|
||||
constructor(private appConfigService: AppConfigService,
|
||||
private adfHttpClient: AdfHttpClient,
|
||||
private storageService: StorageService) {
|
||||
constructor(private appConfigService: AppConfigService, private adfHttpClient: AdfHttpClient, private storageService: StorageService) {
|
||||
this.appConfigService.onLoad.subscribe(() => {
|
||||
this.setConfig();
|
||||
});
|
||||
@@ -72,7 +69,6 @@ export class ContentAuth {
|
||||
if (this.storageService.getItem(AppConfigValues.CONTENT_TICKET_STORAGE_LABEL)) {
|
||||
this.setTicket(this.storageService.getItem(AppConfigValues.CONTENT_TICKET_STORAGE_LABEL));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
saveUsername(username: string) {
|
||||
@@ -148,7 +144,8 @@ export class ContentAuth {
|
||||
this.adfHttpClient.emit('error');
|
||||
this.onError.next('error');
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -200,12 +197,12 @@ export class ContentAuth {
|
||||
|
||||
createTicket(ticketBodyCreate: TicketBody): Promise<TicketEntry> {
|
||||
if (ticketBodyCreate === null || ticketBodyCreate === undefined) {
|
||||
this.onError.next((`Missing param ticketBodyCreate`));
|
||||
this.onError.next(`Missing param ticketBodyCreate`);
|
||||
|
||||
throw new Error(`Missing param ticketBodyCreate`);
|
||||
}
|
||||
|
||||
return this.adfHttpClient.post(this.basePath + '/tickets', {bodyParam: ticketBodyCreate});
|
||||
return this.adfHttpClient.post(this.basePath + '/tickets', { bodyParam: ticketBodyCreate });
|
||||
}
|
||||
|
||||
async requireAlfTicket(): Promise<void> {
|
||||
@@ -216,5 +213,4 @@ export class ContentAuth {
|
||||
deleteTicket(): Promise<any> {
|
||||
return this.adfHttpClient.delete(this.basePath + '/tickets/-me-');
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -22,12 +22,10 @@ import { AppConfigService, AppConfigValues } from '../../app-config/app-config.s
|
||||
import { StorageService } from '../../common/services/storage.service';
|
||||
import { ReplaySubject, Subject } from 'rxjs';
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ProcessAuth {
|
||||
|
||||
onLogin = new ReplaySubject<any>(1);
|
||||
onLogout = new ReplaySubject<any>(1);
|
||||
onError = new Subject<any>();
|
||||
@@ -38,7 +36,8 @@ export class ProcessAuth {
|
||||
};
|
||||
|
||||
authentications: Authentication = {
|
||||
basicAuth: {ticket: ''}, type: 'activiti'
|
||||
basicAuth: { ticket: '' },
|
||||
type: 'activiti'
|
||||
};
|
||||
|
||||
get basePath(): string {
|
||||
@@ -46,9 +45,7 @@ export class ProcessAuth {
|
||||
return this.appConfigService.get<string>(AppConfigValues.BPMHOST) + '/' + contextRootBpm;
|
||||
}
|
||||
|
||||
constructor(private appConfigService: AppConfigService,
|
||||
private adfHttpClient: AdfHttpClient,
|
||||
private storageService: StorageService) {
|
||||
constructor(private appConfigService: AppConfigService, private adfHttpClient: AdfHttpClient, private storageService: StorageService) {
|
||||
this.appConfigService.onLoad.subscribe(() => {
|
||||
this.setConfig();
|
||||
});
|
||||
@@ -118,7 +115,8 @@ export class ProcessAuth {
|
||||
this.onError.next('error');
|
||||
}
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
return promise;
|
||||
@@ -147,7 +145,8 @@ export class ProcessAuth {
|
||||
this.adfHttpClient.emit('error');
|
||||
this.onError.next('error');
|
||||
reject(error);
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -48,7 +48,7 @@ export const AuthGuardSsoRoleService: CanActivateFn = (route: ActivatedRouteSnap
|
||||
}
|
||||
const hasRole = hasRealmRole && hasClientRole;
|
||||
|
||||
if (!hasRole && route?.data && route.data['redirectUrl']) {
|
||||
if (!hasRole && route?.data?.['redirectUrl']) {
|
||||
const router = inject(Router);
|
||||
router.navigate(['/' + route.data['redirectUrl']]);
|
||||
}
|
||||
|
@@ -20,39 +20,53 @@ import { IdentityRoleModel } from '../models/identity-role.model';
|
||||
import { IdentityJoinGroupRequestModel } from '../interfaces/identity-user.service.interface';
|
||||
|
||||
export const mockIdentityGroup1 = {
|
||||
id: 'mock-group-id-1', name: 'Mock Group 1', path: '/mock', subGroups: []
|
||||
id: 'mock-group-id-1',
|
||||
name: 'Mock Group 1',
|
||||
path: '/mock',
|
||||
subGroups: []
|
||||
} as IdentityGroupModel;
|
||||
|
||||
export const mockIdentityGroup2 = {
|
||||
id: 'mock-group-id-2', name: 'Mock Group 2', path: '', subGroups: []
|
||||
id: 'mock-group-id-2',
|
||||
name: 'Mock Group 2',
|
||||
path: '',
|
||||
subGroups: []
|
||||
} as IdentityGroupModel;
|
||||
|
||||
export const mockIdentityGroup3 = {
|
||||
id: 'mock-group-id-3', name: 'Mock Group 3', path: '', subGroups: []
|
||||
id: 'mock-group-id-3',
|
||||
name: 'Mock Group 3',
|
||||
path: '',
|
||||
subGroups: []
|
||||
} as IdentityGroupModel;
|
||||
|
||||
export const mockIdentityGroup4 = {
|
||||
id: 'mock-group-id-4', name: 'Mock Group 4', path: '', subGroups: []
|
||||
id: 'mock-group-id-4',
|
||||
name: 'Mock Group 4',
|
||||
path: '',
|
||||
subGroups: []
|
||||
} as IdentityGroupModel;
|
||||
|
||||
export const mockIdentityGroup5 = {
|
||||
id: 'mock-group-id-5', name: 'Mock Group 5', path: '', subGroups: []
|
||||
id: 'mock-group-id-5',
|
||||
name: 'Mock Group 5',
|
||||
path: '',
|
||||
subGroups: []
|
||||
} as IdentityGroupModel;
|
||||
|
||||
export const mockIdentityGroupsCount = { count: 10 } as IdentityGroupCountModel;
|
||||
|
||||
export const mockIdentityGroups = [
|
||||
mockIdentityGroup1, mockIdentityGroup2, mockIdentityGroup3, mockIdentityGroup4, mockIdentityGroup5
|
||||
];
|
||||
export const mockIdentityGroups = [mockIdentityGroup1, mockIdentityGroup2, mockIdentityGroup3, mockIdentityGroup4, mockIdentityGroup5];
|
||||
|
||||
export const roleMappingMock = [
|
||||
{ id: 'role-id-1', name: 'role-name-1' }, { id: 'role-id-2', name: 'role-name-2' }
|
||||
{ id: 'role-id-1', name: 'role-name-1' },
|
||||
{ id: 'role-id-2', name: 'role-name-2' }
|
||||
];
|
||||
|
||||
export const mockIdentityRoles = [
|
||||
new IdentityRoleModel({id: 'mock-role-id', name: 'MOCK-ADMIN-ROLE'}),
|
||||
new IdentityRoleModel({id: 'mock-role-id', name: 'MOCK-USER-ROLE'}),
|
||||
new IdentityRoleModel({id: 'mock-role-id', name: 'MOCK-ROLE-1'})
|
||||
new IdentityRoleModel({ id: 'mock-role-id', name: 'MOCK-ADMIN-ROLE' }),
|
||||
new IdentityRoleModel({ id: 'mock-role-id', name: 'MOCK-USER-ROLE' }),
|
||||
new IdentityRoleModel({ id: 'mock-role-id', name: 'MOCK-ROLE-1' })
|
||||
];
|
||||
|
||||
export const clientRoles: IdentityRoleModel[] = [
|
||||
@@ -60,14 +74,20 @@ export const clientRoles: IdentityRoleModel[] = [
|
||||
new IdentityRoleModel({ name: 'MOCK-USER-ROLE' })
|
||||
];
|
||||
|
||||
export const mockJoinGroupRequest: IdentityJoinGroupRequestModel = {userId: 'mock-hser-id', groupId: 'mock-group-id', realm: 'mock-realm-name'};
|
||||
export const mockJoinGroupRequest: IdentityJoinGroupRequestModel = { userId: 'mock-hser-id', groupId: 'mock-group-id', realm: 'mock-realm-name' };
|
||||
|
||||
export const mockGroup1 = {
|
||||
id: 'mock-group-id-1', name: 'Mock Group 1', path: '/mock', subGroups: []
|
||||
id: 'mock-group-id-1',
|
||||
name: 'Mock Group 1',
|
||||
path: '/mock',
|
||||
subGroups: []
|
||||
} as IdentityGroupModel;
|
||||
|
||||
export const mockGroup2 = {
|
||||
id: 'mock-group-id-2', name: 'Mock Group 2', path: '', subGroups: []
|
||||
id: 'mock-group-id-2',
|
||||
name: 'Mock Group 2',
|
||||
path: '',
|
||||
subGroups: []
|
||||
} as IdentityGroupModel;
|
||||
|
||||
export const mockGroups = [
|
||||
|
@@ -31,7 +31,6 @@ import { IdentityRoleModel } from '../models/identity-role.model';
|
||||
|
||||
Injectable({ providedIn: 'root' });
|
||||
export class IdentityGroupServiceMock implements IdentityGroupServiceInterface {
|
||||
|
||||
getGroups(): Observable<IdentityGroupModel[]> {
|
||||
return of(mockIdentityGroups);
|
||||
}
|
||||
@@ -81,9 +80,7 @@ export class IdentityGroupServiceMock implements IdentityGroupServiceInterface {
|
||||
return of([]);
|
||||
}
|
||||
|
||||
return of(mockIdentityGroups.filter(group =>
|
||||
group.name.toUpperCase().includes(searchParams.name.toUpperCase())
|
||||
));
|
||||
return of(mockIdentityGroups.filter((group) => group.name.toUpperCase().includes(searchParams.name.toUpperCase())));
|
||||
}
|
||||
|
||||
getGroupRoles(_groupId: string): Observable<IdentityRoleModel[]> {
|
||||
@@ -91,19 +88,21 @@ export class IdentityGroupServiceMock implements IdentityGroupServiceInterface {
|
||||
}
|
||||
|
||||
checkGroupHasRole(groupId: string, roleNames: string[]): Observable<boolean> {
|
||||
return this.getGroupRoles(groupId).pipe(map((groupRoles) => {
|
||||
let hasRole = false;
|
||||
if (groupRoles?.length > 0) {
|
||||
roleNames.forEach((roleName: string) => {
|
||||
const role = groupRoles.find(({ name }) => roleName === name);
|
||||
if (role) {
|
||||
hasRole = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
return hasRole;
|
||||
}));
|
||||
return this.getGroupRoles(groupId).pipe(
|
||||
map((groupRoles) => {
|
||||
let hasRole = false;
|
||||
if (groupRoles?.length > 0) {
|
||||
roleNames.forEach((roleName: string) => {
|
||||
const role = groupRoles.find(({ name }) => roleName === name);
|
||||
if (role) {
|
||||
hasRole = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
return hasRole;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
getClientIdByApplicationName(_applicationName: string): Observable<string> {
|
||||
@@ -119,9 +118,7 @@ export class IdentityGroupServiceMock implements IdentityGroupServiceInterface {
|
||||
}
|
||||
|
||||
checkGroupHasClientApp(groupId: string, clientId: string): Observable<boolean> {
|
||||
return this.getClientRoles(groupId, clientId).pipe(
|
||||
map((response) => response && response.length > 0)
|
||||
);
|
||||
return this.getClientRoles(groupId, clientId).pipe(map((response) => response && response.length > 0));
|
||||
}
|
||||
|
||||
checkGroupHasAnyClientAppRole(groupId: string, clientId: string, roleNames: string[]): Observable<boolean> {
|
||||
|
@@ -18,37 +18,61 @@
|
||||
import { IdentityUserModel } from '../models/identity-user.model';
|
||||
import { IdentityRoleModel } from '../models/identity-role.model';
|
||||
|
||||
export const mockIdentityUser1: IdentityUserModel = { id: 'mock-user-id-1', username: 'userName1', firstName: 'first-name-1', lastName: 'last-name-1', email: 'abc@xyz.com' };
|
||||
export const mockIdentityUser2: IdentityUserModel = { id: 'mock-user-id-2', username: 'userName2', firstName: 'first-name-2', lastName: 'last-name-2', email: 'abcd@xyz.com'};
|
||||
export const mockIdentityUser3: IdentityUserModel = { id: 'mock-user-id-3', username: 'userName3', firstName: 'first-name-3', lastName: 'last-name-3', email: 'abcde@xyz.com' };
|
||||
export const mockIdentityUser4: IdentityUserModel = { id: 'mock-user-id-4', username: 'userName4', firstName: 'first-name-4', lastName: 'last-name-4', email: 'abcde@xyz.com' };
|
||||
export const mockIdentityUser5: IdentityUserModel = { id: 'mock-user-id-5', username: 'userName5', firstName: 'first-name-5', lastName: 'last-name-5', email: 'abcde@xyz.com' };
|
||||
export const mockIdentityUser1: IdentityUserModel = {
|
||||
id: 'mock-user-id-1',
|
||||
username: 'userName1',
|
||||
firstName: 'first-name-1',
|
||||
lastName: 'last-name-1',
|
||||
email: 'abc@xyz.com'
|
||||
};
|
||||
export const mockIdentityUser2: IdentityUserModel = {
|
||||
id: 'mock-user-id-2',
|
||||
username: 'userName2',
|
||||
firstName: 'first-name-2',
|
||||
lastName: 'last-name-2',
|
||||
email: 'abcd@xyz.com'
|
||||
};
|
||||
export const mockIdentityUser3: IdentityUserModel = {
|
||||
id: 'mock-user-id-3',
|
||||
username: 'userName3',
|
||||
firstName: 'first-name-3',
|
||||
lastName: 'last-name-3',
|
||||
email: 'abcde@xyz.com'
|
||||
};
|
||||
export const mockIdentityUser4: IdentityUserModel = {
|
||||
id: 'mock-user-id-4',
|
||||
username: 'userName4',
|
||||
firstName: 'first-name-4',
|
||||
lastName: 'last-name-4',
|
||||
email: 'abcde@xyz.com'
|
||||
};
|
||||
export const mockIdentityUser5: IdentityUserModel = {
|
||||
id: 'mock-user-id-5',
|
||||
username: 'userName5',
|
||||
firstName: 'first-name-5',
|
||||
lastName: 'last-name-5',
|
||||
email: 'abcde@xyz.com'
|
||||
};
|
||||
|
||||
export const mockIdentityUsers: IdentityUserModel[] = [
|
||||
mockIdentityUser1,
|
||||
mockIdentityUser2,
|
||||
mockIdentityUser3,
|
||||
mockIdentityUser4,
|
||||
mockIdentityUser5
|
||||
];
|
||||
export const mockIdentityUsers: IdentityUserModel[] = [mockIdentityUser1, mockIdentityUser2, mockIdentityUser3, mockIdentityUser4, mockIdentityUser5];
|
||||
|
||||
export const mockIdentityRole = new IdentityRoleModel({ id: 'id-1', name: 'MOCK-ADMIN-ROLE'});
|
||||
export const mockIdentityRole = new IdentityRoleModel({ id: 'id-1', name: 'MOCK-ADMIN-ROLE' });
|
||||
|
||||
export const mockAvailableRoles = [
|
||||
new IdentityRoleModel({ id: 'mock-role-id-1', name: 'MOCK-ADMIN-ROLE'}),
|
||||
new IdentityRoleModel({ id: 'mock-role-id-2', name: 'MOCK-USER-ROLE'}),
|
||||
new IdentityRoleModel({ id: 'mock-role-id-1', name: 'MOCK-ADMIN-ROLE' }),
|
||||
new IdentityRoleModel({ id: 'mock-role-id-2', name: 'MOCK-USER-ROLE' }),
|
||||
new IdentityRoleModel({ id: 'mock-role-id-3', name: 'MOCK_MODELER-ROLE' }),
|
||||
new IdentityRoleModel({ id: 'mock-role-id-5', name: 'MOCK-ROLE-2'})
|
||||
new IdentityRoleModel({ id: 'mock-role-id-5', name: 'MOCK-ROLE-2' })
|
||||
];
|
||||
|
||||
export const mockAssignedRoles = [
|
||||
new IdentityRoleModel({ id: 'mock-role-id-1', name: 'MOCK-ADMIN-ROLE'}),
|
||||
new IdentityRoleModel({ id: 'mock-role-id-1', name: 'MOCK-ADMIN-ROLE' }),
|
||||
new IdentityRoleModel({ id: 'mock-role-id-2', name: 'MOCK_MODELER-ROLE' }),
|
||||
new IdentityRoleModel({ id: 'mock-role-id-3', name: 'MOCK-ROLE-1' })
|
||||
];
|
||||
|
||||
export const mockEffectiveRoles = [
|
||||
new IdentityRoleModel({id: 'mock-role-id-1', name: 'MOCK-ACTIVE-ADMIN-ROLE'}),
|
||||
new IdentityRoleModel({id: 'mock-role-id-2', name: 'MOCK-ACTIVE-USER-ROLE'}),
|
||||
new IdentityRoleModel({id: 'mock-role-id-3', name: 'MOCK-ROLE-1'})
|
||||
new IdentityRoleModel({ id: 'mock-role-id-1', name: 'MOCK-ACTIVE-ADMIN-ROLE' }),
|
||||
new IdentityRoleModel({ id: 'mock-role-id-2', name: 'MOCK-ACTIVE-USER-ROLE' }),
|
||||
new IdentityRoleModel({ id: 'mock-role-id-3', name: 'MOCK-ROLE-1' })
|
||||
];
|
||||
|
@@ -35,7 +35,6 @@ import { mockAssignedRoles, mockAvailableRoles, mockEffectiveRoles, mockIdentity
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class IdentityUserServiceMock implements IdentityUserServiceInterface {
|
||||
|
||||
getCurrentUserInfo(): IdentityUserModel {
|
||||
return mockIdentityUser1;
|
||||
}
|
||||
@@ -45,9 +44,7 @@ export class IdentityUserServiceMock implements IdentityUserServiceInterface {
|
||||
return of([]);
|
||||
}
|
||||
|
||||
return of(mockIdentityUsers.filter(user =>
|
||||
user.username.toUpperCase().includes(search.toUpperCase())
|
||||
));
|
||||
return of(mockIdentityUsers.filter((user) => user.username.toUpperCase().includes(search.toUpperCase())));
|
||||
}
|
||||
|
||||
findUserByUsername(username: string): Observable<IdentityUserModel[]> {
|
||||
@@ -55,7 +52,7 @@ export class IdentityUserServiceMock implements IdentityUserServiceInterface {
|
||||
return of([]);
|
||||
}
|
||||
|
||||
return of(mockIdentityUsers.filter(user => user.username === username));
|
||||
return of(mockIdentityUsers.filter((user) => user.username === username));
|
||||
}
|
||||
|
||||
findUserByEmail(email: string): Observable<IdentityUserModel[]> {
|
||||
@@ -63,7 +60,7 @@ export class IdentityUserServiceMock implements IdentityUserServiceInterface {
|
||||
return of([]);
|
||||
}
|
||||
|
||||
return of(mockIdentityUsers.filter(user => user.email === email));
|
||||
return of(mockIdentityUsers.filter((user) => user.email === email));
|
||||
}
|
||||
|
||||
findUserById(id: string): Observable<any> {
|
||||
@@ -71,7 +68,7 @@ export class IdentityUserServiceMock implements IdentityUserServiceInterface {
|
||||
return of([]);
|
||||
}
|
||||
|
||||
return of(mockIdentityUsers.find(user => user.id === id));
|
||||
return of(mockIdentityUsers.find((user) => user.id === id));
|
||||
}
|
||||
|
||||
getClientRoles(userId: string, _clientId: string): Observable<any[]> {
|
||||
@@ -83,9 +80,7 @@ export class IdentityUserServiceMock implements IdentityUserServiceInterface {
|
||||
}
|
||||
|
||||
checkUserHasClientApp(userId: string, clientId: string): Observable<boolean> {
|
||||
return this.getClientRoles(userId, clientId).pipe(
|
||||
map((clientRoles) => clientRoles.length > 0)
|
||||
);
|
||||
return this.getClientRoles(userId, clientId).pipe(map((clientRoles) => clientRoles.length > 0));
|
||||
}
|
||||
|
||||
checkUserHasAnyClientAppRole(userId: string, clientId: string, roleNames: string[]): Observable<boolean> {
|
||||
@@ -112,9 +107,7 @@ export class IdentityUserServiceMock implements IdentityUserServiceInterface {
|
||||
}
|
||||
|
||||
checkUserHasApplicationAccess(userId: string, applicationName: string): Observable<boolean> {
|
||||
return this.getClientIdByApplicationName(applicationName).pipe(
|
||||
switchMap((clientId: string) => this.checkUserHasClientApp(userId, clientId))
|
||||
);
|
||||
return this.getClientIdByApplicationName(applicationName).pipe(switchMap((clientId: string) => this.checkUserHasClientApp(userId, clientId)));
|
||||
}
|
||||
|
||||
checkUserHasAnyApplicationRole(userId: string, applicationName: string, roleNames: string[]): Observable<boolean> {
|
||||
@@ -178,19 +171,21 @@ export class IdentityUserServiceMock implements IdentityUserServiceInterface {
|
||||
}
|
||||
|
||||
checkUserHasRole(userId: string, roleNames: string[]): Observable<boolean> {
|
||||
return this.getUserRoles(userId).pipe(map((userRoles: IdentityRoleModel[]) => {
|
||||
let hasRole = false;
|
||||
if (userRoles && userRoles.length > 0) {
|
||||
roleNames.forEach((roleName: string) => {
|
||||
const role = userRoles.find(({ name }) => roleName === name);
|
||||
if (role) {
|
||||
hasRole = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
return hasRole;
|
||||
}));
|
||||
return this.getUserRoles(userId).pipe(
|
||||
map((userRoles: IdentityRoleModel[]) => {
|
||||
let hasRole = false;
|
||||
if (userRoles && userRoles.length > 0) {
|
||||
roleNames.forEach((roleName: string) => {
|
||||
const role = userRoles.find(({ name }) => roleName === name);
|
||||
if (role) {
|
||||
hasRole = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
return hasRole;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
queryUsers(_requestQuery: IdentityUserQueryCloudRequestModel): Observable<IdentityUserQueryResponse> {
|
||||
|
@@ -128,6 +128,6 @@ export const deleteGroupMappingApi: any = {
|
||||
|
||||
export const applicationDetailsMockApi: any = {
|
||||
oauth2Auth: {
|
||||
callCustomApi: () => Promise.resolve([{id: 'mock-app-id', name: 'mock-app-name'}])
|
||||
callCustomApi: () => Promise.resolve([{ id: 'mock-app-id', name: 'mock-app-name' }])
|
||||
}
|
||||
};
|
||||
|
@@ -29,5 +29,4 @@ export class RedirectionModel {
|
||||
this.url = obj.url || null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,7 +16,18 @@
|
||||
*/
|
||||
|
||||
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { OAuthService, OAuthEvent, OAuthStorage, AUTH_CONFIG, TokenResponse, AuthConfig, OAuthLogger, OAuthErrorEvent, OAuthSuccessEvent, OAuthInfoEvent } from 'angular-oauth2-oidc';
|
||||
import {
|
||||
OAuthService,
|
||||
OAuthEvent,
|
||||
OAuthStorage,
|
||||
AUTH_CONFIG,
|
||||
TokenResponse,
|
||||
AuthConfig,
|
||||
OAuthLogger,
|
||||
OAuthErrorEvent,
|
||||
OAuthSuccessEvent,
|
||||
OAuthInfoEvent
|
||||
} from 'angular-oauth2-oidc';
|
||||
import { of, Subject, timeout } from 'rxjs';
|
||||
import { RedirectAuthService } from './redirect-auth.service';
|
||||
import { AUTH_MODULE_CONFIG } from './auth-config';
|
||||
@@ -43,18 +54,22 @@ describe('RedirectAuthService', () => {
|
||||
retryLoginServiceSpy = jasmine.createSpyObj('RetryLoginService', ['tryToLoginTimes']);
|
||||
timeSyncServiceSpy = jasmine.createSpyObj('TimeSyncService', ['checkTimeSync']);
|
||||
oauthLoggerSpy = jasmine.createSpyObj('OAuthLogger', ['error', 'info', 'warn']);
|
||||
oauthServiceSpy = jasmine.createSpyObj('OAuthService', [
|
||||
'clearHashAfterLogin',
|
||||
'configure',
|
||||
'logOut',
|
||||
'hasValidAccessToken',
|
||||
'hasValidIdToken',
|
||||
'setupAutomaticSilentRefresh',
|
||||
'silentRefresh',
|
||||
'refreshToken',
|
||||
'getIdentityClaims',
|
||||
'getAccessToken'
|
||||
], { clockSkewInSec: 120, events: oauthEvents$, tokenValidationHandler: {} });
|
||||
oauthServiceSpy = jasmine.createSpyObj(
|
||||
'OAuthService',
|
||||
[
|
||||
'clearHashAfterLogin',
|
||||
'configure',
|
||||
'logOut',
|
||||
'hasValidAccessToken',
|
||||
'hasValidIdToken',
|
||||
'setupAutomaticSilentRefresh',
|
||||
'silentRefresh',
|
||||
'refreshToken',
|
||||
'getIdentityClaims',
|
||||
'getAccessToken'
|
||||
],
|
||||
{ clockSkewInSec: 120, events: oauthEvents$, tokenValidationHandler: {} }
|
||||
);
|
||||
authConfigSpy = jasmine.createSpyObj('AuthConfig', ['sessionChecksEnabled']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
@@ -202,8 +217,14 @@ describe('RedirectAuthService', () => {
|
||||
});
|
||||
|
||||
it('should logout user if token has expired due to local machine clock being out of sync', () => {
|
||||
const mockTimeSync: TimeSync = { outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' };
|
||||
const expectedError = new Error(`Token has expired due to local machine clock ${mockTimeSync.localDateTimeISO} being out of sync with server time ${mockTimeSync.serverDateTimeISO}`);
|
||||
const mockTimeSync: TimeSync = {
|
||||
outOfSync: true,
|
||||
localDateTimeISO: '2024-10-10T22:00:18.621Z',
|
||||
serverDateTimeISO: '2024-10-10T22:10:53.000Z'
|
||||
};
|
||||
const expectedError = new Error(
|
||||
`Token has expired due to local machine clock ${mockTimeSync.localDateTimeISO} being out of sync with server time ${mockTimeSync.serverDateTimeISO}`
|
||||
);
|
||||
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(of(mockTimeSync));
|
||||
|
||||
@@ -375,7 +396,7 @@ describe('RedirectAuthService', () => {
|
||||
|
||||
expect(oauthServiceSpy.logOut).not.toHaveBeenCalled();
|
||||
expect(oauthLoggerSpy.error).not.toHaveBeenCalled();
|
||||
expect(await firstEventOccurPromise).toEqual(expectedFakeErrorEvent);;
|
||||
expect(await firstEventOccurPromise).toEqual(expectedFakeErrorEvent);
|
||||
|
||||
try {
|
||||
tick(1000);
|
||||
@@ -387,7 +408,6 @@ describe('RedirectAuthService', () => {
|
||||
}));
|
||||
|
||||
it('should logout user if the second time the refresh token failed', fakeAsync(async () => {
|
||||
|
||||
const expectedErrorCausedBySecondTokenRefreshError = new OAuthErrorEvent('token_refresh_error', { reason: 'second token refresh error' }, {});
|
||||
|
||||
oauthEvents$.next(new OAuthErrorEvent('token_refresh_error', { reason: 'error' }, {}));
|
||||
@@ -398,8 +418,12 @@ describe('RedirectAuthService', () => {
|
||||
}));
|
||||
|
||||
it('should logout user if token_refresh_error is emitted because of clock out of sync', () => {
|
||||
const expectedErrorMessage = new Error('OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z');
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync));
|
||||
const expectedErrorMessage = new Error(
|
||||
'OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z'
|
||||
);
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(
|
||||
of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync)
|
||||
);
|
||||
|
||||
oauthEvents$.next(new OAuthErrorEvent('token_refresh_error', { reason: 'error' }, {}));
|
||||
|
||||
@@ -408,8 +432,12 @@ describe('RedirectAuthService', () => {
|
||||
});
|
||||
|
||||
it('should logout user if discovery_document_load_error is emitted because of clock out of sync', () => {
|
||||
const expectedErrorMessage = new Error('OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z');
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync));
|
||||
const expectedErrorMessage = new Error(
|
||||
'OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z'
|
||||
);
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(
|
||||
of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync)
|
||||
);
|
||||
|
||||
oauthEvents$.next(new OAuthErrorEvent('discovery_document_load_error', { reason: 'error' }, {}));
|
||||
|
||||
@@ -418,8 +446,12 @@ describe('RedirectAuthService', () => {
|
||||
});
|
||||
|
||||
it('should logout user if code_error is emitted because of clock out of sync', () => {
|
||||
const expectedErrorMessage = new Error('OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z');
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync));
|
||||
const expectedErrorMessage = new Error(
|
||||
'OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z'
|
||||
);
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(
|
||||
of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync)
|
||||
);
|
||||
|
||||
oauthEvents$.next(new OAuthErrorEvent('code_error', { reason: 'error' }, {}));
|
||||
|
||||
@@ -428,8 +460,12 @@ describe('RedirectAuthService', () => {
|
||||
});
|
||||
|
||||
it('should logout user if discovery_document_validation_error is emitted because of clock out of sync', () => {
|
||||
const expectedErrorMessage = new Error('OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z');
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync));
|
||||
const expectedErrorMessage = new Error(
|
||||
'OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z'
|
||||
);
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(
|
||||
of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync)
|
||||
);
|
||||
|
||||
oauthEvents$.next(new OAuthErrorEvent('discovery_document_validation_error', { reason: 'error' }, {}));
|
||||
|
||||
@@ -438,8 +474,12 @@ describe('RedirectAuthService', () => {
|
||||
});
|
||||
|
||||
it('should logout user if jwks_load_error is emitted because of clock out of sync', () => {
|
||||
const expectedErrorMessage = new Error('OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z');
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync));
|
||||
const expectedErrorMessage = new Error(
|
||||
'OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z'
|
||||
);
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(
|
||||
of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync)
|
||||
);
|
||||
|
||||
oauthEvents$.next(new OAuthErrorEvent('jwks_load_error', { reason: 'error' }, {}));
|
||||
|
||||
@@ -448,8 +488,12 @@ describe('RedirectAuthService', () => {
|
||||
});
|
||||
|
||||
it('should logout user if silent_refresh_error is emitted because of clock out of sync', () => {
|
||||
const expectedErrorMessage = new Error('OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z');
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync));
|
||||
const expectedErrorMessage = new Error(
|
||||
'OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z'
|
||||
);
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(
|
||||
of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync)
|
||||
);
|
||||
|
||||
oauthEvents$.next(new OAuthErrorEvent('silent_refresh_error', { reason: 'error' }, {}));
|
||||
|
||||
@@ -458,8 +502,12 @@ describe('RedirectAuthService', () => {
|
||||
});
|
||||
|
||||
it('should logout user if user_profile_load_error is emitted because of clock out of sync', () => {
|
||||
const expectedErrorMessage = new Error('OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z');
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync));
|
||||
const expectedErrorMessage = new Error(
|
||||
'OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z'
|
||||
);
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(
|
||||
of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync)
|
||||
);
|
||||
|
||||
oauthEvents$.next(new OAuthErrorEvent('user_profile_load_error', { reason: 'error' }, {}));
|
||||
|
||||
@@ -468,8 +516,12 @@ describe('RedirectAuthService', () => {
|
||||
});
|
||||
|
||||
it('should logout user if token_error is emitted because of clock out of sync', () => {
|
||||
const expectedErrorMessage = new Error('OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z');
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync));
|
||||
const expectedErrorMessage = new Error(
|
||||
'OAuth error occurred due to local machine clock 2024-10-10T22:00:18.621Z being out of sync with server time 2024-10-10T22:10:53.000Z'
|
||||
);
|
||||
timeSyncServiceSpy.checkTimeSync.and.returnValue(
|
||||
of({ outOfSync: true, localDateTimeISO: '2024-10-10T22:00:18.621Z', serverDateTimeISO: '2024-10-10T22:10:53.000Z' } as TimeSync)
|
||||
);
|
||||
|
||||
oauthEvents$.next(new OAuthErrorEvent('token_error', { reason: 'error' }, {}));
|
||||
|
||||
@@ -479,11 +531,10 @@ describe('RedirectAuthService', () => {
|
||||
|
||||
it('should onLogout$ be emitted when logout event occur', () => {
|
||||
let expectedLogoutIsEmitted = false;
|
||||
service.onLogout$.subscribe(() => expectedLogoutIsEmitted = true);
|
||||
service.onLogout$.subscribe(() => (expectedLogoutIsEmitted = true));
|
||||
|
||||
oauthEvents$.next(new OAuthInfoEvent('logout'));
|
||||
|
||||
expect(expectedLogoutIsEmitted).toBeTrue();
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -18,9 +18,9 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
template: '<div data-automation-id="auth-confirmation"></div>',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
template: '<div data-automation-id="auth-confirmation"></div>',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AuthenticationConfirmationComponent {
|
||||
constructor(){}
|
||||
constructor() {}
|
||||
}
|
||||
|
@@ -35,9 +35,7 @@ export class AuthenticationService implements AuthenticationServiceInterface, ee
|
||||
constructor(private injector: Injector, private redirectAuthService: RedirectAuthService) {
|
||||
this.redirectAuthService.onLogin.subscribe((value) => this.onLogin.next(value));
|
||||
|
||||
this.redirectAuthService.onTokenReceived.subscribe(
|
||||
(value) => this.onTokenReceived.next(value)
|
||||
);
|
||||
this.redirectAuthService.onTokenReceived.subscribe((value) => this.onTokenReceived.next(value));
|
||||
|
||||
this.basicAlfrescoAuthService.onLogin.subscribe((value) => this.onLogin.next(value));
|
||||
|
||||
|
@@ -32,11 +32,7 @@ import { OAuth2Service } from './oauth2.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class IdentityGroupService implements IdentityGroupServiceInterface {
|
||||
|
||||
constructor(
|
||||
private oAuth2Service: OAuth2Service,
|
||||
private appConfigService: AppConfigService
|
||||
) {}
|
||||
constructor(private oAuth2Service: OAuth2Service, private appConfigService: AppConfigService) {}
|
||||
|
||||
private get identityHost(): string {
|
||||
return `${this.appConfigService.get('identityHost')}`;
|
||||
@@ -125,18 +121,22 @@ export class IdentityGroupService implements IdentityGroupServiceInterface {
|
||||
|
||||
return this.getTotalGroupsCount().pipe(
|
||||
switchMap((totalCount: IdentityGroupCountModel) =>
|
||||
this.oAuth2Service.get<any[]>({ url, queryParams }).pipe(
|
||||
map((response) => ({
|
||||
entries: response,
|
||||
pagination: {
|
||||
skipCount: requestQuery.first,
|
||||
maxItems: requestQuery.max,
|
||||
count: totalCount.count,
|
||||
hasMoreItems: false,
|
||||
totalItems: totalCount.count
|
||||
}
|
||||
} as IdentityGroupQueryResponse))
|
||||
))
|
||||
this.oAuth2Service.get<any[]>({ url, queryParams }).pipe(
|
||||
map(
|
||||
(response) =>
|
||||
({
|
||||
entries: response,
|
||||
pagination: {
|
||||
skipCount: requestQuery.first,
|
||||
maxItems: requestQuery.max,
|
||||
count: totalCount.count,
|
||||
hasMoreItems: false,
|
||||
totalItems: totalCount.count
|
||||
}
|
||||
} as IdentityGroupQueryResponse)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -222,20 +222,22 @@ export class IdentityGroupService implements IdentityGroupServiceInterface {
|
||||
* @param roleNames Array of role names
|
||||
* @returns True if the group has one or more of the roles, false otherwise
|
||||
*/
|
||||
checkGroupHasRole(groupId: string, roleNames: string[]): Observable<boolean> {
|
||||
return this.getGroupRoles(groupId).pipe(map((groupRoles) => {
|
||||
let hasRole = false;
|
||||
if (groupRoles?.length > 0) {
|
||||
roleNames.forEach((roleName: string) => {
|
||||
const role = groupRoles.find(({ name }) => roleName === name);
|
||||
if (role) {
|
||||
hasRole = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
return hasRole;
|
||||
}));
|
||||
checkGroupHasRole(groupId: string, roleNames: string[]): Observable<boolean> {
|
||||
return this.getGroupRoles(groupId).pipe(
|
||||
map((groupRoles) => {
|
||||
let hasRole = false;
|
||||
if (groupRoles?.length > 0) {
|
||||
roleNames.forEach((roleName: string) => {
|
||||
const role = groupRoles.find(({ name }) => roleName === name);
|
||||
if (role) {
|
||||
hasRole = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
return hasRole;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -246,11 +248,9 @@ export class IdentityGroupService implements IdentityGroupServiceInterface {
|
||||
*/
|
||||
getClientIdByApplicationName(applicationName: string): Observable<string> {
|
||||
const url = `${this.identityHost}/clients`;
|
||||
const queryParams = {clientId: applicationName};
|
||||
const queryParams = { clientId: applicationName };
|
||||
|
||||
return this.oAuth2Service.get<any[]>({ url, queryParams }).pipe(
|
||||
map((response) => response && response.length > 0 ? response[0].id : '')
|
||||
);
|
||||
return this.oAuth2Service.get<any[]>({ url, queryParams }).pipe(map((response) => (response && response.length > 0 ? response[0].id : '')));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,9 +273,7 @@ export class IdentityGroupService implements IdentityGroupServiceInterface {
|
||||
* @returns True if the group has the client app, false otherwise
|
||||
*/
|
||||
checkGroupHasClientApp(groupId: string, clientId: string): Observable<boolean> {
|
||||
return this.getClientRoles(groupId, clientId).pipe(
|
||||
map((response) => response && response.length > 0)
|
||||
);
|
||||
return this.getClientRoles(groupId, clientId).pipe(map((response) => response && response.length > 0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -21,21 +21,31 @@ import { of, throwError } from 'rxjs';
|
||||
import { IdentityRoleResponseModel, IdentityRoleService } from './identity-role.service';
|
||||
|
||||
export const mockIdentityRole1 = {
|
||||
id: 'mock-id-1', name: 'Mock_Role_1', description: 'Mock desc1', clientRole: true, composite: false
|
||||
id: 'mock-id-1',
|
||||
name: 'Mock_Role_1',
|
||||
description: 'Mock desc1',
|
||||
clientRole: true,
|
||||
composite: false
|
||||
};
|
||||
|
||||
export const mockIdentityRole2 = {
|
||||
id: 'mock-id-2', name: 'Mock_Role_2', description: 'Mock desc2', clientRole: false, composite: true
|
||||
id: 'mock-id-2',
|
||||
name: 'Mock_Role_2',
|
||||
description: 'Mock desc2',
|
||||
clientRole: false,
|
||||
composite: true
|
||||
};
|
||||
|
||||
export const mockIdentityRole3 = {
|
||||
id: 'mock-id-3', name: 'Mock_Role_3', description: 'Mock desc3', clientRole: false, composite: false
|
||||
id: 'mock-id-3',
|
||||
name: 'Mock_Role_3',
|
||||
description: 'Mock desc3',
|
||||
clientRole: false,
|
||||
composite: false
|
||||
};
|
||||
|
||||
export const mockIdentityRoles = {
|
||||
entries: [
|
||||
mockIdentityRole1, mockIdentityRole2, mockIdentityRole3
|
||||
],
|
||||
entries: [mockIdentityRole1, mockIdentityRole2, mockIdentityRole3],
|
||||
pagination: {
|
||||
skipCount: 1,
|
||||
maxItems: 5,
|
||||
@@ -50,9 +60,7 @@ describe('IdentityRoleService', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
HttpClientModule
|
||||
]
|
||||
imports: [HttpClientModule]
|
||||
});
|
||||
service = TestBed.inject(IdentityRoleService);
|
||||
});
|
||||
@@ -75,31 +83,29 @@ describe('IdentityRoleService', () => {
|
||||
statusText: 'Created'
|
||||
});
|
||||
spyOn(service, 'addRole').and.returnValue(of(response));
|
||||
service.addRole(mockIdentityRole1).subscribe(
|
||||
(res: any) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.status).toEqual(201);
|
||||
expect(res.statusText).toEqual('Created');
|
||||
done();
|
||||
}
|
||||
);
|
||||
service.addRole(mockIdentityRole1).subscribe((res: any) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.status).toEqual(201);
|
||||
expect(res.statusText).toEqual('Created');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Should not add role if error occurred', () => {
|
||||
const errorResponse = new HttpErrorResponse({
|
||||
error: 'test 404 error',
|
||||
status: 404, statusText: 'Not Found'
|
||||
status: 404,
|
||||
statusText: 'Not Found'
|
||||
});
|
||||
spyOn(service, 'addRole').and.returnValue(throwError(errorResponse));
|
||||
service.addRole(mockIdentityRole1)
|
||||
.subscribe(
|
||||
() => fail('expected an error'),
|
||||
(error) => {
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.statusText).toEqual('Not Found');
|
||||
expect(error.error).toEqual('test 404 error');
|
||||
}
|
||||
);
|
||||
service.addRole(mockIdentityRole1).subscribe(
|
||||
() => fail('expected an error'),
|
||||
(error) => {
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.statusText).toEqual('Not Found');
|
||||
expect(error.error).toEqual('test 404 error');
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should be able to delete role', (done) => {
|
||||
@@ -109,30 +115,28 @@ describe('IdentityRoleService', () => {
|
||||
statusText: 'No Content'
|
||||
});
|
||||
spyOn(service, 'deleteRole').and.returnValue(of(response));
|
||||
service.deleteRole(mockIdentityRole1).subscribe(
|
||||
(res: any) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.status).toEqual(204);
|
||||
expect(res.statusText).toEqual('No Content');
|
||||
done();
|
||||
}
|
||||
);
|
||||
service.deleteRole(mockIdentityRole1).subscribe((res: any) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.status).toEqual(204);
|
||||
expect(res.statusText).toEqual('No Content');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Should not delete role if error occurred', () => {
|
||||
const errorResponse = new HttpErrorResponse({
|
||||
error: 'test 404 error',
|
||||
status: 404, statusText: 'Not Found'
|
||||
status: 404,
|
||||
statusText: 'Not Found'
|
||||
});
|
||||
spyOn(service, 'deleteRole').and.returnValue(throwError(errorResponse));
|
||||
service.deleteRole(mockIdentityRole1)
|
||||
.subscribe(
|
||||
() => fail('expected an error'),
|
||||
(error) => {
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.statusText).toEqual('Not Found');
|
||||
expect(error.error).toEqual('test 404 error');
|
||||
}
|
||||
);
|
||||
service.deleteRole(mockIdentityRole1).subscribe(
|
||||
() => fail('expected an error'),
|
||||
(error) => {
|
||||
expect(error.status).toEqual(404);
|
||||
expect(error.statusText).toEqual('Not Found');
|
||||
expect(error.error).toEqual('test 404 error');
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -22,7 +22,13 @@ import { AppConfigService } from '../../app-config/app-config.service';
|
||||
import { IdentityGroupModel } from '../models/identity-group.model';
|
||||
import { IdentityRoleModel } from '../models/identity-role.model';
|
||||
import { IdentityUserModel } from '../models/identity-user.model';
|
||||
import { IdentityJoinGroupRequestModel, IdentityUserServiceInterface, IdentityUserPasswordModel, IdentityUserQueryCloudRequestModel, IdentityUserQueryResponse } from '../interfaces/identity-user.service.interface';
|
||||
import {
|
||||
IdentityJoinGroupRequestModel,
|
||||
IdentityUserServiceInterface,
|
||||
IdentityUserPasswordModel,
|
||||
IdentityUserQueryCloudRequestModel,
|
||||
IdentityUserQueryResponse
|
||||
} from '../interfaces/identity-user.service.interface';
|
||||
import { JwtHelperService } from './jwt-helper.service';
|
||||
import { OAuth2Service } from './oauth2.service';
|
||||
|
||||
@@ -30,11 +36,7 @@ import { OAuth2Service } from './oauth2.service';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class IdentityUserService implements IdentityUserServiceInterface {
|
||||
|
||||
constructor(
|
||||
private jwtHelperService: JwtHelperService,
|
||||
private oAuth2Service: OAuth2Service,
|
||||
private appConfigService: AppConfigService) { }
|
||||
constructor(private jwtHelperService: JwtHelperService, private oAuth2Service: OAuth2Service, private appConfigService: AppConfigService) {}
|
||||
|
||||
private get identityHost(): string {
|
||||
return `${this.appConfigService.get('identityHost')}`;
|
||||
@@ -86,7 +88,7 @@ export class IdentityUserService implements IdentityUserServiceInterface {
|
||||
const url = this.buildUserUrl();
|
||||
const queryParams = { username };
|
||||
|
||||
return this.oAuth2Service.get({url, queryParams });
|
||||
return this.oAuth2Service.get({ url, queryParams });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,9 +141,7 @@ export class IdentityUserService implements IdentityUserServiceInterface {
|
||||
* @returns True if the user has access, false otherwise
|
||||
*/
|
||||
checkUserHasClientApp(userId: string, clientId: string): Observable<boolean> {
|
||||
return this.getClientRoles(userId, clientId).pipe(
|
||||
map((clientRoles) => clientRoles.length > 0)
|
||||
);
|
||||
return this.getClientRoles(userId, clientId).pipe(map((clientRoles) => clientRoles.length > 0));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,11 +181,7 @@ export class IdentityUserService implements IdentityUserServiceInterface {
|
||||
const url = `${this.identityHost}/clients`;
|
||||
const queryParams = { clientId: applicationName };
|
||||
|
||||
return this.oAuth2Service
|
||||
.get<any[]>({url, queryParams })
|
||||
.pipe(
|
||||
map((response) => response && response.length > 0 ? response[0].id : '')
|
||||
);
|
||||
return this.oAuth2Service.get<any[]>({ url, queryParams }).pipe(map((response) => (response && response.length > 0 ? response[0].id : '')));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,9 +192,7 @@ export class IdentityUserService implements IdentityUserServiceInterface {
|
||||
* @returns True if the user has access, false otherwise
|
||||
*/
|
||||
checkUserHasApplicationAccess(userId: string, applicationName: string): Observable<boolean> {
|
||||
return this.getClientIdByApplicationName(applicationName).pipe(
|
||||
switchMap((clientId: string) => this.checkUserHasClientApp(userId, clientId))
|
||||
);
|
||||
return this.getClientIdByApplicationName(applicationName).pipe(switchMap((clientId: string) => this.checkUserHasClientApp(userId, clientId)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,19 +296,21 @@ export class IdentityUserService implements IdentityUserServiceInterface {
|
||||
* @returns True if the user has one of the roles, false otherwise
|
||||
*/
|
||||
checkUserHasRole(userId: string, roleNames: string[]): Observable<boolean> {
|
||||
return this.getUserRoles(userId).pipe(map((userRoles: IdentityRoleModel[]) => {
|
||||
let hasRole = false;
|
||||
if (userRoles && userRoles.length > 0) {
|
||||
roleNames.forEach((roleName: string) => {
|
||||
const role = userRoles.find(({ name }) => roleName === name);
|
||||
if (role) {
|
||||
hasRole = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
return hasRole;
|
||||
}));
|
||||
return this.getUserRoles(userId).pipe(
|
||||
map((userRoles: IdentityRoleModel[]) => {
|
||||
let hasRole = false;
|
||||
if (userRoles && userRoles.length > 0) {
|
||||
roleNames.forEach((roleName: string) => {
|
||||
const role = userRoles.find(({ name }) => roleName === name);
|
||||
if (role) {
|
||||
hasRole = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
return hasRole;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -330,16 +326,19 @@ export class IdentityUserService implements IdentityUserServiceInterface {
|
||||
return this.getTotalUsersCount().pipe(
|
||||
switchMap((totalCount) =>
|
||||
this.oAuth2Service.get<IdentityUserModel[]>({ url, queryParams }).pipe(
|
||||
map((response) => ({
|
||||
entries: response,
|
||||
pagination: {
|
||||
skipCount: requestQuery.first,
|
||||
maxItems: requestQuery.max,
|
||||
count: totalCount,
|
||||
hasMoreItems: false,
|
||||
totalItems: totalCount
|
||||
}
|
||||
} as IdentityUserQueryResponse))
|
||||
map(
|
||||
(response) =>
|
||||
({
|
||||
entries: response,
|
||||
pagination: {
|
||||
skipCount: requestQuery.first,
|
||||
maxItems: requestQuery.max,
|
||||
count: totalCount,
|
||||
hasMoreItems: false,
|
||||
totalItems: totalCount
|
||||
}
|
||||
} as IdentityUserQueryResponse)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@@ -33,7 +33,7 @@ export class JwtHelperService {
|
||||
static USER_PREFERRED_USERNAME = 'preferred_username';
|
||||
static HXP_AUTHORIZATION = 'hxp_authorization';
|
||||
|
||||
private storageService: OAuthStorage = inject(OAuthStorage)
|
||||
private storageService: OAuthStorage = inject(OAuthStorage);
|
||||
|
||||
/**
|
||||
* Decodes a JSON web token into a JS object.
|
||||
|
@@ -36,17 +36,14 @@ export class OAuth2Service {
|
||||
request<T>(opts: OAuth2RequestParams): Observable<T> {
|
||||
const { httpMethod, url, bodyParam, queryParams } = opts;
|
||||
return from(
|
||||
this.adfHttpClient.request(
|
||||
url,
|
||||
{
|
||||
httpMethod,
|
||||
queryParams,
|
||||
headerParams: {},
|
||||
formParams: {},
|
||||
bodyParam,
|
||||
returnType: Object
|
||||
}
|
||||
)
|
||||
this.adfHttpClient.request(url, {
|
||||
httpMethod,
|
||||
queryParams,
|
||||
headerParams: {},
|
||||
formParams: {},
|
||||
bodyParam,
|
||||
returnType: Object
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -32,13 +32,9 @@ export interface TimeSync {
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TimeSyncService {
|
||||
|
||||
private readonly _http: HttpClient;
|
||||
|
||||
constructor(
|
||||
private _injector: Injector,
|
||||
private _appConfigService: AppConfigService
|
||||
) {
|
||||
constructor(private _injector: Injector, private _appConfigService: AppConfigService) {
|
||||
this._http = this._injector.get(HttpClient);
|
||||
}
|
||||
|
||||
@@ -59,7 +55,7 @@ export class TimeSyncService {
|
||||
serverTimeInMs = serverTimeResponse;
|
||||
}
|
||||
|
||||
const adjustedServerTimeInMs = serverTimeInMs + (roundTripTimeInMs / 2);
|
||||
const adjustedServerTimeInMs = serverTimeInMs + roundTripTimeInMs / 2;
|
||||
const localCurrentTimeInMs = Date.now();
|
||||
const timeOffsetInMs = Math.abs(localCurrentTimeInMs - adjustedServerTimeInMs);
|
||||
const maxAllowedClockSkewInMs = maxAllowedClockSkewInSec * 1000;
|
||||
@@ -71,7 +67,7 @@ export class TimeSyncService {
|
||||
serverDateTimeISO: new Date(adjustedServerTimeInMs).toISOString()
|
||||
};
|
||||
}),
|
||||
catchError(error => throwError(() => new Error(error)))
|
||||
catchError((error) => throwError(() => new Error(error)))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -82,9 +78,7 @@ export class TimeSyncService {
|
||||
* @returns An Observable that emits a boolean indicating whether the local time is out of sync.
|
||||
*/
|
||||
isLocalTimeOutOfSync(maxAllowedClockSkewInSec: number): Observable<boolean> {
|
||||
return this.checkTimeSync(maxAllowedClockSkewInSec).pipe(
|
||||
map(sync => sync.outOfSync)
|
||||
);
|
||||
return this.checkTimeSync(maxAllowedClockSkewInSec).pipe(map((sync) => sync.outOfSync));
|
||||
}
|
||||
|
||||
private getServerTime(): Observable<number> {
|
||||
|
@@ -27,9 +27,7 @@ export class UserAccessService {
|
||||
private globalAccess: string[];
|
||||
private applicationAccess: ApplicationAccessModel[];
|
||||
|
||||
constructor(private jwtHelperService: JwtHelperService,
|
||||
private appConfigService: AppConfigService) {
|
||||
}
|
||||
constructor(private jwtHelperService: JwtHelperService, private appConfigService: AppConfigService) {}
|
||||
|
||||
fetchUserAccess() {
|
||||
if (this.hasRolesInRealmAccess()) {
|
||||
@@ -100,8 +98,10 @@ export class UserAccessService {
|
||||
*/
|
||||
hasApplicationAccess(appName: string, rolesToCheck: string[]): boolean {
|
||||
if (rolesToCheck?.length > 0) {
|
||||
const appAccess = this.hasRolesInRealmAccess() ? this.applicationAccess[appName] : this.applicationAccess.find((app: ApplicationAccessModel) => app.name === appName);
|
||||
return appAccess ? appAccess.roles.some(appRole => rolesToCheck.includes(appRole)) : false;
|
||||
const appAccess = this.hasRolesInRealmAccess()
|
||||
? this.applicationAccess[appName]
|
||||
: this.applicationAccess.find((app: ApplicationAccessModel) => app.name === appName);
|
||||
return appAccess ? appAccess.roles.some((appRole) => rolesToCheck.includes(appRole)) : false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -123,5 +123,5 @@
|
||||
</ng-container>
|
||||
|
||||
<ng-template #buttonContent>
|
||||
<ng-content></ng-content>
|
||||
<ng-content />
|
||||
</ng-template>
|
||||
|
@@ -23,7 +23,7 @@ import { DEFAULT_SEPARATOR } from '../card-view-textitem/card-view-textitem.comp
|
||||
@Component({
|
||||
selector: 'adf-card-view-item-dispatcher',
|
||||
standalone: true,
|
||||
template: '<ng-template #content></ng-template>'
|
||||
template: '<ng-template #content />'
|
||||
})
|
||||
export class CardViewItemDispatcherComponent implements OnChanges {
|
||||
@Input()
|
||||
|
@@ -71,11 +71,11 @@
|
||||
border-bottom: 1px solid var(--adf-metadata-property-panel-border-color);
|
||||
}
|
||||
|
||||
.adf-property-readonly-value {
|
||||
color: var(--adf-metadata-property-panel-label-color);
|
||||
.adf-property-readonly-value:disabled {
|
||||
--mdc-filled-text-field-disabled-input-text-color: var(--adf-metadata-property-panel-title-color);
|
||||
}
|
||||
|
||||
.adf-property-value-editable {
|
||||
.adf-property-value-editable:not(:disabled) {
|
||||
color: var(--adf-metadata-property-panel-title-color);
|
||||
}
|
||||
|
||||
|
@@ -27,7 +27,6 @@ export interface CardViewArrayItem {
|
||||
}
|
||||
|
||||
export class CardViewArrayItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
|
||||
|
||||
type: string = 'array';
|
||||
value: Observable<CardViewArrayItem[]>;
|
||||
noOfItemsToDisplay: number;
|
||||
|
@@ -117,18 +117,20 @@ describe('CardViewBaseItemModel', () => {
|
||||
const isValid = itemModel.isValid('test-against-this');
|
||||
|
||||
expect(isValid).toBe(false);
|
||||
expect(itemModel.getValidationErrors('test-against-this')).toEqual([validator1, validator3 ]);
|
||||
expect(itemModel.getValidationErrors('test-against-this')).toEqual([validator1, validator3]);
|
||||
});
|
||||
|
||||
it('should validate field with special character and return false when there is REGEX constraint and requiresMatch is false', () => {
|
||||
const constrainedProperties: CardViewItemProperties = {
|
||||
...properties,
|
||||
value: 'test.',
|
||||
constraints: [{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '(.*[\\"\\*\\\\\\>\\<\\?\\/\\:\\|]+.*)|(.*[\\.]?.*[\\.]+$)|(.*[ ]+$)', requiresMatch: false }
|
||||
}]
|
||||
constraints: [
|
||||
{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '(.*[\\"\\*\\\\\\>\\<\\?\\/\\:\\|]+.*)|(.*[\\.]?.*[\\.]+$)|(.*[ ]+$)', requiresMatch: false }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const itemModel = new CarViewCustomItemModel(constrainedProperties);
|
||||
@@ -138,11 +140,13 @@ describe('CardViewBaseItemModel', () => {
|
||||
it('should validate field without special character and return true when there is REGEX constraint and requiresMatch is false', () => {
|
||||
const constrainedProperties: CardViewItemProperties = {
|
||||
...properties,
|
||||
constraints: [{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '(.*[\\"\\*\\\\\\>\\<\\?\\/\\:\\|]+.*)|(.*[\\.]?.*[\\.]+$)|(.*[ ]+$)', requiresMatch: false }
|
||||
}]
|
||||
constraints: [
|
||||
{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '(.*[\\"\\*\\\\\\>\\<\\?\\/\\:\\|]+.*)|(.*[\\.]?.*[\\.]+$)|(.*[ ]+$)', requiresMatch: false }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const itemModel = new CarViewCustomItemModel(constrainedProperties);
|
||||
@@ -152,11 +156,13 @@ describe('CardViewBaseItemModel', () => {
|
||||
it('should validate field without special character and return false when there is REGEX constraint and requiresMatch is true', () => {
|
||||
const constrainedProperties: CardViewItemProperties = {
|
||||
...properties,
|
||||
constraints: [{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '(.*[\\"\\*\\\\\\>\\<\\?\\/\\:\\|]+.*)|(.*[\\.]?.*[\\.]+$)|(.*[ ]+$)', requiresMatch: true }
|
||||
}]
|
||||
constraints: [
|
||||
{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '(.*[\\"\\*\\\\\\>\\<\\?\\/\\:\\|]+.*)|(.*[\\.]?.*[\\.]+$)|(.*[ ]+$)', requiresMatch: true }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const itemModel = new CarViewCustomItemModel(constrainedProperties);
|
||||
@@ -167,11 +173,13 @@ describe('CardViewBaseItemModel', () => {
|
||||
const constrainedProperties: CardViewItemProperties = {
|
||||
...properties,
|
||||
value: 'test.',
|
||||
constraints: [{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '(.*[\\"\\*\\\\\\>\\<\\?\\/\\:\\|]+.*)|(.*[\\.]?.*[\\.]+$)|(.*[ ]+$)', requiresMatch: true }
|
||||
}]
|
||||
constraints: [
|
||||
{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '(.*[\\"\\*\\\\\\>\\<\\?\\/\\:\\|]+.*)|(.*[\\.]?.*[\\.]+$)|(.*[ ]+$)', requiresMatch: true }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const itemModel = new CarViewCustomItemModel(constrainedProperties);
|
||||
|
@@ -19,7 +19,6 @@ import { CardViewBoolItemModel } from './card-view-boolitem.model';
|
||||
import { CardViewBoolItemProperties } from '../interfaces/card-view.interfaces';
|
||||
|
||||
describe('CardViewFloatItemModel', () => {
|
||||
|
||||
let properties: CardViewBoolItemProperties;
|
||||
|
||||
beforeEach(() => {
|
||||
|
@@ -19,7 +19,6 @@ import { CardViewFloatItemModel } from './card-view-floatitem.model';
|
||||
import { CardViewTextItemProperties } from '../interfaces/card-view.interfaces';
|
||||
|
||||
describe('CardViewFloatItemModel', () => {
|
||||
|
||||
let properties: CardViewTextItemProperties;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -43,7 +42,7 @@ describe('CardViewFloatItemModel', () => {
|
||||
expect(itemModel.value).toBe(undefined);
|
||||
});
|
||||
|
||||
it('isValid should return the validator\'s value', () => {
|
||||
it("isValid should return the validator's value", () => {
|
||||
const itemModel = new CardViewFloatItemModel(properties);
|
||||
|
||||
expect(itemModel.isValid(42)).toBe(true, 'For 42 it should be true');
|
||||
@@ -63,11 +62,13 @@ describe('CardViewFloatItemModel', () => {
|
||||
value: '42.42',
|
||||
key: 'tribe',
|
||||
dataType: 'd:float',
|
||||
constraints: [{
|
||||
id: 'constraint-id',
|
||||
type: 'MINMAX',
|
||||
parameters: { minValue: 10, maxValue: 40 }
|
||||
}]
|
||||
constraints: [
|
||||
{
|
||||
id: 'constraint-id',
|
||||
type: 'MINMAX',
|
||||
parameters: { minValue: 10, maxValue: 40 }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const itemModel = new CardViewFloatItemModel(constrainedProperties);
|
||||
|
@@ -19,7 +19,6 @@ import { CardViewIntItemModel } from './card-view-intitem.model';
|
||||
import { CardViewTextItemProperties } from '../interfaces/card-view.interfaces';
|
||||
|
||||
describe('CardViewIntItemModel', () => {
|
||||
|
||||
let properties: CardViewTextItemProperties;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -43,7 +42,7 @@ describe('CardViewIntItemModel', () => {
|
||||
expect(itemModel.value).toBe(undefined);
|
||||
});
|
||||
|
||||
it('isValid should return the validator\'s value', () => {
|
||||
it("isValid should return the validator's value", () => {
|
||||
const itemModel = new CardViewIntItemModel(properties);
|
||||
|
||||
expect(itemModel.isValid(42)).toBe(true, 'For 42 it should be true');
|
||||
@@ -63,11 +62,13 @@ describe('CardViewIntItemModel', () => {
|
||||
value: '20',
|
||||
key: 'tribe',
|
||||
dataType: 'd:float',
|
||||
constraints: [{
|
||||
id: 'constraint-id',
|
||||
type: 'MINMAX',
|
||||
parameters: { minValue: 10, maxValue: 15 }
|
||||
}]
|
||||
constraints: [
|
||||
{
|
||||
id: 'constraint-id',
|
||||
type: 'MINMAX',
|
||||
parameters: { minValue: 10, maxValue: 15 }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const itemModel = new CardViewIntItemModel(constrainedProperties);
|
||||
|
@@ -27,7 +27,6 @@ class TestPipe implements PipeTransform {
|
||||
}
|
||||
|
||||
describe('CardViewTextItemModel', () => {
|
||||
|
||||
let properties: CardViewTextItemProperties;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -39,7 +38,6 @@ describe('CardViewTextItemModel', () => {
|
||||
});
|
||||
|
||||
describe('displayValue', () => {
|
||||
|
||||
it('should return the value if it is present', () => {
|
||||
const itemModel = new CardViewTextItemModel(properties);
|
||||
|
||||
@@ -56,18 +54,14 @@ describe('CardViewTextItemModel', () => {
|
||||
});
|
||||
|
||||
it('should apply a pipe on the value if it is present', () => {
|
||||
properties.pipes = [
|
||||
{ pipe: new TestPipe() }
|
||||
];
|
||||
properties.pipes = [{ pipe: new TestPipe() }];
|
||||
const itemModel = new CardViewTextItemModel(properties);
|
||||
|
||||
expect(itemModel.displayValue).toBe('testpiped-Banuk');
|
||||
});
|
||||
|
||||
it('should apply a pipe on the value with parameters if those are present', () => {
|
||||
properties.pipes = [
|
||||
{ pipe: new TestPipe(), params: ['withParams'] }
|
||||
];
|
||||
properties.pipes = [{ pipe: new TestPipe(), params: ['withParams'] }];
|
||||
const itemModel = new CardViewTextItemModel(properties);
|
||||
|
||||
expect(itemModel.displayValue).toBe('testpiped-Banuk-withParams');
|
||||
@@ -91,11 +85,13 @@ describe('CardViewTextItemModel', () => {
|
||||
label: 'Tribe',
|
||||
value: 'test',
|
||||
key: 'tribe',
|
||||
constraints: [{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '^(?=.*test).*', requiresMatch: true }
|
||||
}]
|
||||
constraints: [
|
||||
{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '^(?=.*test).*', requiresMatch: true }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const itemModel = new CardViewTextItemModel(constrainedProperties);
|
||||
@@ -110,11 +106,13 @@ describe('CardViewTextItemModel', () => {
|
||||
label: 'Tribe',
|
||||
value: 'test',
|
||||
key: 'tribe',
|
||||
constraints: [{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '^(?=.*test).*', requiresMatch: false }
|
||||
}]
|
||||
constraints: [
|
||||
{
|
||||
id: 'constraint-id',
|
||||
type: 'REGEX',
|
||||
parameters: { expression: '^(?=.*test).*', requiresMatch: false }
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const itemModel = new CardViewTextItemModel(constrainedProperties);
|
||||
|
@@ -20,9 +20,7 @@ import { CardViewBaseItemModel } from '../models/card-view-baseitem.model';
|
||||
import { CardViewUpdateService, transformKeyToObject } from './card-view-update.service';
|
||||
|
||||
describe('CardViewUpdateService', () => {
|
||||
|
||||
describe('transformKeyToObject', () => {
|
||||
|
||||
it('should return the proper constructed value object for "dotless" keys', () => {
|
||||
const valueObject = transformKeyToObject('property-key', 'property-value');
|
||||
|
||||
@@ -47,7 +45,6 @@ describe('CardViewUpdateService', () => {
|
||||
});
|
||||
|
||||
describe('Service', () => {
|
||||
|
||||
let cardViewUpdateService: CardViewUpdateService;
|
||||
const property: CardViewBaseItemModel = {
|
||||
label: 'property-label',
|
||||
@@ -63,23 +60,17 @@ describe('CardViewUpdateService', () => {
|
||||
});
|
||||
|
||||
it('should send updated message with proper parameters', fakeAsync(() => {
|
||||
|
||||
cardViewUpdateService.itemUpdated$.subscribe(
|
||||
( { target, changed } ) => {
|
||||
expect(target).toBe(property);
|
||||
expect(changed).toEqual({ 'property-key': 'changed-property-value' });
|
||||
}
|
||||
);
|
||||
cardViewUpdateService.itemUpdated$.subscribe(({ target, changed }) => {
|
||||
expect(target).toBe(property);
|
||||
expect(changed).toEqual({ 'property-key': 'changed-property-value' });
|
||||
});
|
||||
cardViewUpdateService.update(property, 'changed-property-value');
|
||||
}));
|
||||
|
||||
it('should send clicked message with proper parameters', fakeAsync(() => {
|
||||
|
||||
cardViewUpdateService.itemClicked$.subscribe(
|
||||
( { target } ) => {
|
||||
expect(target).toBe(property);
|
||||
}
|
||||
);
|
||||
cardViewUpdateService.itemClicked$.subscribe(({ target }) => {
|
||||
expect(target).toBe(property);
|
||||
});
|
||||
cardViewUpdateService.clicked(property);
|
||||
}));
|
||||
});
|
||||
|
@@ -18,7 +18,6 @@
|
||||
import { CardViewItemValidator } from '../interfaces/card-view.interfaces';
|
||||
|
||||
export class CardViewItemFloatValidator implements CardViewItemValidator {
|
||||
|
||||
message = 'CORE.CARDVIEW.VALIDATORS.FLOAT_VALIDATION_ERROR';
|
||||
|
||||
isValid(value: any | any[]): boolean {
|
||||
|
@@ -18,7 +18,6 @@
|
||||
import { CardViewItemValidator } from '../interfaces/card-view.interfaces';
|
||||
|
||||
export class CardViewItemIntValidator implements CardViewItemValidator {
|
||||
|
||||
message = 'CORE.CARDVIEW.VALIDATORS.INT_VALIDATION_ERROR';
|
||||
|
||||
isValid(value: any | any[]): boolean {
|
||||
@@ -26,7 +25,7 @@ export class CardViewItemIntValidator implements CardViewItemValidator {
|
||||
return value.every(this.isIntegerNumber);
|
||||
}
|
||||
|
||||
return value === '' || !isNaN(value) && this.isIntegerNumber(value) && this.isNotOnlySpace(value);
|
||||
return value === '' || (!isNaN(value) && this.isIntegerNumber(value) && this.isNotOnlySpace(value));
|
||||
}
|
||||
|
||||
isIntegerNumber(value: any): boolean {
|
||||
|
@@ -27,11 +27,7 @@ export class CardViewItemPositiveIntValidator implements CardViewItemValidator {
|
||||
|
||||
const valueIsNotSet = value === '';
|
||||
|
||||
return valueIsNotSet ||
|
||||
(
|
||||
!isNaN(value) &&
|
||||
this.isPositiveNumber(value)
|
||||
);
|
||||
return valueIsNotSet || (!isNaN(value) && this.isPositiveNumber(value));
|
||||
}
|
||||
|
||||
private isPositiveNumber(value: any): boolean {
|
||||
|
@@ -20,7 +20,6 @@ import { Observable, of } from 'rxjs';
|
||||
import { CommentsService } from '../interfaces/comments-service.interface';
|
||||
|
||||
export class CommentsServiceMock implements Partial<CommentsService> {
|
||||
|
||||
constructor() {}
|
||||
|
||||
get(_id: string): Observable<CommentModel[]> {
|
||||
@@ -40,36 +39,38 @@ const commentUser = new User({
|
||||
});
|
||||
|
||||
export const commentsResponseMock = {
|
||||
getComments: () => of([
|
||||
new CommentModel({
|
||||
id: 1,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
}),
|
||||
new CommentModel({
|
||||
id: 2,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
}),
|
||||
new CommentModel({
|
||||
id: 3,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
})
|
||||
]),
|
||||
addComment: (message = 'test comment') => of(
|
||||
new CommentModel({
|
||||
id: 1,
|
||||
message,
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
})
|
||||
)
|
||||
getComments: () =>
|
||||
of([
|
||||
new CommentModel({
|
||||
id: 1,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
}),
|
||||
new CommentModel({
|
||||
id: 2,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
}),
|
||||
new CommentModel({
|
||||
id: 3,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
})
|
||||
]),
|
||||
addComment: (message = 'test comment') =>
|
||||
of(
|
||||
new CommentModel({
|
||||
id: 1,
|
||||
message,
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
})
|
||||
)
|
||||
};
|
||||
|
@@ -21,7 +21,6 @@ import { CommentsService } from '../interfaces/comments-service.interface';
|
||||
import { testUser } from './comments.stories.mock';
|
||||
|
||||
export class CommentsServiceStoriesMock implements Partial<CommentsService> {
|
||||
|
||||
constructor() {}
|
||||
|
||||
get(_id: string): Observable<CommentModel[]> {
|
||||
@@ -41,36 +40,38 @@ const commentUser = new User({
|
||||
});
|
||||
|
||||
export const commentsResponseMock = {
|
||||
getComments: () => of([
|
||||
new CommentModel({
|
||||
id: 1,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
}),
|
||||
new CommentModel({
|
||||
id: 2,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
}),
|
||||
new CommentModel({
|
||||
id: 3,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
})
|
||||
]),
|
||||
addComment: (message: string) => of(
|
||||
new CommentModel({
|
||||
id: 1,
|
||||
message,
|
||||
created: new Date(),
|
||||
createdBy: testUser,
|
||||
isSelected: false
|
||||
})
|
||||
)
|
||||
getComments: () =>
|
||||
of([
|
||||
new CommentModel({
|
||||
id: 1,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
}),
|
||||
new CommentModel({
|
||||
id: 2,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
}),
|
||||
new CommentModel({
|
||||
id: 3,
|
||||
message: 'Test Comment',
|
||||
created: new Date(),
|
||||
createdBy: commentUser,
|
||||
isSelected: false
|
||||
})
|
||||
]),
|
||||
addComment: (message: string) =>
|
||||
of(
|
||||
new CommentModel({
|
||||
id: 1,
|
||||
message,
|
||||
created: new Date(),
|
||||
createdBy: testUser,
|
||||
isSelected: false
|
||||
})
|
||||
)
|
||||
};
|
||||
|
@@ -72,35 +72,34 @@ export const testUser: any = {
|
||||
avatarId: '044'
|
||||
};
|
||||
|
||||
|
||||
export const commentsStoriesData: CommentModel[] = [
|
||||
new CommentModel({
|
||||
id: 1,
|
||||
message: `I've done this task, what's next?`,
|
||||
created: getDateXMinutesAgo(30),
|
||||
createdBy: johnDoe,
|
||||
isSelected: false
|
||||
id: 1,
|
||||
message: `I've done this task, what's next?`,
|
||||
created: getDateXMinutesAgo(30),
|
||||
createdBy: johnDoe,
|
||||
isSelected: false
|
||||
}),
|
||||
new CommentModel({
|
||||
id: 2,
|
||||
message: `I've assigned you another one 🤠`,
|
||||
created: getDateXMinutesAgo(15),
|
||||
createdBy: janeEod,
|
||||
isSelected: false
|
||||
id: 2,
|
||||
message: `I've assigned you another one 🤠`,
|
||||
created: getDateXMinutesAgo(15),
|
||||
createdBy: janeEod,
|
||||
isSelected: false
|
||||
}),
|
||||
new CommentModel({
|
||||
id: 3,
|
||||
message: '+1',
|
||||
created: getDateXMinutesAgo(12),
|
||||
createdBy: robertSmith,
|
||||
isSelected: false
|
||||
id: 3,
|
||||
message: '+1',
|
||||
created: getDateXMinutesAgo(12),
|
||||
createdBy: robertSmith,
|
||||
isSelected: false
|
||||
}),
|
||||
new CommentModel({
|
||||
id: 4,
|
||||
message: 'Cheers',
|
||||
created: new Date(),
|
||||
createdBy: johnDoe,
|
||||
isSelected: false
|
||||
id: 4,
|
||||
message: 'Cheers',
|
||||
created: new Date(),
|
||||
createdBy: johnDoe,
|
||||
isSelected: false
|
||||
})
|
||||
];
|
||||
|
||||
|
@@ -25,10 +25,10 @@ export class LogLevelsEnum extends Number {
|
||||
}
|
||||
|
||||
export const logLevels: any[] = [
|
||||
{level: LogLevelsEnum.TRACE, name: 'TRACE'},
|
||||
{level: LogLevelsEnum.DEBUG, name: 'DEBUG'},
|
||||
{level: LogLevelsEnum.INFO, name: 'INFO'},
|
||||
{level: LogLevelsEnum.WARN, name: 'WARN'},
|
||||
{level: LogLevelsEnum.ERROR, name: 'ERROR'},
|
||||
{level: LogLevelsEnum.SILENT, name: 'SILENT'}
|
||||
{ level: LogLevelsEnum.TRACE, name: 'TRACE' },
|
||||
{ level: LogLevelsEnum.DEBUG, name: 'DEBUG' },
|
||||
{ level: LogLevelsEnum.INFO, name: 'INFO' },
|
||||
{ level: LogLevelsEnum.WARN, name: 'WARN' },
|
||||
{ level: LogLevelsEnum.ERROR, name: 'ERROR' },
|
||||
{ level: LogLevelsEnum.SILENT, name: 'SILENT' }
|
||||
];
|
||||
|
@@ -21,7 +21,6 @@ import { Injectable } from '@angular/core';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class CookieService {
|
||||
|
||||
cookieEnabled = false;
|
||||
|
||||
constructor() {
|
||||
@@ -53,7 +52,7 @@ export class CookieService {
|
||||
getItem(key: string): string | null {
|
||||
const regexp = new RegExp('(?:' + key + '|;\\s*' + key + ')=(.*?)(?:;|$)', 'g');
|
||||
const result = regexp.exec(document.cookie);
|
||||
return (result === null) ? null : result[1];
|
||||
return result === null ? null : result[1];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,9 +64,7 @@ export class CookieService {
|
||||
* @param path "Pathname" to store the cookie
|
||||
*/
|
||||
setItem(key: string, data: string, expiration: Date | null = null, path: string | null = null): void {
|
||||
document.cookie = `${key}=${data}` +
|
||||
(expiration ? ';expires=' + expiration.toUTCString() : '') +
|
||||
(path ? `;path=${path}` : ';path=/');
|
||||
document.cookie = `${key}=${data}` + (expiration ? ';expires=' + expiration.toUTCString() : '') + (path ? `;path=${path}` : ';path=/');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,8 +74,7 @@ export class CookieService {
|
||||
* @param path "Pathname" to store the cookie
|
||||
*/
|
||||
deleteCookie(key: string, path: string | null = null): void {
|
||||
document.cookie = key + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;' +
|
||||
(path ? `;path=${path}` : ';path=/');
|
||||
document.cookie = key + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;' + (path ? `;path=${path}` : ';path=/');
|
||||
}
|
||||
|
||||
/** Placeholder for testing purposes - do not use. */
|
||||
|
@@ -42,8 +42,7 @@ export class DownloadService {
|
||||
}
|
||||
|
||||
if (blob) {
|
||||
if (typeof window.navigator !== 'undefined' &&
|
||||
window.navigator['msSaveOrOpenBlob']) {
|
||||
if (window.navigator?.['msSaveOrOpenBlob']) {
|
||||
window.navigator['msSaveOrOpenBlob'](blob, fileName);
|
||||
} else {
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
|
@@ -17,10 +17,13 @@
|
||||
|
||||
import { Type } from '@angular/core';
|
||||
|
||||
const getType = (type: any): any => () => type;
|
||||
const getType =
|
||||
(type: any): any =>
|
||||
() =>
|
||||
type;
|
||||
|
||||
export interface DynamicComponentModel {
|
||||
type: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export type DynamicComponentResolveFunction = (model: DynamicComponentModel) => Type<any>;
|
||||
@@ -31,7 +34,6 @@ export class DynamicComponentResolver {
|
||||
}
|
||||
|
||||
export abstract class DynamicComponentMapper {
|
||||
|
||||
protected defaultValue: Type<any> = undefined;
|
||||
protected types: { [key: string]: DynamicComponentResolveFunction } = {};
|
||||
|
||||
|
@@ -26,7 +26,6 @@ export interface HighlightTransformResult {
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class HighlightTransformService {
|
||||
|
||||
/**
|
||||
* Searches for `search` string(s) within `text` and highlights all occurrences.
|
||||
*
|
||||
@@ -42,7 +41,10 @@ export class HighlightTransformService {
|
||||
if (search && text) {
|
||||
// eslint-disable-next-line no-useless-escape
|
||||
let pattern = search.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
|
||||
pattern = pattern.split(' ').filter((t) => t.length > 0).join('|');
|
||||
pattern = pattern
|
||||
.split(' ')
|
||||
.filter((t) => t.length > 0)
|
||||
.join('|');
|
||||
|
||||
const regex = new RegExp(pattern, 'gi');
|
||||
result = this.removeHtmlTags(text).replace(regex, (match) => {
|
||||
|
@@ -166,11 +166,9 @@ describe('LogService', () => {
|
||||
it('message Observable', fakeAsync(() => {
|
||||
appConfigService.config['logLevel'] = 'trace';
|
||||
|
||||
providesLogComponent.componentInstance.logService.onMessage.subscribe(
|
||||
(message) => {
|
||||
expect(message).toEqual({ text: 'Test message', type: 'LOG' });
|
||||
}
|
||||
);
|
||||
providesLogComponent.componentInstance.logService.onMessage.subscribe((message) => {
|
||||
expect(message).toEqual({ text: 'Test message', type: 'LOG' });
|
||||
});
|
||||
|
||||
providesLogComponent.componentInstance.log();
|
||||
}));
|
||||
|
@@ -24,14 +24,10 @@ import { TranslationService } from '../../translation/translation.service';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PageTitleService {
|
||||
|
||||
private originalTitle: string = '';
|
||||
private translatedTitle: string = '';
|
||||
|
||||
constructor(
|
||||
private titleService: Title,
|
||||
private appConfig: AppConfigService,
|
||||
private translationService: TranslationService) {
|
||||
constructor(private titleService: Title, private appConfig: AppConfigService, private translationService: TranslationService) {
|
||||
translationService.translate.onLangChange.subscribe(() => this.onLanguageChanged());
|
||||
translationService.translate.onTranslationChange.subscribe(() => this.onLanguageChanged());
|
||||
}
|
||||
|
@@ -178,7 +178,7 @@ export class ThumbnailService {
|
||||
*/
|
||||
public getMimeTypeIcon(mimeType: string): string {
|
||||
const icon = this.mimeTypeIcons[mimeType];
|
||||
return (icon || DEFAULT_ICON);
|
||||
return icon || DEFAULT_ICON;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -22,9 +22,7 @@ import { DomSanitizer } from '@angular/platform-browser';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UrlService {
|
||||
|
||||
constructor(private sanitizer: DomSanitizer) {
|
||||
}
|
||||
constructor(private sanitizer: DomSanitizer) {}
|
||||
|
||||
/**
|
||||
* Creates a trusted object URL from the Blob.
|
||||
@@ -37,6 +35,4 @@ export class UrlService {
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
return this.sanitizer.bypassSecurityTrustUrl(url) as string;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -18,7 +18,6 @@
|
||||
import { ObjectUtils } from './object-utils';
|
||||
|
||||
describe('ObjectUtils', () => {
|
||||
|
||||
it('should get top level property value', () => {
|
||||
const obj = {
|
||||
id: 1
|
||||
|
@@ -25,7 +25,6 @@ export class ObjectUtils {
|
||||
* @returns object property value
|
||||
*/
|
||||
static getValue(target: any, key: string): any {
|
||||
|
||||
if (!target || !key) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -80,46 +79,38 @@ export class ObjectUtils {
|
||||
}
|
||||
|
||||
static isBooleanObject(target: any): boolean {
|
||||
return Object.values(target).every(value => typeof value === 'boolean');
|
||||
return Object.values(target).every((value) => typeof value === 'boolean');
|
||||
}
|
||||
|
||||
static booleanPrettify(target: any, enhancer?: (param: string) => string): string {
|
||||
|
||||
if (
|
||||
!target ||
|
||||
ObjectUtils.isEmpty(target) ||
|
||||
!ObjectUtils.isBooleanObject(target)
|
||||
) {
|
||||
if (!target || ObjectUtils.isEmpty(target) || !ObjectUtils.isBooleanObject(target)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (
|
||||
!ObjectUtils.isObject(target) ||
|
||||
!ObjectUtils.hasKeys(target)
|
||||
) {
|
||||
if (!ObjectUtils.isObject(target) || !ObjectUtils.hasKeys(target)) {
|
||||
return target.toString();
|
||||
}
|
||||
|
||||
const greenBorderWhiteCheckSymbol = '✅';
|
||||
const redCrossSymbol = '❌';
|
||||
|
||||
target = Object.keys(target).map((key) => {
|
||||
if (target[key]) {
|
||||
if (enhancer) {
|
||||
return `${greenBorderWhiteCheckSymbol} ${enhancer(key)}`;
|
||||
} else {
|
||||
return `${greenBorderWhiteCheckSymbol} ${key}`;
|
||||
target = Object.keys(target)
|
||||
.map((key) => {
|
||||
if (target[key]) {
|
||||
if (enhancer) {
|
||||
return `${greenBorderWhiteCheckSymbol} ${enhancer(key)}`;
|
||||
} else {
|
||||
return `${greenBorderWhiteCheckSymbol} ${key}`;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (enhancer) {
|
||||
return `${redCrossSymbol} ${enhancer(key)}`;
|
||||
} else {
|
||||
return `${redCrossSymbol} ${key}`;
|
||||
}
|
||||
|
||||
}).join('\n');
|
||||
if (enhancer) {
|
||||
return `${redCrossSymbol} ${enhancer(key)}`;
|
||||
} else {
|
||||
return `${redCrossSymbol} ${key}`;
|
||||
}
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
return target;
|
||||
}
|
||||
|
@@ -18,7 +18,6 @@
|
||||
import { ObjectUtils } from './object-utils';
|
||||
|
||||
export class StringUtils {
|
||||
|
||||
static capitalize(target: string): string {
|
||||
return target.charAt(0).toUpperCase() + target.slice(1).toLowerCase();
|
||||
}
|
||||
@@ -37,7 +36,7 @@ export class StringUtils {
|
||||
|
||||
static removeAll(target: string, ...delimiters: string[]): string {
|
||||
const delimiterObj = {};
|
||||
delimiters.forEach(delimiter => {
|
||||
delimiters.forEach((delimiter) => {
|
||||
delimiterObj[delimiter] = '';
|
||||
});
|
||||
|
||||
@@ -49,8 +48,6 @@ export class StringUtils {
|
||||
const bagOfWords = redactedTarget.split(' ');
|
||||
const capitalizedBagOfWords = bagOfWords.map((word) => StringUtils.capitalize(word));
|
||||
|
||||
|
||||
return capitalizedBagOfWords.join(' ');
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -15,32 +15,26 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
state,
|
||||
style,
|
||||
animate,
|
||||
transition,
|
||||
query,
|
||||
group,
|
||||
sequence,
|
||||
AnimationStateMetadata,
|
||||
AnimationTransitionMetadata
|
||||
} from '@angular/animations';
|
||||
import { state, style, animate, transition, query, group, sequence, AnimationStateMetadata, AnimationTransitionMetadata } from '@angular/animations';
|
||||
|
||||
export const contextMenuAnimation: ( AnimationStateMetadata | AnimationTransitionMetadata)[] = [
|
||||
state('void', style({
|
||||
opacity: 0,
|
||||
transform: 'scale(0.01, 0.01)'
|
||||
})),
|
||||
transition('void => *', sequence([
|
||||
query('.mat-mdc-menu-content', style({ opacity: 0 })),
|
||||
animate('100ms linear', style({ opacity: 1, transform: 'scale(1, 0.5)' })),
|
||||
group([
|
||||
query('.mat-mdc-menu-content', animate('400ms cubic-bezier(0.55, 0, 0.55, 0.2)',
|
||||
style({ opacity: 1 })
|
||||
)),
|
||||
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({ transform: 'scale(1, 1)' }))
|
||||
export const contextMenuAnimation: (AnimationStateMetadata | AnimationTransitionMetadata)[] = [
|
||||
state(
|
||||
'void',
|
||||
style({
|
||||
opacity: 0,
|
||||
transform: 'scale(0.01, 0.01)'
|
||||
})
|
||||
),
|
||||
transition(
|
||||
'void => *',
|
||||
sequence([
|
||||
query('.mat-mdc-menu-content', style({ opacity: 0 })),
|
||||
animate('100ms linear', style({ opacity: 1, transform: 'scale(1, 0.5)' })),
|
||||
group([
|
||||
query('.mat-mdc-menu-content', animate('400ms cubic-bezier(0.55, 0, 0.55, 0.2)', style({ opacity: 1 }))),
|
||||
animate('300ms cubic-bezier(0.25, 0.8, 0.25, 1)', style({ transform: 'scale(1, 1)' }))
|
||||
])
|
||||
])
|
||||
])),
|
||||
),
|
||||
transition('* => void', animate('150ms 50ms linear', style({ opacity: 0 })))
|
||||
];
|
||||
|
@@ -33,11 +33,7 @@ const DEFAULT_CONFIG: ContextMenuOverlayConfig = {
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ContextMenuOverlayService {
|
||||
|
||||
constructor(
|
||||
private injector: Injector,
|
||||
private overlay: Overlay
|
||||
) {}
|
||||
constructor(private injector: Injector, private overlay: Overlay) {}
|
||||
|
||||
open(config: ContextMenuOverlayConfig): ContextMenuOverlayRef {
|
||||
const overlayConfig = { ...DEFAULT_CONFIG, ...config };
|
||||
@@ -53,12 +49,15 @@ export class ContextMenuOverlayService {
|
||||
// prevent native contextmenu on overlay element if config.hasBackdrop is true
|
||||
if (overlayConfig.hasBackdrop) {
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
(overlay as any)._backdropElement
|
||||
.addEventListener('contextmenu', (event) => {
|
||||
(overlay as any)._backdropElement.addEventListener(
|
||||
'contextmenu',
|
||||
(event) => {
|
||||
event.preventDefault();
|
||||
// eslint-disable-next-line no-underscore-dangle
|
||||
(overlay as any)._backdropClick.next(null);
|
||||
}, true);
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
return overlayRef;
|
||||
@@ -88,28 +87,31 @@ export class ContextMenuOverlayService {
|
||||
}
|
||||
|
||||
private getOverlayConfig(config: ContextMenuOverlayConfig): OverlayConfig {
|
||||
const { clientY, clientX } = config.source;
|
||||
const { clientY, clientX } = config.source;
|
||||
|
||||
const fakeElement: any = {
|
||||
getBoundingClientRect: (): ClientRect => ({
|
||||
bottom: clientY,
|
||||
height: 0,
|
||||
left: clientX,
|
||||
right: clientX,
|
||||
top: clientY,
|
||||
width: 0
|
||||
} as any)
|
||||
getBoundingClientRect: (): ClientRect =>
|
||||
({
|
||||
bottom: clientY,
|
||||
height: 0,
|
||||
left: clientX,
|
||||
right: clientX,
|
||||
top: clientY,
|
||||
width: 0
|
||||
} as any)
|
||||
};
|
||||
|
||||
const positionStrategy = this.overlay
|
||||
.position()
|
||||
.flexibleConnectedTo(new ElementRef(fakeElement))
|
||||
.withPositions([{
|
||||
originX: 'start',
|
||||
originY: 'bottom',
|
||||
overlayX: 'start',
|
||||
overlayY: 'top'
|
||||
}]);
|
||||
.withPositions([
|
||||
{
|
||||
originX: 'start',
|
||||
originY: 'bottom',
|
||||
overlayX: 'start',
|
||||
overlayY: 'top'
|
||||
}
|
||||
]);
|
||||
|
||||
const overlayConfig = new OverlayConfig({
|
||||
hasBackdrop: config.hasBackdrop,
|
||||
|
@@ -18,8 +18,7 @@
|
||||
import { OverlayRef } from '@angular/cdk/overlay';
|
||||
|
||||
export class ContextMenuOverlayRef {
|
||||
|
||||
constructor(private overlayRef: OverlayRef) { }
|
||||
constructor(private overlayRef: OverlayRef) {}
|
||||
|
||||
close(): void {
|
||||
this.overlayRef.dispose();
|
||||
|
@@ -20,7 +20,6 @@ import { DataColumn } from '../data/data-column.model';
|
||||
import { DataRow } from '../data/data-row.model';
|
||||
|
||||
export class DataCellEventModel {
|
||||
|
||||
readonly row: DataRow;
|
||||
readonly col: DataColumn;
|
||||
actions: any[];
|
||||
@@ -30,14 +29,11 @@ export class DataCellEventModel {
|
||||
this.col = col;
|
||||
this.actions = actions || [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class DataCellEvent extends BaseEvent<DataCellEventModel> {
|
||||
|
||||
constructor(row: DataRow, col: DataColumn, actions: any[]) {
|
||||
super();
|
||||
this.value = new DataCellEventModel(row, col, actions);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,7 +19,6 @@ import { BaseEvent } from '../../events';
|
||||
import { DataRow } from '../data/data-row.model';
|
||||
|
||||
export class DataRowActionModel {
|
||||
|
||||
row: DataRow;
|
||||
action: any;
|
||||
|
||||
@@ -30,7 +29,6 @@ export class DataRowActionModel {
|
||||
}
|
||||
|
||||
export class DataRowActionEvent extends BaseEvent<DataRowActionModel> {
|
||||
|
||||
// backwards compatibility with 1.2.0 and earlier
|
||||
get args(): DataRowActionModel {
|
||||
return this.value;
|
||||
@@ -40,5 +38,4 @@ export class DataRowActionEvent extends BaseEvent<DataRowActionModel> {
|
||||
super();
|
||||
this.value = new DataRowActionModel(row, action);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ import { DataRow } from '../../data/data-row.model';
|
||||
@Component({
|
||||
selector: 'adf-datatable-row',
|
||||
standalone: true,
|
||||
template: `<ng-content></ng-content>`,
|
||||
template: `<ng-content />`,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: {
|
||||
class: 'adf-datatable-row',
|
||||
|
@@ -104,7 +104,7 @@
|
||||
</ng-container>
|
||||
|
||||
<div *ngIf="col.header" class="adf-datatable-cell-value">
|
||||
<ng-template [ngTemplateOutlet]="col.header" [ngTemplateOutletContext]="{$implicit: col}"></ng-template>
|
||||
<ng-template [ngTemplateOutlet]="col.header" [ngTemplateOutletContext]="{$implicit: col}" />
|
||||
</div>
|
||||
|
||||
<span
|
||||
@@ -112,7 +112,7 @@
|
||||
[class.adf-datatable__header--sorted-desc]="isColumnSorted(col, 'desc')">
|
||||
</span>
|
||||
|
||||
<ng-template *ngIf="allowFiltering" [ngTemplateOutlet]="headerFilterTemplate" [ngTemplateOutletContext]="{$implicit: col}"></ng-template>
|
||||
<ng-template *ngIf="allowFiltering" [ngTemplateOutlet]="headerFilterTemplate" [ngTemplateOutletContext]="{$implicit: col}" />
|
||||
|
||||
<span
|
||||
*ngIf="col.draggable"
|
||||
@@ -434,9 +434,8 @@
|
||||
<div class="adf-no-content-container adf-datatable-cell" role="gridcell">
|
||||
<ng-template *ngIf="noContentTemplate"
|
||||
ngFor [ngForOf]="[data]"
|
||||
[ngForTemplate]="noContentTemplate">
|
||||
</ng-template>
|
||||
<ng-content select="adf-empty-list"></ng-content>
|
||||
[ngForTemplate]="noContentTemplate" />
|
||||
<ng-content select="adf-empty-list" />
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
@@ -448,8 +447,7 @@
|
||||
<div class="adf-no-permission__cell adf-no-content-container adf-datatable-cell">
|
||||
<ng-template *ngIf="noPermissionTemplate"
|
||||
ngFor [ngForOf]="[data]"
|
||||
[ngForTemplate]="noPermissionTemplate">
|
||||
</ng-template>
|
||||
[ngForTemplate]="noPermissionTemplate" />
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
@@ -459,8 +457,7 @@
|
||||
<div class="adf-no-content-container adf-datatable-cell">
|
||||
<ng-template *ngIf="loadingTemplate"
|
||||
ngFor [ngForOf]="[data]"
|
||||
[ngForTemplate]="loadingTemplate">
|
||||
</ng-template>
|
||||
[ngForTemplate]="loadingTemplate" />
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
@@ -38,7 +38,7 @@ import { HarnessLoader } from '@angular/cdk/testing';
|
||||
@Component({
|
||||
selector: 'adf-custom-column-template-component',
|
||||
standalone: true,
|
||||
template: ` <ng-template #tmplRef></ng-template> `
|
||||
template: ` <ng-template #tmplRef /> `
|
||||
})
|
||||
class CustomColumnTemplateComponent {
|
||||
@ViewChild('tmplRef', { static: true }) templateRef: TemplateRef<any>;
|
||||
|
@@ -32,7 +32,6 @@ import { LocalizedDatePipe, TimeAgoPipe } from '../../../pipes';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class DateCellComponent extends DataTableCellComponent implements OnInit {
|
||||
|
||||
@Input()
|
||||
dateConfig: DateConfig;
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<div class="adf-empty-list_template">
|
||||
<ng-content select="[adf-empty-list-header]"></ng-content>
|
||||
<ng-content select="[adf-empty-list-body]"></ng-content>
|
||||
<ng-content select="[adf-empty-list-footer]"></ng-content>
|
||||
<ng-content></ng-content>
|
||||
<ng-content select="[adf-empty-list-header]" />
|
||||
<ng-content select="[adf-empty-list-body]" />
|
||||
<ng-content select="[adf-empty-list-footer]" />
|
||||
<ng-content />
|
||||
</div>
|
@@ -22,11 +22,12 @@ export const mockCarsData: any = [
|
||||
{
|
||||
car_id: 1,
|
||||
car_name: 'Fiat 126p (Process)',
|
||||
car_price: 599.00,
|
||||
car_price: 599.0,
|
||||
fuel_consumption: 5.25789,
|
||||
is_available: 'false',
|
||||
production_start: '1972-04-23',
|
||||
description: 'The Fiat 126 (Type 126) is a four-passenger, rear-engine, city car manufactured and marketed by Fiat over a twenty-eight year production run from 1972 until 2000, over a single generation.',
|
||||
description:
|
||||
'The Fiat 126 (Type 126) is a four-passenger, rear-engine, city car manufactured and marketed by Fiat over a twenty-eight year production run from 1972 until 2000, over a single generation.',
|
||||
icon: 'airport_shuttle',
|
||||
wikipedia_link: 'https://en.wikipedia.org/wiki/Fiat_126'
|
||||
},
|
||||
@@ -48,7 +49,8 @@ export const mockCarsData: any = [
|
||||
fuel_consumption: 6,
|
||||
is_available: 'true',
|
||||
production_start: '1998-06-25T12:25:20',
|
||||
description: 'The Audi A3 is a subcompact executive/small family car (C-segment) manufactured and marketed by the German automaker Audi AG since September 1996, currently in its fourth generation.',
|
||||
description:
|
||||
'The Audi A3 is a subcompact executive/small family car (C-segment) manufactured and marketed by the German automaker Audi AG since September 1996, currently in its fourth generation.',
|
||||
icon: 'directions_car',
|
||||
wikipedia_link: 'https://en.wikipedia.org/wiki/Audi_A3'
|
||||
}
|
||||
|
@@ -15,13 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ViewEncapsulation,
|
||||
Input,
|
||||
OnInit
|
||||
} from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, ViewEncapsulation, Input, OnInit } from '@angular/core';
|
||||
import { DataTableCellComponent } from '../datatable-cell/datatable-cell.component';
|
||||
import { DecimalConfig } from '../../data/data-column.model';
|
||||
import { CommonModule } from '@angular/common';
|
||||
@@ -36,7 +30,6 @@ import { CommonModule } from '@angular/common';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class NumberCellComponent extends DataTableCellComponent implements OnInit {
|
||||
|
||||
@Input()
|
||||
decimalConfig: DecimalConfig;
|
||||
|
||||
|
@@ -19,7 +19,6 @@ import { BaseUIEvent } from '../../events';
|
||||
import { DataRow } from './data-row.model';
|
||||
|
||||
export class DataRowEvent extends BaseUIEvent<DataRow> {
|
||||
|
||||
sender: any;
|
||||
|
||||
constructor(value: DataRow, domEvent: Event, sender?: any) {
|
||||
@@ -28,5 +27,4 @@ export class DataRowEvent extends BaseUIEvent<DataRow> {
|
||||
this.event = domEvent;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,10 +16,5 @@
|
||||
*/
|
||||
|
||||
export class DataSorting {
|
||||
constructor(
|
||||
public key?: string,
|
||||
public direction?: string,
|
||||
public options?: Intl.CollatorOptions
|
||||
) {
|
||||
}
|
||||
constructor(public key?: string, public direction?: string, public options?: Intl.CollatorOptions) {}
|
||||
}
|
||||
|
@@ -24,14 +24,7 @@ import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
@NgModule({
|
||||
declarations: [EditJsonDialogComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
TranslateModule,
|
||||
MatDialogModule,
|
||||
MatButtonModule
|
||||
],
|
||||
imports: [CommonModule, FormsModule, ReactiveFormsModule, TranslateModule, MatDialogModule, MatButtonModule],
|
||||
exports: [EditJsonDialogComponent]
|
||||
})
|
||||
export class EditJsonDialogModule {}
|
||||
|
@@ -17,10 +17,7 @@
|
||||
|
||||
import { Component, OnInit, OnChanges, Input } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import {
|
||||
EditJsonDialogComponent,
|
||||
EditJsonDialogSettings
|
||||
} from './edit-json.dialog';
|
||||
import { EditJsonDialogComponent, EditJsonDialogSettings } from './edit-json.dialog';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-edit-json-dialog-storybook',
|
||||
@@ -75,11 +72,7 @@ export class EditJsonDialogStorybookComponent implements OnInit, OnChanges {
|
||||
.afterClosed()
|
||||
.subscribe((value: string) => {
|
||||
if (value) {
|
||||
this._settings.value = JSON.stringify(
|
||||
JSON.parse(value),
|
||||
null,
|
||||
' '
|
||||
);
|
||||
this._settings.value = JSON.stringify(JSON.parse(value), null, ' ');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -31,16 +31,13 @@ export interface EditJsonDialogSettings {
|
||||
host: { class: 'adf-edit-json-dialog' }
|
||||
})
|
||||
export class EditJsonDialogComponent implements OnInit {
|
||||
|
||||
editable: boolean = false;
|
||||
title: string = 'JSON';
|
||||
|
||||
@Input()
|
||||
value: string = '';
|
||||
|
||||
constructor(
|
||||
@Inject(MAT_DIALOG_DATA) private settings: EditJsonDialogSettings
|
||||
) {}
|
||||
constructor(@Inject(MAT_DIALOG_DATA) private settings: EditJsonDialogSettings) {}
|
||||
|
||||
ngOnInit() {
|
||||
if (this.settings) {
|
||||
|
@@ -20,7 +20,6 @@ import { fakeAsync, tick } from '@angular/core/testing';
|
||||
import { UploadDirective } from './upload.directive';
|
||||
|
||||
describe('UploadDirective', () => {
|
||||
|
||||
let directive: UploadDirective;
|
||||
let nativeElement: any;
|
||||
|
||||
@@ -139,7 +138,7 @@ describe('UploadDirective', () => {
|
||||
directive.enabled = true;
|
||||
directive.mode = ['click'];
|
||||
const files = [{}];
|
||||
const event = {currentTarget: {files}, target: {value: '/testpath/document.pdf'}};
|
||||
const event = { currentTarget: { files }, target: { value: '/testpath/document.pdf' } };
|
||||
|
||||
directive.onSelectFiles(event);
|
||||
expect(event.target.value).toBe('');
|
||||
|
@@ -17,7 +17,6 @@
|
||||
|
||||
/** Base cancellable event implementation */
|
||||
export class BaseEvent<T> {
|
||||
|
||||
private isDefaultPrevented: boolean = false;
|
||||
|
||||
value: T;
|
||||
@@ -29,5 +28,4 @@ export class BaseEvent<T> {
|
||||
preventDefault() {
|
||||
this.isDefaultPrevented = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -4,14 +4,14 @@
|
||||
<div *ngIf="hasTabs()" class="alfresco-tabs-widget">
|
||||
<mat-tab-group>
|
||||
<mat-tab *ngFor="let tab of visibleTabs()" [label]="tab.title | translate ">
|
||||
<ng-template *ngTemplateOutlet="render; context: { fieldToRender: tab.fields }"></ng-template>
|
||||
<ng-template *ngTemplateOutlet="render; context: { fieldToRender: tab.fields }" />
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!formDefinition.hasTabs() && formDefinition.hasFields()">
|
||||
<ng-template *ngTemplateOutlet="render; context: { fieldToRender: formDefinition.fields }"></ng-template>
|
||||
<ng-template *ngTemplateOutlet="render; context: { fieldToRender: formDefinition.fields }" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@@ -7,11 +7,11 @@
|
||||
data-automation-id="adf-inplace-input">
|
||||
|
||||
<mat-label data-automation-id="adf-inplace-input-label">
|
||||
<ng-content select="[label]"></ng-content>
|
||||
<ng-content select="[label]" />
|
||||
</mat-label>
|
||||
|
||||
<mat-error data-automation-id="adf-inplace-input-error">
|
||||
<ng-content select="[error]"></ng-content>
|
||||
<ng-content select="[error]" />
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
@@ -30,7 +30,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'text1',
|
||||
@@ -54,7 +54,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'text2',
|
||||
@@ -88,7 +88,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'multilinetext1',
|
||||
@@ -109,7 +109,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'multilinetext2',
|
||||
@@ -140,7 +140,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'number1',
|
||||
@@ -160,7 +160,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'number2',
|
||||
@@ -190,7 +190,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'checkbox1',
|
||||
@@ -207,7 +207,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'checkbox2',
|
||||
@@ -234,7 +234,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'dropdown1',
|
||||
@@ -261,7 +261,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'dropdown2',
|
||||
@@ -298,7 +298,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'amount1',
|
||||
@@ -321,7 +321,7 @@ export const cloudFormMock = {
|
||||
currency: '$'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'amount2',
|
||||
@@ -354,7 +354,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'date1',
|
||||
@@ -375,7 +375,7 @@ export const cloudFormMock = {
|
||||
dateDisplayFormat: 'D-M-YYYY'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'date2',
|
||||
@@ -406,7 +406,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'radiobuttons1',
|
||||
@@ -442,7 +442,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'radiobuttons2',
|
||||
@@ -488,7 +488,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'AttachFileFieldRepresentation',
|
||||
id: 'attachfile1',
|
||||
@@ -513,7 +513,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'AttachFileFieldRepresentation',
|
||||
id: 'attachfile2',
|
||||
@@ -548,7 +548,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'displayvalue1',
|
||||
@@ -572,7 +572,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'displayvalue2',
|
||||
@@ -606,7 +606,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'displaytext1',
|
||||
@@ -624,7 +624,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'displaytext2',
|
||||
@@ -691,7 +691,7 @@ export const fakeCloudForm = {
|
||||
name: 'Label',
|
||||
tab: null,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'firstName',
|
||||
@@ -710,7 +710,7 @@ export const fakeCloudForm = {
|
||||
regexPattern: null
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'lastName',
|
||||
@@ -775,7 +775,7 @@ export const conditionalUploadWidgetsMock: any = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text0xlk8n',
|
||||
name: 'Text',
|
||||
@@ -793,7 +793,7 @@ export const conditionalUploadWidgetsMock: any = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Attachfile0h9fr1',
|
||||
name: 'Attach file',
|
||||
@@ -863,7 +863,7 @@ export const multilingualForm: any = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'textField',
|
||||
name: 'TEXT_FIELD.TITLE',
|
||||
@@ -881,7 +881,7 @@ export const multilingualForm: any = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: []
|
||||
'2': []
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -891,7 +891,7 @@ export const multilingualForm: any = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'fildUploadField',
|
||||
name: 'FILE_UPLOAD_FIELD.TITLE',
|
||||
@@ -909,7 +909,7 @@ export const multilingualForm: any = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'amountField',
|
||||
name: 'AMOUNT_FIELD.TITLE',
|
||||
@@ -937,7 +937,7 @@ export const multilingualForm: any = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'dateField',
|
||||
name: 'DATE_FIELD.TITLE',
|
||||
@@ -955,7 +955,7 @@ export const multilingualForm: any = {
|
||||
dateDisplayFormat: 'D-M-YYYY'
|
||||
}
|
||||
],
|
||||
2: []
|
||||
'2': []
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -980,7 +980,7 @@ export const fakeMetadataForm = {
|
||||
name: 'Label',
|
||||
tab: null,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'pfx_property_one',
|
||||
@@ -999,7 +999,7 @@ export const fakeMetadataForm = {
|
||||
regexPattern: null
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
type: 'boolean',
|
||||
id: 'pfx_property_two',
|
||||
@@ -1018,7 +1018,7 @@ export const fakeMetadataForm = {
|
||||
regexPattern: null
|
||||
}
|
||||
],
|
||||
3: [
|
||||
'3': [
|
||||
{
|
||||
id: 'content_form_nodes',
|
||||
name: 'Nodes',
|
||||
@@ -1046,7 +1046,7 @@ export const fakeMetadataForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
4: [
|
||||
'4': [
|
||||
{
|
||||
id: 'pfx_property_three',
|
||||
name: 'pfx_property_three',
|
||||
@@ -1081,7 +1081,7 @@ export const fakeMetadataForm = {
|
||||
restLabelProperty: null
|
||||
}
|
||||
],
|
||||
5: [
|
||||
'5': [
|
||||
{
|
||||
id: 'pfx_property_four',
|
||||
name: 'pfx_property_four',
|
||||
@@ -1116,7 +1116,7 @@ export const fakeMetadataForm = {
|
||||
restLabelProperty: null
|
||||
}
|
||||
],
|
||||
6: [
|
||||
'6': [
|
||||
{
|
||||
id: 'pfx_property_five',
|
||||
name: 'pfx_property_five',
|
||||
@@ -1151,7 +1151,7 @@ export const fakeMetadataForm = {
|
||||
restLabelProperty: null
|
||||
}
|
||||
],
|
||||
7: [
|
||||
'7': [
|
||||
{
|
||||
id: 'cmfb85b2a7295ba41209750bca176ccaf9a',
|
||||
name: 'File viewer',
|
||||
@@ -1167,7 +1167,7 @@ export const fakeMetadataForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
8: [
|
||||
'8': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'pfx_property_six',
|
||||
@@ -1186,7 +1186,7 @@ export const fakeMetadataForm = {
|
||||
regexPattern: null
|
||||
}
|
||||
],
|
||||
9: [
|
||||
'9': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'pfx_property_seven',
|
||||
@@ -1205,7 +1205,7 @@ export const fakeMetadataForm = {
|
||||
regexPattern: null
|
||||
}
|
||||
],
|
||||
10: [
|
||||
'10': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'pfx_property_eight',
|
||||
@@ -1248,7 +1248,7 @@ export const fakeViewerForm = {
|
||||
name: 'Label',
|
||||
tab: null,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'content_form_nodes',
|
||||
name: 'Nodes',
|
||||
@@ -1276,7 +1276,7 @@ export const fakeViewerForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'upload_widget',
|
||||
name: 'Nodes',
|
||||
@@ -1304,7 +1304,7 @@ export const fakeViewerForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
3: [
|
||||
'3': [
|
||||
{
|
||||
id: 'cmfb85b2a7295ba41209750bca176ccaf9a',
|
||||
name: 'File viewer',
|
||||
|
@@ -34,7 +34,7 @@ export const formDisplayValueVisibility = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text0bq3ar',
|
||||
name: 'Text',
|
||||
@@ -49,7 +49,7 @@ export const formDisplayValueVisibility = {
|
||||
params: { existingColspan: 1, maxColspan: 2 }
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Displayvalue0g6092',
|
||||
name: 'Display value',
|
||||
@@ -103,7 +103,7 @@ export const formDisplayValueForm = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'DisplayValueColspan',
|
||||
name: 'DisplayValueColspan',
|
||||
@@ -240,7 +240,7 @@ export const formDisplayValueForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Text0howrc',
|
||||
name: 'Text',
|
||||
@@ -341,7 +341,7 @@ export const formDisplayValueCombinedVisibility = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text0bq3ar',
|
||||
name: 'Text',
|
||||
@@ -356,7 +356,7 @@ export const formDisplayValueCombinedVisibility = {
|
||||
params: { existingColspan: 1, maxColspan: 2 }
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Displayvalue0g6092',
|
||||
name: 'Display value',
|
||||
@@ -401,7 +401,7 @@ export const formDisplayValueCombinedVisibility = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'TextTwo',
|
||||
name: 'TextTwo',
|
||||
@@ -416,7 +416,7 @@ export const formDisplayValueCombinedVisibility = {
|
||||
params: { existingColspan: 1, maxColspan: 2 }
|
||||
}
|
||||
],
|
||||
2: []
|
||||
'2': []
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -444,7 +444,7 @@ export const formNumberWidgetVisibility = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Number1',
|
||||
name: 'Number1',
|
||||
@@ -461,7 +461,7 @@ export const formNumberWidgetVisibility = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Number2',
|
||||
name: 'Number2',
|
||||
@@ -519,7 +519,7 @@ export const formNumberTextJson = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'NumberColspan',
|
||||
name: 'NumberColspan',
|
||||
@@ -581,7 +581,7 @@ export const formNumberTextJson = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Text',
|
||||
name: 'Text',
|
||||
@@ -759,7 +759,7 @@ export const formRequiredNumberWidget = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Number1',
|
||||
name: 'Number1',
|
||||
@@ -776,7 +776,7 @@ export const formRequiredNumberWidget = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Number2',
|
||||
name: 'Number2',
|
||||
@@ -835,7 +835,7 @@ export const colspanForm = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Number0u0kiv',
|
||||
name: 'NumberColspan',
|
||||
@@ -862,7 +862,7 @@ export const colspanForm = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Number00fuuk',
|
||||
name: 'Number',
|
||||
@@ -880,7 +880,7 @@ export const colspanForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Number03u9d4',
|
||||
name: 'Number',
|
||||
@@ -907,7 +907,7 @@ export const colspanForm = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text04sjhr',
|
||||
name: 'TextColspan',
|
||||
@@ -935,7 +935,7 @@ export const colspanForm = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text01dask',
|
||||
name: 'Text',
|
||||
@@ -953,7 +953,7 @@ export const colspanForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Text02ds21',
|
||||
name: 'Text',
|
||||
@@ -998,7 +998,7 @@ export const numberNotRequiredForm = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Number0x8cbv',
|
||||
name: 'Number',
|
||||
@@ -1012,7 +1012,7 @@ export const numberNotRequiredForm = {
|
||||
params: { existingColspan: 1, maxColspan: 2 }
|
||||
}
|
||||
],
|
||||
2: []
|
||||
'2': []
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1040,7 +1040,7 @@ export const numberMinMaxForm = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Number0him2z',
|
||||
name: 'Number',
|
||||
@@ -1057,7 +1057,7 @@ export const numberMinMaxForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: []
|
||||
'2': []
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1084,7 +1084,7 @@ export const textWidgetVisibility = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'textOne',
|
||||
name: 'textOne',
|
||||
@@ -1099,7 +1099,7 @@ export const textWidgetVisibility = {
|
||||
params: { existingColspan: 1, maxColspan: 2 }
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'textTwo',
|
||||
name: 'textTwo',
|
||||
@@ -1132,7 +1132,7 @@ export const textWidgetVisibility = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'textThree',
|
||||
name: 'textThree',
|
||||
@@ -1166,7 +1166,7 @@ export const textWidgetVisibility = {
|
||||
params: { existingColspan: 1, maxColspan: 2 }
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'textFour',
|
||||
name: 'textFour',
|
||||
@@ -1228,7 +1228,7 @@ export const numberWidgetVisibilityForm = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text0hs0gt',
|
||||
name: 'TextOne',
|
||||
@@ -1277,7 +1277,7 @@ export const numberWidgetVisibilityForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Text0cuqet',
|
||||
name: 'TextTwo',
|
||||
@@ -1321,7 +1321,7 @@ export const radioWidgetVisibilityForm = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text0cee7g',
|
||||
name: 'Text',
|
||||
@@ -1336,7 +1336,7 @@ export const radioWidgetVisibilityForm = {
|
||||
params: { existingColspan: 1, maxColspan: 2 }
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Radiobuttons03rkbo',
|
||||
name: 'Radio buttons',
|
||||
@@ -1393,7 +1393,7 @@ export const customWidgetForm = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text0vdi18',
|
||||
name: 'herejustoshowstandardones',
|
||||
@@ -1412,7 +1412,7 @@ export const customWidgetForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'bananaforevah0k8gui',
|
||||
name: 'bananaforevah',
|
||||
@@ -1457,7 +1457,7 @@ export const customWidgetFormWithVisibility = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text0vdi18',
|
||||
name: 'herejustoshowstandardones',
|
||||
@@ -1476,7 +1476,7 @@ export const customWidgetFormWithVisibility = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'bananaforevah0k8gui',
|
||||
name: 'bananaforevah',
|
||||
@@ -1529,7 +1529,7 @@ export const formDateVisibility = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Date0hwq20',
|
||||
name: 'Date',
|
||||
@@ -1549,7 +1549,7 @@ export const formDateVisibility = {
|
||||
dateDisplayFormat: 'YYYY-MM-DD'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Text0pqd1u',
|
||||
name: 'Text equal specific date',
|
||||
@@ -1586,7 +1586,7 @@ export const formDateVisibility = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text0uyqd3',
|
||||
name: 'Text NOT equal specific date',
|
||||
@@ -1614,7 +1614,7 @@ export const formDateVisibility = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: []
|
||||
'2': []
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1641,8 +1641,8 @@ export const amountWidgetFormVisibilityMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [],
|
||||
2: [
|
||||
'1': [],
|
||||
'2': [
|
||||
{
|
||||
id: 'Text0id3ic',
|
||||
name: 'Text',
|
||||
@@ -1669,7 +1669,7 @@ export const amountWidgetFormVisibilityMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Amount0kceqc',
|
||||
name: 'Amount',
|
||||
@@ -1707,7 +1707,7 @@ export const amountWidgetFormVisibilityMock = {
|
||||
currency: '$'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Number0yggl7',
|
||||
name: 'Number',
|
||||
@@ -1751,7 +1751,7 @@ export const checkboxWidgetFormVisibilityMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Checkbox0pr51m',
|
||||
name: 'Checkbox1',
|
||||
@@ -1766,7 +1766,7 @@ export const checkboxWidgetFormVisibilityMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Checkbox0fp0zf',
|
||||
name: 'Checkbox2',
|
||||
@@ -1790,7 +1790,7 @@ export const checkboxWidgetFormVisibilityMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Checkbox0lb7ze',
|
||||
name: 'Checkbox',
|
||||
@@ -1813,7 +1813,7 @@ export const checkboxWidgetFormVisibilityMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: []
|
||||
'2': []
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1840,7 +1840,7 @@ export const dateWidgetFormVisibilityMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text5asd0a',
|
||||
name: 'Text',
|
||||
@@ -1858,7 +1858,7 @@ export const dateWidgetFormVisibilityMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Date8wbe3d',
|
||||
name: 'Date',
|
||||
@@ -1912,7 +1912,7 @@ export const multilineWidgetFormVisibilityMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'MultilineTextId',
|
||||
name: 'Multi Line Label',
|
||||
@@ -1976,7 +1976,7 @@ export const multilineWidgetFormVisibilityMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: []
|
||||
'2': []
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -2011,7 +2011,7 @@ export const displayTextWidgetFormVisibilityMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text0tzu53',
|
||||
name: 'Text',
|
||||
@@ -2029,7 +2029,7 @@ export const displayTextWidgetFormVisibilityMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Displaytext0q4w02',
|
||||
name: 'Display text',
|
||||
@@ -2051,7 +2051,7 @@ export const displayTextWidgetFormVisibilityMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
3: [
|
||||
'3': [
|
||||
{
|
||||
id: 'Displaytext8bac2e',
|
||||
name: 'Display text',
|
||||
@@ -2106,7 +2106,7 @@ export const displayBigDecimalWidgetMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Decimal0tzu53',
|
||||
name: 'Bigdecimal',
|
||||
|
@@ -30,7 +30,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'text1',
|
||||
@@ -54,7 +54,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'text2',
|
||||
@@ -88,7 +88,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'multilinetext1',
|
||||
@@ -109,7 +109,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'multilinetext2',
|
||||
@@ -140,7 +140,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'number1',
|
||||
@@ -160,7 +160,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'number2',
|
||||
@@ -190,7 +190,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'checkbox1',
|
||||
@@ -207,7 +207,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'checkbox2',
|
||||
@@ -234,7 +234,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'dropdown1',
|
||||
@@ -261,7 +261,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'dropdown2',
|
||||
@@ -298,7 +298,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'amount1',
|
||||
@@ -321,7 +321,7 @@ export const cloudFormMock = {
|
||||
currency: '$'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'amount2',
|
||||
@@ -354,7 +354,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'date1',
|
||||
@@ -375,7 +375,7 @@ export const cloudFormMock = {
|
||||
dateDisplayFormat: 'D-M-YYYY'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'date2',
|
||||
@@ -406,7 +406,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'radiobuttons1',
|
||||
@@ -442,7 +442,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'radiobuttons2',
|
||||
@@ -488,7 +488,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'AttachFileFieldRepresentation',
|
||||
id: 'attachfile1',
|
||||
@@ -513,7 +513,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'AttachFileFieldRepresentation',
|
||||
id: 'attachfile2',
|
||||
@@ -548,7 +548,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'displayvalue1',
|
||||
@@ -572,7 +572,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'displayvalue2',
|
||||
@@ -606,7 +606,7 @@ export const cloudFormMock = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'displaytext1',
|
||||
@@ -624,7 +624,7 @@ export const cloudFormMock = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'displaytext2',
|
||||
@@ -691,7 +691,7 @@ export const fakeCloudForm = {
|
||||
name: 'Label',
|
||||
tab: null,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'firstName',
|
||||
@@ -710,7 +710,7 @@ export const fakeCloudForm = {
|
||||
regexPattern: null
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'lastName',
|
||||
@@ -775,7 +775,7 @@ export const conditionalUploadWidgetsMock: any = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'Text0xlk8n',
|
||||
name: 'Text',
|
||||
@@ -793,7 +793,7 @@ export const conditionalUploadWidgetsMock: any = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'Attachfile0h9fr1',
|
||||
name: 'Attach file',
|
||||
@@ -863,7 +863,7 @@ export const multilingualForm: any = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'textField',
|
||||
name: 'TEXT_FIELD.TITLE',
|
||||
@@ -881,7 +881,7 @@ export const multilingualForm: any = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: []
|
||||
'2': []
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -891,7 +891,7 @@ export const multilingualForm: any = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'fildUploadField',
|
||||
name: 'FILE_UPLOAD_FIELD.TITLE',
|
||||
@@ -909,7 +909,7 @@ export const multilingualForm: any = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'amountField',
|
||||
name: 'AMOUNT_FIELD.TITLE',
|
||||
@@ -937,7 +937,7 @@ export const multilingualForm: any = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'dateField',
|
||||
name: 'DATE_FIELD.TITLE',
|
||||
@@ -955,7 +955,7 @@ export const multilingualForm: any = {
|
||||
dateDisplayFormat: 'D-M-YYYY'
|
||||
}
|
||||
],
|
||||
2: []
|
||||
'2': []
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -980,7 +980,7 @@ export const fakeMetadataForm = {
|
||||
name: 'Label',
|
||||
tab: null,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'pfx_property_one',
|
||||
@@ -999,7 +999,7 @@ export const fakeMetadataForm = {
|
||||
regexPattern: null
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
type: 'boolean',
|
||||
id: 'pfx_property_two',
|
||||
@@ -1018,7 +1018,7 @@ export const fakeMetadataForm = {
|
||||
regexPattern: null
|
||||
}
|
||||
],
|
||||
3: [
|
||||
'3': [
|
||||
{
|
||||
id: 'content_form_nodes',
|
||||
name: 'Nodes',
|
||||
@@ -1046,7 +1046,7 @@ export const fakeMetadataForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
4: [
|
||||
'4': [
|
||||
{
|
||||
id: 'pfx_property_three',
|
||||
name: 'pfx_property_three',
|
||||
@@ -1081,7 +1081,7 @@ export const fakeMetadataForm = {
|
||||
restLabelProperty: null
|
||||
}
|
||||
],
|
||||
5: [
|
||||
'5': [
|
||||
{
|
||||
id: 'pfx_property_four',
|
||||
name: 'pfx_property_four',
|
||||
@@ -1116,7 +1116,7 @@ export const fakeMetadataForm = {
|
||||
restLabelProperty: null
|
||||
}
|
||||
],
|
||||
6: [
|
||||
'6': [
|
||||
{
|
||||
id: 'pfx_property_five',
|
||||
name: 'pfx_property_five',
|
||||
@@ -1151,7 +1151,7 @@ export const fakeMetadataForm = {
|
||||
restLabelProperty: null
|
||||
}
|
||||
],
|
||||
7: [
|
||||
'7': [
|
||||
{
|
||||
id: 'cmfb85b2a7295ba41209750bca176ccaf9a',
|
||||
name: 'File viewer',
|
||||
@@ -1167,7 +1167,7 @@ export const fakeMetadataForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
8: [
|
||||
'8': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'pfx_property_six',
|
||||
@@ -1186,7 +1186,7 @@ export const fakeMetadataForm = {
|
||||
regexPattern: null
|
||||
}
|
||||
],
|
||||
9: [
|
||||
'9': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'pfx_property_seven',
|
||||
@@ -1205,7 +1205,7 @@ export const fakeMetadataForm = {
|
||||
regexPattern: null
|
||||
}
|
||||
],
|
||||
10: [
|
||||
'10': [
|
||||
{
|
||||
type: 'text',
|
||||
id: 'pfx_property_eight',
|
||||
@@ -1249,7 +1249,7 @@ export const mockDisplayExternalPropertyForm = {
|
||||
tab: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'DisplayExternalProperty02kj65',
|
||||
name: 'Display External Property',
|
||||
@@ -1267,7 +1267,7 @@ export const mockDisplayExternalPropertyForm = {
|
||||
value: 'hr'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'DisplayExternalProperty0ei65x',
|
||||
name: 'Display External Property',
|
||||
@@ -1325,7 +1325,7 @@ export const fakeViewerForm = {
|
||||
name: 'Label',
|
||||
tab: null,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'content_form_nodes',
|
||||
name: 'Nodes',
|
||||
@@ -1353,7 +1353,7 @@ export const fakeViewerForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'upload_widget',
|
||||
name: 'Nodes',
|
||||
@@ -1381,7 +1381,7 @@ export const fakeViewerForm = {
|
||||
}
|
||||
}
|
||||
],
|
||||
3: [
|
||||
'3': [
|
||||
{
|
||||
id: 'cmfb85b2a7295ba41209750bca176ccaf9a',
|
||||
name: 'File viewer',
|
||||
|
@@ -259,7 +259,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
|
||||
private getDefaultDateFormat(jsonField: any): string {
|
||||
let originalType = jsonField.type;
|
||||
if (FormFieldTypes.isReadOnlyType(jsonField.type) && jsonField.params && jsonField.params.field) {
|
||||
if (FormFieldTypes.isReadOnlyType(jsonField.type) && jsonField.params?.field) {
|
||||
originalType = jsonField.params.field.type;
|
||||
}
|
||||
return originalType === FormFieldTypes.DATETIME ? this.defaultDateTimeFormat : this.defaultDateFormat;
|
||||
|
@@ -15,12 +15,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
import { FormOutcomeModel } from './form-outcome.model';
|
||||
|
||||
export class FormOutcomeEvent {
|
||||
|
||||
private readonly _outcome: FormOutcomeModel;
|
||||
private _defaultPrevented: boolean = false;
|
||||
|
||||
@@ -39,5 +38,4 @@ export class FormOutcomeEvent {
|
||||
preventDefault() {
|
||||
this._defaultPrevented = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,7 +19,6 @@ import { FormOutcomeModel } from './form-outcome.model';
|
||||
import { FormModel } from './form.model';
|
||||
|
||||
describe('FormOutcomeModel', () => {
|
||||
|
||||
it('should setup with json config', () => {
|
||||
const json = {
|
||||
id: '<id>',
|
||||
|
@@ -19,7 +19,6 @@ import { FormWidgetModel } from './form-widget.model';
|
||||
import { FormModel } from './form.model';
|
||||
|
||||
describe('FormWidgetModel', () => {
|
||||
|
||||
class FormWidgetModelMock extends FormWidgetModel {
|
||||
constructor(form: FormModel, json: any) {
|
||||
super(form, json);
|
||||
|
@@ -21,7 +21,6 @@ import { FormFieldModel } from './form-field.model';
|
||||
import { TabModel } from './tab.model';
|
||||
|
||||
describe('TabModel', () => {
|
||||
|
||||
it('should setup with json config', () => {
|
||||
const json = {
|
||||
id: '<id>',
|
||||
|
@@ -15,13 +15,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
/* eslint-disable @angular-eslint/component-selector */
|
||||
|
||||
import { WidgetVisibilityModel } from '../../../models/widget-visibility.model';
|
||||
import { FormWidgetModel } from './form-widget.model';
|
||||
|
||||
export class TabModel extends FormWidgetModel {
|
||||
|
||||
title: string;
|
||||
isVisible: boolean = true;
|
||||
visibilityCondition: WidgetVisibilityModel;
|
||||
|
@@ -42,8 +42,8 @@ export class InputMaskDirective implements OnChanges, ControlValueAccessor {
|
||||
};
|
||||
|
||||
private translationMask = {
|
||||
0: { pattern: /\d/ },
|
||||
9: { pattern: /\d/, optional: true },
|
||||
'0': { pattern: /\d/ },
|
||||
'9': { pattern: /\d/, optional: true },
|
||||
'#': { pattern: /\d/, recursive: true },
|
||||
A: { pattern: /[a-zA-Z0-9]/ },
|
||||
S: { pattern: /[a-zA-Z]/ }
|
||||
|
@@ -19,12 +19,10 @@ import { FormModel } from '../components/widgets/core/form.model';
|
||||
import { FormEvent } from './form.event';
|
||||
|
||||
export class FormErrorEvent extends FormEvent {
|
||||
|
||||
readonly error: any;
|
||||
|
||||
constructor(form: FormModel, error: any) {
|
||||
super(form);
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,12 +19,10 @@ import { FormFieldModel } from '../components/widgets/core/form-field.model';
|
||||
import { FormEvent } from './form.event';
|
||||
|
||||
export class FormFieldEvent extends FormEvent {
|
||||
|
||||
readonly field: FormFieldModel;
|
||||
|
||||
constructor(form: any, field: FormFieldModel) {
|
||||
super(form);
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,7 +19,6 @@ import { FormFieldEvent } from './form-field.event';
|
||||
import { FormEvent } from './form.event';
|
||||
|
||||
export class FormRulesEvent extends FormFieldEvent {
|
||||
|
||||
readonly type: string;
|
||||
readonly event: Event;
|
||||
|
||||
@@ -28,5 +27,4 @@ export class FormRulesEvent extends FormFieldEvent {
|
||||
this.type = type;
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
export class FormEvent {
|
||||
|
||||
private isDefaultPrevented: boolean = false;
|
||||
|
||||
readonly form: any;
|
||||
|
@@ -19,11 +19,9 @@ import { FormFieldModel } from '../components/widgets/core/form-field.model';
|
||||
import { FormFieldEvent } from './form-field.event';
|
||||
|
||||
export class ValidateFormFieldEvent extends FormFieldEvent {
|
||||
|
||||
isValid = true;
|
||||
|
||||
constructor(form: any, field: FormFieldModel) {
|
||||
super(form, field);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,7 +19,6 @@ import { FormEvent } from './form.event';
|
||||
import { FormFieldModel } from '../components/widgets/core/form-field.model';
|
||||
|
||||
export class ValidateFormEvent extends FormEvent {
|
||||
|
||||
isValid = true;
|
||||
errorsField: FormFieldModel[] = [];
|
||||
|
||||
|
@@ -58,7 +58,7 @@ export class WidgetVisibilityModel {
|
||||
return this.json.leftValue;
|
||||
} else if (this.leftFormFieldId) {
|
||||
return this.leftFormFieldId;
|
||||
} else if(this.leftRestResponseId){
|
||||
} else if (this.leftRestResponseId) {
|
||||
return this.leftRestResponseId;
|
||||
}
|
||||
return null;
|
||||
@@ -91,7 +91,7 @@ export class WidgetVisibilityModel {
|
||||
return this.json.rightValue;
|
||||
} else if (this.rightFormFieldId) {
|
||||
return this.rightFormFieldId;
|
||||
} else if(this.rightRestResponseId){
|
||||
} else if (this.rightRestResponseId) {
|
||||
return this.rightRestResponseId;
|
||||
}
|
||||
return null;
|
||||
|
@@ -29,7 +29,6 @@ import { FormFieldTypes } from '../components/widgets';
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class FormRenderingService extends DynamicComponentMapper {
|
||||
|
||||
protected defaultValue: Type<any> = widgets.UnknownWidgetComponent;
|
||||
protected types: { [key: string]: DynamicComponentResolveFunction } = {
|
||||
[FormFieldTypes.TEXT]: DynamicComponentResolver.fromType(widgets.TextWidgetComponent),
|
||||
|
@@ -499,7 +499,7 @@ describe('WidgetVisibilityCloudService', () => {
|
||||
value: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
fieldType: 'FormFieldRepresentation',
|
||||
id: 'FIELD_FORM_EMPTY',
|
||||
@@ -613,7 +613,7 @@ describe('WidgetVisibilityCloudService', () => {
|
||||
value: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'radioboxField',
|
||||
name: 'radioboxField test',
|
||||
@@ -777,7 +777,7 @@ describe('WidgetVisibilityCloudService', () => {
|
||||
value: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'CheckboxOne',
|
||||
name: 'CheckboxOne',
|
||||
@@ -797,7 +797,7 @@ describe('WidgetVisibilityCloudService', () => {
|
||||
visibilityCondition: null
|
||||
}
|
||||
],
|
||||
2: [
|
||||
'2': [
|
||||
{
|
||||
id: 'CheckboxThree',
|
||||
name: 'CheckboxThree',
|
||||
|
@@ -757,7 +757,7 @@ describe('WidgetVisibilityService', () => {
|
||||
value: null,
|
||||
numberOfColumns: 2,
|
||||
fields: {
|
||||
1: [
|
||||
'1': [
|
||||
{
|
||||
id: 'radioboxField',
|
||||
name: 'radioboxField test',
|
||||
|
@@ -30,13 +30,13 @@
|
||||
|
||||
<ng-template #toolbarActions>
|
||||
<div class="adf-toolbar-actions">
|
||||
<ng-content select="[adf-toolbar-actions]"></ng-content>
|
||||
<ng-content select="[adf-toolbar-actions]" />
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #navbarTemplate>
|
||||
<adf-navbar [items]="navbarItems">
|
||||
<ng-content select="adf-navbar-item"></ng-content>
|
||||
<ng-content select="adf-navbar-item" />
|
||||
</adf-navbar>
|
||||
</ng-template>
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<adf-navbar-item *ngFor="let item of items"
|
||||
[routerLink]="item.routerLink"
|
||||
[label]="item.label" />
|
||||
<ng-content></ng-content>
|
||||
<ng-content />
|
||||
|
@@ -1,12 +1,12 @@
|
||||
<div *ngIf="showHeader" class="adf-info-drawer-layout-header">
|
||||
<div class="adf-info-drawer-layout-header-title">
|
||||
<ng-content select="[info-drawer-node-icon]"></ng-content>
|
||||
<ng-content select="[info-drawer-title]"></ng-content>
|
||||
<ng-content select="[info-drawer-node-icon]" />
|
||||
<ng-content select="[info-drawer-title]" />
|
||||
</div>
|
||||
<div class="adf-info-drawer-layout-header-buttons">
|
||||
<ng-content select="[info-drawer-buttons]"></ng-content>
|
||||
<ng-content select="[info-drawer-buttons]" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="adf-info-drawer-layout-content">
|
||||
<ng-content select="[info-drawer-content]"></ng-content>
|
||||
<ng-content select="[info-drawer-content]" />
|
||||
</div>
|
||||
|
@@ -2,8 +2,8 @@
|
||||
<img *ngIf="icon" class="adf-info-drawer-icon" alt="{{ 'INFO_DRAWER.ICON' | translate }}" src="{{ icon }}" info-drawer-node-icon>
|
||||
<div *ngIf="title" role="heading" aria-level="1" title="{{ title | translate }}" info-drawer-title>{{ title | translate }}</div>
|
||||
|
||||
<ng-content *ngIf="!title" info-drawer-title select="[info-drawer-title]"></ng-content>
|
||||
<ng-content info-drawer-buttons select="[info-drawer-buttons]"></ng-content>
|
||||
<ng-content *ngIf="!title" info-drawer-title select="[info-drawer-title]" />
|
||||
<ng-content info-drawer-buttons select="[info-drawer-buttons]" />
|
||||
<ng-container info-drawer-content *ngIf="showTabLayout(); then tabLayout else singleLayout" />
|
||||
|
||||
<ng-template #tabLayout>
|
||||
@@ -28,6 +28,6 @@
|
||||
</ng-template>
|
||||
|
||||
<ng-template #singleLayout>
|
||||
<ng-content select="[info-drawer-content]"></ng-content>
|
||||
<ng-content select="[info-drawer-content]" />
|
||||
</ng-template>
|
||||
</adf-info-drawer-layout>
|
||||
|
@@ -40,7 +40,7 @@ import { MatIconModule } from '@angular/material/icon';
|
||||
@Component({
|
||||
selector: 'adf-info-drawer-tab',
|
||||
standalone: true,
|
||||
template: '<ng-template><ng-content></ng-content></ng-template>',
|
||||
template: '<ng-template><ng-content /></ng-template>',
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class InfoDrawerTabComponent {
|
||||
|
@@ -36,7 +36,7 @@
|
||||
{{ title }}
|
||||
</h1>
|
||||
|
||||
<ng-content></ng-content>
|
||||
<ng-content />
|
||||
|
||||
<button
|
||||
*ngIf="showSidenavToggle && position === 'end'"
|
||||
|
@@ -6,12 +6,12 @@
|
||||
[@sidenavAnimation]="sidenavAnimationState"
|
||||
[opened]="!isMobileScreenSize || !hideSidenav"
|
||||
[mode]="isMobileScreenSize ? 'over' : 'side'">
|
||||
<ng-content sidenav select="[app-layout-navigation]"></ng-content>
|
||||
<ng-content sidenav select="[app-layout-navigation]" />
|
||||
</mat-sidenav>
|
||||
|
||||
<div>
|
||||
<div class="adf-container-full-width" [@contentAnimationLeft]="getContentAnimationState()">
|
||||
<ng-content select="[app-layout-content]"></ng-content>
|
||||
<ng-content select="[app-layout-content]" />
|
||||
</div>
|
||||
</div>
|
||||
</mat-sidenav-container>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user