mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-05-12 17:04:46 +00:00
[AAE-10533] Generic App shell for HxP applications (#2679)
* [AAE-10533] Generic App shell for HxP applications * refactor * fix scss mixin path * remove forRoot in content-plugin * remove provided routers * revert router service * revert template usage * Added shell markdown * Move login component to content-plugin * Moved logic from app.component to app.service * remove upload-area from shell * cleaning * cleaning * update md * abstract preferences * allow to set shell parent route * fix preferencesService name * Fix for sidenav * Fix CR comments * [ci:force] * move translation service mock to aca-shared * fix e2e * Fix page title * remove drop area wrapper from whole application * Fix e2e * [ci:force] * Remove blank page from shell * Add upload files dialog * [ci:force] * Remove ExtensionsDataLoaderGuard from shell
This commit is contained in:
parent
3650aff589
commit
456454fee1
@ -36,6 +36,7 @@
|
|||||||
"stylePreprocessorOptions": {
|
"stylePreprocessorOptions": {
|
||||||
"includePaths": [
|
"includePaths": [
|
||||||
"app/src/app/ui",
|
"app/src/app/ui",
|
||||||
|
"app/src/app/content-plugin/ui",
|
||||||
"node_modules"
|
"node_modules"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -252,7 +253,7 @@
|
|||||||
"polyfills": "app/src/polyfills.ts",
|
"polyfills": "app/src/polyfills.ts",
|
||||||
"stylePreprocessorOptions": {
|
"stylePreprocessorOptions": {
|
||||||
"includePaths": [
|
"includePaths": [
|
||||||
"app/src/app/ui",
|
"app/src/app/content-plugin/ui",
|
||||||
"node_modules"
|
"node_modules"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
72
app/src/app/app-shell/app-shell.module.ts
Normal file
72
app/src/app/app-shell/app-shell.module.ts
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2005 - 2021 Alfresco Software, Ltd. All rights reserved.
|
||||||
|
*
|
||||||
|
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||||
|
* pursuant to a written agreement and any use of this program without such an
|
||||||
|
* agreement is prohibited.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { ModuleWithProviders, NgModule } from '@angular/core';
|
||||||
|
import { Routes, provideRoutes, RouterModule, Route } from '@angular/router';
|
||||||
|
import { SHELL_LAYOUT_ROUTE } from './app-shell.routes';
|
||||||
|
import { SidenavLayoutModule } from '@alfresco/adf-core';
|
||||||
|
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
||||||
|
import { ShellLayoutComponent } from './components/shell/shell.component';
|
||||||
|
|
||||||
|
export interface AppShellRoutesConfig {
|
||||||
|
shellParentRoute?: Route;
|
||||||
|
shellChildren: Routes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [SidenavLayoutModule, ExtensionsModule, RouterModule.forChild([]), CommonModule],
|
||||||
|
exports: [ShellLayoutComponent],
|
||||||
|
declarations: [ShellLayoutComponent]
|
||||||
|
})
|
||||||
|
export class AppShellModule {
|
||||||
|
static withRoutes(routes: Routes | AppShellRoutesConfig): ModuleWithProviders<AppShellModule> {
|
||||||
|
if (Array.isArray(routes)) {
|
||||||
|
return getModuleForRoutes(routes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return getModuleForRouteConfig(routes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getModuleForRoutes(routes: Routes): ModuleWithProviders<AppShellModule> {
|
||||||
|
const shellLayoutRoute = SHELL_LAYOUT_ROUTE;
|
||||||
|
|
||||||
|
routes.forEach((childRoute) => {
|
||||||
|
shellLayoutRoute.children.push(childRoute);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
ngModule: AppShellModule,
|
||||||
|
providers: provideRoutes([shellLayoutRoute])
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getModuleForRouteConfig(config: AppShellRoutesConfig): ModuleWithProviders<AppShellModule> {
|
||||||
|
const shellLayoutRoute = SHELL_LAYOUT_ROUTE;
|
||||||
|
|
||||||
|
const shellParentRoute = config.shellParentRoute;
|
||||||
|
const shellChildrenRoutes = config.shellChildren;
|
||||||
|
|
||||||
|
shellLayoutRoute.children.push(...shellChildrenRoutes);
|
||||||
|
|
||||||
|
const rootRoute = shellParentRoute ? shellParentRoute : shellLayoutRoute;
|
||||||
|
|
||||||
|
if (config.shellParentRoute) {
|
||||||
|
if (rootRoute.children === undefined) {
|
||||||
|
rootRoute.children = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
rootRoute.children.push(shellLayoutRoute);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
ngModule: AppShellModule,
|
||||||
|
providers: provideRoutes([rootRoute])
|
||||||
|
};
|
||||||
|
}
|
20
app/src/app/app-shell/app-shell.routes.ts
Normal file
20
app/src/app/app-shell/app-shell.routes.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2005 - 2021 Alfresco Software, Ltd. All rights reserved.
|
||||||
|
*
|
||||||
|
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||||
|
* pursuant to a written agreement and any use of this program without such an
|
||||||
|
* agreement is prohibited.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { InjectionToken } from '@angular/core';
|
||||||
|
import { CanActivate, CanActivateChild, Route } from '@angular/router';
|
||||||
|
import { ShellLayoutComponent } from './components/shell/shell.component';
|
||||||
|
|
||||||
|
export const SHELL_AUTH_TOKEN = new InjectionToken<CanActivate & CanActivateChild>('SHELL_AUTH_TOKEN');
|
||||||
|
|
||||||
|
export const SHELL_LAYOUT_ROUTE: Route = {
|
||||||
|
path: '',
|
||||||
|
component: ShellLayoutComponent,
|
||||||
|
canActivate: [SHELL_AUTH_TOKEN],
|
||||||
|
children: []
|
||||||
|
};
|
48
app/src/app/app-shell/components/shell/shell.component.html
Normal file
48
app/src/app/app-shell/components/shell/shell.component.html
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<adf-sidenav-layout
|
||||||
|
#layout
|
||||||
|
[sidenavMin]="70"
|
||||||
|
[sidenavMax]="320"
|
||||||
|
[stepOver]="600"
|
||||||
|
[hideSidenav]="hideSidenav"
|
||||||
|
[expandedSidenav]="expandedSidenav"
|
||||||
|
(expanded)="onExpanded($event)"
|
||||||
|
>
|
||||||
|
<adf-sidenav-layout-header>
|
||||||
|
<ng-template let-isMenuMinimized="isMenuMinimized">
|
||||||
|
<div
|
||||||
|
role="heading"
|
||||||
|
aria-level="1"
|
||||||
|
*ngIf="!hideSidenav"
|
||||||
|
>
|
||||||
|
<adf-dynamic-component id="app.layout.header" [data]="{ layout }">
|
||||||
|
</adf-dynamic-component>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</adf-sidenav-layout-header>
|
||||||
|
|
||||||
|
<adf-sidenav-layout-navigation>
|
||||||
|
<ng-template let-isMenuMinimized="isMenuMinimized">
|
||||||
|
<div
|
||||||
|
(swipeleft)="hideMenu($event)"
|
||||||
|
[attr.data-automation-id]="isMenuMinimized() ? 'collapsed' : 'expanded'"
|
||||||
|
>
|
||||||
|
<adf-dynamic-component
|
||||||
|
id="app.layout.sidenav"
|
||||||
|
[data]="{ mode: layout.isMenuMinimized ? 'collapsed' : 'expanded'}"
|
||||||
|
>
|
||||||
|
</adf-dynamic-component>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
</adf-sidenav-layout-navigation>
|
||||||
|
|
||||||
|
<adf-sidenav-layout-content>
|
||||||
|
<ng-template>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</ng-template>
|
||||||
|
</adf-sidenav-layout-content>
|
||||||
|
</adf-sidenav-layout>
|
||||||
|
|
||||||
|
<adf-dynamic-component id="app.shell.sibling">
|
||||||
|
</adf-dynamic-component>
|
||||||
|
|
||||||
|
<router-outlet name="viewer"></router-outlet>
|
34
app/src/app/app-shell/components/shell/shell.component.scss
Normal file
34
app/src/app/app-shell/components/shell/shell.component.scss
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
.app-shell {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 0;
|
||||||
|
|
||||||
|
router-outlet[name='viewer'] + * {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 999;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
adf-file-uploading-dialog {
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 599px) {
|
||||||
|
.adf-app-title {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 719px) {
|
||||||
|
.adf-app-logo {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
169
app/src/app/app-shell/components/shell/shell.component.spec.ts
Normal file
169
app/src/app/app-shell/components/shell/shell.component.spec.ts
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2005 - 2021 Alfresco Software, Ltd. All rights reserved.
|
||||||
|
*
|
||||||
|
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||||
|
* pursuant to a written agreement and any use of this program without such an
|
||||||
|
* agreement is prohibited.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||||
|
import { AppConfigService, SidenavLayoutModule } from '@alfresco/adf-core';
|
||||||
|
import { ShellLayoutComponent } from './shell.component';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { Router, NavigationStart, RouterModule } from '@angular/router';
|
||||||
|
import { of, Subject } from 'rxjs';
|
||||||
|
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { ShellAppService, SHELL_APP_SERVICE } from '../../services/shell-app.service';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { TranslateServiceMock } from '@alfresco/aca-shared';
|
||||||
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
|
||||||
|
class MockRouter {
|
||||||
|
private url = 'some-url';
|
||||||
|
private subject = new Subject();
|
||||||
|
events = this.subject.asObservable();
|
||||||
|
routerState = { snapshot: { url: this.url } };
|
||||||
|
|
||||||
|
navigateByUrl(url: string) {
|
||||||
|
const navigationStart = new NavigationStart(0, url);
|
||||||
|
this.subject.next(navigationStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('AppLayoutComponent', () => {
|
||||||
|
let fixture: ComponentFixture<ShellLayoutComponent>;
|
||||||
|
let component: ShellLayoutComponent;
|
||||||
|
let appConfig: AppConfigService;
|
||||||
|
let shellAppService: ShellAppService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const shellService: ShellAppService = {
|
||||||
|
pageHeading$: of('Title'),
|
||||||
|
hideSidenavConditions: [],
|
||||||
|
minimizeSidenavConditions: [],
|
||||||
|
preferencesService: {
|
||||||
|
get: (_key: string) => 'true',
|
||||||
|
set: (_key: string, _value: any) => {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [CommonModule, NoopAnimationsModule, HttpClientModule, SidenavLayoutModule, ExtensionsModule, RouterModule.forChild([])],
|
||||||
|
providers: [
|
||||||
|
Store,
|
||||||
|
{
|
||||||
|
provide: Router,
|
||||||
|
useClass: MockRouter
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: SHELL_APP_SERVICE,
|
||||||
|
useValue: shellService
|
||||||
|
},
|
||||||
|
{ provide: TranslateService, useClass: TranslateServiceMock }
|
||||||
|
],
|
||||||
|
declarations: [ShellLayoutComponent],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
});
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ShellLayoutComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
appConfig = TestBed.inject(AppConfigService);
|
||||||
|
shellAppService = TestBed.inject(SHELL_APP_SERVICE);
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
appConfig.config.languages = [];
|
||||||
|
appConfig.config.locale = 'en';
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('sidenav state', () => {
|
||||||
|
it('should get state from configuration', () => {
|
||||||
|
appConfig.config.sideNav = {
|
||||||
|
expandedSidenav: false,
|
||||||
|
preserveState: false
|
||||||
|
};
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.expandedSidenav).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should resolve state to true is no configuration', () => {
|
||||||
|
appConfig.config.sidenav = {};
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.expandedSidenav).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get state from user settings as true', () => {
|
||||||
|
appConfig.config.sideNav = {
|
||||||
|
expandedSidenav: false,
|
||||||
|
preserveState: true
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(shellAppService.preferencesService, 'get').and.callFake((key) => {
|
||||||
|
if (key === 'expandedSidenav') {
|
||||||
|
return 'true';
|
||||||
|
}
|
||||||
|
return 'false';
|
||||||
|
});
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.expandedSidenav).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get state from user settings as false', () => {
|
||||||
|
appConfig.config.sidenav = {
|
||||||
|
expandedSidenav: false,
|
||||||
|
preserveState: true
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(shellAppService.preferencesService, 'get').and.callFake((key) => {
|
||||||
|
if (key === 'expandedSidenav') {
|
||||||
|
return 'false';
|
||||||
|
}
|
||||||
|
return 'true';
|
||||||
|
});
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
expect(component.expandedSidenav).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should close menu on mobile screen size', () => {
|
||||||
|
component.minimizeSidenav = false;
|
||||||
|
component.layout.container = {
|
||||||
|
isMobileScreenSize: true,
|
||||||
|
toggleMenu: () => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(component.layout.container, 'toggleMenu');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.hideMenu({ preventDefault: () => {} } as any);
|
||||||
|
|
||||||
|
expect(component.layout.container.toggleMenu).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should close menu on mobile screen size also when minimizeSidenav true', () => {
|
||||||
|
fixture.detectChanges();
|
||||||
|
component.minimizeSidenav = true;
|
||||||
|
component.layout.container = {
|
||||||
|
isMobileScreenSize: true,
|
||||||
|
toggleMenu: () => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(component.layout.container, 'toggleMenu');
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
component.hideMenu({ preventDefault: () => {} } as any);
|
||||||
|
|
||||||
|
expect(component.layout.container.toggleMenu).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
123
app/src/app/app-shell/components/shell/shell.component.ts
Normal file
123
app/src/app/app-shell/components/shell/shell.component.ts
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2005 - 2021 Alfresco Software, Ltd. All rights reserved.
|
||||||
|
*
|
||||||
|
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||||
|
* pursuant to a written agreement and any use of this program without such an
|
||||||
|
* agreement is prohibited.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { AppConfigService, SidenavLayoutComponent } from '@alfresco/adf-core';
|
||||||
|
import { Component, Inject, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { NavigationEnd, Router } from '@angular/router';
|
||||||
|
import { Subject, Observable } from 'rxjs';
|
||||||
|
import { filter, takeUntil, map, withLatestFrom } from 'rxjs/operators';
|
||||||
|
import { BreakpointObserver } from '@angular/cdk/layout';
|
||||||
|
import { Directionality } from '@angular/cdk/bidi';
|
||||||
|
import { SHELL_APP_SERVICE, ShellAppService } from '../../services/shell-app.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-shell',
|
||||||
|
templateUrl: './shell.component.html',
|
||||||
|
styleUrls: ['./shell.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
host: { class: 'app-shell' }
|
||||||
|
})
|
||||||
|
export class ShellLayoutComponent implements OnInit, OnDestroy {
|
||||||
|
@ViewChild('layout', { static: true })
|
||||||
|
layout: SidenavLayoutComponent;
|
||||||
|
|
||||||
|
onDestroy$: Subject<boolean> = new Subject<boolean>();
|
||||||
|
isSmallScreen$: Observable<boolean>;
|
||||||
|
|
||||||
|
expandedSidenav: boolean;
|
||||||
|
minimizeSidenav = false;
|
||||||
|
hideSidenav = false;
|
||||||
|
direction: Directionality;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private router: Router,
|
||||||
|
private appConfigService: AppConfigService,
|
||||||
|
private breakpointObserver: BreakpointObserver,
|
||||||
|
@Inject(SHELL_APP_SERVICE) private shellService: ShellAppService
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.isSmallScreen$ = this.breakpointObserver.observe(['(max-width: 600px)']).pipe(map((result) => result.matches));
|
||||||
|
|
||||||
|
this.hideSidenav = this.shellService.hideSidenavConditions.some((el) => this.router.routerState.snapshot.url.includes(el));
|
||||||
|
this.minimizeSidenav = this.shellService.minimizeSidenavConditions.some((el) => this.router.routerState.snapshot.url.includes(el));
|
||||||
|
|
||||||
|
if (!this.minimizeSidenav) {
|
||||||
|
this.expandedSidenav = this.getSidenavState();
|
||||||
|
} else {
|
||||||
|
this.expandedSidenav = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.router.events
|
||||||
|
.pipe(
|
||||||
|
withLatestFrom(this.isSmallScreen$),
|
||||||
|
filter(([event, isSmallScreen]) => isSmallScreen && event instanceof NavigationEnd),
|
||||||
|
takeUntil(this.onDestroy$)
|
||||||
|
)
|
||||||
|
.subscribe(() => {
|
||||||
|
this.layout.container.sidenav.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.router.events
|
||||||
|
.pipe(
|
||||||
|
filter((event) => event instanceof NavigationEnd),
|
||||||
|
takeUntil(this.onDestroy$)
|
||||||
|
)
|
||||||
|
.subscribe((event: NavigationEnd) => {
|
||||||
|
this.minimizeSidenav = this.shellService.minimizeSidenavConditions.some((el) => event.urlAfterRedirects.includes(el));
|
||||||
|
this.hideSidenav = this.shellService.hideSidenavConditions.some((el) => event.urlAfterRedirects.includes(el));
|
||||||
|
|
||||||
|
this.updateState();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.onDestroy$.next(true);
|
||||||
|
this.onDestroy$.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
hideMenu(event: Event) {
|
||||||
|
if (this.layout.container.isMobileScreenSize) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.layout.container.toggleMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateState() {
|
||||||
|
if (this.minimizeSidenav && !this.layout.isMenuMinimized) {
|
||||||
|
this.layout.isMenuMinimized = true;
|
||||||
|
if (!this.layout.container.isMobileScreenSize) {
|
||||||
|
this.layout.container.toggleMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.minimizeSidenav) {
|
||||||
|
if (this.getSidenavState() && this.layout.isMenuMinimized) {
|
||||||
|
this.layout.isMenuMinimized = false;
|
||||||
|
this.layout.container.toggleMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExpanded(state: boolean) {
|
||||||
|
if (!this.minimizeSidenav && this.appConfigService.get('sideNav.preserveState')) {
|
||||||
|
this.shellService.preferencesService.set('expandedSidenav', state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getSidenavState(): boolean {
|
||||||
|
const expand = this.appConfigService.get<boolean>('sideNav.expandedSidenav', true);
|
||||||
|
const preserveState = this.appConfigService.get<boolean>('sideNav.preserveState', true);
|
||||||
|
|
||||||
|
if (preserveState) {
|
||||||
|
return this.shellService.preferencesService.get('expandedSidenav', expand.toString()) === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
return expand;
|
||||||
|
}
|
||||||
|
}
|
10
app/src/app/app-shell/index.ts
Normal file
10
app/src/app/app-shell/index.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2005 - 2021 Alfresco Software, Ltd. All rights reserved.
|
||||||
|
*
|
||||||
|
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||||
|
* pursuant to a written agreement and any use of this program without such an
|
||||||
|
* agreement is prohibited.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './app-shell.module';
|
||||||
|
export * from './services/shell-app.service';
|
24
app/src/app/app-shell/services/shell-app.service.ts
Normal file
24
app/src/app/app-shell/services/shell-app.service.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2005 - 2021 Alfresco Software, Ltd. All rights reserved.
|
||||||
|
*
|
||||||
|
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
||||||
|
* pursuant to a written agreement and any use of this program without such an
|
||||||
|
* agreement is prohibited.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { InjectionToken } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
export interface ShellPreferencesService {
|
||||||
|
set(preferenceKey: string, value: any): void;
|
||||||
|
get(preferenceKey: string, defaultValue: string): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ShellAppService {
|
||||||
|
pageHeading$: Observable<string>;
|
||||||
|
hideSidenavConditions: string[];
|
||||||
|
minimizeSidenavConditions: string[];
|
||||||
|
preferencesService: ShellPreferencesService;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SHELL_APP_SERVICE = new InjectionToken<ShellAppService>('SHELL_APP_SERVICE');
|
@ -1,2 +1,2 @@
|
|||||||
<h1 class="sr-only" title="{{pageHeading | translate}}">{{ pageHeading | translate }}</h1>
|
<h1 class="sr-only" title="{{pageHeading | async | translate}}">{{ pageHeading | async | translate }}</h1>
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Alfresco Example Content Application
|
|
||||||
*
|
|
||||||
* Copyright (C) 2005 - 2020 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 { AppComponent } from './app.component';
|
|
||||||
import { SetInitialStateAction } from '@alfresco/aca-shared/store';
|
|
||||||
import { Router } from '@angular/router';
|
|
||||||
import { TestBed } from '@angular/core/testing';
|
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
|
||||||
let component: AppComponent;
|
|
||||||
let router: Router;
|
|
||||||
|
|
||||||
const storeMock: any = {
|
|
||||||
dispatch: jasmine.createSpy('dispatch')
|
|
||||||
};
|
|
||||||
|
|
||||||
const overlayContainerMock: any = {
|
|
||||||
getContainerElement: jasmine.createSpy('getContainerElement')
|
|
||||||
};
|
|
||||||
|
|
||||||
const configMock: any = {
|
|
||||||
get: (key: string) => {
|
|
||||||
if (key === 'baseShareUrl') {
|
|
||||||
return 'http://localhost:4200/#/preview/s';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
imports: [RouterTestingModule.withRoutes([{ path: 'fake-path', children: [] }])]
|
|
||||||
});
|
|
||||||
|
|
||||||
router = TestBed.inject(Router);
|
|
||||||
|
|
||||||
component = new AppComponent(null, router, null, storeMock, configMock, null, null, null, null, null, null, null, null, overlayContainerMock);
|
|
||||||
|
|
||||||
storeMock.dispatch = jasmine.createSpy('dispatch');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should setup baseShareUrl as per config', (done) => {
|
|
||||||
storeMock.dispatch.and.callFake((action: SetInitialStateAction) => {
|
|
||||||
expect(action.payload.sharedUrl).toBe('http://localhost:4200/#/preview/s/');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
component.loadAppSettings();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onFileUploadedError', () => {
|
|
||||||
it('should dispatch 403 error message', () => {
|
|
||||||
component.onFileUploadedError({ error: { status: 403 } } as any);
|
|
||||||
expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe('APP.MESSAGES.UPLOAD.ERROR.403');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should dispatch 404 error message', () => {
|
|
||||||
component.onFileUploadedError({ error: { status: 404 } } as any);
|
|
||||||
expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe('APP.MESSAGES.UPLOAD.ERROR.404');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should dispatch 409 error message', () => {
|
|
||||||
component.onFileUploadedError({ error: { status: 409 } } as any);
|
|
||||||
expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe('APP.MESSAGES.UPLOAD.ERROR.CONFLICT');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should dispatch 500 error message', () => {
|
|
||||||
component.onFileUploadedError({ error: { status: 500 } } as any);
|
|
||||||
expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe('APP.MESSAGES.UPLOAD.ERROR.500');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should dispatch 504 error message', () => {
|
|
||||||
component.onFileUploadedError({ error: { status: 504 } } as any);
|
|
||||||
expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe('APP.MESSAGES.UPLOAD.ERROR.504');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should dispatch generic error message', () => {
|
|
||||||
component.onFileUploadedError({ error: { status: 999 } } as any);
|
|
||||||
expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe('APP.MESSAGES.UPLOAD.ERROR.GENERIC');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,233 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Alfresco Example Content Application
|
|
||||||
*
|
|
||||||
* Copyright (C) 2005 - 2020 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 {
|
|
||||||
AlfrescoApiService,
|
|
||||||
AppConfigService,
|
|
||||||
AuthenticationService,
|
|
||||||
FileUploadErrorEvent,
|
|
||||||
PageTitleService,
|
|
||||||
UploadService,
|
|
||||||
SharedLinksApiService
|
|
||||||
} from '@alfresco/adf-core';
|
|
||||||
import { GroupService } from '@alfresco/adf-content-services';
|
|
||||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
|
||||||
import { ActivatedRoute, Router, ActivationEnd } from '@angular/router';
|
|
||||||
import { Store } from '@ngrx/store';
|
|
||||||
import {
|
|
||||||
AppStore,
|
|
||||||
AppState,
|
|
||||||
SetCurrentUrlAction,
|
|
||||||
SetInitialStateAction,
|
|
||||||
SetUserProfileAction,
|
|
||||||
SnackbarErrorAction,
|
|
||||||
CloseModalDialogsAction,
|
|
||||||
SetRepositoryInfoAction,
|
|
||||||
getCustomCssPath,
|
|
||||||
getCustomWebFontPath
|
|
||||||
} from '@alfresco/aca-shared/store';
|
|
||||||
import { filter, takeUntil } from 'rxjs/operators';
|
|
||||||
import { RouterExtensionService, AppService, ContentApiService } from '@alfresco/aca-shared';
|
|
||||||
import { DiscoveryEntry, GroupEntry, Group } from '@alfresco/js-api';
|
|
||||||
import { Subject } from 'rxjs';
|
|
||||||
import { INITIAL_APP_STATE } from './store/initial-state';
|
|
||||||
import { OverlayContainer } from '@angular/cdk/overlay';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-root',
|
|
||||||
templateUrl: './app.component.html',
|
|
||||||
styleUrls: ['./app.component.scss']
|
|
||||||
})
|
|
||||||
export class AppComponent implements OnInit, OnDestroy {
|
|
||||||
onDestroy$: Subject<boolean> = new Subject<boolean>();
|
|
||||||
pageHeading = '';
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private route: ActivatedRoute,
|
|
||||||
private router: Router,
|
|
||||||
private pageTitle: PageTitleService,
|
|
||||||
private store: Store<AppStore>,
|
|
||||||
private config: AppConfigService,
|
|
||||||
private alfrescoApiService: AlfrescoApiService,
|
|
||||||
private authenticationService: AuthenticationService,
|
|
||||||
private uploadService: UploadService,
|
|
||||||
private routerExtensionService: RouterExtensionService,
|
|
||||||
private contentApi: ContentApiService,
|
|
||||||
private appService: AppService,
|
|
||||||
private sharedLinksApiService: SharedLinksApiService,
|
|
||||||
private groupService: GroupService,
|
|
||||||
private overlayContainer: OverlayContainer
|
|
||||||
) {}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.alfrescoApiService.getInstance().on('error', (error: { status: number; response: any }) => {
|
|
||||||
if (error.status === 401 && !this.alfrescoApiService.isExcludedErrorListener(error?.response?.req?.url)) {
|
|
||||||
if (!this.authenticationService.isLoggedIn()) {
|
|
||||||
this.store.dispatch(new CloseModalDialogsAction());
|
|
||||||
|
|
||||||
let redirectUrl = this.route.snapshot.queryParams['redirectUrl'];
|
|
||||||
if (!redirectUrl) {
|
|
||||||
redirectUrl = this.router.url;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.router.navigate(['/login'], {
|
|
||||||
queryParams: { redirectUrl }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.loadAppSettings();
|
|
||||||
|
|
||||||
this.loadCustomCss();
|
|
||||||
this.loadCustomWebFont();
|
|
||||||
|
|
||||||
const { router, pageTitle } = this;
|
|
||||||
|
|
||||||
this.router.events
|
|
||||||
.pipe(filter((event) => event instanceof ActivationEnd && event.snapshot.children.length === 0))
|
|
||||||
.subscribe((event: ActivationEnd) => {
|
|
||||||
const snapshot: any = event.snapshot || {};
|
|
||||||
const data: any = snapshot.data || {};
|
|
||||||
|
|
||||||
this.pageHeading = data.title || '';
|
|
||||||
pageTitle.setTitle(data.title || '');
|
|
||||||
this.store.dispatch(new SetCurrentUrlAction(router.url));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.routerExtensionService.mapExtensionRoutes();
|
|
||||||
|
|
||||||
this.uploadService.fileUploadError.subscribe((error) => this.onFileUploadedError(error));
|
|
||||||
|
|
||||||
this.sharedLinksApiService.error.pipe(takeUntil(this.onDestroy$)).subscribe((err: { message: string }) => {
|
|
||||||
this.store.dispatch(new SnackbarErrorAction(err.message));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.appService.ready$.pipe(takeUntil(this.onDestroy$)).subscribe((isReady) => {
|
|
||||||
if (isReady) {
|
|
||||||
this.loadRepositoryStatus();
|
|
||||||
this.loadUserProfile();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.overlayContainer.getContainerElement().setAttribute('role', 'region');
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.onDestroy$.next(true);
|
|
||||||
this.onDestroy$.complete();
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadRepositoryStatus() {
|
|
||||||
this.contentApi.getRepositoryInformation().subscribe((response: DiscoveryEntry) => {
|
|
||||||
this.store.dispatch(new SetRepositoryInfoAction(response.entry.repository));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async loadUserProfile() {
|
|
||||||
const groupsEntries: GroupEntry[] = await this.groupService.listAllGroupMembershipsForPerson('-me-', { maxItems: 250 });
|
|
||||||
|
|
||||||
const groups: Group[] = [];
|
|
||||||
|
|
||||||
if (groupsEntries) {
|
|
||||||
groups.push(...groupsEntries.map((obj) => obj.entry));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.contentApi.getPerson('-me-').subscribe((person) => {
|
|
||||||
this.store.dispatch(new SetUserProfileAction({ person: person.entry, groups }));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
loadAppSettings() {
|
|
||||||
let baseShareUrl = this.config.get<string>('baseShareUrl');
|
|
||||||
if (!baseShareUrl.endsWith('/')) {
|
|
||||||
baseShareUrl += '/';
|
|
||||||
}
|
|
||||||
|
|
||||||
const state: AppState = {
|
|
||||||
...INITIAL_APP_STATE,
|
|
||||||
appName: this.config.get<string>('application.name'),
|
|
||||||
headerColor: this.config.get<string>('headerColor'),
|
|
||||||
headerTextColor: this.config.get<string>('headerTextColor', '#000000'),
|
|
||||||
logoPath: this.config.get<string>('application.logo'),
|
|
||||||
headerImagePath: this.config.get<string>('application.headerImagePath'),
|
|
||||||
customCssPath: this.config.get<string>('customCssPath'),
|
|
||||||
webFontPath: this.config.get<string>('webFontPath'),
|
|
||||||
sharedUrl: baseShareUrl
|
|
||||||
};
|
|
||||||
|
|
||||||
this.store.dispatch(new SetInitialStateAction(state));
|
|
||||||
}
|
|
||||||
|
|
||||||
onFileUploadedError(error: FileUploadErrorEvent) {
|
|
||||||
let message = 'APP.MESSAGES.UPLOAD.ERROR.GENERIC';
|
|
||||||
|
|
||||||
if (error.error.status === 403) {
|
|
||||||
message = 'APP.MESSAGES.UPLOAD.ERROR.403';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.error.status === 404) {
|
|
||||||
message = 'APP.MESSAGES.UPLOAD.ERROR.404';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.error.status === 409) {
|
|
||||||
message = 'APP.MESSAGES.UPLOAD.ERROR.CONFLICT';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.error.status === 500) {
|
|
||||||
message = 'APP.MESSAGES.UPLOAD.ERROR.500';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error.error.status === 504) {
|
|
||||||
message = 'APP.MESSAGES.UPLOAD.ERROR.504';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.store.dispatch(new SnackbarErrorAction(message));
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadCustomCss(): void {
|
|
||||||
this.store.select(getCustomCssPath).subscribe((cssPath) => {
|
|
||||||
if (cssPath) {
|
|
||||||
this.createLink(cssPath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private loadCustomWebFont(): void {
|
|
||||||
this.store.select(getCustomWebFontPath).subscribe((fontUrl) => {
|
|
||||||
if (fontUrl) {
|
|
||||||
this.createLink(fontUrl);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private createLink(url: string): void {
|
|
||||||
const cssLinkElement = document.createElement('link');
|
|
||||||
cssLinkElement.setAttribute('rel', 'stylesheet');
|
|
||||||
cssLinkElement.setAttribute('type', 'text/css');
|
|
||||||
cssLinkElement.setAttribute('href', url);
|
|
||||||
document.head.appendChild(cssLinkElement);
|
|
||||||
}
|
|
||||||
}
|
|
43
app/src/app/app.components.ts
Normal file
43
app/src/app/app.components.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Alfresco Example Content Application
|
||||||
|
*
|
||||||
|
* Copyright (C) 2005 - 2020 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 { Component } from '@angular/core';
|
||||||
|
import { Observable, Subject } from 'rxjs';
|
||||||
|
import { AppService } from '@alfresco/aca-shared';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.scss']
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
onDestroy$: Subject<boolean> = new Subject<boolean>();
|
||||||
|
pageHeading: Observable<string>;
|
||||||
|
|
||||||
|
constructor(private appService: AppService) {
|
||||||
|
this.pageHeading = this.appService.pageHeading$;
|
||||||
|
this.appService.init();
|
||||||
|
}
|
||||||
|
}
|
@ -23,50 +23,15 @@
|
|||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { BrowserModule, HammerModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { RouterModule } from '@angular/router';
|
|
||||||
import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
||||||
import { TRANSLATION_PROVIDER, CoreModule, AppConfigService, DebugAppConfigService } from '@alfresco/adf-core';
|
|
||||||
import { ContentModule, ContentVersionService } from '@alfresco/adf-content-services';
|
|
||||||
import { SharedModule } from '@alfresco/aca-shared';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { TRANSLATION_PROVIDER, AppConfigService, DebugAppConfigService, CoreModule, AuthGuard } from '@alfresco/adf-core';
|
||||||
import { APP_ROUTES } from './app.routes';
|
import { AppService, SharedModule } from '@alfresco/aca-shared';
|
||||||
|
|
||||||
import { FilesComponent } from './components/files/files.component';
|
|
||||||
import { LibrariesComponent } from './components/libraries/libraries.component';
|
|
||||||
import { FavoriteLibrariesComponent } from './components/favorite-libraries/favorite-libraries.component';
|
|
||||||
import { ViewProfileModule } from './components/view-profile/view-profile.module';
|
|
||||||
|
|
||||||
import { AppStoreModule } from './store/app-store.module';
|
|
||||||
import { MaterialModule } from './material.module';
|
|
||||||
import { AppExtensionsModule } from './extensions.module';
|
import { AppExtensionsModule } from './extensions.module';
|
||||||
import { CoreExtensionsModule } from './extensions/core.extensions.module';
|
|
||||||
import { AppInfoDrawerModule } from './components/info-drawer/info.drawer.module';
|
|
||||||
import { DirectivesModule } from './directives/directives.module';
|
|
||||||
import { ContextMenuModule } from './components/context-menu/context-menu.module';
|
|
||||||
import { ExtensionsModule } from '@alfresco/adf-extensions';
|
|
||||||
import { AppToolbarModule } from './components/toolbar/toolbar.module';
|
|
||||||
import { AppCreateMenuModule } from './components/create-menu/create-menu.module';
|
|
||||||
import { AppSidenavModule } from './components/sidenav/sidenav.module';
|
|
||||||
import { AppCommonModule } from './components/common/common.module';
|
|
||||||
import { AppLayoutModule } from './components/layout/layout.module';
|
|
||||||
import { AppSearchInputModule } from './components/search/search-input.module';
|
|
||||||
import { DocumentListCustomComponentsModule } from './components/dl-custom-components/document-list-custom-components.module';
|
|
||||||
import { AppSearchResultsModule } from './components/search/search-results.module';
|
|
||||||
import { AppLoginModule } from './components/login/login.module';
|
|
||||||
import { AppHeaderModule } from './components/header/header.module';
|
|
||||||
import { AppNodeVersionModule } from './components/node-version/node-version.module';
|
|
||||||
import { FavoritesComponent } from './components/favorites/favorites.component';
|
|
||||||
import { RecentFilesComponent } from './components/recent-files/recent-files.component';
|
|
||||||
import { SharedFilesComponent } from './components/shared-files/shared-files.component';
|
|
||||||
import { CreateFromTemplateDialogComponent } from './dialogs/node-template/create-from-template.dialog';
|
|
||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
import { DetailsComponent } from './components/details/details.component';
|
|
||||||
import { ContentUrlService } from './services/content-url.service';
|
|
||||||
import { HomeComponent } from './components/home/home.component';
|
|
||||||
|
|
||||||
import { registerLocaleData } from '@angular/common';
|
import { registerLocaleData } from '@angular/common';
|
||||||
import localeFr from '@angular/common/locales/fr';
|
import localeFr from '@angular/common/locales/fr';
|
||||||
@ -85,6 +50,18 @@ import localePl from '@angular/common/locales/pl';
|
|||||||
import localeFi from '@angular/common/locales/fi';
|
import localeFi from '@angular/common/locales/fi';
|
||||||
import localeDa from '@angular/common/locales/da';
|
import localeDa from '@angular/common/locales/da';
|
||||||
import localeSv from '@angular/common/locales/sv';
|
import localeSv from '@angular/common/locales/sv';
|
||||||
|
import { AppShellModule, SHELL_APP_SERVICE } from './app-shell';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { AppComponent } from './app.components';
|
||||||
|
import { SHELL_AUTH_TOKEN } from './app-shell/app-shell.routes';
|
||||||
|
import { CONTENT_LAYOUT_ROUTES } from './content-plugin/content.routes';
|
||||||
|
import { ContentServiceExtensionModule } from './content-plugin/content-services-extension.module';
|
||||||
|
import { CoreExtensionsModule } from './extensions/core.extensions.module';
|
||||||
|
import { INITIAL_APP_STATE } from './content-plugin/store/initial-state';
|
||||||
|
import { ContentVersionService } from '@alfresco/adf-content-services';
|
||||||
|
import { ContentUrlService } from './content-plugin/services/content-url.service';
|
||||||
|
import { STORE_INITIAL_APP_DATA } from '@alfresco/aca-shared/store';
|
||||||
|
|
||||||
registerLocaleData(localeFr);
|
registerLocaleData(localeFr);
|
||||||
registerLocaleData(localeDe);
|
registerLocaleData(localeDe);
|
||||||
@ -106,54 +83,38 @@ registerLocaleData(localeSv);
|
|||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
CoreModule.forRoot(),
|
||||||
|
SharedModule.forRoot(),
|
||||||
|
CoreExtensionsModule.forRoot(),
|
||||||
environment.e2e ? NoopAnimationsModule : BrowserAnimationsModule,
|
environment.e2e ? NoopAnimationsModule : BrowserAnimationsModule,
|
||||||
FormsModule,
|
RouterModule.forRoot([], {
|
||||||
ReactiveFormsModule,
|
|
||||||
RouterModule.forRoot(APP_ROUTES, {
|
|
||||||
useHash: true,
|
useHash: true,
|
||||||
enableTracing: false, // enable for debug only
|
enableTracing: false, // enable for debug only
|
||||||
relativeLinkResolution: 'legacy'
|
relativeLinkResolution: 'legacy'
|
||||||
}),
|
}),
|
||||||
MaterialModule,
|
|
||||||
CoreModule.forRoot(),
|
|
||||||
ContentModule.forRoot(),
|
|
||||||
SharedModule.forRoot(),
|
|
||||||
AppStoreModule,
|
|
||||||
CoreExtensionsModule.forRoot(),
|
|
||||||
ExtensionsModule.forRoot(),
|
|
||||||
AppExtensionsModule,
|
AppExtensionsModule,
|
||||||
AppLoginModule,
|
AppShellModule.withRoutes({
|
||||||
AppCommonModule,
|
shellChildren: [CONTENT_LAYOUT_ROUTES]
|
||||||
AppLayoutModule,
|
}),
|
||||||
DirectivesModule,
|
ContentServiceExtensionModule
|
||||||
ContextMenuModule,
|
|
||||||
AppInfoDrawerModule,
|
|
||||||
AppToolbarModule,
|
|
||||||
AppSidenavModule,
|
|
||||||
AppCreateMenuModule,
|
|
||||||
DocumentListCustomComponentsModule,
|
|
||||||
AppSearchInputModule,
|
|
||||||
AppSearchResultsModule,
|
|
||||||
AppHeaderModule,
|
|
||||||
AppNodeVersionModule,
|
|
||||||
HammerModule,
|
|
||||||
ViewProfileModule
|
|
||||||
],
|
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
|
||||||
FilesComponent,
|
|
||||||
DetailsComponent,
|
|
||||||
LibrariesComponent,
|
|
||||||
FavoriteLibrariesComponent,
|
|
||||||
FavoritesComponent,
|
|
||||||
RecentFilesComponent,
|
|
||||||
SharedFilesComponent,
|
|
||||||
CreateFromTemplateDialogComponent,
|
|
||||||
HomeComponent
|
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
|
{ provide: AppService, useClass: AppService },
|
||||||
{ provide: AppConfigService, useClass: DebugAppConfigService },
|
{ provide: AppConfigService, useClass: DebugAppConfigService },
|
||||||
{ provide: ContentVersionService, useClass: ContentUrlService },
|
{ provide: ContentVersionService, useClass: ContentUrlService },
|
||||||
|
{
|
||||||
|
provide: SHELL_APP_SERVICE,
|
||||||
|
useClass: AppService
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: SHELL_AUTH_TOKEN,
|
||||||
|
useClass: AuthGuard
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: STORE_INITIAL_APP_DATA,
|
||||||
|
useValue: INITIAL_APP_STATE
|
||||||
|
},
|
||||||
{
|
{
|
||||||
provide: TRANSLATION_PROVIDER,
|
provide: TRANSLATION_PROVIDER,
|
||||||
multi: true,
|
multi: true,
|
||||||
@ -163,6 +124,7 @@ registerLocaleData(localeSv);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
declarations: [AppComponent],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
@ -1,575 +0,0 @@
|
|||||||
/*!
|
|
||||||
* @license
|
|
||||||
* Alfresco Example Content Application
|
|
||||||
*
|
|
||||||
* Copyright (C) 2005 - 2020 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 { Routes } from '@angular/router';
|
|
||||||
import { AppLayoutComponent } from './components/layout/app-layout/app-layout.component';
|
|
||||||
import { FilesComponent } from './components/files/files.component';
|
|
||||||
import { LibrariesComponent } from './components/libraries/libraries.component';
|
|
||||||
import { FavoriteLibrariesComponent } from './components/favorite-libraries/favorite-libraries.component';
|
|
||||||
import { SearchResultsComponent } from './components/search/search-results/search-results.component';
|
|
||||||
import { SearchLibrariesResultsComponent } from './components/search/search-libraries-results/search-libraries-results.component';
|
|
||||||
import { LoginComponent } from './components/login/login.component';
|
|
||||||
import { AppSharedRuleGuard, GenericErrorComponent, ExtensionsDataLoaderGuard } from '@alfresco/aca-shared';
|
|
||||||
import { AuthGuard, BlankPageComponent } from '@alfresco/adf-core';
|
|
||||||
import { FavoritesComponent } from './components/favorites/favorites.component';
|
|
||||||
import { RecentFilesComponent } from './components/recent-files/recent-files.component';
|
|
||||||
import { SharedFilesComponent } from './components/shared-files/shared-files.component';
|
|
||||||
import { DetailsComponent } from './components/details/details.component';
|
|
||||||
import { HomeComponent } from './components/home/home.component';
|
|
||||||
import { ViewProfileComponent } from './components/view-profile/view-profile.component';
|
|
||||||
import { ViewProfileRuleGuard } from './components/view-profile/view-profile.guard';
|
|
||||||
|
|
||||||
export const APP_ROUTES: Routes = [
|
|
||||||
{
|
|
||||||
path: 'blank',
|
|
||||||
component: BlankPageComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'login',
|
|
||||||
component: LoginComponent,
|
|
||||||
data: {
|
|
||||||
title: 'APP.SIGN_IN'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'preview/s/:id',
|
|
||||||
loadChildren: () => import('./components/shared-link-view/shared-link-view.module').then((m) => m.AppSharedLinkViewModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view',
|
|
||||||
component: AppLayoutComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: ':nodeId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: AppLayoutComponent,
|
|
||||||
canActivate: [AuthGuard, ExtensionsDataLoaderGuard],
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'profile',
|
|
||||||
canActivate: [ViewProfileRuleGuard],
|
|
||||||
component: ViewProfileComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: HomeComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'personal-files',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: FilesComponent,
|
|
||||||
data: {
|
|
||||||
sortingPreferenceKey: 'personal-files',
|
|
||||||
title: 'APP.BROWSE.PERSONAL.TITLE',
|
|
||||||
defaultNodeId: '-my-'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'details/:nodeId',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: DetailsComponent,
|
|
||||||
data: {
|
|
||||||
navigateSource: 'personal-files'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: ':activeTab',
|
|
||||||
component: DetailsComponent,
|
|
||||||
data: {
|
|
||||||
title: 'APP.BROWSE.PERSONAL.PERMISSIONS.TITLE',
|
|
||||||
navigateSource: 'personal-files'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
// deprecated, backwards compatibility with ACA 1.8
|
|
||||||
{
|
|
||||||
path: 'preview/:nodeId',
|
|
||||||
loadChildren: () => import('./components/preview/preview.module').then((m) => m.PreviewModule),
|
|
||||||
data: {
|
|
||||||
navigateSource: 'personal-files'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'personal-files'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId/:versionId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'personal-files'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'personal-files/:folderId',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: FilesComponent,
|
|
||||||
data: {
|
|
||||||
title: 'APP.BROWSE.PERSONAL.TITLE',
|
|
||||||
sortingPreferenceKey: 'personal-files'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId/:versionId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'personal-files'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
// deprecated, backwards compatibility with ACA 1.8
|
|
||||||
{
|
|
||||||
path: 'preview/:nodeId',
|
|
||||||
loadChildren: () => import('./components/preview/preview.module').then((m) => m.PreviewModule),
|
|
||||||
data: {
|
|
||||||
navigateSource: 'personal-files'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// deprecated, backwards compatibility with ACA 1.8
|
|
||||||
{
|
|
||||||
path: ':folderId/preview/:nodeId',
|
|
||||||
loadChildren: () => import('./components/preview/preview.module').then((m) => m.PreviewModule),
|
|
||||||
data: {
|
|
||||||
navigateSource: 'personal-files'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'personal-files'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'libraries',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: LibrariesComponent,
|
|
||||||
data: {
|
|
||||||
title: 'APP.BROWSE.LIBRARIES.MENU.MY_LIBRARIES.TITLE',
|
|
||||||
sortingPreferenceKey: 'libraries'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'libraries/:folderId',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: FilesComponent,
|
|
||||||
data: {
|
|
||||||
title: 'APP.BROWSE.LIBRARIES.MENU.MY_LIBRARIES.TITLE',
|
|
||||||
sortingPreferenceKey: 'libraries-files'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// deprecated, backwards compatibility with ACA 1.8
|
|
||||||
{
|
|
||||||
path: 'preview/:nodeId',
|
|
||||||
loadChildren: () => import('./components/preview/preview.module').then((m) => m.PreviewModule),
|
|
||||||
data: {
|
|
||||||
navigateSource: 'libraries'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'libraries'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId/:versionId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'libraries'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'favorite',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
pathMatch: 'full',
|
|
||||||
redirectTo: 'libraries'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'libraries',
|
|
||||||
component: FavoriteLibrariesComponent,
|
|
||||||
data: {
|
|
||||||
title: 'APP.BROWSE.LIBRARIES.MENU.FAVORITE_LIBRARIES.TITLE',
|
|
||||||
sortingPreferenceKey: 'favorite-libraries'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'favorite/libraries/:folderId',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: FilesComponent,
|
|
||||||
data: {
|
|
||||||
title: 'APP.BROWSE.LIBRARIES.MENU.FAVORITE_LIBRARIES.TITLE',
|
|
||||||
sortingPreferenceKey: 'libraries-files'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'libraries'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId/:versionId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'libraries'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'favorites',
|
|
||||||
data: {
|
|
||||||
sortingPreferenceKey: 'favorites'
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: FavoritesComponent,
|
|
||||||
data: {
|
|
||||||
title: 'APP.BROWSE.FAVORITES.TITLE',
|
|
||||||
sortingPreferenceKey: 'favorites'
|
|
||||||
}
|
|
||||||
// loadChildren:
|
|
||||||
// './components/favorites/favorites.module#AppFavoritesModule'
|
|
||||||
},
|
|
||||||
// deprecated, backwards compatibility with ACA 1.8
|
|
||||||
{
|
|
||||||
path: 'preview/:nodeId',
|
|
||||||
loadChildren: () => import('./components/preview/preview.module').then((m) => m.PreviewModule),
|
|
||||||
data: {
|
|
||||||
navigateSource: 'favorites'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'favorites'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId/:versionId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'favorites'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'recent-files',
|
|
||||||
data: {
|
|
||||||
sortingPreferenceKey: 'recent-files'
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: RecentFilesComponent,
|
|
||||||
data: {
|
|
||||||
title: 'APP.BROWSE.RECENT.TITLE'
|
|
||||||
}
|
|
||||||
// loadChildren:
|
|
||||||
// './components/recent-files/recent-files.module#AppRecentFilesModule'
|
|
||||||
},
|
|
||||||
// deprecated, backwards compatibility with ACA 1.8
|
|
||||||
{
|
|
||||||
path: 'preview/:nodeId',
|
|
||||||
loadChildren: () => import('./components/preview/preview.module').then((m) => m.PreviewModule),
|
|
||||||
data: {
|
|
||||||
navigateSource: 'recent-files'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'recent-files'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId/:versionId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'recent-files'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'shared',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
title: 'APP.BROWSE.SHARED.TITLE',
|
|
||||||
sortingPreferenceKey: 'shared-files'
|
|
||||||
},
|
|
||||||
component: SharedFilesComponent
|
|
||||||
// loadChildren:
|
|
||||||
// './components/shared-files/shared-files.module#AppSharedFilesModule'
|
|
||||||
},
|
|
||||||
// deprecated, backwards compatibility with ACA 1.8
|
|
||||||
{
|
|
||||||
path: 'preview/:nodeId',
|
|
||||||
loadChildren: () => import('./components/preview/preview.module').then((m) => m.PreviewModule),
|
|
||||||
data: {
|
|
||||||
navigateSource: 'shared'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'shared'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId/:versionId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'shared'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
canActivateChild: [AppSharedRuleGuard],
|
|
||||||
canActivate: [AppSharedRuleGuard]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'trashcan',
|
|
||||||
loadChildren: () => import('./components/trashcan/trashcan.module').then((m) => m.AppTrashcanModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'search',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: SearchResultsComponent,
|
|
||||||
data: {
|
|
||||||
title: 'APP.BROWSE.SEARCH.TITLE'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// deprecated, backwards compatibility with ACA 1.8
|
|
||||||
{
|
|
||||||
path: 'preview/:nodeId',
|
|
||||||
loadChildren: () => import('./components/preview/preview.module').then((m) => m.PreviewModule),
|
|
||||||
data: {
|
|
||||||
navigateSource: 'search'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'search'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId/:versionId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'search'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'search-libraries',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
component: SearchLibrariesResultsComponent,
|
|
||||||
data: {
|
|
||||||
title: 'APP.BROWSE.SEARCH.TITLE'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'view/:nodeId',
|
|
||||||
outlet: 'viewer',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
data: {
|
|
||||||
navigateSource: 'search'
|
|
||||||
},
|
|
||||||
loadChildren: () => import('./components/viewer/viewer.module').then((m) => m.AppViewerModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'nodes/:nodeId',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: '',
|
|
||||||
loadChildren: () => import('@alfresco/aca-folder-rules').then((m) => m.AcaFolderRulesModule)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '**',
|
|
||||||
component: GenericErrorComponent
|
|
||||||
}
|
|
||||||
],
|
|
||||||
canActivateChild: [AuthGuard]
|
|
||||||
}
|
|
||||||
];
|
|
@ -30,7 +30,7 @@ import { MatButtonModule } from '@angular/material/button';
|
|||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatListModule } from '@angular/material/list';
|
import { MatListModule } from '@angular/material/list';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
import { CoreExtensionsModule } from '../../extensions/core.extensions.module';
|
import { CoreExtensionsModule } from '../../../extensions/core.extensions.module';
|
||||||
import { AppCommonModule } from '../common/common.module';
|
import { AppCommonModule } from '../common/common.module';
|
||||||
import { ContextMenuItemComponent } from './context-menu-item.component';
|
import { ContextMenuItemComponent } from './context-menu-item.component';
|
||||||
import { OutsideEventDirective } from './context-menu-outside-event.directive';
|
import { OutsideEventDirective } from './context-menu-outside-event.directive';
|
@ -26,8 +26,8 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { AppTestingModule } from '../../testing/app-testing.module';
|
import { AppTestingModule } from '../../testing/app-testing.module';
|
||||||
import { DetailsComponent } from './details.component';
|
import { DetailsComponent } from './details.component';
|
||||||
import { MetadataTabComponent } from './../info-drawer/metadata-tab/metadata-tab.component';
|
import { MetadataTabComponent } from '../info-drawer/metadata-tab/metadata-tab.component';
|
||||||
import { CommentsTabComponent } from './../info-drawer/comments-tab/comments-tab.component';
|
import { CommentsTabComponent } from '../info-drawer/comments-tab/comments-tab.component';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { of, Subject } from 'rxjs';
|
import { of, Subject } from 'rxjs';
|
||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
@ -28,7 +28,7 @@ import { NgModule } from '@angular/core';
|
|||||||
import { CustomNameColumnComponent } from './name-column/name-column.component';
|
import { CustomNameColumnComponent } from './name-column/name-column.component';
|
||||||
import { LockedByModule } from '@alfresco/aca-shared';
|
import { LockedByModule } from '@alfresco/aca-shared';
|
||||||
import { ContentModule } from '@alfresco/adf-content-services';
|
import { ContentModule } from '@alfresco/adf-content-services';
|
||||||
import { MaterialModule } from '../../material.module';
|
import { MaterialModule } from '../../../material.module';
|
||||||
import { CoreModule } from '@alfresco/adf-core';
|
import { CoreModule } from '@alfresco/adf-core';
|
||||||
import { ThumbnailColumnComponent } from './thumbnail-column/thumbnail-column.component';
|
import { ThumbnailColumnComponent } from './thumbnail-column/thumbnail-column.component';
|
||||||
|
|
@ -4,8 +4,8 @@
|
|||||||
[tooltip]="appName$ | async"
|
[tooltip]="appName$ | async"
|
||||||
[color]="headerColor$ | async"
|
[color]="headerColor$ | async"
|
||||||
[title]="appName$ | async"
|
[title]="appName$ | async"
|
||||||
(clicked)="toggleClicked.emit($event)"
|
(clicked)="onToggleSidenav($event)"
|
||||||
[expandedSidenav]="expandedSidenav"
|
[expandedSidenav]="isSidenavExpanded"
|
||||||
>
|
>
|
||||||
<div class="adf-toolbar--spacer adf-toolbar-divider"></div>
|
<div class="adf-toolbar--spacer adf-toolbar-divider"></div>
|
||||||
|
|
@ -30,7 +30,7 @@ import { ContentActionRef } from '@alfresco/adf-extensions';
|
|||||||
import { AppStore, getHeaderColor, getAppName, getLogoPath, getHeaderImagePath, getHeaderTextColor } from '@alfresco/aca-shared/store';
|
import { AppStore, getHeaderColor, getAppName, getLogoPath, getHeaderImagePath, getHeaderTextColor } from '@alfresco/aca-shared/store';
|
||||||
import { AppExtensionService } from '@alfresco/aca-shared';
|
import { AppExtensionService } from '@alfresco/aca-shared';
|
||||||
import { takeUntil } from 'rxjs/operators';
|
import { takeUntil } from 'rxjs/operators';
|
||||||
import { AppConfigService } from '@alfresco/adf-core';
|
import { AppConfigService, SidenavLayoutComponent } from '@alfresco/adf-core';
|
||||||
import { isContentServiceEnabled } from '@alfresco/aca-shared/rules';
|
import { isContentServiceEnabled } from '@alfresco/aca-shared/rules';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -42,11 +42,18 @@ import { isContentServiceEnabled } from '@alfresco/aca-shared/rules';
|
|||||||
})
|
})
|
||||||
export class AppHeaderComponent implements OnInit, OnDestroy {
|
export class AppHeaderComponent implements OnInit, OnDestroy {
|
||||||
private onDestroy$: Subject<boolean> = new Subject<boolean>();
|
private onDestroy$: Subject<boolean> = new Subject<boolean>();
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
toggleClicked = new EventEmitter();
|
toggleClicked = new EventEmitter();
|
||||||
|
|
||||||
@Input() expandedSidenav = true;
|
@Input() expandedSidenav = true;
|
||||||
|
|
||||||
|
@Input() data: { layout?: SidenavLayoutComponent; isMenuMinimized?: boolean } = {};
|
||||||
|
|
||||||
|
get isSidenavExpanded(): boolean {
|
||||||
|
return !this.data.isMenuMinimized ?? this.expandedSidenav;
|
||||||
|
}
|
||||||
|
|
||||||
appName$: Observable<string>;
|
appName$: Observable<string>;
|
||||||
headerColor$: Observable<any>;
|
headerColor$: Observable<any>;
|
||||||
headerTextColor$: Observable<string>;
|
headerTextColor$: Observable<string>;
|
||||||
@ -55,7 +62,7 @@ export class AppHeaderComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
actions: Array<ContentActionRef> = [];
|
actions: Array<ContentActionRef> = [];
|
||||||
|
|
||||||
constructor(store: Store<AppStore>, private appExtensions: AppExtensionService, private appConfigService: AppConfigService) {
|
constructor(public store: Store<AppStore>, private appExtensions: AppExtensionService, private appConfigService: AppConfigService) {
|
||||||
this.headerColor$ = store.select(getHeaderColor);
|
this.headerColor$ = store.select(getHeaderColor);
|
||||||
this.headerTextColor$ = store.select(getHeaderTextColor);
|
this.headerTextColor$ = store.select(getHeaderTextColor);
|
||||||
this.appName$ = store.select(getAppName);
|
this.appName$ = store.select(getAppName);
|
||||||
@ -80,6 +87,10 @@ export class AppHeaderComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onToggleSidenav(_event: boolean): void {
|
||||||
|
this.data.layout.toggleMenu();
|
||||||
|
}
|
||||||
|
|
||||||
isContentServiceEnabled(): boolean {
|
isContentServiceEnabled(): boolean {
|
||||||
return isContentServiceEnabled();
|
return isContentServiceEnabled();
|
||||||
}
|
}
|
@ -29,7 +29,7 @@ import { ExtensionsModule } from '@alfresco/adf-extensions';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { DirectivesModule } from '../../directives/directives.module';
|
import { DirectivesModule } from '../../directives/directives.module';
|
||||||
import { MaterialModule } from '../../material.module';
|
import { MaterialModule } from '../../../material.module';
|
||||||
import { CommentsTabComponent } from './comments-tab/comments-tab.component';
|
import { CommentsTabComponent } from './comments-tab/comments-tab.component';
|
||||||
import { MetadataTabComponent } from './metadata-tab/metadata-tab.component';
|
import { MetadataTabComponent } from './metadata-tab/metadata-tab.component';
|
||||||
import { LibraryMetadataTabComponent } from './library-metadata-tab/library-metadata-tab.component';
|
import { LibraryMetadataTabComponent } from './library-metadata-tab/library-metadata-tab.component';
|
@ -27,9 +27,11 @@ import { NgModule } from '@angular/core';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { CoreModule } from '@alfresco/adf-core';
|
import { CoreModule } from '@alfresco/adf-core';
|
||||||
import { LoginComponent } from './login.component';
|
import { LoginComponent } from './login.component';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule, CoreModule.forChild()],
|
imports: [CommonModule, CoreModule.forChild(), TranslateModule.forChild()],
|
||||||
|
exports: [LoginComponent],
|
||||||
declarations: [LoginComponent]
|
declarations: [LoginComponent]
|
||||||
})
|
})
|
||||||
export class AppLoginModule {}
|
export class AppLoginModule {}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user