mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-05-12 17:04:46 +00:00
[ACA-2193] Lock node - unlock after new version is uploaded (#924)
* unlock node api call * unlock action and effect * unlock node after version upload * check if locked * clear version input on dialog cancel event * update viewer on node version upload * update viewer on file upload delete * test * update tests * update tests * rename evaluators * update docs
This commit is contained in:
parent
65e0a1138c
commit
894a928187
@ -76,42 +76,44 @@ and perform document list reload if needed.
|
||||
|
||||
Below is the list of public actions types you can use in the plugin definitions as a reference to the action:
|
||||
|
||||
| Name | Payload | Description |
|
||||
| -- | -- | -- |
|
||||
| SET_CURRENT_FOLDER | Node | Notify components about currently opened folder. |
|
||||
| SET_CURRENT_URL | string | Notify components about current browser URL. |
|
||||
| SET_USER_PROFILE | Person | Assign current user profile. |
|
||||
| TOGGLE_INFO_DRAWER | n/a | Toggle info drawer for the selected node. |
|
||||
| ADD_FAVORITE | MinimalNodeEntity[] | Add nodes (or selection) to favorites. |
|
||||
| REMOVE_FAVORITE | MinimalNodeEntity[] | Removes nodes (or selection) from favorites. |
|
||||
| DELETE_LIBRARY | string | Delete a Library by id. Takes selected node if payload not provided. |
|
||||
| CREATE_LIBRARY | n/a | Invoke a "Create Library" dialog. |
|
||||
| SET_SELECTED_NODES | MinimalNodeEntity[] | Notify components about selected nodes. |
|
||||
| DELETE_NODES | MinimalNodeEntity[] | Delete the nodes (or selection). Supports undo actions. |
|
||||
| UNDO_DELETE_NODES | any[] | Reverts deletion of nodes (or selection). |
|
||||
| RESTORE_DELETED_NODES | MinimalNodeEntity[] | Restores deleted nodes (or selection). Typically used with Trashcan. |
|
||||
| PURGE_DELETED_NODES | MinimalNodeEntity[] | Permanently delete nodes (or selection). Typically used with Trashcan. |
|
||||
| DOWNLOAD_NODES | MinimalNodeEntity[] | Download nodes (or selections). Creates a ZIP archive for folders or multiple items. |
|
||||
| CREATE_FOLDER | string | Invoke a "Create Folder" dialog for the opened folder (or the parent folder id in the payload). |
|
||||
| EDIT_FOLDER | MinimalNodeEntity | Invoke an "Edit Folder" dialog for the node (or selection). |
|
||||
| SHARE_NODE | MinimalNodeEntity | Invoke a "Share" dialog for the node (or selection). |
|
||||
| UNSHARE_NODES | MinimalNodeEntity[] | Remove nodes (or selection) from the shared nodes (does not remove content). |
|
||||
| COPY_NODES | MinimalNodeEntity[] | Invoke a "Copy" dialog for the nodes (or selection). Supports undo actions. |
|
||||
| MOVE_NODES | MinimalNodeEntity[] | Invoke a "Move" dialog for the nodes (or selection). Supports undo actions. |
|
||||
| MANAGE_PERMISSIONS | MinimalNodeEntity | Invoke a "Manage Permissions" dialog for the node (or selection). |
|
||||
| MANAGE_VERSIONS | MinimalNodeEntity | Invoke a "Manage Versions" dialog for the node (or selection). |
|
||||
| NAVIGATE_URL | string | Navigate to a given route URL within the application. |
|
||||
| NAVIGATE_ROUTE | any[] | Navigate to a particular Route (supports parameters). |
|
||||
| NAVIGATE_FOLDER | MinimalNodeEntity | Navigate to a folder based on the Node properties. |
|
||||
| NAVIGATE_PARENT_FOLDER | MinimalNodeEntity | Navigate to a containing folder based on the Node properties. |
|
||||
| NAVIGATE_LIBRARY | string | Navigate to library. |
|
||||
| SEARCH_BY_TERM | string | Perform a simple search by the term and navigate to Search results. |
|
||||
| SNACKBAR_INFO | string | Show information snackbar with the message provided. |
|
||||
| SNACKBAR_WARNING | string | Show warning snackbar with the message provided. |
|
||||
| SNACKBAR_ERROR | string | Show error snackbar with the message provided. |
|
||||
| UPLOAD_FILES | n/a | Invoke "Upload Files" dialog and upload files to the currently opened folder. |
|
||||
| UPLOAD_FOLDER | n/a | Invoke "Upload Folder" dialog and upload selected folder to the currently opened one. |
|
||||
| VIEW_FILE | MinimalNodeEntity | Preview the file (or selection) in the Viewer. |
|
||||
| PRINT_FILE | MinimalNodeEntity | Print the file opened in the Viewer (or selected). |
|
||||
| FULLSCREEN_VIEWER | n/a | Enters fullscreen mode to view the file opened in the Viewer. |
|
||||
| LOGOUT | n/a | Log out and redirect to Login screen. |
|
||||
| Name | Payload | Description |
|
||||
| ---------------------- | ------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| SET_CURRENT_FOLDER | Node | Notify components about currently opened folder. |
|
||||
| SET_CURRENT_URL | string | Notify components about current browser URL. |
|
||||
| SET_USER_PROFILE | Person | Assign current user profile. |
|
||||
| TOGGLE_INFO_DRAWER | n/a | Toggle info drawer for the selected node. |
|
||||
| ADD_FAVORITE | MinimalNodeEntity[] | Add nodes (or selection) to favorites. |
|
||||
| REMOVE_FAVORITE | MinimalNodeEntity[] | Removes nodes (or selection) from favorites. |
|
||||
| DELETE_LIBRARY | string | Delete a Library by id. Takes selected node if payload not provided. |
|
||||
| CREATE_LIBRARY | n/a | Invoke a "Create Library" dialog. |
|
||||
| SET_SELECTED_NODES | MinimalNodeEntity[] | Notify components about selected nodes. |
|
||||
| DELETE_NODES | MinimalNodeEntity[] | Delete the nodes (or selection). Supports undo actions. |
|
||||
| UNDO_DELETE_NODES | any[] | Reverts deletion of nodes (or selection). |
|
||||
| RESTORE_DELETED_NODES | MinimalNodeEntity[] | Restores deleted nodes (or selection). Typically used with Trashcan. |
|
||||
| PURGE_DELETED_NODES | MinimalNodeEntity[] | Permanently delete nodes (or selection). Typically used with Trashcan. |
|
||||
| DOWNLOAD_NODES | MinimalNodeEntity[] | Download nodes (or selections). Creates a ZIP archive for folders or multiple items. |
|
||||
| CREATE_FOLDER | string | Invoke a "Create Folder" dialog for the opened folder (or the parent folder id in the payload). |
|
||||
| EDIT_FOLDER | MinimalNodeEntity | Invoke an "Edit Folder" dialog for the node (or selection). |
|
||||
| SHARE_NODE | MinimalNodeEntity | Invoke a "Share" dialog for the node (or selection). |
|
||||
| UNSHARE_NODES | MinimalNodeEntity[] | Remove nodes (or selection) from the shared nodes (does not remove content). |
|
||||
| COPY_NODES | MinimalNodeEntity[] | Invoke a "Copy" dialog for the nodes (or selection). Supports undo actions. |
|
||||
| MOVE_NODES | MinimalNodeEntity[] | Invoke a "Move" dialog for the nodes (or selection). Supports undo actions. |
|
||||
| MANAGE_PERMISSIONS | MinimalNodeEntity | Invoke a "Manage Permissions" dialog for the node (or selection). |
|
||||
| MANAGE_VERSIONS | MinimalNodeEntity | Invoke a "Manage Versions" dialog for the node (or selection). |
|
||||
| NAVIGATE_URL | string | Navigate to a given route URL within the application. |
|
||||
| NAVIGATE_ROUTE | any[] | Navigate to a particular Route (supports parameters). |
|
||||
| NAVIGATE_FOLDER | MinimalNodeEntity | Navigate to a folder based on the Node properties. |
|
||||
| NAVIGATE_PARENT_FOLDER | MinimalNodeEntity | Navigate to a containing folder based on the Node properties. |
|
||||
| NAVIGATE_LIBRARY | string | Navigate to library. |
|
||||
| SEARCH_BY_TERM | string | Perform a simple search by the term and navigate to Search results. |
|
||||
| SNACKBAR_INFO | string | Show information snackbar with the message provided. |
|
||||
| SNACKBAR_WARNING | string | Show warning snackbar with the message provided. |
|
||||
| SNACKBAR_ERROR | string | Show error snackbar with the message provided. |
|
||||
| UPLOAD_FILES | n/a | Invoke "Upload Files" dialog and upload files to the currently opened folder. |
|
||||
| UPLOAD_FOLDER | n/a | Invoke "Upload Folder" dialog and upload selected folder to the currently opened one. |
|
||||
| UPLOAD_FILE_VERSION | n/a | Invoke "New File Version" dialog. |
|
||||
| VIEW_FILE | MinimalNodeEntity | Preview the file (or selection) in the Viewer. |
|
||||
| UNLOCK_WRITE | NodeEntry | Unlock file from read only mode |
|
||||
| PRINT_FILE | MinimalNodeEntity | Print the file opened in the Viewer (or selected). |
|
||||
| FULLSCREEN_VIEWER | n/a | Enters fullscreen mode to view the file opened in the Viewer. |
|
||||
| LOGOUT | n/a | Log out and redirect to Login screen. |
|
||||
|
@ -148,6 +148,9 @@ The button will be visible only when the linked rule evaluates to `true`.
|
||||
| app.selection.hasNoLibraryRole | The selected Library node has no role property. |
|
||||
| app.selection.folder | A single Folder node is selected. |
|
||||
| app.selection.folder.canUpdate | User has permissions to update the selected folder. |
|
||||
| app.selection.folder.canUpdate | User has permissions to update the selected folder. |
|
||||
| app.selection.file.canLock | User has permissions to lock file. |
|
||||
| app.selection.file.canUnlock | User has permissions to unlock file. |
|
||||
| repository.isQuickShareEnabled | Whether the quick share repository option is enabled or not. |
|
||||
|
||||
## Navigation Evaluators
|
||||
@ -176,6 +179,8 @@ for example mixing `core.every` and `core.not`.
|
||||
| app.navigation.isNotRecentFiles | Current page is not **Recent Files**. |
|
||||
| app.navigation.isSearchResults | User is using the **Search Results** page. |
|
||||
| app.navigation.isNotSearchResults | Current page is not the **Search Results**. |
|
||||
| app.navigation.isSharedPreview | Current page is preview **Shared Files** |
|
||||
| app.navigation.isFavoritesPreview | Current page is preview **Favorites** |
|
||||
|
||||
**Tip:** See the [Registration](/extending/registration) section for more details
|
||||
on how to register your own entries to be re-used at runtime.
|
||||
|
@ -25,11 +25,19 @@
|
||||
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import {
|
||||
TestBed,
|
||||
ComponentFixture,
|
||||
async,
|
||||
fakeAsync,
|
||||
tick
|
||||
} from '@angular/core/testing';
|
||||
import {
|
||||
UserPreferencesService,
|
||||
AppConfigPipe,
|
||||
NodeFavoriteDirective
|
||||
NodeFavoriteDirective,
|
||||
UploadService,
|
||||
AlfrescoApiService
|
||||
} from '@alfresco/adf-core';
|
||||
import { PreviewComponent } from './preview.component';
|
||||
import { of, throwError } from 'rxjs';
|
||||
@ -38,6 +46,7 @@ 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';
|
||||
import { ContentManagementService } from '../../services/content-management.service';
|
||||
|
||||
describe('PreviewComponent', () => {
|
||||
let fixture: ComponentFixture<PreviewComponent>;
|
||||
@ -46,10 +55,14 @@ describe('PreviewComponent', () => {
|
||||
let route: ActivatedRoute;
|
||||
let preferences: UserPreferencesService;
|
||||
let contentApi: ContentApiService;
|
||||
let uploadService: UploadService;
|
||||
let alfrescoApiService: AlfrescoApiService;
|
||||
let contentManagementService: ContentManagementService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [AppTestingModule, EffectsModule.forRoot([NodeEffects])],
|
||||
providers: [AlfrescoApiService, ContentManagementService],
|
||||
declarations: [
|
||||
AppConfigPipe,
|
||||
PreviewComponent,
|
||||
@ -66,6 +79,9 @@ describe('PreviewComponent', () => {
|
||||
route = TestBed.get(ActivatedRoute);
|
||||
preferences = TestBed.get(UserPreferencesService);
|
||||
contentApi = TestBed.get(ContentApiService);
|
||||
uploadService = TestBed.get(UploadService);
|
||||
alfrescoApiService = TestBed.get(AlfrescoApiService);
|
||||
contentManagementService = TestBed.get(ContentManagementService);
|
||||
});
|
||||
|
||||
it('should extract the property path root', () => {
|
||||
@ -697,4 +713,29 @@ describe('PreviewComponent', () => {
|
||||
const ids = await component.getFileIds('recent-files');
|
||||
expect(ids).toEqual(['node2', 'node1']);
|
||||
});
|
||||
|
||||
it('should return to parent folder on nodesDeleted event', async(() => {
|
||||
spyOn(component, 'navigateToFileLocation');
|
||||
fixture.detectChanges();
|
||||
contentManagementService.nodesDeleted.next();
|
||||
|
||||
expect(component.navigateToFileLocation).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should return to parent folder on fileUploadDeleted event', async(() => {
|
||||
spyOn(component, 'navigateToFileLocation');
|
||||
fixture.detectChanges();
|
||||
uploadService.fileUploadDeleted.next();
|
||||
|
||||
expect(component.navigateToFileLocation).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should emit nodeUpdated event on fileUploadComplete event', fakeAsync(() => {
|
||||
spyOn(alfrescoApiService.nodeUpdated, 'next');
|
||||
fixture.detectChanges();
|
||||
uploadService.fileUploadComplete.next(<any>{ data: { entry: {} } });
|
||||
tick(300);
|
||||
|
||||
expect(alfrescoApiService.nodeUpdated.next).toHaveBeenCalled();
|
||||
}));
|
||||
});
|
||||
|
@ -38,7 +38,13 @@ import {
|
||||
UrlSegment,
|
||||
PRIMARY_OUTLET
|
||||
} from '@angular/router';
|
||||
import { UserPreferencesService, ObjectUtils } from '@alfresco/adf-core';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import {
|
||||
UserPreferencesService,
|
||||
ObjectUtils,
|
||||
UploadService,
|
||||
AlfrescoApiService
|
||||
} from '@alfresco/adf-core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { AppStore } from '../../store/states/app.state';
|
||||
import { SetSelectedNodesAction } from '../../store/actions';
|
||||
@ -84,6 +90,8 @@ export class PreviewComponent extends PageComponent
|
||||
private appDataService: AppDataService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private apiService: AlfrescoApiService,
|
||||
private uploadService: UploadService,
|
||||
store: Store<AppStore>,
|
||||
extensions: AppExtensionService,
|
||||
content: ContentManagementService
|
||||
@ -122,7 +130,15 @@ export class PreviewComponent extends PageComponent
|
||||
this.subscriptions = this.subscriptions.concat([
|
||||
this.content.nodesDeleted.subscribe(() =>
|
||||
this.navigateToFileLocation(true)
|
||||
)
|
||||
),
|
||||
|
||||
this.uploadService.fileUploadDeleted.subscribe(() =>
|
||||
this.navigateToFileLocation(true)
|
||||
),
|
||||
|
||||
this.uploadService.fileUploadComplete
|
||||
.pipe(debounceTime(300))
|
||||
.subscribe(file => this.apiService.nodeUpdated.next(file.data.entry))
|
||||
]);
|
||||
|
||||
this.openWith = this.extensions.openWithActions;
|
||||
|
@ -111,8 +111,8 @@ export class CoreExtensionsModule {
|
||||
|
||||
extensions.setEvaluators({
|
||||
'app.selection.canDelete': app.canDeleteSelection,
|
||||
'app.selection.canUnlockFile': app.canUnlockFile,
|
||||
'app.selection.canLockFile': app.canLockFile,
|
||||
'app.selection.file.canUnlock': app.canUnlockFile,
|
||||
'app.selection.file.canLock': app.canLockFile,
|
||||
'app.selection.canDownload': app.canDownloadSelection,
|
||||
'app.selection.notEmpty': app.hasSelection,
|
||||
'app.selection.canUnshare': app.canUnshareNodes,
|
||||
|
@ -281,4 +281,8 @@ export class ContentApiService {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
unlockNode(nodeId: string, opts?) {
|
||||
return this.api.nodesApi.unlockNode(nodeId, opts);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,8 @@ import {
|
||||
MoveNodesAction,
|
||||
CopyNodesAction,
|
||||
ShareNodeAction,
|
||||
SetSelectedNodesAction
|
||||
SetSelectedNodesAction,
|
||||
UnlockWriteAction
|
||||
} from '../store/actions';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { NodeEffects } from '../store/effects/node.effects';
|
||||
@ -1567,4 +1568,34 @@ describe('ContentManagementService', () => {
|
||||
);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('Unlock Node', () => {
|
||||
it('should unlock node', fakeAsync(() => {
|
||||
spyOn(contentApi, 'unlockNode').and.returnValue(Promise.resolve({}));
|
||||
|
||||
store.dispatch(new UnlockWriteAction({ entry: { id: 'node-id' } }));
|
||||
tick();
|
||||
flush();
|
||||
|
||||
expect(contentApi.unlockNode).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should raise error when unlock node fails', fakeAsync(done => {
|
||||
spyOn(contentApi, 'unlockNode').and.callFake(
|
||||
() => new Promise((resolve, reject) => reject('error'))
|
||||
);
|
||||
spyOn(store, 'dispatch').and.callThrough();
|
||||
store.dispatch(
|
||||
new UnlockWriteAction({ entry: { id: 'node-id', name: 'some-file' } })
|
||||
);
|
||||
tick();
|
||||
flush();
|
||||
|
||||
expect(store.dispatch['calls'].argsFor(1)[0]).toEqual(
|
||||
new SnackbarErrorAction('APP.MESSAGES.ERRORS.UNLOCK_NODE', {
|
||||
fileName: 'some-file'
|
||||
})
|
||||
);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
@ -51,7 +51,8 @@ import {
|
||||
SiteEntry,
|
||||
DeletedNodesPaging,
|
||||
PathInfoEntity,
|
||||
SiteBody
|
||||
SiteBody,
|
||||
NodeEntry
|
||||
} from '@alfresco/js-api';
|
||||
import { NodePermissionService } from './node-permission.service';
|
||||
import { NodeInfo, DeletedNodeInfo, DeleteStatus } from '../store/models';
|
||||
@ -1217,4 +1218,14 @@ export class ContentManagementService {
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
unlockNode(node: NodeEntry) {
|
||||
this.contentApi.unlockNode(node.entry.id).catch(() => {
|
||||
this.store.dispatch(
|
||||
new SnackbarErrorAction('APP.MESSAGES.ERRORS.UNLOCK_NODE', {
|
||||
fileName: node.entry.name
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ export const PRINT_FILE = 'PRINT_FILE';
|
||||
export const FULLSCREEN_VIEWER = 'FULLSCREEN_VIEWER';
|
||||
export const MANAGE_VERSIONS = 'MANAGE_VERSIONS';
|
||||
export const EDIT_OFFLINE = 'EDIT_OFFLINE';
|
||||
export const UNLOCK_WRITE = 'UNLOCK_WRITE_LOCK';
|
||||
|
||||
export class SetSelectedNodesAction implements Action {
|
||||
readonly type = SET_SELECTED_NODES;
|
||||
@ -128,3 +129,8 @@ export class EditOfflineAction implements Action {
|
||||
readonly type = EDIT_OFFLINE;
|
||||
constructor(public payload: any) {}
|
||||
}
|
||||
|
||||
export class UnlockWriteAction implements Action {
|
||||
readonly type = UNLOCK_WRITE;
|
||||
constructor(public payload: any) {}
|
||||
}
|
||||
|
@ -42,7 +42,10 @@ import {
|
||||
EditFolderAction,
|
||||
CopyNodesAction,
|
||||
MoveNodesAction,
|
||||
ManagePermissionsAction
|
||||
ManagePermissionsAction,
|
||||
UnlockWriteAction,
|
||||
FullscreenViewerAction,
|
||||
PrintFileAction
|
||||
} from '../actions/node.actions';
|
||||
import { SetCurrentFolderAction } from '../actions/app.actions';
|
||||
|
||||
@ -398,4 +401,62 @@ describe('NodeEffects', () => {
|
||||
expect(contentService.managePermissions).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('printFile$', () => {
|
||||
it('it should print node content from payload', () => {
|
||||
spyOn(contentService, 'printFile').and.stub();
|
||||
const node: any = { entry: { id: 'node-id' } };
|
||||
|
||||
store.dispatch(new PrintFileAction(node));
|
||||
|
||||
expect(contentService.printFile).toHaveBeenCalledWith(node);
|
||||
});
|
||||
|
||||
it('it should print node content from store', fakeAsync(() => {
|
||||
spyOn(contentService, 'printFile').and.stub();
|
||||
const node: any = { entry: { isFile: true, id: 'node-id' } };
|
||||
|
||||
store.dispatch(new SetSelectedNodesAction([node]));
|
||||
|
||||
tick(100);
|
||||
|
||||
store.dispatch(new PrintFileAction(null));
|
||||
|
||||
expect(contentService.printFile).toHaveBeenCalledWith(node);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('fullscreenViewer$', () => {
|
||||
it('should call fullscreen viewer', () => {
|
||||
spyOn(contentService, 'fullscreenViewer').and.stub();
|
||||
|
||||
store.dispatch(new FullscreenViewerAction(null));
|
||||
|
||||
expect(contentService.fullscreenViewer).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('unlockWrite$', () => {
|
||||
it('should unlock node from payload', () => {
|
||||
spyOn(contentService, 'unlockNode').and.stub();
|
||||
const node: any = { entry: { id: 'node-id' } };
|
||||
|
||||
store.dispatch(new UnlockWriteAction(node));
|
||||
|
||||
expect(contentService.unlockNode).toHaveBeenCalledWith(node);
|
||||
});
|
||||
|
||||
it('should unlock node from store selection', fakeAsync(() => {
|
||||
spyOn(contentService, 'unlockNode').and.stub();
|
||||
const node: any = { entry: { isFile: true, id: 'node-id' } };
|
||||
|
||||
store.dispatch(new SetSelectedNodesAction([node]));
|
||||
|
||||
tick(100);
|
||||
|
||||
store.dispatch(new UnlockWriteAction(null));
|
||||
|
||||
expect(contentService.unlockNode).toHaveBeenCalledWith(node);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
@ -44,7 +44,9 @@ import {
|
||||
ShareNodeAction,
|
||||
SHARE_NODE,
|
||||
ManageVersionsAction,
|
||||
MANAGE_VERSIONS
|
||||
MANAGE_VERSIONS,
|
||||
UnlockWriteAction,
|
||||
UNLOCK_WRITE
|
||||
} from '../actions';
|
||||
import { ContentManagementService } from '../../services/content-management.service';
|
||||
import { currentFolder, appSelection } from '../selectors/app.selectors';
|
||||
@ -316,4 +318,23 @@ export class NodeEffects {
|
||||
this.contentService.fullscreenViewer();
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
unlockWrite$ = this.actions$.pipe(
|
||||
ofType<UnlockWriteAction>(UNLOCK_WRITE),
|
||||
map(action => {
|
||||
if (action && action.payload) {
|
||||
this.contentService.unlockNode(action.payload);
|
||||
} else {
|
||||
this.store
|
||||
.select(appSelection)
|
||||
.pipe(take(1))
|
||||
.subscribe(selection => {
|
||||
if (selection && selection.file) {
|
||||
this.contentService.unlockNode(selection.file);
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -34,7 +34,8 @@ import {
|
||||
UPLOAD_FOLDER,
|
||||
UPLOAD_FILE_VERSION,
|
||||
UploadFileVersionAction,
|
||||
SnackbarErrorAction
|
||||
SnackbarErrorAction,
|
||||
UnlockWriteAction
|
||||
} from '../actions';
|
||||
import {
|
||||
map,
|
||||
@ -42,7 +43,9 @@ import {
|
||||
flatMap,
|
||||
distinctUntilChanged,
|
||||
catchError,
|
||||
switchMap
|
||||
switchMap,
|
||||
tap,
|
||||
filter
|
||||
} from 'rxjs/operators';
|
||||
import { FileUtils, FileModel, UploadService } from '@alfresco/adf-core';
|
||||
import { currentFolder } from '../selectors/app.selectors';
|
||||
@ -114,6 +117,12 @@ export class UploadEffects {
|
||||
return fromEvent(this.fileVersionInput, 'change').pipe(
|
||||
distinctUntilChanged(),
|
||||
flatMap(() => this.contentService.versionUploadDialog().afterClosed()),
|
||||
tap(form => {
|
||||
if (!form) {
|
||||
this.fileVersionInput.value = '';
|
||||
}
|
||||
}),
|
||||
filter(form => !!form),
|
||||
flatMap(form => forkJoin(of(form), this.contentService.getNodeInfo())),
|
||||
map(([form, node]) => {
|
||||
const file = this.fileVersionInput.files[0];
|
||||
@ -134,7 +143,7 @@ export class UploadEffects {
|
||||
);
|
||||
|
||||
this.fileVersionInput.value = '';
|
||||
this.uploadQueue([fileModel]);
|
||||
this.uploadVersion(fileModel);
|
||||
}),
|
||||
catchError(error => {
|
||||
this.fileVersionInput.value = '';
|
||||
@ -176,4 +185,21 @@ export class UploadEffects {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private uploadVersion(file: FileModel) {
|
||||
this.ngZone.run(() => {
|
||||
this.uploadService.addToQueue(file);
|
||||
this.uploadService.uploadFilesInTheQueue();
|
||||
|
||||
this.uploadService.fileUploadComplete.subscribe(completed => {
|
||||
if (
|
||||
file.data.entry.properties &&
|
||||
file.data.entry.properties['cm:lockType'] === 'WRITE_LOCK' &&
|
||||
completed.data.entry.id === file.data.entry.id
|
||||
) {
|
||||
this.store.dispatch(new UnlockWriteAction(completed.data));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -251,8 +251,8 @@
|
||||
"type": "rule",
|
||||
"value": "core.some",
|
||||
"parameters": [
|
||||
{ "type": "rule", "value": "app.selection.canUnlockFile" },
|
||||
{ "type": "rule", "value": "app.selection.canLockFile" }
|
||||
{ "type": "rule", "value": "app.selection.file.canUnlock" },
|
||||
{ "type": "rule", "value": "app.selection.file.canLock" }
|
||||
]
|
||||
}
|
||||
]
|
||||
|
Loading…
x
Reference in New Issue
Block a user