mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-02 17:53:30 +00:00
[MNT-25612] ADW Metadata Drawer ignores read‑only presets (readOnlyAs… (#12095)
This commit is contained in:
+13
-1
@@ -299,6 +299,18 @@ describe('ContentMetadataComponent', () => {
|
||||
expect(contentMetadataService.getGroupedProperties).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should pass preset to getBasicProperties when calling getProperties', fakeAsync(() => {
|
||||
const testNode = { ...node, name: 'test-node' };
|
||||
component.preset = 'custom-preset';
|
||||
const getBasicPropertiesSpy = spyOn(contentMetadataService, 'getBasicProperties').and.returnValue(of([]));
|
||||
getGroupedPropertiesSpy.and.returnValue(of([]));
|
||||
|
||||
component.ngOnChanges({ node: new SimpleChange(null, testNode, false) });
|
||||
tick(600);
|
||||
|
||||
expect(getBasicPropertiesSpy).toHaveBeenCalledWith(testNode, 'custom-preset');
|
||||
}));
|
||||
|
||||
describe('Save button - Grouped Properties', () => {
|
||||
beforeEach(() => {
|
||||
getGroupedPropertiesSpy.and.returnValue(
|
||||
@@ -858,7 +870,7 @@ describe('ContentMetadataComponent', () => {
|
||||
component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) });
|
||||
|
||||
expect(contentMetadataService.getContentTypeProperty).toHaveBeenCalledWith(expectedNode);
|
||||
expect(contentMetadataService.getBasicProperties).toHaveBeenCalledWith(expectedNode);
|
||||
expect(contentMetadataService.getBasicProperties).toHaveBeenCalledWith(expectedNode, preset);
|
||||
});
|
||||
|
||||
it('should pass through the loaded basic properties to the card view', async () => {
|
||||
|
||||
+1
-1
@@ -473,7 +473,7 @@ export class ContentMetadataComponent implements OnChanges, OnInit {
|
||||
}
|
||||
|
||||
private getProperties(node: Node) {
|
||||
const properties$ = this.contentMetadataService.getBasicProperties(node);
|
||||
const properties$ = this.contentMetadataService.getBasicProperties(node, this.preset);
|
||||
const contentTypeProperty$ = this.contentMetadataService.getContentTypeProperty(node);
|
||||
return zip(properties$, contentTypeProperty$).pipe(
|
||||
map(([properties, contentTypeProperty]) => {
|
||||
|
||||
+35
@@ -214,6 +214,41 @@ describe('ContentMetaDataService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should mark basic properties as read-only when preset defines readOnlyProperties (includeAll)', async () => {
|
||||
setConfig('custom', [{ includeAll: true, readOnlyProperties: ['cm:name', 'cm:title'] }]);
|
||||
|
||||
const res = await firstValueFrom(service.getBasicProperties(fakeNode, 'custom'));
|
||||
const nameProperty = res.find((property) => property.key === 'properties.cm:name');
|
||||
const titleProperty = res.find((property) => property.key === 'properties.cm:title');
|
||||
const authorProperty = res.find((property) => property.key === 'properties.cm:author');
|
||||
|
||||
expect(nameProperty.editable).toBeFalse();
|
||||
expect(titleProperty.editable).toBeFalse();
|
||||
expect(authorProperty.editable).toBeTrue();
|
||||
});
|
||||
|
||||
it('should mark basic properties as read-only when layout items are not editable', async () => {
|
||||
setConfig('custom', [
|
||||
{
|
||||
items: [
|
||||
{ type: 'cm:content', properties: ['cm:name'], editable: false },
|
||||
{ aspect: 'cm:titled', properties: ['cm:title', 'cm:description'], editable: false }
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
const res = await firstValueFrom(service.getBasicProperties(fakeNode, 'custom'));
|
||||
const nameProperty = res.find((property) => property.key === 'properties.cm:name');
|
||||
const titleProperty = res.find((property) => property.key === 'properties.cm:title');
|
||||
const descriptionProperty = res.find((property) => property.key === 'properties.cm:description');
|
||||
const authorProperty = res.find((property) => property.key === 'properties.cm:author');
|
||||
|
||||
expect(nameProperty.editable).toBeFalse();
|
||||
expect(titleProperty.editable).toBeFalse();
|
||||
expect(descriptionProperty.editable).toBeFalse();
|
||||
expect(authorProperty.editable).toBeTrue();
|
||||
});
|
||||
|
||||
it('should return the content type property', () => {
|
||||
spyOn(contentPropertyService, 'getContentTypeCardItem').and.returnValue(of([{ label: 'hello i am a weird content type' } as CardViewItem]));
|
||||
|
||||
|
||||
@@ -20,12 +20,22 @@ import { Node } from '@alfresco/js-api';
|
||||
import { BasicPropertiesService } from './basic-properties.service';
|
||||
import { Observable, of, iif, Subject } from 'rxjs';
|
||||
import { PropertyGroupTranslatorService } from './property-groups-translator.service';
|
||||
import { CardViewItem } from '@alfresco/adf-core';
|
||||
import { AppConfigService, CardViewItem } from '@alfresco/adf-core';
|
||||
import { CardViewGroup, OrganisedPropertyGroup, PresetConfig } from '../interfaces/content-metadata.interfaces';
|
||||
import { ContentMetadataConfigFactory } from './config/content-metadata-config.factory';
|
||||
import { PropertyDescriptorsService } from './property-descriptors.service';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { ContentTypePropertiesService } from './content-type-property.service';
|
||||
import { LayoutOrientedConfig, LayoutOrientedConfigLayoutBlock } from '../interfaces/layout-oriented-config.interface';
|
||||
import { Property } from '../interfaces/property.interface';
|
||||
|
||||
interface LayoutBlockWithReadOnly extends LayoutOrientedConfigLayoutBlock {
|
||||
readOnlyProperties?: string | string[];
|
||||
}
|
||||
|
||||
const CONTENT_METADATA_CONFIG_KEY = 'content-metadata';
|
||||
const BASIC_PROPERTY_KEY_PREFIX = 'properties.';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
@@ -35,11 +45,62 @@ export class ContentMetadataService {
|
||||
private readonly propertyGroupTranslatorService = inject(PropertyGroupTranslatorService);
|
||||
private readonly propertyDescriptorsService = inject(PropertyDescriptorsService);
|
||||
private readonly contentTypePropertyService = inject(ContentTypePropertiesService);
|
||||
private readonly appConfig = inject(AppConfigService);
|
||||
|
||||
error = new Subject<{ statusCode: number; message: string }>();
|
||||
|
||||
getBasicProperties(node: Node): Observable<CardViewItem[]> {
|
||||
return of(this.basicPropertiesService.getProperties(node));
|
||||
getBasicProperties(node: Node, preset: string | PresetConfig = 'default'): Observable<CardViewItem[]> {
|
||||
const properties = this.basicPropertiesService.getProperties(node);
|
||||
const readOnlyProperties = this.getReadOnlyPropertyNames(preset);
|
||||
|
||||
if (readOnlyProperties.length) {
|
||||
properties.forEach((property) => {
|
||||
const propertyName = this.getBasicPropertyName(property.key);
|
||||
if (propertyName && readOnlyProperties.includes(propertyName)) {
|
||||
property.editable = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return of(properties);
|
||||
}
|
||||
|
||||
private getBasicPropertyName(key: string): string | undefined {
|
||||
return key?.startsWith(BASIC_PROPERTY_KEY_PREFIX) ? key.slice(BASIC_PROPERTY_KEY_PREFIX.length) : undefined;
|
||||
}
|
||||
|
||||
private getReadOnlyPropertyNames(preset: string | PresetConfig): string[] {
|
||||
const presetConfig = typeof preset === 'string' ? this.appConfig.config[CONTENT_METADATA_CONFIG_KEY]?.presets?.[preset] : preset;
|
||||
|
||||
if (this.isLayoutConfig(presetConfig)) {
|
||||
return presetConfig.reduce((readOnly, block) => readOnly.concat(this.getLayoutBlockReadOnlyNames(block)), [] as string[]);
|
||||
}
|
||||
|
||||
if (presetConfig != null && typeof presetConfig === 'object') {
|
||||
return this.normaliseToArray(presetConfig.readOnlyProperties);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
private isLayoutConfig(config: unknown): config is LayoutOrientedConfig {
|
||||
return Array.isArray(config);
|
||||
}
|
||||
|
||||
private getLayoutBlockReadOnlyNames(block: LayoutBlockWithReadOnly): string[] {
|
||||
const blockReadOnly = this.normaliseToArray(block?.readOnlyProperties);
|
||||
const nonEditableItems = (block?.items || [])
|
||||
.filter((item) => item?.editable === false)
|
||||
.reduce((names, item) => names.concat(this.normaliseToArray(item.properties)), [] as string[]);
|
||||
|
||||
return blockReadOnly.concat(nonEditableItems);
|
||||
}
|
||||
|
||||
private normaliseToArray(value: string | string[] | Property[] | undefined): string[] {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map((item) => (typeof item === 'string' ? item : item?.name)).filter((name): name is string => typeof name === 'string');
|
||||
}
|
||||
return typeof value === 'string' ? [value] : [];
|
||||
}
|
||||
|
||||
getContentTypeProperty(node: Node): Observable<CardViewItem[]> {
|
||||
|
||||
Reference in New Issue
Block a user