mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-05-12 17:04:46 +00:00
node locking enhancements and fixes (#955)
* optimize image resolver * allow previewing locked files * allow selecting locked nodes * fix comments and metadata tabs * improved lock checks * remove obsolete "experimental" directive
This commit is contained in:
parent
46c8062f2f
commit
4cde12dfee
@ -26,7 +26,9 @@ export class AosEditOnlineService {
|
||||
// const checkedOut = node.aspectNames.find(
|
||||
// (aspect: string) => aspect === 'cm:checkedOut'
|
||||
// );
|
||||
const checkedOut = node.properties['cm:lockType'] === 'WRITE_LOCK';
|
||||
const checkedOut =
|
||||
node.properties['cm:lockType'] === 'WRITE_LOCK' ||
|
||||
node.properties['cm:lockType'] === 'READ_ONLY_LOCK';
|
||||
const lockOwner = node.properties['cm:lockOwner'];
|
||||
const differentLockOwner =
|
||||
lockOwner.id !== this.alfrescoAuthenticationService.getEcmUsername();
|
||||
|
@ -32,7 +32,10 @@ export function canOpenWithOffice(
|
||||
}
|
||||
*/
|
||||
|
||||
if (file.entry.properties['cm:lockType'] === 'WRITE_LOCK') {
|
||||
if (
|
||||
file.entry.properties['cm:lockType'] === 'WRITE_LOCK' ||
|
||||
file.entry.properties['cm:lockType'] === 'READ_ONLY_LOCK'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
"logo": "assets/images/alfresco-logo-flower.svg",
|
||||
"copyright": "© 2017 - 2018 Alfresco Software, Inc. All rights reserved."
|
||||
},
|
||||
"experimental": {},
|
||||
"headerColor": "#2196F3",
|
||||
"languagePicker": false,
|
||||
"pagination": {
|
||||
|
@ -28,6 +28,7 @@ import { EDIT_OFFLINE } from '../../../store/actions';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
import { Subject } from 'rxjs';
|
||||
import { filter, takeUntil } from 'rxjs/operators';
|
||||
import { isLocked } from '../../../utils/node.utils';
|
||||
|
||||
@Component({
|
||||
selector: 'aca-custom-name-column',
|
||||
@ -84,11 +85,6 @@ export class CustomNameColumnComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
isFileWriteLocked() {
|
||||
return !!(
|
||||
this.node &&
|
||||
this.node.entry &&
|
||||
this.node.entry.properties &&
|
||||
this.node.entry.properties['cm:lockType'] === 'WRITE_LOCK'
|
||||
);
|
||||
return isLocked(this.node);
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,6 @@
|
||||
</adf-breadcrumb>
|
||||
|
||||
<adf-toolbar class="inline">
|
||||
<app-document-display-mode
|
||||
*ifExperimental="'cardview'"
|
||||
></app-document-display-mode>
|
||||
|
||||
<ng-container *ngFor="let entry of actions; trackBy: trackByActionId">
|
||||
<aca-toolbar-action [actionRef]="entry"></aca-toolbar-action>
|
||||
</ng-container>
|
||||
|
@ -39,7 +39,6 @@ import { DocumentListComponent } from '@alfresco/adf-content-services';
|
||||
import { FavoriteLibrariesComponent } from './favorite-libraries.component';
|
||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { ContentApiService } from '../../services/content-api.service';
|
||||
import { ExperimentalDirective } from '../../directives/experimental.directive';
|
||||
import { ContentManagementService } from '../../services/content-management.service';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { LibraryEffects, RouterEffects } from '../../store/effects';
|
||||
@ -77,8 +76,7 @@ describe('FavoriteLibrariesComponent', () => {
|
||||
NodeFavoriteDirective,
|
||||
DocumentListComponent,
|
||||
FavoriteLibrariesComponent,
|
||||
AppConfigPipe,
|
||||
ExperimentalDirective
|
||||
AppConfigPipe
|
||||
],
|
||||
providers: [ContentManagementService, UserPreferencesService],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
|
@ -40,7 +40,6 @@ import { of } from 'rxjs';
|
||||
import { FavoritesComponent } from './favorites.component';
|
||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { ContentApiService } from '../../services/content-api.service';
|
||||
import { ExperimentalDirective } from '../../directives/experimental.directive';
|
||||
|
||||
describe('FavoritesComponent', () => {
|
||||
let fixture: ComponentFixture<FavoritesComponent>;
|
||||
@ -83,8 +82,7 @@ describe('FavoritesComponent', () => {
|
||||
NodeFavoriteDirective,
|
||||
DocumentListComponent,
|
||||
FavoritesComponent,
|
||||
AppConfigPipe,
|
||||
ExperimentalDirective
|
||||
AppConfigPipe
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
|
@ -46,7 +46,6 @@ import { NodeActionsService } from '../../services/node-actions.service';
|
||||
import { FilesComponent } from './files.component';
|
||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { ContentApiService } from '../../services/content-api.service';
|
||||
import { ExperimentalDirective } from '../../directives/experimental.directive';
|
||||
import { of, throwError } from 'rxjs';
|
||||
|
||||
describe('FilesComponent', () => {
|
||||
@ -70,8 +69,7 @@ describe('FilesComponent', () => {
|
||||
NodeFavoriteDirective,
|
||||
DocumentListComponent,
|
||||
FileSizePipe,
|
||||
AppConfigPipe,
|
||||
ExperimentalDirective
|
||||
AppConfigPipe
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
|
@ -156,11 +156,6 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PageComponent.isLockedNode(node.entry)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
this.showPreview(node);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||
import { NodePermissionService } from '../../../services/node-permission.service';
|
||||
import { isLocked } from '../../../utils/node.utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-comments-tab',
|
||||
@ -42,7 +43,11 @@ export class CommentsTabComponent {
|
||||
|
||||
constructor(private permission: NodePermissionService) {}
|
||||
|
||||
get canUpdateNode() {
|
||||
return this.node && this.permission.check(this.node, ['update']);
|
||||
get canUpdateNode(): boolean {
|
||||
if (this.node && this.node.isFile && !isLocked({ entry: this.node })) {
|
||||
return this.permission.check(this.node, ['update']);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||
import { NodePermissionService } from '../../../services/node-permission.service';
|
||||
import { AppExtensionService } from '../../../extensions/extension.service';
|
||||
import { AppConfigService } from '@alfresco/adf-core';
|
||||
import { isLocked } from '../../../utils/node.utils';
|
||||
|
||||
@Component({
|
||||
selector: 'app-metadata-tab',
|
||||
@ -64,26 +65,11 @@ export class MetadataTabComponent {
|
||||
}
|
||||
}
|
||||
|
||||
get canUpdateNode() {
|
||||
if (this.node) {
|
||||
if (this.fileIsLocked()) {
|
||||
return false;
|
||||
}
|
||||
get canUpdateNode(): boolean {
|
||||
if (this.node && this.node.isFile && !isLocked({ entry: this.node })) {
|
||||
return this.permission.check(this.node, ['update']);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private fileIsLocked() {
|
||||
if (!this.node.isFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
this.node.isLocked ||
|
||||
(this.node.properties &&
|
||||
this.node.properties['cm:lockType'] === 'READ_ONLY_LOCK')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ import {
|
||||
import { DocumentListComponent } from '@alfresco/adf-content-services';
|
||||
import { LibrariesComponent } from './libraries.component';
|
||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { ExperimentalDirective } from '../../directives/experimental.directive';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { LibraryEffects } from '../../store/effects';
|
||||
|
||||
@ -67,8 +66,7 @@ describe('LibrariesComponent', () => {
|
||||
NodeFavoriteDirective,
|
||||
DocumentListComponent,
|
||||
LibrariesComponent,
|
||||
AppConfigPipe,
|
||||
ExperimentalDirective
|
||||
AppConfigPipe
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
|
@ -44,6 +44,7 @@ import {
|
||||
sharedUrl
|
||||
} from '../store/selectors/app.selectors';
|
||||
import { AppStore } from '../store/states/app.state';
|
||||
import { isLocked, isLibrary } from '../utils/node.utils';
|
||||
|
||||
export abstract class PageComponent implements OnInit, OnDestroy {
|
||||
onDestroy$: Subject<boolean> = new Subject<boolean>();
|
||||
@ -64,28 +65,6 @@ export abstract class PageComponent implements OnInit, OnDestroy {
|
||||
|
||||
protected subscriptions: Subscription[] = [];
|
||||
|
||||
static isLockedNode(node) {
|
||||
return (
|
||||
node.isLocked ||
|
||||
(node.properties && node.properties['cm:lockType'] === 'READ_ONLY_LOCK')
|
||||
);
|
||||
}
|
||||
|
||||
static isWriteLockedNode(node) {
|
||||
return node.properties && node.properties['cm:lockType'] === 'WRITE_LOCK';
|
||||
}
|
||||
|
||||
static isLibrary(entry) {
|
||||
return (
|
||||
(entry.guid &&
|
||||
entry.id &&
|
||||
entry.preset &&
|
||||
entry.title &&
|
||||
entry.visibility) ||
|
||||
entry.nodeType === 'st:site'
|
||||
);
|
||||
}
|
||||
|
||||
constructor(
|
||||
protected store: Store<AppStore>,
|
||||
protected extensions: AppExtensionService,
|
||||
@ -137,16 +116,11 @@ export abstract class PageComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
imageResolver(row: ShareDataRow): string | null {
|
||||
const entry: MinimalNodeEntryEntity = row.node.entry;
|
||||
|
||||
if (
|
||||
PageComponent.isLockedNode(entry) ||
|
||||
PageComponent.isWriteLockedNode(entry)
|
||||
) {
|
||||
if (isLocked(row.node)) {
|
||||
return 'assets/images/baseline-lock-24px.svg';
|
||||
}
|
||||
|
||||
if (PageComponent.isLibrary(entry)) {
|
||||
if (isLibrary(row.node)) {
|
||||
return 'assets/images/baseline-library_books-24px.svg';
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,6 @@ import {
|
||||
import { PreviewComponent } from './preview.component';
|
||||
import { of, throwError } from 'rxjs';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { ExperimentalDirective } from '../../directives/experimental.directive';
|
||||
import { NodeEffects } from '../../store/effects/node.effects';
|
||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { ContentApiService } from '../../services/content-api.service';
|
||||
@ -63,12 +62,7 @@ describe('PreviewComponent', () => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [AppTestingModule, EffectsModule.forRoot([NodeEffects])],
|
||||
providers: [AlfrescoApiService, ContentManagementService],
|
||||
declarations: [
|
||||
AppConfigPipe,
|
||||
PreviewComponent,
|
||||
NodeFavoriteDirective,
|
||||
ExperimentalDirective
|
||||
],
|
||||
declarations: [AppConfigPipe, PreviewComponent, NodeFavoriteDirective],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
|
||||
|
@ -38,7 +38,6 @@ import { ContentManagementService } from '../../services/content-management.serv
|
||||
|
||||
import { RecentFilesComponent } from './recent-files.component';
|
||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { ExperimentalDirective } from '../../directives/experimental.directive';
|
||||
|
||||
describe('RecentFilesComponent', () => {
|
||||
let fixture: ComponentFixture<RecentFilesComponent>;
|
||||
@ -66,8 +65,7 @@ describe('RecentFilesComponent', () => {
|
||||
NodeFavoriteDirective,
|
||||
DocumentListComponent,
|
||||
RecentFilesComponent,
|
||||
AppConfigPipe,
|
||||
ExperimentalDirective
|
||||
AppConfigPipe
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
|
@ -79,11 +79,6 @@ export class RecentFilesComponent extends PageComponent implements OnInit {
|
||||
|
||||
onNodeDoubleClick(node: MinimalNodeEntity) {
|
||||
if (node && node.entry) {
|
||||
if (PageComponent.isLockedNode(node.entry)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
this.showPreview(node);
|
||||
}
|
||||
}
|
||||
|
@ -177,11 +177,6 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PageComponent.isLockedNode(node.entry)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
this.showPreview(node);
|
||||
}
|
||||
}
|
||||
|
@ -81,22 +81,4 @@
|
||||
Language Picker
|
||||
</mat-checkbox>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<ng-container *ngIf="experimental.length">
|
||||
<mat-expansion-panel *ngIf="(profile$ | async)?.isAdmin">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
{{ 'APP.SETTINGS.EXPERIMENTAL-FEATURES' | translate }}
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<div *ngFor="let flag of experimental">
|
||||
<mat-checkbox
|
||||
[(ngModel)]="flag.value"
|
||||
(change)="onToggleExperimentalFeature(flag.key, $event)"
|
||||
>
|
||||
{{ flag.key }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</ng-container>
|
||||
</mat-accordion>
|
||||
|
@ -64,7 +64,6 @@ export class SettingsComponent implements OnInit {
|
||||
appName$: Observable<string>;
|
||||
headerColor$: Observable<string>;
|
||||
languagePicker$: Observable<boolean>;
|
||||
experimental: Array<{ key: string; value: boolean }> = [];
|
||||
|
||||
constructor(
|
||||
private store: Store<AppStore>,
|
||||
@ -96,15 +95,6 @@ export class SettingsComponent implements OnInit {
|
||||
});
|
||||
|
||||
this.reset();
|
||||
|
||||
const settings = this.appConfig.get('experimental');
|
||||
this.experimental = Object.keys(settings).map(key => {
|
||||
const value = this.appConfig.get(`experimental.${key}`);
|
||||
return {
|
||||
key,
|
||||
value: value === true || value === 'true'
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
apply(model: RepositoryConfig, isValid: boolean) {
|
||||
@ -142,8 +132,4 @@ export class SettingsComponent implements OnInit {
|
||||
this.storage.setItem('languagePicker', event.checked.toString());
|
||||
this.store.dispatch(new SetLanguagePickerAction(event.checked));
|
||||
}
|
||||
|
||||
onToggleExperimentalFeature(key: string, event: MatCheckboxChange) {
|
||||
this.storage.setItem(`experimental.${key}`, event.checked.toString());
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ import { DocumentListComponent } from '@alfresco/adf-content-services';
|
||||
import { ContentManagementService } from '../../services/content-management.service';
|
||||
import { SharedFilesComponent } from './shared-files.component';
|
||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { ExperimentalDirective } from '../../directives/experimental.directive';
|
||||
|
||||
describe('SharedFilesComponent', () => {
|
||||
let fixture: ComponentFixture<SharedFilesComponent>;
|
||||
@ -65,8 +64,7 @@ describe('SharedFilesComponent', () => {
|
||||
NodeFavoriteDirective,
|
||||
DocumentListComponent,
|
||||
SharedFilesComponent,
|
||||
AppConfigPipe,
|
||||
ExperimentalDirective
|
||||
AppConfigPipe
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
|
@ -36,7 +36,6 @@ import { DocumentListComponent } from '@alfresco/adf-content-services';
|
||||
import { ContentManagementService } from '../../services/content-management.service';
|
||||
import { TrashcanComponent } from './trashcan.component';
|
||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||
import { ExperimentalDirective } from '../../directives/experimental.directive';
|
||||
|
||||
describe('TrashcanComponent', () => {
|
||||
let fixture: ComponentFixture<TrashcanComponent>;
|
||||
@ -64,8 +63,7 @@ describe('TrashcanComponent', () => {
|
||||
NodeFavoriteDirective,
|
||||
DocumentListComponent,
|
||||
TrashcanComponent,
|
||||
AppConfigPipe,
|
||||
ExperimentalDirective
|
||||
AppConfigPipe
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
|
@ -24,7 +24,6 @@
|
||||
*/
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { ExperimentalDirective } from './experimental.directive';
|
||||
import { DocumentListDirective } from './document-list.directive';
|
||||
import { PaginationDirective } from './pagination.directive';
|
||||
import { LibraryMembershipDirective } from './library-membership.directive';
|
||||
@ -33,7 +32,6 @@ import { LockNodeDirective } from './lock-node.directive';
|
||||
|
||||
export function directives() {
|
||||
return [
|
||||
ExperimentalDirective,
|
||||
DocumentListDirective,
|
||||
PaginationDirective,
|
||||
LibraryMembershipDirective,
|
||||
|
@ -29,9 +29,7 @@ import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { UserPreferencesService } from '@alfresco/adf-core';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppStore } from '../store/states/app.state';
|
||||
import { SetSelectedNodesAction } from '../store/actions';
|
||||
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
|
||||
|
||||
@Directive({
|
||||
selector: '[acaDocumentList]'
|
||||
@ -45,7 +43,7 @@ export class DocumentListDirective implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
constructor(
|
||||
private store: Store<AppStore>,
|
||||
private store: Store<any>,
|
||||
private documentList: DocumentListComponent,
|
||||
private preferences: UserPreferencesService,
|
||||
private route: ActivatedRoute,
|
||||
@ -104,11 +102,6 @@ export class DocumentListDirective implements OnInit, OnDestroy {
|
||||
@HostListener('node-select', ['$event'])
|
||||
onNodeSelect(event: CustomEvent) {
|
||||
if (!!event.detail && !!event.detail.node) {
|
||||
const node: MinimalNodeEntryEntity = event.detail.node.entry;
|
||||
if (node && this.isLockedNode(node)) {
|
||||
this.unSelectLockedNodes(this.documentList);
|
||||
}
|
||||
|
||||
this.updateSelection();
|
||||
}
|
||||
}
|
||||
@ -123,47 +116,11 @@ export class DocumentListDirective implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private updateSelection() {
|
||||
const selection = this.documentList.selection
|
||||
.filter(node => !this.isLockedNode(node.entry))
|
||||
.map(node => {
|
||||
node['isLibrary'] = this.isLibrary;
|
||||
return node;
|
||||
});
|
||||
const selection = this.documentList.selection.map(node => {
|
||||
node['isLibrary'] = this.isLibrary;
|
||||
return node;
|
||||
});
|
||||
|
||||
this.store.dispatch(new SetSelectedNodesAction(selection));
|
||||
}
|
||||
|
||||
private isLockedNode(node): boolean {
|
||||
return (
|
||||
node.isLocked ||
|
||||
(node.properties && node.properties['cm:lockType'] === 'READ_ONLY_LOCK')
|
||||
);
|
||||
}
|
||||
|
||||
private isLockedRow(row): boolean {
|
||||
return (
|
||||
row.getValue('isLocked') ||
|
||||
(row.getValue('properties') &&
|
||||
row.getValue('properties')['cm:lockType'] === 'READ_ONLY_LOCK')
|
||||
);
|
||||
}
|
||||
|
||||
private unSelectLockedNodes(documentList: DocumentListComponent) {
|
||||
documentList.selection = documentList.selection.filter(
|
||||
item => !this.isLockedNode(item.entry)
|
||||
);
|
||||
|
||||
const dataTable = documentList.dataTable;
|
||||
if (dataTable && dataTable.data) {
|
||||
const rows = dataTable.data.getRows();
|
||||
|
||||
if (rows && rows.length > 0) {
|
||||
rows.forEach(r => {
|
||||
if (this.isLockedRow(r)) {
|
||||
r.isSelected = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,105 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2018 Alfresco Software Limited
|
||||
*
|
||||
* This file is part of the Alfresco Example Content Application.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
Directive,
|
||||
TemplateRef,
|
||||
ViewContainerRef,
|
||||
Input,
|
||||
EmbeddedViewRef
|
||||
} from '@angular/core';
|
||||
import { AppConfigService, StorageService } from '@alfresco/adf-core';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
@Directive({
|
||||
// tslint:disable-next-line:directive-selector
|
||||
selector: '[ifExperimental]'
|
||||
})
|
||||
export class ExperimentalDirective {
|
||||
private elseTemplateRef: TemplateRef<any>;
|
||||
private elseViewRef: EmbeddedViewRef<any>;
|
||||
private shouldRender: boolean;
|
||||
|
||||
constructor(
|
||||
private templateRef: TemplateRef<any>,
|
||||
private viewContainerRef: ViewContainerRef,
|
||||
private storage: StorageService,
|
||||
private config: AppConfigService
|
||||
) {}
|
||||
|
||||
@Input()
|
||||
set ifExperimental(featureKey: string) {
|
||||
const key = `experimental.${featureKey}`;
|
||||
|
||||
const override = this.storage.getItem(key);
|
||||
|
||||
if (override === 'true') {
|
||||
this.shouldRender = true;
|
||||
}
|
||||
|
||||
if (!environment.production) {
|
||||
const value = this.config.get(key);
|
||||
if (value === true || value === 'true') {
|
||||
this.shouldRender = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (override !== 'true' && environment.production) {
|
||||
this.shouldRender = false;
|
||||
}
|
||||
|
||||
this.updateView();
|
||||
}
|
||||
|
||||
@Input()
|
||||
set ifExperimentalElse(templateRef: TemplateRef<any>) {
|
||||
this.elseTemplateRef = templateRef;
|
||||
this.elseViewRef = null;
|
||||
this.updateView();
|
||||
}
|
||||
|
||||
private updateView() {
|
||||
if (this.shouldRender) {
|
||||
this.viewContainerRef.clear();
|
||||
this.elseViewRef = null;
|
||||
|
||||
if (this.templateRef) {
|
||||
this.viewContainerRef.createEmbeddedView(this.templateRef);
|
||||
}
|
||||
} else {
|
||||
if (this.elseViewRef) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.viewContainerRef.clear();
|
||||
|
||||
if (this.elseTemplateRef) {
|
||||
this.elseViewRef = this.viewContainerRef.createEmbeddedView(
|
||||
this.elseTemplateRef
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -32,6 +32,7 @@ import {
|
||||
} from '@angular/core';
|
||||
import { NodeEntry, NodeBodyLock, SharedLinkEntry } from '@alfresco/js-api';
|
||||
import { AlfrescoApiService } from '@alfresco/adf-core';
|
||||
import { isLocked } from '../utils/node.utils';
|
||||
|
||||
@Directive({
|
||||
selector: '[acaLockNode]',
|
||||
@ -52,33 +53,28 @@ export class LockNodeDirective {
|
||||
|
||||
constructor(private alfrescoApiService: AlfrescoApiService) {}
|
||||
|
||||
isNodeLocked() {
|
||||
return !!(
|
||||
this.node &&
|
||||
this.node.entry.properties &&
|
||||
this.node.entry.properties['cm:lockType'] === 'WRITE_LOCK'
|
||||
);
|
||||
isNodeLocked(): boolean {
|
||||
return isLocked(this.node);
|
||||
}
|
||||
|
||||
private async toggleLock(node: NodeEntry | SharedLinkEntry) {
|
||||
const id = (<SharedLinkEntry>node).entry.nodeId || node.entry.id;
|
||||
if (this.isNodeLocked()) {
|
||||
|
||||
if (isLocked(this.node)) {
|
||||
try {
|
||||
const response = await this.unlockNode(id);
|
||||
const isLocked = false;
|
||||
|
||||
this.update(response.entry);
|
||||
this.toggle.emit(isLocked);
|
||||
this.toggle.emit(false);
|
||||
} catch (error) {
|
||||
this.unlockError.emit(error);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const response = await this.lockNode(id);
|
||||
const isLocked = true;
|
||||
|
||||
this.update(response.entry);
|
||||
this.toggle.emit(isLocked);
|
||||
this.toggle.emit(true);
|
||||
} catch (error) {
|
||||
this.lockError.emit(error);
|
||||
}
|
||||
|
@ -310,7 +310,9 @@ export function isWriteLocked(
|
||||
context.selection.file &&
|
||||
context.selection.file.entry &&
|
||||
context.selection.file.entry.properties &&
|
||||
context.selection.file.entry.properties['cm:lockType'] === 'WRITE_LOCK'
|
||||
(context.selection.file.entry.properties['cm:lockType'] === 'WRITE_LOCK' ||
|
||||
context.selection.file.entry.properties['cm:lockType'] ===
|
||||
'READ_ONLY_LOCK')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,32 +0,0 @@
|
||||
/*!
|
||||
* @license
|
||||
* Alfresco Example Content Application
|
||||
*
|
||||
* Copyright (C) 2005 - 2018 Alfresco Software Limited
|
||||
*
|
||||
* This file is part of the Alfresco Example Content Application.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ExperimentalGuard } from './experimental-guard.service';
|
||||
|
||||
describe('ExperimentalGuard', () => {
|
||||
it('should be defined', () => {
|
||||
expect(ExperimentalGuard).toBeDefined();
|
||||
});
|
||||
});
|
@ -1,35 +0,0 @@
|
||||
import { CanActivate, ActivatedRouteSnapshot, Router } from '@angular/router';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AppConfigService, StorageService } from '@alfresco/adf-core';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
@Injectable()
|
||||
export class ExperimentalGuard implements CanActivate {
|
||||
constructor(
|
||||
private config: AppConfigService,
|
||||
private storage: StorageService,
|
||||
private router: Router
|
||||
) {}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot) {
|
||||
const key = `experimental.${route.data.ifExperimentalKey}`;
|
||||
const value = this.config.get(key);
|
||||
const override = this.storage.getItem(key);
|
||||
|
||||
if (override === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!environment.production) {
|
||||
if (value === true || value === 'true') {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.router.navigate(['/']);
|
||||
}
|
||||
|
||||
this.router.navigate(['/']);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -23,10 +23,28 @@
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ExperimentalDirective } from './experimental.directive';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
|
||||
describe('ExperimentalDirective', () => {
|
||||
it('should be defined', () => {
|
||||
expect(ExperimentalDirective).toBeDefined();
|
||||
});
|
||||
});
|
||||
export function isLocked(node: { entry: Node }): boolean {
|
||||
const { entry } = node;
|
||||
|
||||
return (
|
||||
(entry && entry.isLocked) ||
|
||||
(entry.properties &&
|
||||
(entry.properties['cm:lockType'] === 'READ_ONLY_LOCK' ||
|
||||
entry.properties['cm:lockType'] === 'WRITE_LOCK'))
|
||||
);
|
||||
}
|
||||
|
||||
export function isLibrary(node: { entry: Node | any }): boolean {
|
||||
const { entry } = node;
|
||||
|
||||
return (
|
||||
(entry.guid &&
|
||||
entry.id &&
|
||||
entry.preset &&
|
||||
entry.title &&
|
||||
entry.visibility) ||
|
||||
entry.nodeType === 'st:site'
|
||||
);
|
||||
}
|
@ -41,7 +41,6 @@
|
||||
"TITLE": "Einstellungen",
|
||||
"APPLICATION-SETTINGS": "Anwendungseinstellungen",
|
||||
"REPOSITORY-SETTINGS": "Repository-Einstellungen",
|
||||
"EXPERIMENTAL-FEATURES": "Testfunktionen",
|
||||
"INVALID-VALUE-FORMAT": "Wert in ungültigem Format",
|
||||
"REQUIRED-FIELD": "Dieses Feld ist erforderlich.",
|
||||
"RESET": "Zurücksetzen",
|
||||
|
@ -41,7 +41,6 @@
|
||||
"TITLE": "Settings",
|
||||
"APPLICATION-SETTINGS": "Application Settings",
|
||||
"REPOSITORY-SETTINGS": "Repository Settings",
|
||||
"EXPERIMENTAL-FEATURES": "Experimental Features",
|
||||
"INVALID-VALUE-FORMAT": "Invalid value format",
|
||||
"REQUIRED-FIELD": "This field is required",
|
||||
"RESET": "Reset",
|
||||
|
@ -41,7 +41,6 @@
|
||||
"TITLE": "Configuración",
|
||||
"APPLICATION-SETTINGS": "Configuración de la aplicación",
|
||||
"REPOSITORY-SETTINGS": "Configuración del repositorio",
|
||||
"EXPERIMENTAL-FEATURES": "Funciones experimentales",
|
||||
"INVALID-VALUE-FORMAT": "Formato de valor no válido",
|
||||
"REQUIRED-FIELD": "Este campo es obligatorio",
|
||||
"RESET": "Reiniciar",
|
||||
|
@ -41,7 +41,6 @@
|
||||
"TITLE": "Paramètres",
|
||||
"APPLICATION-SETTINGS": "Paramètres de l'application",
|
||||
"REPOSITORY-SETTINGS": "Paramètres de l'entrepôt",
|
||||
"EXPERIMENTAL-FEATURES": "Fonctionnalités expérimentales",
|
||||
"INVALID-VALUE-FORMAT": "Format de valeur non valide",
|
||||
"REQUIRED-FIELD": "Ce champ doit être renseigné",
|
||||
"RESET": "Réinitialiser",
|
||||
|
@ -41,7 +41,6 @@
|
||||
"TITLE": "Impostazioni",
|
||||
"APPLICATION-SETTINGS": "Impostazioni applicazione",
|
||||
"REPOSITORY-SETTINGS": "Impostazioni repository",
|
||||
"EXPERIMENTAL-FEATURES": "Funzioni sperimentali",
|
||||
"INVALID-VALUE-FORMAT": "Formato valore non valido",
|
||||
"REQUIRED-FIELD": "Questo campo è obbligatorio",
|
||||
"RESET": "Reimposta",
|
||||
|
@ -41,7 +41,6 @@
|
||||
"TITLE": "設定",
|
||||
"APPLICATION-SETTINGS": "アプリケーションの設定",
|
||||
"REPOSITORY-SETTINGS": "リポジトリの設定",
|
||||
"EXPERIMENTAL-FEATURES": "試験的な機能",
|
||||
"INVALID-VALUE-FORMAT": "無効な値形式",
|
||||
"REQUIRED-FIELD": "このフィールドは必須です",
|
||||
"RESET": "リセット",
|
||||
|
@ -41,7 +41,6 @@
|
||||
"TITLE": "Innstillinger",
|
||||
"APPLICATION-SETTINGS": "Programinnstillinger",
|
||||
"REPOSITORY-SETTINGS": "Databaseinnstillinger",
|
||||
"EXPERIMENTAL-FEATURES": "Eksperimentelle funksjoner",
|
||||
"INVALID-VALUE-FORMAT": "Ugyldig verdiformat",
|
||||
"REQUIRED-FIELD": "Dette feltet er obligatorisk",
|
||||
"RESET": "Tilbakestill",
|
||||
|
@ -41,7 +41,6 @@
|
||||
"TITLE": "Instellingen",
|
||||
"APPLICATION-SETTINGS": "Toepassingsinstellingen",
|
||||
"REPOSITORY-SETTINGS": "Opslagplaatsinstellingen",
|
||||
"EXPERIMENTAL-FEATURES": "Experimentele onderdelen",
|
||||
"INVALID-VALUE-FORMAT": "Ongeldige indeling van waarde",
|
||||
"REQUIRED-FIELD": "Dit veld is vereist",
|
||||
"RESET": "Opnieuw instellen",
|
||||
|
@ -41,7 +41,6 @@
|
||||
"TITLE": "Configurações",
|
||||
"APPLICATION-SETTINGS": "Configurações do aplicativo",
|
||||
"REPOSITORY-SETTINGS": "Configurações do repositório",
|
||||
"EXPERIMENTAL-FEATURES": "Recursos experimentais",
|
||||
"INVALID-VALUE-FORMAT": "Formato de valor inválido",
|
||||
"REQUIRED-FIELD": "Este campo é obrigatório",
|
||||
"RESET": "Redefinir",
|
||||
|
@ -41,7 +41,6 @@
|
||||
"TITLE": "Параметры",
|
||||
"APPLICATION-SETTINGS": "Настройки приложений",
|
||||
"REPOSITORY-SETTINGS": "Настройки репозитория",
|
||||
"EXPERIMENTAL-FEATURES": "Экспериментальные функции",
|
||||
"INVALID-VALUE-FORMAT": "Недопустимый формат значения",
|
||||
"REQUIRED-FIELD": "Это обязательное поле",
|
||||
"RESET": "Сброс",
|
||||
|
@ -41,7 +41,6 @@
|
||||
"TITLE": "设置",
|
||||
"APPLICATION-SETTINGS": "应用程序设置",
|
||||
"REPOSITORY-SETTINGS": "存储库设置",
|
||||
"EXPERIMENTAL-FEATURES": "试验性功能",
|
||||
"INVALID-VALUE-FORMAT": "值格式无效",
|
||||
"REQUIRED-FIELD": "此字段为必填字段",
|
||||
"RESET": "重置",
|
||||
|
Loading…
x
Reference in New Issue
Block a user