diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000000..d1ad3d5ade
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1,37 @@
+# Each line is a file pattern followed by one or more owners.
+
+ # These owners will be the default owners for everything in
+# the repo. Unless a later match takes precedence,
+# these users will be requested for
+# review when someone opens a pull request.
+* @eromano @popovicsandras @DenysVuika
+
+ # Order is important; the last matching pattern takes the most
+# precedence. When someone opens a pull request that only
+# modifies JS files, only @js-owner and not the global
+# owner(s) will be requested for a review.
+e2e/* @eromano @cristinaj @gmandakini @marouanbentaleb
+
+ # You can also use email addresses if you prefer. They'll be
+# used to look up users just like we do for commit author
+# emails.
+#*.go docs@example.com
+docs/* @m-hulbert @eromano
+
+ # In this example, @doctocat owns any files in the build/logs
+# directory at the root of the repository and any of its
+# subdirectories.
+#/build/logs/ @doctocat
+
+ # The `docs/*` pattern will match files like
+# `docs/getting-started.md` but not further nested files like
+# `docs/build-app/troubleshooting.md`.
+#docs/* docs@example.com
+
+ # In this example, @octocat owns any file in an apps directory
+# anywhere in your repository.
+#apps/ @octocat
+
+ # In this example, @doctocat owns any file in the `/docs`
+# directory in the root of your repository.
+#/docs/ @doctocat
diff --git a/README.md b/README.md
index 3579f2e550..58e5f3d4e9 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@
-
+
+ [expandedSidenav]="expandedSidenav" (expanded)="setState($event)" [position]="position" data-automation-id="sidenav-layout">
diff --git a/demo-shell/src/app/components/app-layout/app-layout.component.ts b/demo-shell/src/app/components/app-layout/app-layout.component.ts
index 686a5fd604..84a3186de6 100644
--- a/demo-shell/src/app/components/app-layout/app-layout.component.ts
+++ b/demo-shell/src/app/components/app-layout/app-layout.component.ts
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-import { Component, ViewEncapsulation, OnInit } from '@angular/core';
+import { Component, ViewEncapsulation, OnInit, OnDestroy } from '@angular/core';
import { UserPreferencesService, AppConfigService, AlfrescoApiService, UserPreferenceValues } from '@alfresco/adf-core';
import { HeaderDataService } from '../header-data/header-data.service';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
templateUrl: 'app-layout.component.html',
@@ -27,8 +29,8 @@ import { HeaderDataService } from '../header-data/header-data.service';
},
encapsulation: ViewEncapsulation.None
})
-
-export class AppLayoutComponent implements OnInit {
+export class AppLayoutComponent implements OnInit, OnDestroy {
+ private onDestroy$ = new Subject();
links: Array = [
{ href: '/home', icon: 'home', title: 'APP_LAYOUT.HOME' },
@@ -72,7 +74,7 @@ export class AppLayoutComponent implements OnInit {
{ href: '/webscript', icon: 'extension', title: 'APP_LAYOUT.WEBSCRIPT' },
{ href: '/tag', icon: 'local_offer', title: 'APP_LAYOUT.TAG' },
{ href: '/social', icon: 'thumb_up', title: 'APP_LAYOUT.SOCIAL' },
- { href: '/date', icon: 'calendar_today', title: 'APP_LAYOUT.DATE' },
+ { href: '/pipes', icon: 'layers', title: 'APP_LAYOUT.PIPES' },
{ href: '/settings-layout', icon: 'settings', title: 'APP_LAYOUT.SETTINGS' },
{ href: '/config-editor', icon: 'code', title: 'APP_LAYOUT.CONFIG-EDITOR' },
{ href: '/extendedSearch', icon: 'search', title: 'APP_LAYOUT.SEARCH' },
@@ -108,14 +110,42 @@ export class AppLayoutComponent implements OnInit {
this.expandedSidenav = expand;
}
- this.headerService.hideMenu.subscribe((show) => this.showMenu = show);
- this.headerService.color.subscribe((color) => this.color = color);
- this.headerService.title.subscribe((title) => this.title = title);
- this.headerService.logo.subscribe((path) => this.logo = path);
- this.headerService.redirectUrl.subscribe((redirectUrl) => this.redirectUrl = redirectUrl);
- this.headerService.tooltip.subscribe((tooltip) => this.tooltip = tooltip);
- this.headerService.position.subscribe((position) => this.position = position);
- this.headerService.hideSidenav.subscribe((hideSidenav) => this.hideSidenav = hideSidenav);
+ this.headerService.hideMenu
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(show => this.showMenu = show);
+
+ this.headerService.color
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(color => this.color = color);
+
+ this.headerService.title
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(title => this.title = title);
+
+ this.headerService.logo
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(path => this.logo = path);
+
+ this.headerService.redirectUrl
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(redirectUrl => this.redirectUrl = redirectUrl);
+
+ this.headerService.tooltip
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(tooltip => this.tooltip = tooltip);
+
+ this.headerService.position
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(position => this.position = position);
+
+ this.headerService.hideSidenav
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(hideSidenav => this.hideSidenav = hideSidenav);
+ }
+
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
constructor(
diff --git a/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.html b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.html
index dfbfe67660..23e7bea30c 100644
--- a/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.html
+++ b/demo-shell/src/app/components/app-layout/cloud/form-demo/cloud-form-demo.component.html
@@ -1,7 +1,7 @@
-
+
-
+
-
\ No newline at end of file
diff --git a/demo-shell/src/app/components/card-view/card-view.component.html b/demo-shell/src/app/components/card-view/card-view.component.html
index e39f4116c8..87c8edd452 100644
--- a/demo-shell/src/app/components/card-view/card-view.component.html
+++ b/demo-shell/src/app/components/card-view/card-view.component.html
@@ -4,7 +4,9 @@
+ [editable]="true"
+ [displayClearAction]="showClearDateAction"
+ [displayNoneOption]="showNoneOption">
@@ -22,6 +24,20 @@
(change)="toggleEditable()"
[checked]="isEditable">
Editable
+
+
+ Show clear date icon
+
+
+ Show none option
diff --git a/demo-shell/src/app/components/card-view/card-view.component.ts b/demo-shell/src/app/components/card-view/card-view.component.ts
index 0f4a283367..0c3f50e61b 100644
--- a/demo-shell/src/app/components/card-view/card-view.component.ts
+++ b/demo-shell/src/app/components/card-view/card-view.component.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import { Component, OnInit, ElementRef, ViewChild } from '@angular/core';
+import { Component, OnInit, ElementRef, ViewChild, OnDestroy } from '@angular/core';
import {
CardViewTextItemModel,
CardViewDateItemModel,
@@ -27,23 +27,30 @@ import {
CardViewSelectItemModel,
CardViewUpdateService,
CardViewMapItemModel,
- UpdateNotification
+ UpdateNotification,
+ DecimalNumberPipe
} from '@alfresco/adf-core';
-import { of } from 'rxjs';
+import { of, Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
templateUrl: './card-view.component.html',
styleUrls: ['./card-view.component.scss']
})
-export class CardViewComponent implements OnInit {
+export class CardViewComponent implements OnInit, OnDestroy {
@ViewChild('console') console: ElementRef;
isEditable = true;
properties: any;
logs: string[];
+ showClearDateAction = false;
+ showNoneOption = false;
- constructor(private cardViewUpdateService: CardViewUpdateService) {
+ private onDestroy$ = new Subject();
+
+ constructor(private cardViewUpdateService: CardViewUpdateService,
+ private decimalNumberPipe: DecimalNumberPipe) {
this.logs = [];
this.createCard();
}
@@ -53,7 +60,14 @@ export class CardViewComponent implements OnInit {
}
ngOnInit() {
- this.cardViewUpdateService.itemUpdated$.subscribe(this.onItemChange.bind(this));
+ this.cardViewUpdateService.itemUpdated$
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(this.onItemChange.bind(this));
+ }
+
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
createCard() {
@@ -102,7 +116,8 @@ export class CardViewComponent implements OnInit {
value: 9.9,
key: 'float',
default: 0.0,
- editable: this.isEditable
+ editable: this.isEditable,
+ pipes: [{ pipe: this.decimalNumberPipe}]
}),
new CardViewKeyValuePairsItemModel({
label: 'CardView Key-Value Pairs Item',
@@ -153,6 +168,14 @@ export class CardViewComponent implements OnInit {
this.createCard();
}
+ toggleClearDate() {
+ this.showClearDateAction = !this.showClearDateAction;
+ }
+
+ toggleNoneOption() {
+ this.showNoneOption = !this.showNoneOption;
+ }
+
reset() {
this.isEditable = true;
this.createCard();
diff --git a/demo-shell/src/app/components/cloud/cloud-breadcrumb-component.ts b/demo-shell/src/app/components/cloud/cloud-breadcrumb-component.ts
index d3edf12944..90816e16bd 100644
--- a/demo-shell/src/app/components/cloud/cloud-breadcrumb-component.ts
+++ b/demo-shell/src/app/components/cloud/cloud-breadcrumb-component.ts
@@ -19,26 +19,24 @@ import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
- selector: 'app-cloud-breadcrumbs',
- templateUrl: './cloud-breadcrumb-component.html',
- styleUrls: ['cloud-breadcrumb-component.scss']
+ selector: 'app-cloud-breadcrumbs',
+ templateUrl: './cloud-breadcrumb-component.html',
+ styleUrls: ['cloud-breadcrumb-component.scss']
})
export class CloudBreadcrumbsComponent implements OnInit {
+ appName: string;
+ filterName: string;
- appName: string;
- filterName: string;
+ constructor(private route: ActivatedRoute) {}
- constructor(private route: ActivatedRoute) { }
-
- ngOnInit() {
- this.route.parent.params.subscribe((
- params) => {
- this.appName = params.appName;
- });
- this.route.queryParams.subscribe((params) => {
- if (params.filterName) {
- this.filterName = params.filterName;
- }
- });
- }
+ ngOnInit() {
+ this.route.parent.params.subscribe(params => {
+ this.appName = params.appName;
+ });
+ this.route.queryParams.subscribe(params => {
+ if (params.filterName) {
+ this.filterName = params.filterName;
+ }
+ });
+ }
}
diff --git a/demo-shell/src/app/components/cloud/cloud-filters-demo.component.ts b/demo-shell/src/app/components/cloud/cloud-filters-demo.component.ts
index 7f27a2aa3a..2a193bfdbe 100644
--- a/demo-shell/src/app/components/cloud/cloud-filters-demo.component.ts
+++ b/demo-shell/src/app/components/cloud/cloud-filters-demo.component.ts
@@ -46,8 +46,9 @@ export class CloudFiltersDemoComponent implements OnInit {
) {}
ngOnInit() {
- this.currentTaskFilter$ = this.cloudLayoutService.getCurrentTaskFilterParam();
- this.currentProcessFilter$ = this.cloudLayoutService.getCurrentProcessFilterParam();
+ this.currentTaskFilter$ = this.cloudLayoutService.taskFilter$;
+ this.currentProcessFilter$ = this.cloudLayoutService.processFilter$;
+
let root = '';
if (this.route.snapshot && this.route.snapshot.firstChild) {
root = this.route.snapshot.firstChild.url[0].path;
@@ -62,13 +63,13 @@ export class CloudFiltersDemoComponent implements OnInit {
}
onTaskFilterSelected(filter) {
- this.cloudLayoutService.setCurrentTaskFilterParam({id: filter.id});
+ this.cloudLayoutService.setCurrentTaskFilterParam({id: filter && filter.id ? filter.id : ''});
const currentFilter = Object.assign({}, filter);
this.router.navigate([`/cloud/${this.appName}/tasks/`], { queryParams: currentFilter });
}
onProcessFilterSelected(filter) {
- this.cloudLayoutService.setCurrentProcessFilterParam({id: filter.id});
+ this.cloudLayoutService.setCurrentProcessFilterParam({id: filter && filter.id ? filter.id : ''});
const currentFilter = Object.assign({}, filter);
this.router.navigate([`/cloud/${this.appName}/processes/`], { queryParams: currentFilter });
}
diff --git a/demo-shell/src/app/components/cloud/cloud-viewer.component.ts b/demo-shell/src/app/components/cloud/cloud-viewer.component.ts
index a65bfe0b5c..14623f5330 100644
--- a/demo-shell/src/app/components/cloud/cloud-viewer.component.ts
+++ b/demo-shell/src/app/components/cloud/cloud-viewer.component.ts
@@ -15,32 +15,24 @@
* limitations under the License.
*/
-import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
-import { Subscription } from 'rxjs';
import { Params } from '@angular/router/src/shared';
@Component({
selector: 'app-cloud-viewer',
templateUrl: './cloud-viewer.component.html'
})
-export class CloudViewerComponent implements OnInit, OnDestroy {
+export class CloudViewerComponent implements OnInit {
nodeId: string;
- private sub: Subscription;
-
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
- this.sub = this.route.params.subscribe((params: Params) => {
+ this.route.params.subscribe((params: Params) => {
this.nodeId = params['nodeId'];
});
}
-
- ngOnDestroy() {
- this.sub.unsubscribe();
- }
-
}
diff --git a/demo-shell/src/app/components/cloud/community/community-cloud.component.ts b/demo-shell/src/app/components/cloud/community/community-cloud.component.ts
index 6303699344..40f92e73b4 100644
--- a/demo-shell/src/app/components/cloud/community/community-cloud.component.ts
+++ b/demo-shell/src/app/components/cloud/community/community-cloud.component.ts
@@ -29,7 +29,7 @@ import { CloudLayoutService } from '../services/cloud-layout.service';
height: 100% !important;
}
`],
- encapsulation: ViewEncapsulation.None
+ encapsulation: ViewEncapsulation.None
})
export class CommunityCloudComponent {
diff --git a/demo-shell/src/app/components/cloud/community/community-filters.component.ts b/demo-shell/src/app/components/cloud/community/community-filters.component.ts
index 39e64d288f..f3cf42d129 100644
--- a/demo-shell/src/app/components/cloud/community/community-filters.component.ts
+++ b/demo-shell/src/app/components/cloud/community/community-filters.component.ts
@@ -45,8 +45,9 @@ export class CommunityCloudFiltersDemoComponent implements OnInit {
) {}
ngOnInit() {
- this.currentTaskFilter$ = this.cloudLayoutService.getCurrentTaskFilterParam();
- this.currentProcessFilter$ = this.cloudLayoutService.getCurrentProcessFilterParam();
+ this.currentTaskFilter$ = this.cloudLayoutService.taskFilter$;
+ this.currentProcessFilter$ = this.cloudLayoutService.processFilter$;
+
let root = '';
if (this.route.snapshot && this.route.snapshot.firstChild) {
root = this.route.snapshot.firstChild.url[0].path;
diff --git a/demo-shell/src/app/components/cloud/community/community-processes-cloud.component.ts b/demo-shell/src/app/components/cloud/community/community-processes-cloud.component.ts
index c7d658b9b1..4092e9a573 100644
--- a/demo-shell/src/app/components/cloud/community/community-processes-cloud.component.ts
+++ b/demo-shell/src/app/components/cloud/community/community-processes-cloud.component.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import { Component, ViewChild, OnInit } from '@angular/core';
+import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import {
ProcessListCloudComponent,
ProcessFilterCloudModel,
@@ -27,12 +27,14 @@ import {
import { ActivatedRoute, Router } from '@angular/router';
import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core';
import { CloudLayoutService } from '../services/cloud-layout.service';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
+import { Pagination } from '@alfresco/js-api';
@Component({
templateUrl: './community-processes-cloud.component.html'
})
-export class CommunityProcessesCloudDemoComponent implements OnInit {
-
+export class CommunityProcessesCloudDemoComponent implements OnInit, OnDestroy {
public static ACTION_SAVE_AS = 'saveAs';
static PROCESS_FILTER_PROPERTY_KEYS = 'adf-edit-process-filter';
@@ -56,6 +58,8 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
editedFilter: ProcessFilterCloudModel;
+ private onDestroy$ = new Subject();
+
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -63,7 +67,10 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
private userPreference: UserPreferencesService,
private processFilterCloudService: ProcessFilterCloudService,
private appConfig: AppConfigService) {
- const properties = this.appConfig.get>(CommunityProcessesCloudDemoComponent.PROCESS_FILTER_PROPERTY_KEYS);
+ const properties = this.appConfig.get>(
+ CommunityProcessesCloudDemoComponent.PROCESS_FILTER_PROPERTY_KEYS
+ );
+
if (properties) {
this.processFilterProperties = properties;
}
@@ -71,6 +78,7 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
ngOnInit() {
this.isFilterLoaded = false;
+
this.route.parent.params.subscribe((params) => {
this.appName = params.appName;
});
@@ -85,14 +93,23 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
}
});
- this.cloudLayoutService.getCurrentSettings()
- .subscribe((settings) => this.setCurrentSettings(settings));
+ this.cloudLayoutService
+ .settings$
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(settings => this.setCurrentSettings(settings));
+ }
+
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
loadDefaultFilters() {
- this.processFilterCloudService.getProcessFilters('community').subscribe( (filters: ProcessFilterCloudModel[]) => {
- this.onFilterChange(filters[0]);
- });
+ this.processFilterCloudService
+ .getProcessFilters('community')
+ .subscribe((filters: ProcessFilterCloudModel[]) => {
+ this.onFilterChange(filters[0]);
+ });
}
setCurrentSettings(settings) {
@@ -103,7 +120,7 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
}
}
- onChangePageSize(event) {
+ onChangePageSize(event: Pagination) {
this.userPreference.paginationSize = event.maxItems;
}
@@ -111,13 +128,18 @@ export class CommunityProcessesCloudDemoComponent implements OnInit {
this.selectedRows = [];
}
- onRowClick(processInstanceId) {
+ onRowClick(processInstanceId: string) {
this.router.navigate([`/cloud/community/process-details/${processInstanceId}`]);
}
onFilterChange(query: any) {
this.editedFilter = Object.assign({}, query);
- this.sortArray = [new ProcessListCloudSortingModel({ orderBy: this.editedFilter.sort, direction: this.editedFilter.order })];
+ this.sortArray = [
+ new ProcessListCloudSortingModel({
+ orderBy: this.editedFilter.sort,
+ direction: this.editedFilter.order
+ })
+ ];
}
onProcessFilterAction(filterAction: any) {
diff --git a/demo-shell/src/app/components/cloud/community/community-task-cloud.component.ts b/demo-shell/src/app/components/cloud/community/community-task-cloud.component.ts
index 1e77a51372..94c38ddb1c 100644
--- a/demo-shell/src/app/components/cloud/community/community-task-cloud.component.ts
+++ b/demo-shell/src/app/components/cloud/community/community-task-cloud.component.ts
@@ -15,11 +15,14 @@
* limitations under the License.
*/
-import { Component, ViewChild, OnInit } from '@angular/core';
+import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { TaskListCloudComponent, TaskListCloudSortingModel, TaskFilterCloudModel, TaskFilterCloudService } from '@alfresco/adf-process-services-cloud';
import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core';
import { ActivatedRoute, Router } from '@angular/router';
import { CloudLayoutService } from '../services/cloud-layout.service';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
+import { Pagination } from '@alfresco/js-api';
@Component({
templateUrl: './community-task-cloud.component.html',
@@ -28,8 +31,7 @@ import { CloudLayoutService } from '../services/cloud-layout.service';
}
`]
})
-export class CommunityTasksCloudDemoComponent implements OnInit {
-
+export class CommunityTasksCloudDemoComponent implements OnInit, OnDestroy {
public static ACTION_SAVE_AS = 'saveAs';
static TASK_FILTER_PROPERTY_KEYS = 'adf-edit-task-filter';
@@ -51,6 +53,8 @@ export class CommunityTasksCloudDemoComponent implements OnInit {
selectionMode: string;
taskDetailsRedirection: boolean;
+ private onDestroy$ = new Subject();
+
constructor(
private cloudLayoutService: CloudLayoutService,
private route: ActivatedRoute,
@@ -79,14 +83,23 @@ export class CommunityTasksCloudDemoComponent implements OnInit {
}
});
- this.cloudLayoutService.getCurrentSettings()
- .subscribe((settings) => this.setCurrentSettings(settings));
+ this.cloudLayoutService
+ .settings$
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(settings => this.setCurrentSettings(settings));
+ }
+
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
loadDefaultFilters() {
- this.taskFilterCloudService.getTaskListFilters('community').subscribe( (filters: TaskFilterCloudModel[]) => {
- this.onFilterChange(filters[0]);
- });
+ this.taskFilterCloudService
+ .getTaskListFilters('community')
+ .subscribe((filters: TaskFilterCloudModel[]) => {
+ this.onFilterChange(filters[0]);
+ });
}
setCurrentSettings(settings) {
@@ -98,7 +111,7 @@ export class CommunityTasksCloudDemoComponent implements OnInit {
}
}
- onChangePageSize(event) {
+ onChangePageSize(event: Pagination) {
this.userPreference.paginationSize = event.maxItems;
}
@@ -106,7 +119,7 @@ export class CommunityTasksCloudDemoComponent implements OnInit {
this.selectedRows = [];
}
- onRowClick(taskId) {
+ onRowClick(taskId: string) {
if (!this.multiselect && this.selectionMode !== 'multiple' && this.taskDetailsRedirection) {
this.router.navigate([`/cloud/community/task-details/${taskId}`]);
}
diff --git a/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.scss b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.scss
index e97ca949e4..e3cc8d8c52 100644
--- a/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.scss
+++ b/demo-shell/src/app/components/cloud/community/community-task-details-cloud.component.scss
@@ -5,7 +5,7 @@
display: flex;
}
- &-task-tiitle {
+ &-task-title {
margin-left:15px;
}
diff --git a/demo-shell/src/app/components/cloud/community/community.module.ts b/demo-shell/src/app/components/cloud/community/community.module.ts
new file mode 100644
index 0000000000..6b10e6b435
--- /dev/null
+++ b/demo-shell/src/app/components/cloud/community/community.module.ts
@@ -0,0 +1,97 @@
+/*!
+ * @license
+ * Copyright 2019 Alfresco Software, Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+import { CommonModule } from '@angular/common';
+import { CoreModule } from '@alfresco/adf-core';
+import { FlexLayoutModule } from '@angular/flex-layout';
+import {
+ ProcessServicesCloudModule,
+ LocalPreferenceCloudService,
+ PROCESS_FILTERS_SERVICE_TOKEN,
+ TASK_FILTERS_SERVICE_TOKEN
+} from '@alfresco/adf-process-services-cloud';
+
+import { CommunityCloudComponent } from './community-cloud.component';
+import { CommunityTasksCloudDemoComponent } from './community-task-cloud.component';
+import { CommunityCloudFiltersDemoComponent } from './community-filters.component';
+import { CommunityProcessesCloudDemoComponent } from './community-processes-cloud.component';
+import { CommunityStartProcessCloudDemoComponent } from './community-start-process-cloud.component';
+import { CommunityStartTaskCloudDemoComponent } from './community-start-task-cloud.component';
+import { CommunityProcessDetailsCloudDemoComponent } from './community-process-details-cloud.component';
+import { CommunityTaskDetailsCloudDemoComponent } from './community-task-details-cloud.component';
+import { AppCloudSharedModule } from '../shared/cloud.shared.module';
+
+const routes: Routes = [
+ {
+ path: '',
+ component: CommunityCloudComponent,
+ children: [
+ {
+ path: 'tasks',
+ component: CommunityTasksCloudDemoComponent
+ },
+ {
+ path: 'processes',
+ component: CommunityProcessesCloudDemoComponent
+ },
+ {
+ path: 'start-task',
+ component: CommunityStartTaskCloudDemoComponent
+ },
+ {
+ path: 'start-process',
+ component: CommunityStartProcessCloudDemoComponent
+ },
+ {
+ path: 'task-details/:taskId',
+ component: CommunityTaskDetailsCloudDemoComponent
+ },
+ {
+ path: 'process-details/:processInstanceId',
+ component: CommunityProcessDetailsCloudDemoComponent
+ }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [
+ CommonModule,
+ CoreModule.forChild(),
+ ProcessServicesCloudModule,
+ RouterModule.forChild(routes),
+ AppCloudSharedModule,
+ FlexLayoutModule
+ ],
+ declarations: [
+ CommunityCloudComponent,
+ CommunityTasksCloudDemoComponent,
+ CommunityCloudFiltersDemoComponent,
+ CommunityProcessesCloudDemoComponent,
+ CommunityStartProcessCloudDemoComponent,
+ CommunityStartTaskCloudDemoComponent,
+ CommunityProcessDetailsCloudDemoComponent,
+ CommunityTaskDetailsCloudDemoComponent
+ ],
+ providers: [
+ { provide: PROCESS_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService },
+ { provide: TASK_FILTERS_SERVICE_TOKEN, useClass: LocalPreferenceCloudService }
+ ]
+})
+export class AppCommunityModule {}
diff --git a/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts
index 31a417e206..40455ff8c2 100644
--- a/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts
+++ b/demo-shell/src/app/components/cloud/processes-cloud-demo.component.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import { Component, ViewChild, OnInit } from '@angular/core';
+import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import {
ProcessListCloudComponent,
ProcessFilterCloudModel,
@@ -25,13 +25,16 @@ import {
import { ActivatedRoute, Router } from '@angular/router';
import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core';
-import { CloudLayoutService } from './services/cloud-layout.service';
+import { CloudLayoutService, CloudServiceSettings } from './services/cloud-layout.service';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
+import { Pagination } from '@alfresco/js-api';
@Component({
templateUrl: './processes-cloud-demo.component.html',
styleUrls: ['./processes-cloud-demo.component.scss']
})
-export class ProcessesCloudDemoComponent implements OnInit {
+export class ProcessesCloudDemoComponent implements OnInit, OnDestroy {
public static ACTION_SAVE_AS = 'saveAs';
static PROCESS_FILTER_PROPERTY_KEYS = 'adf-edit-process-filter';
@@ -57,6 +60,8 @@ export class ProcessesCloudDemoComponent implements OnInit {
editedFilter: ProcessFilterCloudModel;
+ private onDestroy$ = new Subject();
+
constructor(
private route: ActivatedRoute,
private router: Router,
@@ -81,11 +86,17 @@ export class ProcessesCloudDemoComponent implements OnInit {
this.filterId = params.id;
});
- this.cloudLayoutService.getCurrentSettings()
- .subscribe((settings) => this.setCurrentSettings(settings));
+ this.cloudLayoutService.settings$
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(settings => this.setCurrentSettings(settings));
}
- setCurrentSettings(settings) {
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
+ }
+
+ setCurrentSettings(settings: CloudServiceSettings) {
if (settings) {
this.multiselect = settings.multiselect;
this.testingMode = settings.testingMode;
@@ -94,7 +105,7 @@ export class ProcessesCloudDemoComponent implements OnInit {
}
}
- onChangePageSize(event) {
+ onChangePageSize(event: Pagination) {
this.userPreference.paginationSize = event.maxItems;
}
@@ -102,7 +113,7 @@ export class ProcessesCloudDemoComponent implements OnInit {
this.selectedRows = [];
}
- onRowClick(processInstanceId) {
+ onRowClick(processInstanceId: string) {
if (!this.multiselect && this.selectionMode !== 'multiple' && this.processDetailsRedirection) {
this.router.navigate([`/cloud/${this.appName}/process-details/${processInstanceId}`]);
}
@@ -110,7 +121,12 @@ export class ProcessesCloudDemoComponent implements OnInit {
onFilterChange(query: any) {
this.editedFilter = Object.assign({}, query);
- this.sortArray = [new ProcessListCloudSortingModel({ orderBy: this.editedFilter.sort, direction: this.editedFilter.order })];
+ this.sortArray = [
+ new ProcessListCloudSortingModel({
+ orderBy: this.editedFilter.sort,
+ direction: this.editedFilter.order
+ })
+ ];
}
onProcessFilterAction(filterAction: any) {
diff --git a/demo-shell/src/app/components/cloud/services/cloud-layout.service.ts b/demo-shell/src/app/components/cloud/services/cloud-layout.service.ts
index 7bf710169c..d3041063d3 100644
--- a/demo-shell/src/app/components/cloud/services/cloud-layout.service.ts
+++ b/demo-shell/src/app/components/cloud/services/cloud-layout.service.ts
@@ -16,14 +16,28 @@
*/
import { Injectable } from '@angular/core';
-import { Observable, BehaviorSubject } from 'rxjs';
+import { BehaviorSubject } from 'rxjs';
+
+export interface CloudServiceSettings {
+ multiselect: boolean;
+ testingMode: boolean;
+ taskDetailsRedirection: boolean;
+ processDetailsRedirection: boolean;
+ selectionMode: string;
+}
+
+export interface FilterSettings {
+ id?: string;
+ index?: number;
+ key?: string;
+}
@Injectable({
providedIn: 'root'
})
export class CloudLayoutService {
- private settings = {
+ private settings: CloudServiceSettings = {
multiselect: false,
testingMode: false,
taskDetailsRedirection: true,
@@ -31,40 +45,19 @@ export class CloudLayoutService {
selectionMode: 'single'
};
- private filterTaskSubject: BehaviorSubject = new BehaviorSubject({index: 0});
- private filterTask$: Observable;
- private filterProcessSubject: BehaviorSubject = new BehaviorSubject({index: 0});
- private filterProcess$: Observable;
- private settingsSubject: BehaviorSubject = new BehaviorSubject(this.settings);
- private settings$: Observable;
+ taskFilter$ = new BehaviorSubject({index: 0});
+ processFilter$ = new BehaviorSubject({index: 0});
+ settings$ = new BehaviorSubject(this.settings);
- constructor() {
- this.filterTask$ = this.filterTaskSubject.asObservable();
- this.filterProcess$ = this.filterProcessSubject.asObservable();
- this.settings$ = this.settingsSubject.asObservable();
+ setCurrentTaskFilterParam(param: FilterSettings) {
+ this.taskFilter$.next(param);
}
- getCurrentTaskFilterParam() {
- return this.filterTask$;
+ setCurrentProcessFilterParam(param: FilterSettings) {
+ this.processFilter$.next(param);
}
- setCurrentTaskFilterParam(param) {
- this.filterTaskSubject.next(param);
- }
-
- getCurrentProcessFilterParam() {
- return this.filterProcess$;
- }
-
- setCurrentProcessFilterParam(param) {
- this.filterProcessSubject.next(param);
- }
-
- getCurrentSettings() {
- return this.settings$;
- }
-
- setCurrentSettings(param) {
- this.settingsSubject.next(param);
+ setCurrentSettings(param: CloudServiceSettings) {
+ this.settings$.next(param);
}
}
diff --git a/demo-shell/src/app/components/cloud/cloud-settings.component.html b/demo-shell/src/app/components/cloud/shared/cloud-settings.component.html
similarity index 100%
rename from demo-shell/src/app/components/cloud/cloud-settings.component.html
rename to demo-shell/src/app/components/cloud/shared/cloud-settings.component.html
diff --git a/demo-shell/src/app/components/cloud/cloud-settings.component.scss b/demo-shell/src/app/components/cloud/shared/cloud-settings.component.scss
similarity index 100%
rename from demo-shell/src/app/components/cloud/cloud-settings.component.scss
rename to demo-shell/src/app/components/cloud/shared/cloud-settings.component.scss
diff --git a/demo-shell/src/app/components/cloud/cloud-settings.component.ts b/demo-shell/src/app/components/cloud/shared/cloud-settings.component.ts
similarity index 80%
rename from demo-shell/src/app/components/cloud/cloud-settings.component.ts
rename to demo-shell/src/app/components/cloud/shared/cloud-settings.component.ts
index cdb7a31fb8..d21e308386 100644
--- a/demo-shell/src/app/components/cloud/cloud-settings.component.ts
+++ b/demo-shell/src/app/components/cloud/shared/cloud-settings.component.ts
@@ -15,15 +15,18 @@
* limitations under the License.
*/
-import { Component, OnInit } from '@angular/core';
-import { CloudLayoutService } from './services/cloud-layout.service';
+import { Component, OnInit, OnDestroy } from '@angular/core';
+import { CloudLayoutService } from '../services/cloud-layout.service';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-cloud-settings',
templateUrl: './cloud-settings.component.html',
styleUrls: ['./cloud-settings.component.scss']
})
-export class CloudSettingsComponent implements OnInit {
+export class CloudSettingsComponent implements OnInit, OnDestroy {
+ private onDestroy$ = new Subject();
multiselect: boolean;
selectionMode: string;
@@ -40,8 +43,15 @@ export class CloudSettingsComponent implements OnInit {
constructor(private cloudLayoutService: CloudLayoutService) { }
ngOnInit() {
- this.cloudLayoutService.getCurrentSettings()
- .subscribe((settings) => this.setCurrentSettings(settings));
+ this.cloudLayoutService
+ .settings$
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(settings => this.setCurrentSettings(settings));
+ }
+
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
setCurrentSettings(settings) {
diff --git a/demo-shell/src/app/components/blob-preview/blob-preview.module.ts b/demo-shell/src/app/components/cloud/shared/cloud.shared.module.ts
similarity index 53%
rename from demo-shell/src/app/components/blob-preview/blob-preview.module.ts
rename to demo-shell/src/app/components/cloud/shared/cloud.shared.module.ts
index 9e056eac9c..a67fc6e948 100644
--- a/demo-shell/src/app/components/blob-preview/blob-preview.module.ts
+++ b/demo-shell/src/app/components/cloud/shared/cloud.shared.module.ts
@@ -16,34 +16,22 @@
*/
import { NgModule } from '@angular/core';
-import { Routes, RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
-import { CoreModule, InfoDrawerModule } from '@alfresco/adf-core';
-import { ContentDirectiveModule, ContentMetadataModule, VersionManagerModule } from '@alfresco/adf-content-services';
-import { BlobPreviewComponent } from './blob-preview.component';
-
-const routes: Routes = [
- {
- path: '',
- component: BlobPreviewComponent
- }
-];
+import { CloudSettingsComponent } from './cloud-settings.component';
+import { MatDialogModule, MatInputModule, MatSelectModule, MatSlideToggleModule } from '@angular/material';
+import { CoreModule } from '@alfresco/adf-core';
@NgModule({
imports: [
CommonModule,
- RouterModule.forChild(routes),
CoreModule.forChild(),
- InfoDrawerModule,
- ContentDirectiveModule,
- ContentMetadataModule,
- VersionManagerModule
+ MatDialogModule,
+ MatInputModule,
+ MatSelectModule,
+ MatSlideToggleModule
],
- declarations: [
- BlobPreviewComponent
- ],
- exports: [
- BlobPreviewComponent
- ]
+ declarations: [ CloudSettingsComponent ],
+ exports: [ CommonModule, CloudSettingsComponent]
})
-export class BlobPreviewModule {}
+
+export class AppCloudSharedModule {}
diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html
index d1e7f8c7ec..c1a956acec 100644
--- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html
+++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.html
@@ -8,10 +8,12 @@
[taskId]="taskId"
(cancelClick)="goBack()"
(taskCompleted)="onTaskCompleted()"
+ (taskClaimed)="onTaskClaimed()"
+ (taskUnclaimed)="onTaskUnclaimed()"
(formSaved)="onFormSaved()">
-
diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.scss b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.scss
index e97ca949e4..e3cc8d8c52 100644
--- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.scss
+++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.scss
@@ -5,7 +5,7 @@
display: flex;
}
- &-task-tiitle {
+ &-task-title {
margin-left:15px;
}
diff --git a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts
index 95eefeaebe..9a724895e5 100644
--- a/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts
+++ b/demo-shell/src/app/components/cloud/task-details-cloud-demo.component.ts
@@ -15,9 +15,10 @@
* limitations under the License.
*/
-import { Component } from '@angular/core';
+import { Component, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { NotificationService } from '@alfresco/adf-core';
+import { TaskHeaderCloudComponent } from '@alfresco/adf-process-services-cloud';
@Component({
templateUrl: './task-details-cloud-demo.component.html',
@@ -25,6 +26,9 @@ import { NotificationService } from '@alfresco/adf-core';
})
export class TaskDetailsCloudDemoComponent {
+ @ViewChild('taskHeader')
+ taskHeader: TaskHeaderCloudComponent;
+
taskId: string;
appName: string;
@@ -54,6 +58,14 @@ export class TaskDetailsCloudDemoComponent {
this.goBack();
}
+ onTaskClaimed() {
+ this.taskHeader.ngOnInit();
+ }
+
+ onTaskUnclaimed() {
+ this.taskHeader.ngOnInit();
+ }
+
onFormContentClicked(resourceId) {
this.router.navigate([`/cloud/${this.appName}/task-details/${this.taskId}/files/${resourceId.nodeId}/view`]);
}
diff --git a/demo-shell/src/app/components/cloud/tasks-cloud-demo.component.ts b/demo-shell/src/app/components/cloud/tasks-cloud-demo.component.ts
index 4cc0058347..daa4aeed93 100644
--- a/demo-shell/src/app/components/cloud/tasks-cloud-demo.component.ts
+++ b/demo-shell/src/app/components/cloud/tasks-cloud-demo.component.ts
@@ -15,17 +15,19 @@
* limitations under the License.
*/
-import { Component, ViewChild, OnInit } from '@angular/core';
+import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { TaskListCloudComponent, TaskListCloudSortingModel, TaskFilterCloudModel } from '@alfresco/adf-process-services-cloud';
import { UserPreferencesService, AppConfigService } from '@alfresco/adf-core';
import { ActivatedRoute, Router } from '@angular/router';
import { CloudLayoutService } from './services/cloud-layout.service';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
templateUrl: 'tasks-cloud-demo.component.html',
styleUrls: ['tasks-cloud-demo.component.scss']
})
-export class TasksCloudDemoComponent implements OnInit {
+export class TasksCloudDemoComponent implements OnInit, OnDestroy {
public static ACTION_SAVE_AS = 'saveAs';
static TASK_FILTER_PROPERTY_KEYS = 'adf-edit-task-filter';
@@ -50,6 +52,8 @@ export class TasksCloudDemoComponent implements OnInit {
selectionMode: string;
taskDetailsRedirection: boolean;
+ private onDestroy$ = new Subject();
+
constructor(
private cloudLayoutService: CloudLayoutService,
private route: ActivatedRoute,
@@ -75,8 +79,14 @@ export class TasksCloudDemoComponent implements OnInit {
this.filterId = params.id;
});
- this.cloudLayoutService.getCurrentSettings()
- .subscribe((settings) => this.setCurrentSettings(settings));
+ this.cloudLayoutService.settings$
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(settings => this.setCurrentSettings(settings));
+ }
+
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
setCurrentSettings(settings) {
diff --git a/demo-shell/src/app/components/config-editor/config-editor.component.ts b/demo-shell/src/app/components/config-editor/config-editor.component.ts
index d133897b49..32bcc6d893 100644
--- a/demo-shell/src/app/components/config-editor/config-editor.component.ts
+++ b/demo-shell/src/app/components/config-editor/config-editor.component.ts
@@ -15,20 +15,24 @@
* limitations under the License.
*/
-import { Component } from '@angular/core';
+import { Component, OnDestroy } from '@angular/core';
import {
AppConfigService,
NotificationService,
UserPreferencesService,
UserPreferenceValues
} from '@alfresco/adf-core';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-config-editor',
templateUrl: 'config-editor.component.html',
styleUrls: ['./config-editor.component.scss']
})
-export class ConfigEditorComponent {
+export class ConfigEditorComponent implements OnDestroy {
+
+ private onDestroy$ = new Subject();
editor: any;
code: any;
@@ -83,15 +87,23 @@ export class ConfigEditorComponent {
this.indentCode();
}
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
+ }
+
textOrientationClick() {
this.isUserPreference = true;
this.userPreferenceProperty = 'textOrientation';
- this.userPreferencesService.select(this.userPreferenceProperty).subscribe((textOrientation: number) => {
- this.code = JSON.stringify(textOrientation);
- this.field = 'textOrientation';
- this.indentCode();
- });
+ this.userPreferencesService
+ .select(this.userPreferenceProperty)
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe((textOrientation: number) => {
+ this.code = JSON.stringify(textOrientation);
+ this.field = 'textOrientation';
+ this.indentCode();
+ });
this.indentCode();
}
@@ -99,21 +111,27 @@ export class ConfigEditorComponent {
infinitePaginationConfClick() {
this.isUserPreference = true;
this.userPreferenceProperty = UserPreferenceValues.PaginationSize;
- this.userPreferencesService.select(this.userPreferenceProperty).subscribe((pageSize: number) => {
- this.code = JSON.stringify(pageSize);
- this.field = 'adf-infinite-pagination';
- this.indentCode();
- });
+ this.userPreferencesService
+ .select(this.userPreferenceProperty)
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe((pageSize: number) => {
+ this.code = JSON.stringify(pageSize);
+ this.field = 'adf-infinite-pagination';
+ this.indentCode();
+ });
}
supportedPageSizesClick() {
this.isUserPreference = true;
this.userPreferenceProperty = UserPreferenceValues.SupportedPageSizes;
- this.userPreferencesService.select(this.userPreferenceProperty).subscribe((supportedPageSizes: number) => {
- this.code = JSON.stringify(supportedPageSizes);
- this.field = 'adf-supported-page-size';
- this.indentCode();
- });
+ this.userPreferencesService
+ .select(this.userPreferenceProperty)
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe((supportedPageSizes: number) => {
+ this.code = JSON.stringify(supportedPageSizes);
+ this.field = 'adf-supported-page-size';
+ this.indentCode();
+ });
}
indentCode() {
diff --git a/demo-shell/src/app/components/date/date.component.html b/demo-shell/src/app/components/date/date.component.html
deleted file mode 100644
index a4821deb0f..0000000000
--- a/demo-shell/src/app/components/date/date.component.html
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
Date Pipes
-
-
-
-
-
-
-
-
- {{language.label}}
-
-
-
-
-
AdfLocalizedDate Pipe - Default
-
{{ today | adfLocalizedDate }}
-
-
AdfLocalizedDate Pipe - Custom format
-
{{ today | adfLocalizedDate : format }}
-
-
AdfLocalizedDate Pipe - Custom format and locale
-
{{ today | adfLocalizedDate : format : locale }}
-
-
AdfTimeAgo Pipe
-
{{ today | adfTimeAgo }}
-
-
AdfTimeAgo Pipe - Custom locale
-
{{ today | adfTimeAgo : locale}}
-
diff --git a/demo-shell/src/app/components/date/date.component.scss b/demo-shell/src/app/components/date/date.component.scss
deleted file mode 100644
index 720ae78a4d..0000000000
--- a/demo-shell/src/app/components/date/date.component.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-.adf-date-pipes-container {
- padding: 20px;
-}
-
-.adf-date-field {
- margin: 20px;
-}
diff --git a/demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts b/demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts
index 54c43bce43..a4fa1189a1 100644
--- a/demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts
+++ b/demo-shell/src/app/components/document-list/extension-presets/name-column/name-column.component.ts
@@ -25,9 +25,10 @@ import {
OnDestroy
} from '@angular/core';
import { NodeEntry } from '@alfresco/js-api';
-import { BehaviorSubject, Subscription } from 'rxjs';
+import { BehaviorSubject, Subject } from 'rxjs';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { Node } from '@alfresco/js-api';
+import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-name-column',
@@ -47,24 +48,26 @@ export class NameColumnComponent implements OnInit, OnDestroy {
displayText$ = new BehaviorSubject('');
node: NodeEntry;
- private sub: Subscription;
+ private onDestroy$ = new Subject();
constructor(private element: ElementRef, private alfrescoApiService: AlfrescoApiService) {}
ngOnInit() {
this.updateValue();
- this.sub = this.alfrescoApiService.nodeUpdated.subscribe((node: Node) => {
- const row = this.context.row;
- if (row) {
- const { entry } = row.node;
+ this.alfrescoApiService.nodeUpdated
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe((node: Node) => {
+ const row = this.context.row;
+ if (row) {
+ const { entry } = row.node;
- if (entry === node) {
- row.node = { entry };
- this.updateValue();
+ if (entry === node) {
+ row.node = { entry };
+ this.updateValue();
+ }
}
- }
- });
+ });
}
protected updateValue() {
@@ -87,9 +90,7 @@ export class NameColumnComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
- if (this.sub) {
- this.sub.unsubscribe();
- this.sub = null;
- }
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
}
diff --git a/demo-shell/src/app/components/file-view/file-view.component.html b/demo-shell/src/app/components/file-view/file-view.component.html
index e6274e0b69..553ea01d97 100644
--- a/demo-shell/src/app/components/file-view/file-view.component.html
+++ b/demo-shell/src/app/components/file-view/file-view.component.html
@@ -1,4 +1,4 @@
-
+
@@ -284,14 +284,16 @@
-
-
@@ -314,6 +316,7 @@
diff --git a/demo-shell/src/app/components/file-view/file-view.component.ts b/demo-shell/src/app/components/file-view/file-view.component.ts
index e5b4187f87..f5e46304e4 100644
--- a/demo-shell/src/app/components/file-view/file-view.component.ts
+++ b/demo-shell/src/app/components/file-view/file-view.component.ts
@@ -16,9 +16,10 @@
*/
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
-import { ActivatedRoute, Router } from '@angular/router';
+import { ActivatedRoute, Router, PRIMARY_OUTLET } from '@angular/router';
import { ContentService, AllowableOperationsEnum, PermissionsEnum, NodesApiService } from '@alfresco/adf-core';
import { MatSnackBar } from '@angular/material';
+import { PreviewService } from '../../services/preview.service';
@Component({
selector: 'app-file-view',
@@ -57,12 +58,15 @@ export class FileViewComponent implements OnInit {
showTabWithIconAndLabel = false;
desiredAspect: string = null;
showAspect: string = null;
+ content: Blob;
+ name: string;
constructor(private router: Router,
private route: ActivatedRoute,
private snackBar: MatSnackBar,
private nodeApiService: NodesApiService,
- private contentServices: ContentService) {
+ private contentServices: ContentService,
+ private preview: PreviewService) {
}
ngOnInit() {
@@ -81,10 +85,18 @@ export class FileViewComponent implements OnInit {
},
() => this.router.navigate(['/files', id])
);
+ } else if (this.preview.content) {
+ this.content = this.preview.content;
+ this.displayName = this.preview.name;
}
});
}
+ onViewerVisibilityChanged() {
+ const primaryUrl = this.router.parseUrl(this.router.url).root.children[PRIMARY_OUTLET].toString();
+ this.router.navigateByUrl(primaryUrl);
+ }
+
onUploadError(errorMessage: string) {
this.snackBar.open(errorMessage, '', { duration: 4000 });
}
diff --git a/demo-shell/src/app/components/files/files.component.html b/demo-shell/src/app/components/files/files.component.html
index 1234e1f9dc..3575817454 100644
--- a/demo-shell/src/app/components/files/files.component.html
+++ b/demo-shell/src/app/components/files/files.component.html
@@ -94,7 +94,9 @@
(click)="createLibrary()">
library_add
-
delete
- this.onFileUploadEvent(value));
- this.uploadService.fileUploadDeleted.subscribe((value) => this.onFileUploadEvent(value));
- this.contentService.folderCreated.subscribe((value) => this.onFolderCreated(value));
- this.onCreateFolder = this.contentService.folderCreate.subscribe((value) => this.onFolderAction(value));
- this.onEditFolder = this.contentService.folderEdit.subscribe((value) => this.onFolderAction(value));
+ this.uploadService.fileUploadComplete
+ .pipe(
+ debounceTime(300),
+ takeUntil(this.onDestroy$)
+ )
+ .subscribe(value => this.onFileUploadEvent(value));
+
+ this.uploadService.fileUploadDeleted
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(value => this.onFileUploadEvent(value));
+
+ this.contentService.folderCreated
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(value => this.onFolderCreated(value));
+
+ this.contentService.folderCreate
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(value => this.onFolderAction(value));
+
+ this.contentService.folderEdit
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(value => this.onFolderAction(value));
this.contentMetadataService.error
.pipe(takeUntil(this.onDestroy$))
@@ -286,9 +298,6 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
}
ngOnDestroy() {
- this.onCreateFolder.unsubscribe();
- this.onEditFolder.unsubscribe();
-
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
@@ -383,21 +392,21 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
switch (errorStatusCode) {
case 403:
- translatedErrorMessage = this.translateService.get('OPERATION.ERROR.PERMISSION');
+ translatedErrorMessage = this.translateService.instant('OPERATION.ERROR.PERMISSION');
break;
case 409:
- translatedErrorMessage = this.translateService.get('OPERATION.ERROR.CONFLICT');
+ translatedErrorMessage = this.translateService.instant('OPERATION.ERROR.CONFLICT');
break;
default:
- translatedErrorMessage = this.translateService.get('OPERATION.ERROR.UNKNOWN');
+ translatedErrorMessage = this.translateService.instant('OPERATION.ERROR.UNKNOWN');
}
- this.openSnackMessage(translatedErrorMessage.value);
+ this.openSnackMessage(translatedErrorMessage);
}
onContentActionSuccess(message) {
- const translatedMessage: any = this.translateService.get(message);
- this.openSnackMessage(translatedMessage.value);
+ const translatedMessage: any = this.translateService.instant(message);
+ this.openSnackMessage(translatedMessage);
this.documentList.reload();
}
@@ -424,8 +433,8 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
width: '630px'
});
} else {
- const translatedErrorMessage: any = this.translateService.get('OPERATION.ERROR.PERMISSION');
- this.openSnackMessage(translatedErrorMessage.value);
+ const translatedErrorMessage: any = this.translateService.instant('OPERATION.ERROR.PERMISSION');
+ this.openSnackMessage(translatedErrorMessage);
}
}
@@ -442,8 +451,8 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
width: '630px'
});
} else {
- const translatedErrorMessage: any = this.translateService.get('OPERATION.ERROR.PERMISSION');
- this.openSnackMessage(translatedErrorMessage.value);
+ const translatedErrorMessage: any = this.translateService.instant('OPERATION.ERROR.PERMISSION');
+ this.openSnackMessage(translatedErrorMessage);
}
}
@@ -592,7 +601,7 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
width: '400px'
});
- dialogInstance.componentInstance.error.subscribe((message) => {
+ dialogInstance.componentInstance.error.subscribe((message: string) => {
this.notificationService.openSnackMessage(message);
});
}
diff --git a/demo-shell/src/app/components/form/form-list.component.ts b/demo-shell/src/app/components/form/form-list.component.ts
index 4ad54895e7..bf4e2934ef 100644
--- a/demo-shell/src/app/components/form/form-list.component.ts
+++ b/demo-shell/src/app/components/form/form-list.component.ts
@@ -15,16 +15,18 @@
* limitations under the License.
*/
-import { Component, ViewChild } from '@angular/core';
+import { Component, ViewChild, OnDestroy, OnInit } from '@angular/core';
import { FormModel, FormService, LogService, FormOutcomeEvent } from '@alfresco/adf-core';
import { FormComponent } from '@alfresco/adf-process-services';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-form-list',
templateUrl: 'form-list.component.html',
styleUrls: ['form-list.component.scss']
})
-export class FormListComponent {
+export class FormListComponent implements OnInit, OnDestroy {
@ViewChild('adfForm')
activitiForm: FormComponent;
@@ -38,13 +40,24 @@ export class FormListComponent {
restoredData: any = {};
showValidationIcon = false;
+ private onDestroy$ = new Subject();
constructor(private formService: FormService, private logService: LogService) {
+ }
+
+ ngOnInit() {
// Prevent default outcome actions
- formService.executeOutcome.subscribe((formOutcomeEvent: FormOutcomeEvent) => {
- formOutcomeEvent.preventDefault();
- this.logService.log(formOutcomeEvent.outcome);
- });
+ this.formService.executeOutcome
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe((formOutcomeEvent: FormOutcomeEvent) => {
+ formOutcomeEvent.preventDefault();
+ this.logService.log(formOutcomeEvent.outcome);
+ });
+ }
+
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
onRowDblClick(event: CustomEvent) {
diff --git a/demo-shell/src/app/components/form/form-loading.component.ts b/demo-shell/src/app/components/form/form-loading.component.ts
index ff9e71ecce..42e4227a8c 100644
--- a/demo-shell/src/app/components/form/form-loading.component.ts
+++ b/demo-shell/src/app/components/form/form-loading.component.ts
@@ -15,46 +15,60 @@
* limitations under the License.
*/
-import { Component, Inject, OnInit } from '@angular/core';
-import { FormModel, FormService, FormOutcomeEvent, CoreAutomationService } from '@alfresco/adf-core';
+import { Component, Inject, OnInit, OnDestroy } from '@angular/core';
+import {
+ FormModel,
+ FormService,
+ FormOutcomeEvent,
+ CoreAutomationService
+} from '@alfresco/adf-core';
import { InMemoryFormService } from '../../services/in-memory-form.service';
import { FakeFormService } from './fake-form.service';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-form-loading',
templateUrl: 'form-loading.component.html',
styleUrls: ['form-loading.component.scss'],
- providers: [
- { provide: FormService, useClass: FakeFormService }
- ]
+ providers: [{ provide: FormService, useClass: FakeFormService }]
})
-export class FormLoadingComponent implements OnInit {
-
+export class FormLoadingComponent implements OnInit, OnDestroy {
form: FormModel;
typeaheadFieldValue = '';
selectFieldValue = '';
radioButtonFieldValue = '';
formattedData = {};
- constructor(@Inject(FormService) private formService: InMemoryFormService,
- private automationService: CoreAutomationService) {
- formService.executeOutcome.subscribe((formOutcomeEvent: FormOutcomeEvent) => {
- formOutcomeEvent.preventDefault();
- });
- }
+ private onDestroy$ = new Subject();
+
+ constructor(
+ @Inject(FormService) private formService: InMemoryFormService,
+ private automationService: CoreAutomationService
+ ) {}
ngOnInit() {
+ this.formService.executeOutcome
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe((formOutcomeEvent: FormOutcomeEvent) => {
+ formOutcomeEvent.preventDefault();
+ });
+
this.formattedData = {};
const formDefinitionJSON: any = this.automationService.forms.getSimpleFormDefinition();
this.form = this.formService.parseForm(formDefinitionJSON);
}
- onLoadButtonClicked() {
- this.formattedData = {
- 'typeaheadField': this.typeaheadFieldValue,
- 'selectBox': this.selectFieldValue,
- 'radioButton': this.radioButtonFieldValue
- };
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
+ onLoadButtonClicked() {
+ this.formattedData = {
+ typeaheadField: this.typeaheadFieldValue,
+ selectBox: this.selectFieldValue,
+ radioButton: this.radioButtonFieldValue
+ };
+ }
}
diff --git a/demo-shell/src/app/components/form/form.component.ts b/demo-shell/src/app/components/form/form.component.ts
index 33ba5fec89..8559e4d031 100644
--- a/demo-shell/src/app/components/form/form.component.ts
+++ b/demo-shell/src/app/components/form/form.component.ts
@@ -18,7 +18,8 @@
import { Component, Inject, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import { FormModel, FormFieldModel, FormService, FormOutcomeEvent, NotificationService, CoreAutomationService } from '@alfresco/adf-core';
import { InMemoryFormService } from '../../services/in-memory-form.service';
-import { Subscription } from 'rxjs';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-form',
@@ -35,7 +36,6 @@ export class FormComponent implements OnInit, OnDestroy {
errorFields: FormFieldModel[] = [];
formConfig: string;
editor: any;
- private subscriptions: Subscription[] = [];
editorOptions = {
theme: 'vs-dark',
@@ -46,15 +46,11 @@ export class FormComponent implements OnInit, OnDestroy {
automaticLayout: true
};
+ private onDestroy$ = new Subject();
+
constructor(@Inject(FormService) private formService: InMemoryFormService,
private notificationService: NotificationService,
private automationService: CoreAutomationService) {
-
- this.subscriptions.push(
- formService.executeOutcome.subscribe((formOutcomeEvent: FormOutcomeEvent) => {
- formOutcomeEvent.preventDefault();
- })
- );
}
logErrors(errorFields: FormFieldModel[]) {
@@ -62,13 +58,21 @@ export class FormComponent implements OnInit, OnDestroy {
}
ngOnInit() {
- this.formConfig = JSON.stringify(this.automationService.forms.getFormDefinition());
+ this.formService.executeOutcome
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe((formOutcomeEvent: FormOutcomeEvent) => {
+ formOutcomeEvent.preventDefault();
+ });
+
+ this.formConfig = JSON.stringify(
+ this.automationService.forms.getFormDefinition()
+ );
this.parseForm();
}
ngOnDestroy() {
- this.subscriptions.forEach((subscription) => subscription.unsubscribe());
- this.subscriptions = [];
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
onInitFormEditor(editor) {
diff --git a/demo-shell/src/app/components/header-data/header-data.service.ts b/demo-shell/src/app/components/header-data/header-data.service.ts
index 33eda6d066..6977549479 100644
--- a/demo-shell/src/app/components/header-data/header-data.service.ts
+++ b/demo-shell/src/app/components/header-data/header-data.service.ts
@@ -24,14 +24,14 @@ export class HeaderDataService {
show = true;
- @Output() hideMenu: EventEmitter = new EventEmitter();
- @Output() color: EventEmitter = new EventEmitter();
- @Output() title: EventEmitter = new EventEmitter();
- @Output() logo: EventEmitter = new EventEmitter();
- @Output() redirectUrl: EventEmitter = new EventEmitter();
- @Output() tooltip: EventEmitter = new EventEmitter();
- @Output() position: EventEmitter = new EventEmitter();
- @Output() hideSidenav: EventEmitter = new EventEmitter();
+ @Output() hideMenu = new EventEmitter();
+ @Output() color = new EventEmitter();
+ @Output() title = new EventEmitter();
+ @Output() logo = new EventEmitter();
+ @Output() redirectUrl = new EventEmitter();
+ @Output() tooltip = new EventEmitter();
+ @Output() position = new EventEmitter();
+ @Output() hideSidenav = new EventEmitter();
hideMenuButton() {
this.show = !this.show;
@@ -59,11 +59,11 @@ export class HeaderDataService {
this.tooltip.emit(tooltip);
}
- changePosition(position) {
+ changePosition(position: string) {
this.position.emit(position);
}
- changeSidenavVisibility(hideSidenav) {
+ changeSidenavVisibility(hideSidenav: boolean) {
this.hideSidenav.emit(hideSidenav);
}
}
diff --git a/demo-shell/src/app/components/log/log.component.ts b/demo-shell/src/app/components/log/log.component.ts
index 5ea521fe35..a86105c665 100644
--- a/demo-shell/src/app/components/log/log.component.ts
+++ b/demo-shell/src/app/components/log/log.component.ts
@@ -15,36 +15,57 @@
* limitations under the License.
*/
-import { Component, HostListener } from '@angular/core';
+import { Component, HostListener, OnDestroy, OnInit } from '@angular/core';
import { LogService, ObjectDataTableAdapter } from '@alfresco/adf-core';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-log',
templateUrl: './log.component.html',
styleUrls: ['./log.component.css']
})
-export class LogComponent {
+export class LogComponent implements OnInit, OnDestroy {
logs: any[] = [];
show = false;
ctrlLKey = 12;
logsData: ObjectDataTableAdapter;
- constructor(public logService: LogService) {
+ private onDestroy$ = new Subject();
- logService.onMessage.subscribe((message) => {
- let contentMessage = '';
- try {
- contentMessage = JSON.stringify(message.text);
- } catch (error) {
- return;
- }
- this.logs.push({ type: message.type, text: contentMessage});
- this.logsData = new ObjectDataTableAdapter(this.logs, [
- { type: 'text', key: 'type', title: 'Log level', sortable: true },
- { type: 'text', key: 'text', title: 'Message', sortable: false }
- ]);
+ constructor(public logService: LogService) {}
- });
+ ngOnInit() {
+ this.logService.onMessage
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(message => {
+ let contentMessage = '';
+ try {
+ contentMessage = JSON.stringify(message.text);
+ } catch (error) {
+ return;
+ }
+ this.logs.push({ type: message.type, text: contentMessage });
+ this.logsData = new ObjectDataTableAdapter(this.logs, [
+ {
+ type: 'text',
+ key: 'type',
+ title: 'Log level',
+ sortable: true
+ },
+ {
+ type: 'text',
+ key: 'text',
+ title: 'Message',
+ sortable: false
+ }
+ ]);
+ });
+ }
+
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
@HostListener('document:keypress', ['$event'])
@@ -54,6 +75,5 @@ export class LogComponent {
if (key === this.ctrlLKey) {
this.show = !this.show;
}
-
}
}
diff --git a/demo-shell/src/app/components/notifications/notifications.component.ts b/demo-shell/src/app/components/notifications/notifications.component.ts
index 2c2074bd8d..44fee12a70 100644
--- a/demo-shell/src/app/components/notifications/notifications.component.ts
+++ b/demo-shell/src/app/components/notifications/notifications.component.ts
@@ -15,16 +15,18 @@
* limitations under the License.
*/
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, OnDestroy } from '@angular/core';
import { NotificationService } from '@alfresco/adf-core';
import { MatSnackBarConfig } from '@angular/material';
import { FormBuilder, FormGroup, FormControl } from '@angular/forms';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
templateUrl: './notifications.component.html',
styleUrls: ['./notifications.component.scss']
})
-export class NotificationsComponent implements OnInit {
+export class NotificationsComponent implements OnInit, OnDestroy {
message = 'I ♥️ ADF';
withAction = false;
@@ -55,6 +57,8 @@ export class NotificationsComponent implements OnInit {
defaultDuration = 20000;
+ private onDestroy$ = new Subject();
+
constructor(private notificationService: NotificationService,
private formBuilder: FormBuilder) {
this.snackBarConfig.duration = this.defaultDuration;
@@ -69,10 +73,15 @@ export class NotificationsComponent implements OnInit {
});
this.configForm.valueChanges
- .subscribe((configFormValues) =>
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(configFormValues =>
this.setSnackBarConfig(configFormValues)
);
+ }
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
setSnackBarConfig(configFormValues: any) {
diff --git a/demo-shell/src/app/components/permissions/demo-permissions.component.ts b/demo-shell/src/app/components/permissions/demo-permissions.component.ts
index d40bc426e0..321357dc3d 100644
--- a/demo-shell/src/app/components/permissions/demo-permissions.component.ts
+++ b/demo-shell/src/app/components/permissions/demo-permissions.component.ts
@@ -48,9 +48,11 @@ export class DemoPermissionComponent implements OnInit {
}
});
}
- this.nodeService.getNode(this.nodeId, {include: ['permissions'] }).subscribe( (currentNode: MinimalNodeEntryEntity) => {
- this.toggleStatus = currentNode.permissions.isInheritanceEnabled;
- });
+ this.nodeService
+ .getNode(this.nodeId, {include: ['permissions'] })
+ .subscribe( (currentNode: MinimalNodeEntryEntity) => {
+ this.toggleStatus = currentNode.permissions.isInheritanceEnabled;
+ });
}
onUpdatedPermissions(node: MinimalNodeEntryEntity) {
@@ -63,9 +65,12 @@ export class DemoPermissionComponent implements OnInit {
}
openAddPermissionDialog(event: Event) {
- this.nodePermissionDialogService.updateNodePermissionByDialog(this.nodeId).subscribe(
- () => this.displayPermissionComponent.reload(),
- (error) => this.showErrorMessage(error));
+ this.nodePermissionDialogService
+ .updateNodePermissionByDialog(this.nodeId)
+ .subscribe(
+ () => this.displayPermissionComponent.reload(),
+ (error) => this.showErrorMessage(error)
+ );
}
showErrorMessage(error) {
diff --git a/demo-shell/src/app/components/pipes/pipes.component.html b/demo-shell/src/app/components/pipes/pipes.component.html
new file mode 100644
index 0000000000..9018e2d5a9
--- /dev/null
+++ b/demo-shell/src/app/components/pipes/pipes.component.html
@@ -0,0 +1,109 @@
+ADF Pipes
+
+
+
+
+
+ Localized dates
+
+
+ adfLocalizedDate
+
+
+
+
+
+
+
+
+
+
+ {{language.label}}
+
+
+
+
+ AdfLocalizedDate Pipe - Default
+ {{ today | adfLocalizedDate }}
+
+ AdfLocalizedDate Pipe - Custom format
+ {{ today | adfLocalizedDate : format }}
+
+ AdfLocalizedDate Pipe - Custom format and locale
+ {{ today | adfLocalizedDate : format : locale }}
+
+
+
+
+
+ Time ago
+
+
+ adfTimeAgo
+
+
+
+
+
+
+
+
+
+
+ {{language.label}}
+
+
+
+ AdfTimeAgo Pipe - Default
+ {{ today | adfTimeAgo }}
+
+ AdfTimeAgo Pipe - Custom locale
+ {{ today | adfTimeAgo : locale}}
+
+
+
+
+
+ Decimal numbers
+
+
+ adfDecimalNumber
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{language.label}}
+
+
+
+
+ AdfDecimalNumber Pipe - Default
+ {{ number | adfDecimalNumber }}
+
+ AdfDecimalNumber Pipe - Custom digits config
+ {{ number | adfDecimalNumber : decimalValues }}
+
+ AdfDecimalNumber Pipe - Custom locale
+ {{ number | adfDecimalNumber : {} : locale }}
+
+ AdfDecimalNumber Pipe - Custom digits config and locale
+ {{ number | adfDecimalNumber : decimalValues : locale }}
+
+
+
+
diff --git a/demo-shell/src/app/components/pipes/pipes.component.scss b/demo-shell/src/app/components/pipes/pipes.component.scss
new file mode 100644
index 0000000000..9ed9b6f6a6
--- /dev/null
+++ b/demo-shell/src/app/components/pipes/pipes.component.scss
@@ -0,0 +1,7 @@
+h2 {
+ padding: 20px;
+}
+
+.adf-input-field {
+ margin: 20px;
+}
diff --git a/demo-shell/src/app/components/date/date.component.ts b/demo-shell/src/app/components/pipes/pipes.component.ts
similarity index 75%
rename from demo-shell/src/app/components/date/date.component.ts
rename to demo-shell/src/app/components/pipes/pipes.component.ts
index 372621d1d6..5d10e99419 100644
--- a/demo-shell/src/app/components/date/date.component.ts
+++ b/demo-shell/src/app/components/pipes/pipes.component.ts
@@ -19,15 +19,21 @@ import { Component } from '@angular/core';
import { AppConfigService } from '@alfresco/adf-core';
@Component({
- selector: 'app-date-page',
- templateUrl: './date.component.html',
- styleUrls: ['date.component.scss']
+ selector: 'app-pipes-page',
+ templateUrl: './pipes.component.html',
+ styleUrls: ['pipes.component.scss']
})
-export class DateComponent {
+export class PipesComponent {
today = new Date();
locale: string;
format: string;
+ number = 12345.56;
+ decimalValues = {
+ minIntegerDigits: undefined,
+ minFractionDigits: undefined,
+ maxFractionDigits: undefined
+ };
languages: any[];
constructor(private appConfig: AppConfigService) {
diff --git a/demo-shell/src/app/components/date/date.module.ts b/demo-shell/src/app/components/pipes/pipes.module.ts
similarity index 86%
rename from demo-shell/src/app/components/date/date.module.ts
rename to demo-shell/src/app/components/pipes/pipes.module.ts
index 84d757f2d4..38d2822b4d 100644
--- a/demo-shell/src/app/components/date/date.module.ts
+++ b/demo-shell/src/app/components/pipes/pipes.module.ts
@@ -17,14 +17,14 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
-import { DateComponent } from './date.component';
+import { PipesComponent } from './pipes.component';
import { CommonModule } from '@angular/common';
import { CoreModule } from '@alfresco/adf-core';
const routes: Routes = [
{
path: '',
- component: DateComponent
+ component: PipesComponent
}
];
@@ -34,6 +34,6 @@ const routes: Routes = [
CoreModule.forChild(),
RouterModule.forChild(routes)
],
- declarations: [DateComponent]
+ declarations: [PipesComponent]
})
-export class AppDateModule {}
+export class AppPipesModule {}
diff --git a/demo-shell/src/app/components/process-list-demo/process-list-demo.component.ts b/demo-shell/src/app/components/process-list-demo/process-list-demo.component.ts
index 76d46f6892..518fbca260 100644
--- a/demo-shell/src/app/components/process-list-demo/process-list-demo.component.ts
+++ b/demo-shell/src/app/components/process-list-demo/process-list-demo.component.ts
@@ -15,17 +15,18 @@
* limitations under the License.
*/
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl, AbstractControl } from '@angular/forms';
import { ActivatedRoute, Params } from '@angular/router';
-import { debounceTime } from 'rxjs/operators';
+import { debounceTime, takeUntil } from 'rxjs/operators';
+import { Subject } from 'rxjs';
@Component({
templateUrl: './process-list-demo.component.html',
styleUrls: [`./process-list-demo.component.scss`]
})
-export class ProcessListDemoComponent implements OnInit {
+export class ProcessListDemoComponent implements OnInit, OnDestroy {
DEFAULT_SIZE = 20;
@@ -54,6 +55,8 @@ export class ProcessListDemoComponent implements OnInit {
{value: 'created-desc', title: 'Created (desc)'}
];
+ private onDestroy$ = new Subject();
+
constructor(private route: ActivatedRoute,
private formBuilder: FormBuilder) {
}
@@ -72,6 +75,11 @@ export class ProcessListDemoComponent implements OnInit {
this.buildForm();
}
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
+ }
+
buildForm() {
this.processListForm = this.formBuilder.group({
processAppId: new FormControl(this.appId, [Validators.pattern('^[0-9]*$'), Validators.min(this.minValue)]),
@@ -84,10 +92,9 @@ export class ProcessListDemoComponent implements OnInit {
});
this.processListForm.valueChanges
- .pipe(
- debounceTime(500)
- )
- .subscribe((processFilter) => {
+ .pipe(takeUntil(this.onDestroy$))
+ .pipe(debounceTime(500))
+ .subscribe(processFilter => {
if (this.isFormValid()) {
this.filterProcesses(processFilter);
}
diff --git a/demo-shell/src/app/components/process-service/form-node-viewer.component.ts b/demo-shell/src/app/components/process-service/form-node-viewer.component.ts
index 9311e344cb..245dd835d0 100644
--- a/demo-shell/src/app/components/process-service/form-node-viewer.component.ts
+++ b/demo-shell/src/app/components/process-service/form-node-viewer.component.ts
@@ -15,32 +15,25 @@
* limitations under the License.
*/
-import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
-import { Subscription } from 'rxjs';
@Component({
selector: 'app-form-node-viewer',
templateUrl: './form-node-viewer.component.html',
styleUrls: ['./form-node-viewer.component.css']
})
-export class FormNodeViewerComponent implements OnInit, OnDestroy {
+export class FormNodeViewerComponent implements OnInit {
nodeId: string;
- private sub: Subscription;
-
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
- this.sub = this.route.params.subscribe((params) => {
+ this.route.params.subscribe((params) => {
this.nodeId = params['id'];
});
}
- ngOnDestroy() {
- this.sub.unsubscribe();
- }
-
}
diff --git a/demo-shell/src/app/components/process-service/form-viewer.component.ts b/demo-shell/src/app/components/process-service/form-viewer.component.ts
index b2d1e8f61f..496dcb2993 100644
--- a/demo-shell/src/app/components/process-service/form-viewer.component.ts
+++ b/demo-shell/src/app/components/process-service/form-viewer.component.ts
@@ -15,9 +15,8 @@
* limitations under the License.
*/
-import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
-import { Subscription } from 'rxjs';
import { Params } from '@angular/router/src/shared';
@Component({
@@ -25,23 +24,16 @@ import { Params } from '@angular/router/src/shared';
templateUrl: './form-viewer.component.html',
styleUrls: ['./form-viewer.component.css']
})
-export class FormViewerComponent implements OnInit, OnDestroy {
+export class FormViewerComponent implements OnInit {
taskId: string;
- private sub: Subscription;
-
constructor(private route: ActivatedRoute) {
}
ngOnInit() {
- this.sub = this.route.params.subscribe((params: Params) => {
+ this.route.params.subscribe((params: Params) => {
this.taskId = params['id'];
});
}
-
- ngOnDestroy() {
- this.sub.unsubscribe();
- }
-
}
diff --git a/demo-shell/src/app/components/process-service/process-attachments.component.ts b/demo-shell/src/app/components/process-service/process-attachments.component.ts
index 7012cedf56..f79897f07a 100644
--- a/demo-shell/src/app/components/process-service/process-attachments.component.ts
+++ b/demo-shell/src/app/components/process-service/process-attachments.component.ts
@@ -22,7 +22,8 @@ import { UploadService } from '@alfresco/adf-core';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { AppConfigService } from '@alfresco/adf-core';
import { PreviewService } from '../../services/preview.service';
-import { Subscription } from 'rxjs';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
export function processUploadServiceFactory(api: AlfrescoApiService, config: AppConfigService) {
return new ProcessUploadService(api, config);
@@ -51,7 +52,7 @@ export class ProcessAttachmentsComponent implements OnInit, OnChanges, OnDestroy
processInstance: ProcessInstance;
- private subscriptions: Subscription[] = [];
+ private onDestroy$ = new Subject();
constructor(
private uploadService: UploadService,
@@ -60,11 +61,9 @@ export class ProcessAttachmentsComponent implements OnInit, OnChanges, OnDestroy
) {}
ngOnInit() {
- this.subscriptions.push(
- this.uploadService.fileUploadComplete.subscribe(
- (value) => this.onFileUploadComplete(value.data)
- )
- );
+ this.uploadService.fileUploadComplete
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(value => this.onFileUploadComplete(value.data));
}
ngOnChanges() {
@@ -77,8 +76,8 @@ export class ProcessAttachmentsComponent implements OnInit, OnChanges, OnDestroy
}
ngOnDestroy() {
- this.subscriptions.forEach((subscription) => subscription.unsubscribe());
- this.subscriptions = [];
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
onFileUploadComplete(content: any) {
diff --git a/demo-shell/src/app/components/process-service/process-service.component.scss b/demo-shell/src/app/components/process-service/process-service.component.scss
index cb6ee5e4cc..e72b969d66 100644
--- a/demo-shell/src/app/components/process-service/process-service.component.scss
+++ b/demo-shell/src/app/components/process-service/process-service.component.scss
@@ -93,11 +93,6 @@
align-items: center;
}
- .mat-expansion-panel-header.mat-expanded .mat-expansion-panel-header-title {
- color: mat-color($primary);
- opacity: 1;
- }
-
.adf-accordion-title-padding {
padding-left: 20px;
}
diff --git a/demo-shell/src/app/components/process-service/process-service.component.ts b/demo-shell/src/app/components/process-service/process-service.component.ts
index 1d94f49d57..46c45a065e 100644
--- a/demo-shell/src/app/components/process-service/process-service.component.ts
+++ b/demo-shell/src/app/components/process-service/process-service.component.ts
@@ -35,7 +35,7 @@ import {
UserProcessInstanceFilterRepresentation
} from '@alfresco/js-api';
import {
- FORM_FIELD_VALIDATORS, FormEvent, FormFieldEvent, FormRenderingService, FormService,
+ FORM_FIELD_VALIDATORS, FormRenderingService, FormService,
DynamicTableRow, ValidateDynamicTableRowEvent, AppConfigService, PaginationComponent, UserPreferenceValues
} from '@alfresco/adf-core';
@@ -57,12 +57,13 @@ import {
TaskListComponent
} from '@alfresco/adf-process-services';
import { LogService } from '@alfresco/adf-core';
-import { AlfrescoApiService, UserPreferencesService, ValidateFormEvent } from '@alfresco/adf-core';
-import { Subscription } from 'rxjs';
+import { AlfrescoApiService, UserPreferencesService } from '@alfresco/adf-core';
+import { Subject } from 'rxjs';
import { /*CustomEditorComponent*/ CustomStencil01 } from './custom-editor/custom-editor.component';
import { DemoFieldValidator } from './demo-field-validator';
import { PreviewService } from '../../services/preview.service';
import { Location } from '@angular/common';
+import { takeUntil } from 'rxjs/operators';
const currentProcessIdNew = '__NEW__';
const currentTaskIdNew = '__NEW__';
@@ -160,7 +161,7 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
new DemoFieldValidator()
];
- private subscriptions: Subscription[] = [];
+ private onDestroy$ = new Subject();
constructor(private elementRef: ElementRef,
private route: ActivatedRoute,
@@ -184,17 +185,28 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
// Uncomment this line to map 'custom_stencil_01' to local editor component
formRenderingService.setComponentTypeResolver('custom_stencil_01', () => CustomStencil01, true);
- this.subscriptions.push(
- formService.formLoaded.subscribe((formEvent: FormEvent) => {
+ formService.formLoaded
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(formEvent => {
this.logService.log(`Form loaded: ${formEvent.form.id}`);
- }),
- formService.formFieldValueChanged.subscribe((formFieldEvent: FormFieldEvent) => {
+ });
+
+ formService.formFieldValueChanged
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(formFieldEvent => {
this.logService.log(`Field value changed. Form: ${formFieldEvent.form.id}, Field: ${formFieldEvent.field.id}, Value: ${formFieldEvent.field.value}`);
- }),
- this.preferenceService.select(UserPreferenceValues.PaginationSize).subscribe((pageSize) => {
+ });
+
+ this.preferenceService
+ .select(UserPreferenceValues.PaginationSize)
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe((pageSize) => {
this.paginationPageSize = pageSize;
- }),
- formService.validateDynamicTableRow.subscribe(
+ });
+
+ formService.validateDynamicTableRow
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(
(validateDynamicTableRowEvent: ValidateDynamicTableRowEvent) => {
const row: DynamicTableRow = validateDynamicTableRowEvent.row;
if (row && row.value && row.value.name === 'admin') {
@@ -203,23 +215,28 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
validateDynamicTableRowEvent.preventDefault();
}
}
- ),
+ );
- formService.formContentClicked.subscribe((content) => {
+ formService.formContentClicked
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe((content) => {
this.showContentPreview(content);
- }),
+ });
- formService.validateForm.subscribe((validateFormEvent: ValidateFormEvent) => {
+ formService.validateForm
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(validateFormEvent => {
this.logService.log('Error form:' + validateFormEvent.errorsField);
- })
- );
+ });
// Uncomment this block to see form event handling in action
/*
- formService.formEvents.subscribe((event: Event) => {
- this.logService.log('Event fired:' + event.type);
- this.logService.log('Event Target:' + event.target);
- });
+ formService.formEvents
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe((event: Event) => {
+ this.logService.log('Event fired:' + event.type);
+ this.logService.log('Event Target:' + event.target);
+ });
*/
}
@@ -247,8 +264,8 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
}
ngOnDestroy() {
- this.subscriptions.forEach((subscription) => subscription.unsubscribe());
- this.subscriptions = [];
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
onTaskFilterClick(filter: FilterRepresentationModel): void {
diff --git a/demo-shell/src/app/components/process-service/task-attachments.component.ts b/demo-shell/src/app/components/process-service/task-attachments.component.ts
index f235452b58..47a114d697 100644
--- a/demo-shell/src/app/components/process-service/task-attachments.component.ts
+++ b/demo-shell/src/app/components/process-service/task-attachments.component.ts
@@ -19,12 +19,13 @@ import { Component, Input, OnChanges, OnInit, ViewChild, OnDestroy } from '@angu
import {
TaskListService,
TaskAttachmentListComponent,
- TaskDetailsModel,
- TaskUploadService
+ TaskUploadService,
+ TaskDetailsModel
} from '@alfresco/adf-process-services';
-import { UploadService, AlfrescoApiService, AppConfigService, FileUploadCompleteEvent } from '@alfresco/adf-core';
+import { UploadService, AlfrescoApiService, AppConfigService } from '@alfresco/adf-core';
import { PreviewService } from '../../services/preview.service';
-import { Subscription } from 'rxjs';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
export function taskUploadServiceFactory(api: AlfrescoApiService, config: AppConfigService) {
return new TaskUploadService(api, config);
@@ -51,9 +52,9 @@ export class TaskAttachmentsComponent implements OnInit, OnChanges, OnDestroy {
@Input()
taskId: string;
- taskDetails: any;
+ taskDetails: TaskDetailsModel;
- private subscriptions: Subscription[] = [];
+ private onDestroy$ = new Subject();
constructor(
private uploadService: UploadService,
@@ -62,25 +63,22 @@ export class TaskAttachmentsComponent implements OnInit, OnChanges, OnDestroy {
}
ngOnInit() {
- this.subscriptions.push(
- this.uploadService.fileUploadComplete.subscribe(
- (fileUploadCompleteEvent: FileUploadCompleteEvent) => this.onFileUploadComplete(fileUploadCompleteEvent.data)
- )
- );
+ this.uploadService.fileUploadComplete
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(event => this.onFileUploadComplete(event.data));
}
ngOnChanges() {
if (this.taskId) {
- this.activitiTaskList.getTaskDetails(this.taskId)
- .subscribe((taskDetails: TaskDetailsModel) => {
- this.taskDetails = taskDetails;
- });
+ this.activitiTaskList
+ .getTaskDetails(this.taskId)
+ .subscribe(taskDetails => this.taskDetails = taskDetails);
}
}
ngOnDestroy() {
- this.subscriptions.forEach((subscription) => subscription.unsubscribe());
- this.subscriptions = [];
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
onFileUploadComplete(content: any) {
diff --git a/demo-shell/src/app/components/search/search-result.component.ts b/demo-shell/src/app/components/search/search-result.component.ts
index 075a9f64a3..13f0870ec4 100644
--- a/demo-shell/src/app/components/search/search-result.component.ts
+++ b/demo-shell/src/app/components/search/search-result.component.ts
@@ -20,7 +20,8 @@ import { Router, ActivatedRoute, Params } from '@angular/router';
import { NodePaging, Pagination, ResultSetPaging } from '@alfresco/js-api';
import { SearchQueryBuilderService } from '@alfresco/adf-content-services';
import { UserPreferencesService, SearchService, AppConfigService } from '@alfresco/adf-core';
-import { Subscription } from 'rxjs';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'app-search-result-component',
@@ -38,7 +39,7 @@ export class SearchResultComponent implements OnInit, OnDestroy {
sorting = ['name', 'asc'];
- private subscriptions: Subscription[] = [];
+ private onDestroy$ = new Subject();
constructor(public router: Router,
private config: AppConfigService,
@@ -55,19 +56,21 @@ export class SearchResultComponent implements OnInit, OnDestroy {
this.sorting = this.getSorting();
- this.subscriptions.push(
- this.queryBuilder.updated.subscribe(() => {
+ this.queryBuilder.updated
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(() => {
this.sorting = this.getSorting();
this.isLoading = true;
- }),
+ });
- this.queryBuilder.executed.subscribe((resultSetPaging: ResultSetPaging) => {
+ this.queryBuilder.executed
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe((resultSetPaging: ResultSetPaging) => {
this.queryBuilder.paging.skipCount = 0;
this.onSearchResultLoaded(resultSetPaging);
this.isLoading = false;
- })
- );
+ });
if (this.route) {
this.route.params.forEach((params: Params) => {
@@ -102,8 +105,8 @@ export class SearchResultComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
- this.subscriptions.forEach((subscription) => subscription.unsubscribe());
- this.subscriptions = [];
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
onSearchResultLoaded(resultSetPaging: ResultSetPaging) {
diff --git a/demo-shell/src/app/components/task-list-demo/task-list-demo.component.ts b/demo-shell/src/app/components/task-list-demo/task-list-demo.component.ts
index d93624ed7f..061bafae13 100644
--- a/demo-shell/src/app/components/task-list-demo/task-list-demo.component.ts
+++ b/demo-shell/src/app/components/task-list-demo/task-list-demo.component.ts
@@ -15,11 +15,12 @@
* limitations under the License.
*/
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, OnDestroy } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl, AbstractControl } from '@angular/forms';
import { ActivatedRoute, Params } from '@angular/router';
-import { debounceTime } from 'rxjs/operators';
+import { debounceTime, takeUntil } from 'rxjs/operators';
import moment from 'moment-es6';
+import { Subject } from 'rxjs';
@Component({
selector: 'app-task-list-demo',
@@ -27,7 +28,7 @@ import moment from 'moment-es6';
styleUrls: [`./task-list-demo.component.scss`]
})
-export class TaskListDemoComponent implements OnInit {
+export class TaskListDemoComponent implements OnInit, OnDestroy {
DEFAULT_SIZE = 20;
taskListForm: FormGroup;
@@ -75,6 +76,8 @@ export class TaskListDemoComponent implements OnInit {
{value: 'due-desc', title: 'Due (desc)'}
];
+ private onDestroy$ = new Subject();
+
constructor(private route: ActivatedRoute,
private formBuilder: FormBuilder) {
}
@@ -94,6 +97,11 @@ export class TaskListDemoComponent implements OnInit {
this.buildForm();
}
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
+ }
+
buildForm() {
this.taskListForm = this.formBuilder.group({
taskAppId: new FormControl(this.defaultAppId, [Validators.pattern('^[0-9]*$')]),
@@ -114,9 +122,10 @@ export class TaskListDemoComponent implements OnInit {
this.taskListForm.valueChanges
.pipe(
- debounceTime(500)
+ debounceTime(500),
+ takeUntil(this.onDestroy$)
)
- .subscribe((taskFilter) => {
+ .subscribe(taskFilter => {
if (this.isFormValid()) {
this.filterTasks(taskFilter);
}
diff --git a/demo-shell/src/app/components/trashcan/trashcan.component.ts b/demo-shell/src/app/components/trashcan/trashcan.component.ts
index 7183417bb4..e94f3794ea 100644
--- a/demo-shell/src/app/components/trashcan/trashcan.component.ts
+++ b/demo-shell/src/app/components/trashcan/trashcan.component.ts
@@ -15,32 +15,42 @@
* limitations under the License.
*/
-import { Component, ViewChild } from '@angular/core';
+import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core';
import { DocumentListComponent } from '@alfresco/adf-content-services';
import { UserPreferencesService, UserPreferenceValues, RestoreMessageModel, NotificationService } from '@alfresco/adf-core';
import { Router } from '@angular/router';
import { PathInfoEntity } from '@alfresco/js-api';
+import { Subject } from 'rxjs';
+import { takeUntil } from 'rxjs/operators';
@Component({
templateUrl: './trashcan.component.html',
styleUrls: ['trashcan.component.scss']
})
-export class TrashcanComponent {
+export class TrashcanComponent implements OnInit, OnDestroy {
@ViewChild('documentList')
documentList: DocumentListComponent;
currentLocale;
+ private onDestroy$ = new Subject();
+
constructor(
private preference: UserPreferencesService,
private router: Router,
- private notificationService: NotificationService
- ) {
+ private notificationService: NotificationService) {
+ }
+
+ ngOnInit() {
this.preference
.select(UserPreferenceValues.Locale)
- .subscribe((locale) => {
- this.currentLocale = locale;
- });
+ .pipe(takeUntil(this.onDestroy$))
+ .subscribe(locale => this.currentLocale = locale);
+ }
+
+ ngOnDestroy() {
+ this.onDestroy$.next(true);
+ this.onDestroy$.complete();
}
onRestore(restoreMessage: RestoreMessageModel) {
diff --git a/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.eot b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.eot
new file mode 100755
index 0000000000..70508ebabc
Binary files /dev/null and b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.eot differ
diff --git a/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.ijmap b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.ijmap
new file mode 100755
index 0000000000..d9f1d259f3
--- /dev/null
+++ b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.ijmap
@@ -0,0 +1 @@
+{"icons":{"e84d":{"name":"3d Rotation"},"eb3b":{"name":"Ac Unit"},"e190":{"name":"Access Alarm"},"e191":{"name":"Access Alarms"},"e192":{"name":"Access Time"},"e84e":{"name":"Accessibility"},"e914":{"name":"Accessible"},"e84f":{"name":"Account Balance"},"e850":{"name":"Account Balance Wallet"},"e851":{"name":"Account Box"},"e853":{"name":"Account Circle"},"e60e":{"name":"Adb"},"e145":{"name":"Add"},"e439":{"name":"Add A Photo"},"e193":{"name":"Add Alarm"},"e003":{"name":"Add Alert"},"e146":{"name":"Add Box"},"e147":{"name":"Add Circle"},"e148":{"name":"Add Circle Outline"},"e567":{"name":"Add Location"},"e854":{"name":"Add Shopping Cart"},"e39d":{"name":"Add To Photos"},"e05c":{"name":"Add To Queue"},"e39e":{"name":"Adjust"},"e630":{"name":"Airline Seat Flat"},"e631":{"name":"Airline Seat Flat Angled"},"e632":{"name":"Airline Seat Individual Suite"},"e633":{"name":"Airline Seat Legroom Extra"},"e634":{"name":"Airline Seat Legroom Normal"},"e635":{"name":"Airline Seat Legroom Reduced"},"e636":{"name":"Airline Seat Recline Extra"},"e637":{"name":"Airline Seat Recline Normal"},"e195":{"name":"Airplanemode Active"},"e194":{"name":"Airplanemode Inactive"},"e055":{"name":"Airplay"},"eb3c":{"name":"Airport Shuttle"},"e855":{"name":"Alarm"},"e856":{"name":"Alarm Add"},"e857":{"name":"Alarm Off"},"e858":{"name":"Alarm On"},"e019":{"name":"Album"},"eb3d":{"name":"All Inclusive"},"e90b":{"name":"All Out"},"e859":{"name":"Android"},"e85a":{"name":"Announcement"},"e5c3":{"name":"Apps"},"e149":{"name":"Archive"},"e5c4":{"name":"Arrow Back"},"e5db":{"name":"Arrow Downward"},"e5c5":{"name":"Arrow Drop Down"},"e5c6":{"name":"Arrow Drop Down Circle"},"e5c7":{"name":"Arrow Drop Up"},"e5c8":{"name":"Arrow Forward"},"e5d8":{"name":"Arrow Upward"},"e060":{"name":"Art Track"},"e85b":{"name":"Aspect Ratio"},"e85c":{"name":"Assessment"},"e85d":{"name":"Assignment"},"e85e":{"name":"Assignment Ind"},"e85f":{"name":"Assignment Late"},"e860":{"name":"Assignment Return"},"e861":{"name":"Assignment Returned"},"e862":{"name":"Assignment Turned In"},"e39f":{"name":"Assistant"},"e3a0":{"name":"Assistant Photo"},"e226":{"name":"Attach File"},"e227":{"name":"Attach Money"},"e2bc":{"name":"Attachment"},"e3a1":{"name":"Audiotrack"},"e863":{"name":"Autorenew"},"e01b":{"name":"Av Timer"},"e14a":{"name":"Backspace"},"e864":{"name":"Backup"},"e19c":{"name":"Battery Alert"},"e1a3":{"name":"Battery Charging Full"},"e1a4":{"name":"Battery Full"},"e1a5":{"name":"Battery Std"},"e1a6":{"name":"Battery Unknown"},"eb3e":{"name":"Beach Access"},"e52d":{"name":"Beenhere"},"e14b":{"name":"Block"},"e1a7":{"name":"Bluetooth"},"e60f":{"name":"Bluetooth Audio"},"e1a8":{"name":"Bluetooth Connected"},"e1a9":{"name":"Bluetooth Disabled"},"e1aa":{"name":"Bluetooth Searching"},"e3a2":{"name":"Blur Circular"},"e3a3":{"name":"Blur Linear"},"e3a4":{"name":"Blur Off"},"e3a5":{"name":"Blur On"},"e865":{"name":"Book"},"e866":{"name":"Bookmark"},"e867":{"name":"Bookmark Border"},"e228":{"name":"Border All"},"e229":{"name":"Border Bottom"},"e22a":{"name":"Border Clear"},"e22b":{"name":"Border Color"},"e22c":{"name":"Border Horizontal"},"e22d":{"name":"Border Inner"},"e22e":{"name":"Border Left"},"e22f":{"name":"Border Outer"},"e230":{"name":"Border Right"},"e231":{"name":"Border Style"},"e232":{"name":"Border Top"},"e233":{"name":"Border Vertical"},"e06b":{"name":"Branding Watermark"},"e3a6":{"name":"Brightness 1"},"e3a7":{"name":"Brightness 2"},"e3a8":{"name":"Brightness 3"},"e3a9":{"name":"Brightness 4"},"e3aa":{"name":"Brightness 5"},"e3ab":{"name":"Brightness 6"},"e3ac":{"name":"Brightness 7"},"e1ab":{"name":"Brightness Auto"},"e1ac":{"name":"Brightness High"},"e1ad":{"name":"Brightness Low"},"e1ae":{"name":"Brightness Medium"},"e3ad":{"name":"Broken Image"},"e3ae":{"name":"Brush"},"e6dd":{"name":"Bubble Chart"},"e868":{"name":"Bug Report"},"e869":{"name":"Build"},"e43c":{"name":"Burst Mode"},"e0af":{"name":"Business"},"eb3f":{"name":"Business Center"},"e86a":{"name":"Cached"},"e7e9":{"name":"Cake"},"e0b0":{"name":"Call"},"e0b1":{"name":"Call End"},"e0b2":{"name":"Call Made"},"e0b3":{"name":"Call Merge"},"e0b4":{"name":"Call Missed"},"e0e4":{"name":"Call Missed Outgoing"},"e0b5":{"name":"Call Received"},"e0b6":{"name":"Call Split"},"e06c":{"name":"Call To Action"},"e3af":{"name":"Camera"},"e3b0":{"name":"Camera Alt"},"e8fc":{"name":"Camera Enhance"},"e3b1":{"name":"Camera Front"},"e3b2":{"name":"Camera Rear"},"e3b3":{"name":"Camera Roll"},"e5c9":{"name":"Cancel"},"e8f6":{"name":"Card Giftcard"},"e8f7":{"name":"Card Membership"},"e8f8":{"name":"Card Travel"},"eb40":{"name":"Casino"},"e307":{"name":"Cast"},"e308":{"name":"Cast Connected"},"e3b4":{"name":"Center Focus Strong"},"e3b5":{"name":"Center Focus Weak"},"e86b":{"name":"Change History"},"e0b7":{"name":"Chat"},"e0ca":{"name":"Chat Bubble"},"e0cb":{"name":"Chat Bubble Outline"},"e5ca":{"name":"Check"},"e834":{"name":"Check Box"},"e835":{"name":"Check Box Outline Blank"},"e86c":{"name":"Check Circle"},"e5cb":{"name":"Chevron Left"},"e5cc":{"name":"Chevron Right"},"eb41":{"name":"Child Care"},"eb42":{"name":"Child Friendly"},"e86d":{"name":"Chrome Reader Mode"},"e86e":{"name":"Class"},"e14c":{"name":"Clear"},"e0b8":{"name":"Clear All"},"e5cd":{"name":"Close"},"e01c":{"name":"Closed Caption"},"e2bd":{"name":"Cloud"},"e2be":{"name":"Cloud Circle"},"e2bf":{"name":"Cloud Done"},"e2c0":{"name":"Cloud Download"},"e2c1":{"name":"Cloud Off"},"e2c2":{"name":"Cloud Queue"},"e2c3":{"name":"Cloud Upload"},"e86f":{"name":"Code"},"e3b6":{"name":"Collections"},"e431":{"name":"Collections Bookmark"},"e3b7":{"name":"Color Lens"},"e3b8":{"name":"Colorize"},"e0b9":{"name":"Comment"},"e3b9":{"name":"Compare"},"e915":{"name":"Compare Arrows"},"e30a":{"name":"Computer"},"e638":{"name":"Confirmation Number"},"e0d0":{"name":"Contact Mail"},"e0cf":{"name":"Contact Phone"},"e0ba":{"name":"Contacts"},"e14d":{"name":"Content Copy"},"e14e":{"name":"Content Cut"},"e14f":{"name":"Content Paste"},"e3ba":{"name":"Control Point"},"e3bb":{"name":"Control Point Duplicate"},"e90c":{"name":"Copyright"},"e150":{"name":"Create"},"e2cc":{"name":"Create New Folder"},"e870":{"name":"Credit Card"},"e3be":{"name":"Crop"},"e3bc":{"name":"Crop 16 9"},"e3bd":{"name":"Crop 3 2"},"e3bf":{"name":"Crop 5 4"},"e3c0":{"name":"Crop 7 5"},"e3c1":{"name":"Crop Din"},"e3c2":{"name":"Crop Free"},"e3c3":{"name":"Crop Landscape"},"e3c4":{"name":"Crop Original"},"e3c5":{"name":"Crop Portrait"},"e437":{"name":"Crop Rotate"},"e3c6":{"name":"Crop Square"},"e871":{"name":"Dashboard"},"e1af":{"name":"Data Usage"},"e916":{"name":"Date Range"},"e3c7":{"name":"Dehaze"},"e872":{"name":"Delete"},"e92b":{"name":"Delete Forever"},"e16c":{"name":"Delete Sweep"},"e873":{"name":"Description"},"e30b":{"name":"Desktop Mac"},"e30c":{"name":"Desktop Windows"},"e3c8":{"name":"Details"},"e30d":{"name":"Developer Board"},"e1b0":{"name":"Developer Mode"},"e335":{"name":"Device Hub"},"e1b1":{"name":"Devices"},"e337":{"name":"Devices Other"},"e0bb":{"name":"Dialer Sip"},"e0bc":{"name":"Dialpad"},"e52e":{"name":"Directions"},"e52f":{"name":"Directions Bike"},"e532":{"name":"Directions Boat"},"e530":{"name":"Directions Bus"},"e531":{"name":"Directions Car"},"e534":{"name":"Directions Railway"},"e566":{"name":"Directions Run"},"e533":{"name":"Directions Subway"},"e535":{"name":"Directions Transit"},"e536":{"name":"Directions Walk"},"e610":{"name":"Disc Full"},"e875":{"name":"Dns"},"e612":{"name":"Do Not Disturb"},"e611":{"name":"Do Not Disturb Alt"},"e643":{"name":"Do Not Disturb Off"},"e644":{"name":"Do Not Disturb On"},"e30e":{"name":"Dock"},"e7ee":{"name":"Domain"},"e876":{"name":"Done"},"e877":{"name":"Done All"},"e917":{"name":"Donut Large"},"e918":{"name":"Donut Small"},"e151":{"name":"Drafts"},"e25d":{"name":"Drag Handle"},"e613":{"name":"Drive Eta"},"e1b2":{"name":"Dvr"},"e3c9":{"name":"Edit"},"e568":{"name":"Edit Location"},"e8fb":{"name":"Eject"},"e0be":{"name":"Email"},"e63f":{"name":"Enhanced Encryption"},"e01d":{"name":"Equalizer"},"e000":{"name":"Error"},"e001":{"name":"Error Outline"},"e926":{"name":"Euro Symbol"},"e56d":{"name":"Ev Station"},"e878":{"name":"Event"},"e614":{"name":"Event Available"},"e615":{"name":"Event Busy"},"e616":{"name":"Event Note"},"e903":{"name":"Event Seat"},"e879":{"name":"Exit To App"},"e5ce":{"name":"Expand Less"},"e5cf":{"name":"Expand More"},"e01e":{"name":"Explicit"},"e87a":{"name":"Explore"},"e3ca":{"name":"Exposure"},"e3cb":{"name":"Exposure Neg 1"},"e3cc":{"name":"Exposure Neg 2"},"e3cd":{"name":"Exposure Plus 1"},"e3ce":{"name":"Exposure Plus 2"},"e3cf":{"name":"Exposure Zero"},"e87b":{"name":"Extension"},"e87c":{"name":"Face"},"e01f":{"name":"Fast Forward"},"e020":{"name":"Fast Rewind"},"e87d":{"name":"Favorite"},"e87e":{"name":"Favorite Border"},"e06d":{"name":"Featured Play List"},"e06e":{"name":"Featured Video"},"e87f":{"name":"Feedback"},"e05d":{"name":"Fiber Dvr"},"e061":{"name":"Fiber Manual Record"},"e05e":{"name":"Fiber New"},"e06a":{"name":"Fiber Pin"},"e062":{"name":"Fiber Smart Record"},"e2c4":{"name":"File Download"},"e2c6":{"name":"File Upload"},"e3d3":{"name":"Filter"},"e3d0":{"name":"Filter 1"},"e3d1":{"name":"Filter 2"},"e3d2":{"name":"Filter 3"},"e3d4":{"name":"Filter 4"},"e3d5":{"name":"Filter 5"},"e3d6":{"name":"Filter 6"},"e3d7":{"name":"Filter 7"},"e3d8":{"name":"Filter 8"},"e3d9":{"name":"Filter 9"},"e3da":{"name":"Filter 9 Plus"},"e3db":{"name":"Filter B And W"},"e3dc":{"name":"Filter Center Focus"},"e3dd":{"name":"Filter Drama"},"e3de":{"name":"Filter Frames"},"e3df":{"name":"Filter Hdr"},"e152":{"name":"Filter List"},"e3e0":{"name":"Filter None"},"e3e2":{"name":"Filter Tilt Shift"},"e3e3":{"name":"Filter Vintage"},"e880":{"name":"Find In Page"},"e881":{"name":"Find Replace"},"e90d":{"name":"Fingerprint"},"e5dc":{"name":"First Page"},"eb43":{"name":"Fitness Center"},"e153":{"name":"Flag"},"e3e4":{"name":"Flare"},"e3e5":{"name":"Flash Auto"},"e3e6":{"name":"Flash Off"},"e3e7":{"name":"Flash On"},"e539":{"name":"Flight"},"e904":{"name":"Flight Land"},"e905":{"name":"Flight Takeoff"},"e3e8":{"name":"Flip"},"e882":{"name":"Flip To Back"},"e883":{"name":"Flip To Front"},"e2c7":{"name":"Folder"},"e2c8":{"name":"Folder Open"},"e2c9":{"name":"Folder Shared"},"e617":{"name":"Folder Special"},"e167":{"name":"Font Download"},"e234":{"name":"Format Align Center"},"e235":{"name":"Format Align Justify"},"e236":{"name":"Format Align Left"},"e237":{"name":"Format Align Right"},"e238":{"name":"Format Bold"},"e239":{"name":"Format Clear"},"e23a":{"name":"Format Color Fill"},"e23b":{"name":"Format Color Reset"},"e23c":{"name":"Format Color Text"},"e23d":{"name":"Format Indent Decrease"},"e23e":{"name":"Format Indent Increase"},"e23f":{"name":"Format Italic"},"e240":{"name":"Format Line Spacing"},"e241":{"name":"Format List Bulleted"},"e242":{"name":"Format List Numbered"},"e243":{"name":"Format Paint"},"e244":{"name":"Format Quote"},"e25e":{"name":"Format Shapes"},"e245":{"name":"Format Size"},"e246":{"name":"Format Strikethrough"},"e247":{"name":"Format Textdirection L To R"},"e248":{"name":"Format Textdirection R To L"},"e249":{"name":"Format Underlined"},"e0bf":{"name":"Forum"},"e154":{"name":"Forward"},"e056":{"name":"Forward 10"},"e057":{"name":"Forward 30"},"e058":{"name":"Forward 5"},"eb44":{"name":"Free Breakfast"},"e5d0":{"name":"Fullscreen"},"e5d1":{"name":"Fullscreen Exit"},"e24a":{"name":"Functions"},"e927":{"name":"G Translate"},"e30f":{"name":"Gamepad"},"e021":{"name":"Games"},"e90e":{"name":"Gavel"},"e155":{"name":"Gesture"},"e884":{"name":"Get App"},"e908":{"name":"Gif"},"eb45":{"name":"Golf Course"},"e1b3":{"name":"Gps Fixed"},"e1b4":{"name":"Gps Not Fixed"},"e1b5":{"name":"Gps Off"},"e885":{"name":"Grade"},"e3e9":{"name":"Gradient"},"e3ea":{"name":"Grain"},"e1b8":{"name":"Graphic Eq"},"e3eb":{"name":"Grid Off"},"e3ec":{"name":"Grid On"},"e7ef":{"name":"Group"},"e7f0":{"name":"Group Add"},"e886":{"name":"Group Work"},"e052":{"name":"Hd"},"e3ed":{"name":"Hdr Off"},"e3ee":{"name":"Hdr On"},"e3f1":{"name":"Hdr Strong"},"e3f2":{"name":"Hdr Weak"},"e310":{"name":"Headset"},"e311":{"name":"Headset Mic"},"e3f3":{"name":"Healing"},"e023":{"name":"Hearing"},"e887":{"name":"Help"},"e8fd":{"name":"Help Outline"},"e024":{"name":"High Quality"},"e25f":{"name":"Highlight"},"e888":{"name":"Highlight Off"},"e889":{"name":"History"},"e88a":{"name":"Home"},"eb46":{"name":"Hot Tub"},"e53a":{"name":"Hotel"},"e88b":{"name":"Hourglass Empty"},"e88c":{"name":"Hourglass Full"},"e902":{"name":"Http"},"e88d":{"name":"Https"},"e3f4":{"name":"Image"},"e3f5":{"name":"Image Aspect Ratio"},"e0e0":{"name":"Import Contacts"},"e0c3":{"name":"Import Export"},"e912":{"name":"Important Devices"},"e156":{"name":"Inbox"},"e909":{"name":"Indeterminate Check Box"},"e88e":{"name":"Info"},"e88f":{"name":"Info Outline"},"e890":{"name":"Input"},"e24b":{"name":"Insert Chart"},"e24c":{"name":"Insert Comment"},"e24d":{"name":"Insert Drive File"},"e24e":{"name":"Insert Emoticon"},"e24f":{"name":"Insert Invitation"},"e250":{"name":"Insert Link"},"e251":{"name":"Insert Photo"},"e891":{"name":"Invert Colors"},"e0c4":{"name":"Invert Colors Off"},"e3f6":{"name":"Iso"},"e312":{"name":"Keyboard"},"e313":{"name":"Keyboard Arrow Down"},"e314":{"name":"Keyboard Arrow Left"},"e315":{"name":"Keyboard Arrow Right"},"e316":{"name":"Keyboard Arrow Up"},"e317":{"name":"Keyboard Backspace"},"e318":{"name":"Keyboard Capslock"},"e31a":{"name":"Keyboard Hide"},"e31b":{"name":"Keyboard Return"},"e31c":{"name":"Keyboard Tab"},"e31d":{"name":"Keyboard Voice"},"eb47":{"name":"Kitchen"},"e892":{"name":"Label"},"e893":{"name":"Label Outline"},"e3f7":{"name":"Landscape"},"e894":{"name":"Language"},"e31e":{"name":"Laptop"},"e31f":{"name":"Laptop Chromebook"},"e320":{"name":"Laptop Mac"},"e321":{"name":"Laptop Windows"},"e5dd":{"name":"Last Page"},"e895":{"name":"Launch"},"e53b":{"name":"Layers"},"e53c":{"name":"Layers Clear"},"e3f8":{"name":"Leak Add"},"e3f9":{"name":"Leak Remove"},"e3fa":{"name":"Lens"},"e02e":{"name":"Library Add"},"e02f":{"name":"Library Books"},"e030":{"name":"Library Music"},"e90f":{"name":"Lightbulb Outline"},"e919":{"name":"Line Style"},"e91a":{"name":"Line Weight"},"e260":{"name":"Linear Scale"},"e157":{"name":"Link"},"e438":{"name":"Linked Camera"},"e896":{"name":"List"},"e0c6":{"name":"Live Help"},"e639":{"name":"Live Tv"},"e53f":{"name":"Local Activity"},"e53d":{"name":"Local Airport"},"e53e":{"name":"Local Atm"},"e540":{"name":"Local Bar"},"e541":{"name":"Local Cafe"},"e542":{"name":"Local Car Wash"},"e543":{"name":"Local Convenience Store"},"e556":{"name":"Local Dining"},"e544":{"name":"Local Drink"},"e545":{"name":"Local Florist"},"e546":{"name":"Local Gas Station"},"e547":{"name":"Local Grocery Store"},"e548":{"name":"Local Hospital"},"e549":{"name":"Local Hotel"},"e54a":{"name":"Local Laundry Service"},"e54b":{"name":"Local Library"},"e54c":{"name":"Local Mall"},"e54d":{"name":"Local Movies"},"e54e":{"name":"Local Offer"},"e54f":{"name":"Local Parking"},"e550":{"name":"Local Pharmacy"},"e551":{"name":"Local Phone"},"e552":{"name":"Local Pizza"},"e553":{"name":"Local Play"},"e554":{"name":"Local Post Office"},"e555":{"name":"Local Printshop"},"e557":{"name":"Local See"},"e558":{"name":"Local Shipping"},"e559":{"name":"Local Taxi"},"e7f1":{"name":"Location City"},"e1b6":{"name":"Location Disabled"},"e0c7":{"name":"Location Off"},"e0c8":{"name":"Location On"},"e1b7":{"name":"Location Searching"},"e897":{"name":"Lock"},"e898":{"name":"Lock Open"},"e899":{"name":"Lock Outline"},"e3fc":{"name":"Looks"},"e3fb":{"name":"Looks 3"},"e3fd":{"name":"Looks 4"},"e3fe":{"name":"Looks 5"},"e3ff":{"name":"Looks 6"},"e400":{"name":"Looks One"},"e401":{"name":"Looks Two"},"e028":{"name":"Loop"},"e402":{"name":"Loupe"},"e16d":{"name":"Low Priority"},"e89a":{"name":"Loyalty"},"e158":{"name":"Mail"},"e0e1":{"name":"Mail Outline"},"e55b":{"name":"Map"},"e159":{"name":"Markunread"},"e89b":{"name":"Markunread Mailbox"},"e322":{"name":"Memory"},"e5d2":{"name":"Menu"},"e252":{"name":"Merge Type"},"e0c9":{"name":"Message"},"e029":{"name":"Mic"},"e02a":{"name":"Mic None"},"e02b":{"name":"Mic Off"},"e618":{"name":"Mms"},"e253":{"name":"Mode Comment"},"e254":{"name":"Mode Edit"},"e263":{"name":"Monetization On"},"e25c":{"name":"Money Off"},"e403":{"name":"Monochrome Photos"},"e7f2":{"name":"Mood"},"e7f3":{"name":"Mood Bad"},"e619":{"name":"More"},"e5d3":{"name":"More Horiz"},"e5d4":{"name":"More Vert"},"e91b":{"name":"Motorcycle"},"e323":{"name":"Mouse"},"e168":{"name":"Move To Inbox"},"e02c":{"name":"Movie"},"e404":{"name":"Movie Creation"},"e43a":{"name":"Movie Filter"},"e6df":{"name":"Multiline Chart"},"e405":{"name":"Music Note"},"e063":{"name":"Music Video"},"e55c":{"name":"My Location"},"e406":{"name":"Nature"},"e407":{"name":"Nature People"},"e408":{"name":"Navigate Before"},"e409":{"name":"Navigate Next"},"e55d":{"name":"Navigation"},"e569":{"name":"Near Me"},"e1b9":{"name":"Network Cell"},"e640":{"name":"Network Check"},"e61a":{"name":"Network Locked"},"e1ba":{"name":"Network Wifi"},"e031":{"name":"New Releases"},"e16a":{"name":"Next Week"},"e1bb":{"name":"Nfc"},"e641":{"name":"No Encryption"},"e0cc":{"name":"No Sim"},"e033":{"name":"Not Interested"},"e06f":{"name":"Note"},"e89c":{"name":"Note Add"},"e7f4":{"name":"Notifications"},"e7f7":{"name":"Notifications Active"},"e7f5":{"name":"Notifications None"},"e7f6":{"name":"Notifications Off"},"e7f8":{"name":"Notifications Paused"},"e90a":{"name":"Offline Pin"},"e63a":{"name":"Ondemand Video"},"e91c":{"name":"Opacity"},"e89d":{"name":"Open In Browser"},"e89e":{"name":"Open In New"},"e89f":{"name":"Open With"},"e7f9":{"name":"Pages"},"e8a0":{"name":"Pageview"},"e40a":{"name":"Palette"},"e925":{"name":"Pan Tool"},"e40b":{"name":"Panorama"},"e40c":{"name":"Panorama Fish Eye"},"e40d":{"name":"Panorama Horizontal"},"e40e":{"name":"Panorama Vertical"},"e40f":{"name":"Panorama Wide Angle"},"e7fa":{"name":"Party Mode"},"e034":{"name":"Pause"},"e035":{"name":"Pause Circle Filled"},"e036":{"name":"Pause Circle Outline"},"e8a1":{"name":"Payment"},"e7fb":{"name":"People"},"e7fc":{"name":"People Outline"},"e8a2":{"name":"Perm Camera Mic"},"e8a3":{"name":"Perm Contact Calendar"},"e8a4":{"name":"Perm Data Setting"},"e8a5":{"name":"Perm Device Information"},"e8a6":{"name":"Perm Identity"},"e8a7":{"name":"Perm Media"},"e8a8":{"name":"Perm Phone Msg"},"e8a9":{"name":"Perm Scan Wifi"},"e7fd":{"name":"Person"},"e7fe":{"name":"Person Add"},"e7ff":{"name":"Person Outline"},"e55a":{"name":"Person Pin"},"e56a":{"name":"Person Pin Circle"},"e63b":{"name":"Personal Video"},"e91d":{"name":"Pets"},"e0cd":{"name":"Phone"},"e324":{"name":"Phone Android"},"e61b":{"name":"Phone Bluetooth Speaker"},"e61c":{"name":"Phone Forwarded"},"e61d":{"name":"Phone In Talk"},"e325":{"name":"Phone Iphone"},"e61e":{"name":"Phone Locked"},"e61f":{"name":"Phone Missed"},"e620":{"name":"Phone Paused"},"e326":{"name":"Phonelink"},"e0db":{"name":"Phonelink Erase"},"e0dc":{"name":"Phonelink Lock"},"e327":{"name":"Phonelink Off"},"e0dd":{"name":"Phonelink Ring"},"e0de":{"name":"Phonelink Setup"},"e410":{"name":"Photo"},"e411":{"name":"Photo Album"},"e412":{"name":"Photo Camera"},"e43b":{"name":"Photo Filter"},"e413":{"name":"Photo Library"},"e432":{"name":"Photo Size Select Actual"},"e433":{"name":"Photo Size Select Large"},"e434":{"name":"Photo Size Select Small"},"e415":{"name":"Picture As Pdf"},"e8aa":{"name":"Picture In Picture"},"e911":{"name":"Picture In Picture Alt"},"e6c4":{"name":"Pie Chart"},"e6c5":{"name":"Pie Chart Outlined"},"e55e":{"name":"Pin Drop"},"e55f":{"name":"Place"},"e037":{"name":"Play Arrow"},"e038":{"name":"Play Circle Filled"},"e039":{"name":"Play Circle Outline"},"e906":{"name":"Play For Work"},"e03b":{"name":"Playlist Add"},"e065":{"name":"Playlist Add Check"},"e05f":{"name":"Playlist Play"},"e800":{"name":"Plus One"},"e801":{"name":"Poll"},"e8ab":{"name":"Polymer"},"eb48":{"name":"Pool"},"e0ce":{"name":"Portable Wifi Off"},"e416":{"name":"Portrait"},"e63c":{"name":"Power"},"e336":{"name":"Power Input"},"e8ac":{"name":"Power Settings New"},"e91e":{"name":"Pregnant Woman"},"e0df":{"name":"Present To All"},"e8ad":{"name":"Print"},"e645":{"name":"Priority High"},"e80b":{"name":"Public"},"e255":{"name":"Publish"},"e8ae":{"name":"Query Builder"},"e8af":{"name":"Question Answer"},"e03c":{"name":"Queue"},"e03d":{"name":"Queue Music"},"e066":{"name":"Queue Play Next"},"e03e":{"name":"Radio"},"e837":{"name":"Radio Button Checked"},"e836":{"name":"Radio Button Unchecked"},"e560":{"name":"Rate Review"},"e8b0":{"name":"Receipt"},"e03f":{"name":"Recent Actors"},"e91f":{"name":"Record Voice Over"},"e8b1":{"name":"Redeem"},"e15a":{"name":"Redo"},"e5d5":{"name":"Refresh"},"e15b":{"name":"Remove"},"e15c":{"name":"Remove Circle"},"e15d":{"name":"Remove Circle Outline"},"e067":{"name":"Remove From Queue"},"e417":{"name":"Remove Red Eye"},"e928":{"name":"Remove Shopping Cart"},"e8fe":{"name":"Reorder"},"e040":{"name":"Repeat"},"e041":{"name":"Repeat One"},"e042":{"name":"Replay"},"e059":{"name":"Replay 10"},"e05a":{"name":"Replay 30"},"e05b":{"name":"Replay 5"},"e15e":{"name":"Reply"},"e15f":{"name":"Reply All"},"e160":{"name":"Report"},"e8b2":{"name":"Report Problem"},"e56c":{"name":"Restaurant"},"e561":{"name":"Restaurant Menu"},"e8b3":{"name":"Restore"},"e929":{"name":"Restore Page"},"e0d1":{"name":"Ring Volume"},"e8b4":{"name":"Room"},"eb49":{"name":"Room Service"},"e418":{"name":"Rotate 90 Degrees Ccw"},"e419":{"name":"Rotate Left"},"e41a":{"name":"Rotate Right"},"e920":{"name":"Rounded Corner"},"e328":{"name":"Router"},"e921":{"name":"Rowing"},"e0e5":{"name":"Rss Feed"},"e642":{"name":"Rv Hookup"},"e562":{"name":"Satellite"},"e161":{"name":"Save"},"e329":{"name":"Scanner"},"e8b5":{"name":"Schedule"},"e80c":{"name":"School"},"e1be":{"name":"Screen Lock Landscape"},"e1bf":{"name":"Screen Lock Portrait"},"e1c0":{"name":"Screen Lock Rotation"},"e1c1":{"name":"Screen Rotation"},"e0e2":{"name":"Screen Share"},"e623":{"name":"Sd Card"},"e1c2":{"name":"Sd Storage"},"e8b6":{"name":"Search"},"e32a":{"name":"Security"},"e162":{"name":"Select All"},"e163":{"name":"Send"},"e811":{"name":"Sentiment Dissatisfied"},"e812":{"name":"Sentiment Neutral"},"e813":{"name":"Sentiment Satisfied"},"e814":{"name":"Sentiment Very Dissatisfied"},"e815":{"name":"Sentiment Very Satisfied"},"e8b8":{"name":"Settings"},"e8b9":{"name":"Settings Applications"},"e8ba":{"name":"Settings Backup Restore"},"e8bb":{"name":"Settings Bluetooth"},"e8bd":{"name":"Settings Brightness"},"e8bc":{"name":"Settings Cell"},"e8be":{"name":"Settings Ethernet"},"e8bf":{"name":"Settings Input Antenna"},"e8c0":{"name":"Settings Input Component"},"e8c1":{"name":"Settings Input Composite"},"e8c2":{"name":"Settings Input Hdmi"},"e8c3":{"name":"Settings Input Svideo"},"e8c4":{"name":"Settings Overscan"},"e8c5":{"name":"Settings Phone"},"e8c6":{"name":"Settings Power"},"e8c7":{"name":"Settings Remote"},"e1c3":{"name":"Settings System Daydream"},"e8c8":{"name":"Settings Voice"},"e80d":{"name":"Share"},"e8c9":{"name":"Shop"},"e8ca":{"name":"Shop Two"},"e8cb":{"name":"Shopping Basket"},"e8cc":{"name":"Shopping Cart"},"e261":{"name":"Short Text"},"e6e1":{"name":"Show Chart"},"e043":{"name":"Shuffle"},"e1c8":{"name":"Signal Cellular 4 Bar"},"e1cd":{"name":"Signal Cellular Connected No Internet 4 Bar"},"e1ce":{"name":"Signal Cellular No Sim"},"e1cf":{"name":"Signal Cellular Null"},"e1d0":{"name":"Signal Cellular Off"},"e1d8":{"name":"Signal Wifi 4 Bar"},"e1d9":{"name":"Signal Wifi 4 Bar Lock"},"e1da":{"name":"Signal Wifi Off"},"e32b":{"name":"Sim Card"},"e624":{"name":"Sim Card Alert"},"e044":{"name":"Skip Next"},"e045":{"name":"Skip Previous"},"e41b":{"name":"Slideshow"},"e068":{"name":"Slow Motion Video"},"e32c":{"name":"Smartphone"},"eb4a":{"name":"Smoke Free"},"eb4b":{"name":"Smoking Rooms"},"e625":{"name":"Sms"},"e626":{"name":"Sms Failed"},"e046":{"name":"Snooze"},"e164":{"name":"Sort"},"e053":{"name":"Sort By Alpha"},"eb4c":{"name":"Spa"},"e256":{"name":"Space Bar"},"e32d":{"name":"Speaker"},"e32e":{"name":"Speaker Group"},"e8cd":{"name":"Speaker Notes"},"e92a":{"name":"Speaker Notes Off"},"e0d2":{"name":"Speaker Phone"},"e8ce":{"name":"Spellcheck"},"e838":{"name":"Star"},"e83a":{"name":"Star Border"},"e839":{"name":"Star Half"},"e8d0":{"name":"Stars"},"e0d3":{"name":"Stay Current Landscape"},"e0d4":{"name":"Stay Current Portrait"},"e0d5":{"name":"Stay Primary Landscape"},"e0d6":{"name":"Stay Primary Portrait"},"e047":{"name":"Stop"},"e0e3":{"name":"Stop Screen Share"},"e1db":{"name":"Storage"},"e8d1":{"name":"Store"},"e563":{"name":"Store Mall Directory"},"e41c":{"name":"Straighten"},"e56e":{"name":"Streetview"},"e257":{"name":"Strikethrough S"},"e41d":{"name":"Style"},"e5d9":{"name":"Subdirectory Arrow Left"},"e5da":{"name":"Subdirectory Arrow Right"},"e8d2":{"name":"Subject"},"e064":{"name":"Subscriptions"},"e048":{"name":"Subtitles"},"e56f":{"name":"Subway"},"e8d3":{"name":"Supervisor Account"},"e049":{"name":"Surround Sound"},"e0d7":{"name":"Swap Calls"},"e8d4":{"name":"Swap Horiz"},"e8d5":{"name":"Swap Vert"},"e8d6":{"name":"Swap Vertical Circle"},"e41e":{"name":"Switch Camera"},"e41f":{"name":"Switch Video"},"e627":{"name":"Sync"},"e628":{"name":"Sync Disabled"},"e629":{"name":"Sync Problem"},"e62a":{"name":"System Update"},"e8d7":{"name":"System Update Alt"},"e8d8":{"name":"Tab"},"e8d9":{"name":"Tab Unselected"},"e32f":{"name":"Tablet"},"e330":{"name":"Tablet Android"},"e331":{"name":"Tablet Mac"},"e420":{"name":"Tag Faces"},"e62b":{"name":"Tap And Play"},"e564":{"name":"Terrain"},"e262":{"name":"Text Fields"},"e165":{"name":"Text Format"},"e0d8":{"name":"Textsms"},"e421":{"name":"Texture"},"e8da":{"name":"Theaters"},"e8db":{"name":"Thumb Down"},"e8dc":{"name":"Thumb Up"},"e8dd":{"name":"Thumbs Up Down"},"e62c":{"name":"Time To Leave"},"e422":{"name":"Timelapse"},"e922":{"name":"Timeline"},"e425":{"name":"Timer"},"e423":{"name":"Timer 10"},"e424":{"name":"Timer 3"},"e426":{"name":"Timer Off"},"e264":{"name":"Title"},"e8de":{"name":"Toc"},"e8df":{"name":"Today"},"e8e0":{"name":"Toll"},"e427":{"name":"Tonality"},"e913":{"name":"Touch App"},"e332":{"name":"Toys"},"e8e1":{"name":"Track Changes"},"e565":{"name":"Traffic"},"e570":{"name":"Train"},"e571":{"name":"Tram"},"e572":{"name":"Transfer Within A Station"},"e428":{"name":"Transform"},"e8e2":{"name":"Translate"},"e8e3":{"name":"Trending Down"},"e8e4":{"name":"Trending Flat"},"e8e5":{"name":"Trending Up"},"e429":{"name":"Tune"},"e8e6":{"name":"Turned In"},"e8e7":{"name":"Turned In Not"},"e333":{"name":"Tv"},"e169":{"name":"Unarchive"},"e166":{"name":"Undo"},"e5d6":{"name":"Unfold Less"},"e5d7":{"name":"Unfold More"},"e923":{"name":"Update"},"e1e0":{"name":"Usb"},"e8e8":{"name":"Verified User"},"e258":{"name":"Vertical Align Bottom"},"e259":{"name":"Vertical Align Center"},"e25a":{"name":"Vertical Align Top"},"e62d":{"name":"Vibration"},"e070":{"name":"Video Call"},"e071":{"name":"Video Label"},"e04a":{"name":"Video Library"},"e04b":{"name":"Videocam"},"e04c":{"name":"Videocam Off"},"e338":{"name":"Videogame Asset"},"e8e9":{"name":"View Agenda"},"e8ea":{"name":"View Array"},"e8eb":{"name":"View Carousel"},"e8ec":{"name":"View Column"},"e42a":{"name":"View Comfy"},"e42b":{"name":"View Compact"},"e8ed":{"name":"View Day"},"e8ee":{"name":"View Headline"},"e8ef":{"name":"View List"},"e8f0":{"name":"View Module"},"e8f1":{"name":"View Quilt"},"e8f2":{"name":"View Stream"},"e8f3":{"name":"View Week"},"e435":{"name":"Vignette"},"e8f4":{"name":"Visibility"},"e8f5":{"name":"Visibility Off"},"e62e":{"name":"Voice Chat"},"e0d9":{"name":"Voicemail"},"e04d":{"name":"Volume Down"},"e04e":{"name":"Volume Mute"},"e04f":{"name":"Volume Off"},"e050":{"name":"Volume Up"},"e0da":{"name":"Vpn Key"},"e62f":{"name":"Vpn Lock"},"e1bc":{"name":"Wallpaper"},"e002":{"name":"Warning"},"e334":{"name":"Watch"},"e924":{"name":"Watch Later"},"e42c":{"name":"Wb Auto"},"e42d":{"name":"Wb Cloudy"},"e42e":{"name":"Wb Incandescent"},"e436":{"name":"Wb Iridescent"},"e430":{"name":"Wb Sunny"},"e63d":{"name":"Wc"},"e051":{"name":"Web"},"e069":{"name":"Web Asset"},"e16b":{"name":"Weekend"},"e80e":{"name":"Whatshot"},"e1bd":{"name":"Widgets"},"e63e":{"name":"Wifi"},"e1e1":{"name":"Wifi Lock"},"e1e2":{"name":"Wifi Tethering"},"e8f9":{"name":"Work"},"e25b":{"name":"Wrap Text"},"e8fa":{"name":"Youtube Searched For"},"e8ff":{"name":"Zoom In"},"e900":{"name":"Zoom Out"},"e56b":{"name":"Zoom Out Map"}}}
\ No newline at end of file
diff --git a/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.svg b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.svg
new file mode 100755
index 0000000000..a449327e22
--- /dev/null
+++ b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.svg
@@ -0,0 +1,2373 @@
+
+
+
+
+
+Created by FontForge 20151118 at Mon Feb 8 11:58:02 2016
+ By shyndman
+Copyright 2015 Google, Inc. All Rights Reserved.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.ttf b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.ttf
new file mode 100755
index 0000000000..7015564ad1
Binary files /dev/null and b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.ttf differ
diff --git a/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.woff b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.woff
new file mode 100755
index 0000000000..b648a3eea2
Binary files /dev/null and b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.woff differ
diff --git a/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.woff2 b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.woff2
new file mode 100755
index 0000000000..9fa2112520
Binary files /dev/null and b/demo-shell/src/assets/fonts/material-icons/MaterialIcons-Regular.woff2 differ
diff --git a/demo-shell/src/assets/fonts/material-icons/README.md b/demo-shell/src/assets/fonts/material-icons/README.md
new file mode 100755
index 0000000000..ce4141ecad
--- /dev/null
+++ b/demo-shell/src/assets/fonts/material-icons/README.md
@@ -0,0 +1,9 @@
+The recommended way to use the Material Icons font is by linking to the web font hosted on Google Fonts:
+
+```html
+
+```
+
+Read more in our full usage guide:
+http://google.github.io/material-design-icons/#icon-font-for-the-web
diff --git a/demo-shell/src/assets/fonts/material-icons/codepoints b/demo-shell/src/assets/fonts/material-icons/codepoints
new file mode 100755
index 0000000000..3c8b075074
--- /dev/null
+++ b/demo-shell/src/assets/fonts/material-icons/codepoints
@@ -0,0 +1,932 @@
+3d_rotation e84d
+ac_unit eb3b
+access_alarm e190
+access_alarms e191
+access_time e192
+accessibility e84e
+accessible e914
+account_balance e84f
+account_balance_wallet e850
+account_box e851
+account_circle e853
+adb e60e
+add e145
+add_a_photo e439
+add_alarm e193
+add_alert e003
+add_box e146
+add_circle e147
+add_circle_outline e148
+add_location e567
+add_shopping_cart e854
+add_to_photos e39d
+add_to_queue e05c
+adjust e39e
+airline_seat_flat e630
+airline_seat_flat_angled e631
+airline_seat_individual_suite e632
+airline_seat_legroom_extra e633
+airline_seat_legroom_normal e634
+airline_seat_legroom_reduced e635
+airline_seat_recline_extra e636
+airline_seat_recline_normal e637
+airplanemode_active e195
+airplanemode_inactive e194
+airplay e055
+airport_shuttle eb3c
+alarm e855
+alarm_add e856
+alarm_off e857
+alarm_on e858
+album e019
+all_inclusive eb3d
+all_out e90b
+android e859
+announcement e85a
+apps e5c3
+archive e149
+arrow_back e5c4
+arrow_downward e5db
+arrow_drop_down e5c5
+arrow_drop_down_circle e5c6
+arrow_drop_up e5c7
+arrow_forward e5c8
+arrow_upward e5d8
+art_track e060
+aspect_ratio e85b
+assessment e85c
+assignment e85d
+assignment_ind e85e
+assignment_late e85f
+assignment_return e860
+assignment_returned e861
+assignment_turned_in e862
+assistant e39f
+assistant_photo e3a0
+attach_file e226
+attach_money e227
+attachment e2bc
+audiotrack e3a1
+autorenew e863
+av_timer e01b
+backspace e14a
+backup e864
+battery_alert e19c
+battery_charging_full e1a3
+battery_full e1a4
+battery_std e1a5
+battery_unknown e1a6
+beach_access eb3e
+beenhere e52d
+block e14b
+bluetooth e1a7
+bluetooth_audio e60f
+bluetooth_connected e1a8
+bluetooth_disabled e1a9
+bluetooth_searching e1aa
+blur_circular e3a2
+blur_linear e3a3
+blur_off e3a4
+blur_on e3a5
+book e865
+bookmark e866
+bookmark_border e867
+border_all e228
+border_bottom e229
+border_clear e22a
+border_color e22b
+border_horizontal e22c
+border_inner e22d
+border_left e22e
+border_outer e22f
+border_right e230
+border_style e231
+border_top e232
+border_vertical e233
+branding_watermark e06b
+brightness_1 e3a6
+brightness_2 e3a7
+brightness_3 e3a8
+brightness_4 e3a9
+brightness_5 e3aa
+brightness_6 e3ab
+brightness_7 e3ac
+brightness_auto e1ab
+brightness_high e1ac
+brightness_low e1ad
+brightness_medium e1ae
+broken_image e3ad
+brush e3ae
+bubble_chart e6dd
+bug_report e868
+build e869
+burst_mode e43c
+business e0af
+business_center eb3f
+cached e86a
+cake e7e9
+call e0b0
+call_end e0b1
+call_made e0b2
+call_merge e0b3
+call_missed e0b4
+call_missed_outgoing e0e4
+call_received e0b5
+call_split e0b6
+call_to_action e06c
+camera e3af
+camera_alt e3b0
+camera_enhance e8fc
+camera_front e3b1
+camera_rear e3b2
+camera_roll e3b3
+cancel e5c9
+card_giftcard e8f6
+card_membership e8f7
+card_travel e8f8
+casino eb40
+cast e307
+cast_connected e308
+center_focus_strong e3b4
+center_focus_weak e3b5
+change_history e86b
+chat e0b7
+chat_bubble e0ca
+chat_bubble_outline e0cb
+check e5ca
+check_box e834
+check_box_outline_blank e835
+check_circle e86c
+chevron_left e5cb
+chevron_right e5cc
+child_care eb41
+child_friendly eb42
+chrome_reader_mode e86d
+class e86e
+clear e14c
+clear_all e0b8
+close e5cd
+closed_caption e01c
+cloud e2bd
+cloud_circle e2be
+cloud_done e2bf
+cloud_download e2c0
+cloud_off e2c1
+cloud_queue e2c2
+cloud_upload e2c3
+code e86f
+collections e3b6
+collections_bookmark e431
+color_lens e3b7
+colorize e3b8
+comment e0b9
+compare e3b9
+compare_arrows e915
+computer e30a
+confirmation_number e638
+contact_mail e0d0
+contact_phone e0cf
+contacts e0ba
+content_copy e14d
+content_cut e14e
+content_paste e14f
+control_point e3ba
+control_point_duplicate e3bb
+copyright e90c
+create e150
+create_new_folder e2cc
+credit_card e870
+crop e3be
+crop_16_9 e3bc
+crop_3_2 e3bd
+crop_5_4 e3bf
+crop_7_5 e3c0
+crop_din e3c1
+crop_free e3c2
+crop_landscape e3c3
+crop_original e3c4
+crop_portrait e3c5
+crop_rotate e437
+crop_square e3c6
+dashboard e871
+data_usage e1af
+date_range e916
+dehaze e3c7
+delete e872
+delete_forever e92b
+delete_sweep e16c
+description e873
+desktop_mac e30b
+desktop_windows e30c
+details e3c8
+developer_board e30d
+developer_mode e1b0
+device_hub e335
+devices e1b1
+devices_other e337
+dialer_sip e0bb
+dialpad e0bc
+directions e52e
+directions_bike e52f
+directions_boat e532
+directions_bus e530
+directions_car e531
+directions_railway e534
+directions_run e566
+directions_subway e533
+directions_transit e535
+directions_walk e536
+disc_full e610
+dns e875
+do_not_disturb e612
+do_not_disturb_alt e611
+do_not_disturb_off e643
+do_not_disturb_on e644
+dock e30e
+domain e7ee
+done e876
+done_all e877
+donut_large e917
+donut_small e918
+drafts e151
+drag_handle e25d
+drive_eta e613
+dvr e1b2
+edit e3c9
+edit_location e568
+eject e8fb
+email e0be
+enhanced_encryption e63f
+equalizer e01d
+error e000
+error_outline e001
+euro_symbol e926
+ev_station e56d
+event e878
+event_available e614
+event_busy e615
+event_note e616
+event_seat e903
+exit_to_app e879
+expand_less e5ce
+expand_more e5cf
+explicit e01e
+explore e87a
+exposure e3ca
+exposure_neg_1 e3cb
+exposure_neg_2 e3cc
+exposure_plus_1 e3cd
+exposure_plus_2 e3ce
+exposure_zero e3cf
+extension e87b
+face e87c
+fast_forward e01f
+fast_rewind e020
+favorite e87d
+favorite_border e87e
+featured_play_list e06d
+featured_video e06e
+feedback e87f
+fiber_dvr e05d
+fiber_manual_record e061
+fiber_new e05e
+fiber_pin e06a
+fiber_smart_record e062
+file_download e2c4
+file_upload e2c6
+filter e3d3
+filter_1 e3d0
+filter_2 e3d1
+filter_3 e3d2
+filter_4 e3d4
+filter_5 e3d5
+filter_6 e3d6
+filter_7 e3d7
+filter_8 e3d8
+filter_9 e3d9
+filter_9_plus e3da
+filter_b_and_w e3db
+filter_center_focus e3dc
+filter_drama e3dd
+filter_frames e3de
+filter_hdr e3df
+filter_list e152
+filter_none e3e0
+filter_tilt_shift e3e2
+filter_vintage e3e3
+find_in_page e880
+find_replace e881
+fingerprint e90d
+first_page e5dc
+fitness_center eb43
+flag e153
+flare e3e4
+flash_auto e3e5
+flash_off e3e6
+flash_on e3e7
+flight e539
+flight_land e904
+flight_takeoff e905
+flip e3e8
+flip_to_back e882
+flip_to_front e883
+folder e2c7
+folder_open e2c8
+folder_shared e2c9
+folder_special e617
+font_download e167
+format_align_center e234
+format_align_justify e235
+format_align_left e236
+format_align_right e237
+format_bold e238
+format_clear e239
+format_color_fill e23a
+format_color_reset e23b
+format_color_text e23c
+format_indent_decrease e23d
+format_indent_increase e23e
+format_italic e23f
+format_line_spacing e240
+format_list_bulleted e241
+format_list_numbered e242
+format_paint e243
+format_quote e244
+format_shapes e25e
+format_size e245
+format_strikethrough e246
+format_textdirection_l_to_r e247
+format_textdirection_r_to_l e248
+format_underlined e249
+forum e0bf
+forward e154
+forward_10 e056
+forward_30 e057
+forward_5 e058
+free_breakfast eb44
+fullscreen e5d0
+fullscreen_exit e5d1
+functions e24a
+g_translate e927
+gamepad e30f
+games e021
+gavel e90e
+gesture e155
+get_app e884
+gif e908
+golf_course eb45
+gps_fixed e1b3
+gps_not_fixed e1b4
+gps_off e1b5
+grade e885
+gradient e3e9
+grain e3ea
+graphic_eq e1b8
+grid_off e3eb
+grid_on e3ec
+group e7ef
+group_add e7f0
+group_work e886
+hd e052
+hdr_off e3ed
+hdr_on e3ee
+hdr_strong e3f1
+hdr_weak e3f2
+headset e310
+headset_mic e311
+healing e3f3
+hearing e023
+help e887
+help_outline e8fd
+high_quality e024
+highlight e25f
+highlight_off e888
+history e889
+home e88a
+hot_tub eb46
+hotel e53a
+hourglass_empty e88b
+hourglass_full e88c
+http e902
+https e88d
+image e3f4
+image_aspect_ratio e3f5
+import_contacts e0e0
+import_export e0c3
+important_devices e912
+inbox e156
+indeterminate_check_box e909
+info e88e
+info_outline e88f
+input e890
+insert_chart e24b
+insert_comment e24c
+insert_drive_file e24d
+insert_emoticon e24e
+insert_invitation e24f
+insert_link e250
+insert_photo e251
+invert_colors e891
+invert_colors_off e0c4
+iso e3f6
+keyboard e312
+keyboard_arrow_down e313
+keyboard_arrow_left e314
+keyboard_arrow_right e315
+keyboard_arrow_up e316
+keyboard_backspace e317
+keyboard_capslock e318
+keyboard_hide e31a
+keyboard_return e31b
+keyboard_tab e31c
+keyboard_voice e31d
+kitchen eb47
+label e892
+label_outline e893
+landscape e3f7
+language e894
+laptop e31e
+laptop_chromebook e31f
+laptop_mac e320
+laptop_windows e321
+last_page e5dd
+launch e895
+layers e53b
+layers_clear e53c
+leak_add e3f8
+leak_remove e3f9
+lens e3fa
+library_add e02e
+library_books e02f
+library_music e030
+lightbulb_outline e90f
+line_style e919
+line_weight e91a
+linear_scale e260
+link e157
+linked_camera e438
+list e896
+live_help e0c6
+live_tv e639
+local_activity e53f
+local_airport e53d
+local_atm e53e
+local_bar e540
+local_cafe e541
+local_car_wash e542
+local_convenience_store e543
+local_dining e556
+local_drink e544
+local_florist e545
+local_gas_station e546
+local_grocery_store e547
+local_hospital e548
+local_hotel e549
+local_laundry_service e54a
+local_library e54b
+local_mall e54c
+local_movies e54d
+local_offer e54e
+local_parking e54f
+local_pharmacy e550
+local_phone e551
+local_pizza e552
+local_play e553
+local_post_office e554
+local_printshop e555
+local_see e557
+local_shipping e558
+local_taxi e559
+location_city e7f1
+location_disabled e1b6
+location_off e0c7
+location_on e0c8
+location_searching e1b7
+lock e897
+lock_open e898
+lock_outline e899
+looks e3fc
+looks_3 e3fb
+looks_4 e3fd
+looks_5 e3fe
+looks_6 e3ff
+looks_one e400
+looks_two e401
+loop e028
+loupe e402
+low_priority e16d
+loyalty e89a
+mail e158
+mail_outline e0e1
+map e55b
+markunread e159
+markunread_mailbox e89b
+memory e322
+menu e5d2
+merge_type e252
+message e0c9
+mic e029
+mic_none e02a
+mic_off e02b
+mms e618
+mode_comment e253
+mode_edit e254
+monetization_on e263
+money_off e25c
+monochrome_photos e403
+mood e7f2
+mood_bad e7f3
+more e619
+more_horiz e5d3
+more_vert e5d4
+motorcycle e91b
+mouse e323
+move_to_inbox e168
+movie e02c
+movie_creation e404
+movie_filter e43a
+multiline_chart e6df
+music_note e405
+music_video e063
+my_location e55c
+nature e406
+nature_people e407
+navigate_before e408
+navigate_next e409
+navigation e55d
+near_me e569
+network_cell e1b9
+network_check e640
+network_locked e61a
+network_wifi e1ba
+new_releases e031
+next_week e16a
+nfc e1bb
+no_encryption e641
+no_sim e0cc
+not_interested e033
+note e06f
+note_add e89c
+notifications e7f4
+notifications_active e7f7
+notifications_none e7f5
+notifications_off e7f6
+notifications_paused e7f8
+offline_pin e90a
+ondemand_video e63a
+opacity e91c
+open_in_browser e89d
+open_in_new e89e
+open_with e89f
+pages e7f9
+pageview e8a0
+palette e40a
+pan_tool e925
+panorama e40b
+panorama_fish_eye e40c
+panorama_horizontal e40d
+panorama_vertical e40e
+panorama_wide_angle e40f
+party_mode e7fa
+pause e034
+pause_circle_filled e035
+pause_circle_outline e036
+payment e8a1
+people e7fb
+people_outline e7fc
+perm_camera_mic e8a2
+perm_contact_calendar e8a3
+perm_data_setting e8a4
+perm_device_information e8a5
+perm_identity e8a6
+perm_media e8a7
+perm_phone_msg e8a8
+perm_scan_wifi e8a9
+person e7fd
+person_add e7fe
+person_outline e7ff
+person_pin e55a
+person_pin_circle e56a
+personal_video e63b
+pets e91d
+phone e0cd
+phone_android e324
+phone_bluetooth_speaker e61b
+phone_forwarded e61c
+phone_in_talk e61d
+phone_iphone e325
+phone_locked e61e
+phone_missed e61f
+phone_paused e620
+phonelink e326
+phonelink_erase e0db
+phonelink_lock e0dc
+phonelink_off e327
+phonelink_ring e0dd
+phonelink_setup e0de
+photo e410
+photo_album e411
+photo_camera e412
+photo_filter e43b
+photo_library e413
+photo_size_select_actual e432
+photo_size_select_large e433
+photo_size_select_small e434
+picture_as_pdf e415
+picture_in_picture e8aa
+picture_in_picture_alt e911
+pie_chart e6c4
+pie_chart_outlined e6c5
+pin_drop e55e
+place e55f
+play_arrow e037
+play_circle_filled e038
+play_circle_outline e039
+play_for_work e906
+playlist_add e03b
+playlist_add_check e065
+playlist_play e05f
+plus_one e800
+poll e801
+polymer e8ab
+pool eb48
+portable_wifi_off e0ce
+portrait e416
+power e63c
+power_input e336
+power_settings_new e8ac
+pregnant_woman e91e
+present_to_all e0df
+print e8ad
+priority_high e645
+public e80b
+publish e255
+query_builder e8ae
+question_answer e8af
+queue e03c
+queue_music e03d
+queue_play_next e066
+radio e03e
+radio_button_checked e837
+radio_button_unchecked e836
+rate_review e560
+receipt e8b0
+recent_actors e03f
+record_voice_over e91f
+redeem e8b1
+redo e15a
+refresh e5d5
+remove e15b
+remove_circle e15c
+remove_circle_outline e15d
+remove_from_queue e067
+remove_red_eye e417
+remove_shopping_cart e928
+reorder e8fe
+repeat e040
+repeat_one e041
+replay e042
+replay_10 e059
+replay_30 e05a
+replay_5 e05b
+reply e15e
+reply_all e15f
+report e160
+report_problem e8b2
+restaurant e56c
+restaurant_menu e561
+restore e8b3
+restore_page e929
+ring_volume e0d1
+room e8b4
+room_service eb49
+rotate_90_degrees_ccw e418
+rotate_left e419
+rotate_right e41a
+rounded_corner e920
+router e328
+rowing e921
+rss_feed e0e5
+rv_hookup e642
+satellite e562
+save e161
+scanner e329
+schedule e8b5
+school e80c
+screen_lock_landscape e1be
+screen_lock_portrait e1bf
+screen_lock_rotation e1c0
+screen_rotation e1c1
+screen_share e0e2
+sd_card e623
+sd_storage e1c2
+search e8b6
+security e32a
+select_all e162
+send e163
+sentiment_dissatisfied e811
+sentiment_neutral e812
+sentiment_satisfied e813
+sentiment_very_dissatisfied e814
+sentiment_very_satisfied e815
+settings e8b8
+settings_applications e8b9
+settings_backup_restore e8ba
+settings_bluetooth e8bb
+settings_brightness e8bd
+settings_cell e8bc
+settings_ethernet e8be
+settings_input_antenna e8bf
+settings_input_component e8c0
+settings_input_composite e8c1
+settings_input_hdmi e8c2
+settings_input_svideo e8c3
+settings_overscan e8c4
+settings_phone e8c5
+settings_power e8c6
+settings_remote e8c7
+settings_system_daydream e1c3
+settings_voice e8c8
+share e80d
+shop e8c9
+shop_two e8ca
+shopping_basket e8cb
+shopping_cart e8cc
+short_text e261
+show_chart e6e1
+shuffle e043
+signal_cellular_4_bar e1c8
+signal_cellular_connected_no_internet_4_bar e1cd
+signal_cellular_no_sim e1ce
+signal_cellular_null e1cf
+signal_cellular_off e1d0
+signal_wifi_4_bar e1d8
+signal_wifi_4_bar_lock e1d9
+signal_wifi_off e1da
+sim_card e32b
+sim_card_alert e624
+skip_next e044
+skip_previous e045
+slideshow e41b
+slow_motion_video e068
+smartphone e32c
+smoke_free eb4a
+smoking_rooms eb4b
+sms e625
+sms_failed e626
+snooze e046
+sort e164
+sort_by_alpha e053
+spa eb4c
+space_bar e256
+speaker e32d
+speaker_group e32e
+speaker_notes e8cd
+speaker_notes_off e92a
+speaker_phone e0d2
+spellcheck e8ce
+star e838
+star_border e83a
+star_half e839
+stars e8d0
+stay_current_landscape e0d3
+stay_current_portrait e0d4
+stay_primary_landscape e0d5
+stay_primary_portrait e0d6
+stop e047
+stop_screen_share e0e3
+storage e1db
+store e8d1
+store_mall_directory e563
+straighten e41c
+streetview e56e
+strikethrough_s e257
+style e41d
+subdirectory_arrow_left e5d9
+subdirectory_arrow_right e5da
+subject e8d2
+subscriptions e064
+subtitles e048
+subway e56f
+supervisor_account e8d3
+surround_sound e049
+swap_calls e0d7
+swap_horiz e8d4
+swap_vert e8d5
+swap_vertical_circle e8d6
+switch_camera e41e
+switch_video e41f
+sync e627
+sync_disabled e628
+sync_problem e629
+system_update e62a
+system_update_alt e8d7
+tab e8d8
+tab_unselected e8d9
+tablet e32f
+tablet_android e330
+tablet_mac e331
+tag_faces e420
+tap_and_play e62b
+terrain e564
+text_fields e262
+text_format e165
+textsms e0d8
+texture e421
+theaters e8da
+thumb_down e8db
+thumb_up e8dc
+thumbs_up_down e8dd
+time_to_leave e62c
+timelapse e422
+timeline e922
+timer e425
+timer_10 e423
+timer_3 e424
+timer_off e426
+title e264
+toc e8de
+today e8df
+toll e8e0
+tonality e427
+touch_app e913
+toys e332
+track_changes e8e1
+traffic e565
+train e570
+tram e571
+transfer_within_a_station e572
+transform e428
+translate e8e2
+trending_down e8e3
+trending_flat e8e4
+trending_up e8e5
+tune e429
+turned_in e8e6
+turned_in_not e8e7
+tv e333
+unarchive e169
+undo e166
+unfold_less e5d6
+unfold_more e5d7
+update e923
+usb e1e0
+verified_user e8e8
+vertical_align_bottom e258
+vertical_align_center e259
+vertical_align_top e25a
+vibration e62d
+video_call e070
+video_label e071
+video_library e04a
+videocam e04b
+videocam_off e04c
+videogame_asset e338
+view_agenda e8e9
+view_array e8ea
+view_carousel e8eb
+view_column e8ec
+view_comfy e42a
+view_compact e42b
+view_day e8ed
+view_headline e8ee
+view_list e8ef
+view_module e8f0
+view_quilt e8f1
+view_stream e8f2
+view_week e8f3
+vignette e435
+visibility e8f4
+visibility_off e8f5
+voice_chat e62e
+voicemail e0d9
+volume_down e04d
+volume_mute e04e
+volume_off e04f
+volume_up e050
+vpn_key e0da
+vpn_lock e62f
+wallpaper e1bc
+warning e002
+watch e334
+watch_later e924
+wb_auto e42c
+wb_cloudy e42d
+wb_incandescent e42e
+wb_iridescent e436
+wb_sunny e430
+wc e63d
+web e051
+web_asset e069
+weekend e16b
+whatshot e80e
+widgets e1bd
+wifi e63e
+wifi_lock e1e1
+wifi_tethering e1e2
+work e8f9
+wrap_text e25b
+youtube_searched_for e8fa
+zoom_in e8ff
+zoom_out e900
+zoom_out_map e56b
diff --git a/demo-shell/src/assets/fonts/material-icons/material-icons.css b/demo-shell/src/assets/fonts/material-icons/material-icons.css
new file mode 100755
index 0000000000..2270c09d01
--- /dev/null
+++ b/demo-shell/src/assets/fonts/material-icons/material-icons.css
@@ -0,0 +1,36 @@
+@font-face {
+ font-family: 'Material Icons';
+ font-style: normal;
+ font-weight: 400;
+ src: url(MaterialIcons-Regular.eot); /* For IE6-8 */
+ src: local('Material Icons'),
+ local('MaterialIcons-Regular'),
+ url(MaterialIcons-Regular.woff2) format('woff2'),
+ url(MaterialIcons-Regular.woff) format('woff'),
+ url(MaterialIcons-Regular.ttf) format('truetype');
+}
+
+.material-icons {
+ font-family: 'Material Icons';
+ font-weight: normal;
+ font-style: normal;
+ font-size: 24px; /* Preferred icon size */
+ display: inline-block;
+ line-height: 1;
+ text-transform: none;
+ letter-spacing: normal;
+ word-wrap: normal;
+ white-space: nowrap;
+ direction: ltr;
+
+ /* Support for all WebKit browsers. */
+ -webkit-font-smoothing: antialiased;
+ /* Support for Safari and Chrome. */
+ text-rendering: optimizeLegibility;
+
+ /* Support for Firefox. */
+ -moz-osx-font-smoothing: grayscale;
+
+ /* Support for IE. */
+ font-feature-settings: 'liga';
+}
diff --git a/demo-shell/src/assets/fonts/muli/Muli-Black.ttf b/demo-shell/src/assets/fonts/muli/Muli-Black.ttf
new file mode 100755
index 0000000000..76825b8170
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-Black.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-BlackItalic.ttf b/demo-shell/src/assets/fonts/muli/Muli-BlackItalic.ttf
new file mode 100755
index 0000000000..70762c09d9
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-BlackItalic.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-Bold.ttf b/demo-shell/src/assets/fonts/muli/Muli-Bold.ttf
new file mode 100755
index 0000000000..732c3ec02e
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-Bold.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-BoldItalic.ttf b/demo-shell/src/assets/fonts/muli/Muli-BoldItalic.ttf
new file mode 100755
index 0000000000..1dac1c9cb6
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-BoldItalic.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-ExtraBold.ttf b/demo-shell/src/assets/fonts/muli/Muli-ExtraBold.ttf
new file mode 100755
index 0000000000..a8ef44cec3
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-ExtraBold.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-ExtraBoldItalic.ttf b/demo-shell/src/assets/fonts/muli/Muli-ExtraBoldItalic.ttf
new file mode 100755
index 0000000000..b99e68d460
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-ExtraBoldItalic.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-ExtraLight.ttf b/demo-shell/src/assets/fonts/muli/Muli-ExtraLight.ttf
new file mode 100755
index 0000000000..ffe7b29deb
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-ExtraLight.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-ExtraLightItalic.ttf b/demo-shell/src/assets/fonts/muli/Muli-ExtraLightItalic.ttf
new file mode 100755
index 0000000000..eb8b36a0a3
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-ExtraLightItalic.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-Italic.ttf b/demo-shell/src/assets/fonts/muli/Muli-Italic.ttf
new file mode 100755
index 0000000000..e1599293f2
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-Italic.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-Light.ttf b/demo-shell/src/assets/fonts/muli/Muli-Light.ttf
new file mode 100755
index 0000000000..4e66b6979f
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-Light.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-LightItalic.ttf b/demo-shell/src/assets/fonts/muli/Muli-LightItalic.ttf
new file mode 100755
index 0000000000..85ac251328
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-LightItalic.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-Regular.ttf b/demo-shell/src/assets/fonts/muli/Muli-Regular.ttf
new file mode 100755
index 0000000000..1dfd643187
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-Regular.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-SemiBold.ttf b/demo-shell/src/assets/fonts/muli/Muli-SemiBold.ttf
new file mode 100755
index 0000000000..096a15e424
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-SemiBold.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/Muli-SemiBoldItalic.ttf b/demo-shell/src/assets/fonts/muli/Muli-SemiBoldItalic.ttf
new file mode 100755
index 0000000000..6d7bcc8569
Binary files /dev/null and b/demo-shell/src/assets/fonts/muli/Muli-SemiBoldItalic.ttf differ
diff --git a/demo-shell/src/assets/fonts/muli/OFL.txt b/demo-shell/src/assets/fonts/muli/OFL.txt
new file mode 100755
index 0000000000..1016891d2d
--- /dev/null
+++ b/demo-shell/src/assets/fonts/muli/OFL.txt
@@ -0,0 +1,93 @@
+Copyright (c) 2016 The Muli Project Authors (contact@sansoxygen.com)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/demo-shell/src/assets/fonts/muli/muli.css b/demo-shell/src/assets/fonts/muli/muli.css
new file mode 100644
index 0000000000..609c76fc9a
--- /dev/null
+++ b/demo-shell/src/assets/fonts/muli/muli.css
@@ -0,0 +1,63 @@
+/* vietnamese */
+@font-face {
+ font-family: 'Muli';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Muli Regular'),
+ local('Muli-Regular'),
+ url(Muli-Regular.ttf) format('truetype');
+ unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
+ }
+ /* latin-ext */
+ @font-face {
+ font-family: 'Muli';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Muli Regular'),
+ local('Muli-Regular'),
+ url(Muli-Regular.ttf) format('truetype');
+ unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
+ }
+ /* latin */
+ @font-face {
+ font-family: 'Muli';
+ font-style: normal;
+ font-weight: 400;
+ src: local('Muli Regular'),
+ local('Muli-Regular'),
+ url(Muli-Regular.ttf) format('truetype');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
+ }
+
+/* vietnamese */
+@font-face {
+ font-family: 'Muli';
+ font-style: normal;
+ font-weight: 100;
+ src: local('Muli Light'),
+ local('Muli-Light'),
+ url(Muli-Light.ttf) format('truetype');
+ unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
+}
+
+/* latin-ext */
+@font-face {
+ font-family: 'Muli';
+ font-style: normal;
+ font-weight: 100;
+ src: local('Muli Light'),
+ local('Muli-Light'),
+ url(Muli-Light.ttf) format('truetype');
+ unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
+}
+
+/* latin */
+@font-face {
+ font-family: 'Muli';
+ font-style: normal;
+ font-weight: 100;
+ src: local('Muli Light'),
+ local('Muli-Light'),
+ url(Muli-Light.ttf) format('truetype');
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
+}
diff --git a/lib/core/context-menu/context-menu.service.spec.ts b/demo-shell/src/environments/environment.e2e.ts
similarity index 67%
rename from lib/core/context-menu/context-menu.service.spec.ts
rename to demo-shell/src/environments/environment.e2e.ts
index 2e705760a7..75794a8611 100644
--- a/lib/core/context-menu/context-menu.service.spec.ts
+++ b/demo-shell/src/environments/environment.e2e.ts
@@ -15,18 +15,7 @@
* limitations under the License.
*/
-import { ContextMenuService } from './context-menu.service';
-
-describe('ContextMenuService', () => {
-
- let service;
-
- beforeEach(() => {
- service = new ContextMenuService();
- });
-
- it('should setup default show subject', () => {
- expect(service.show).toBeDefined();
- });
-
-});
+export const environment = {
+ production: false,
+ e2e: true
+};
diff --git a/demo-shell/src/environments/environment.prod.ts b/demo-shell/src/environments/environment.prod.ts
index 6755c5e302..774915cd9e 100644
--- a/demo-shell/src/environments/environment.prod.ts
+++ b/demo-shell/src/environments/environment.prod.ts
@@ -16,5 +16,6 @@
*/
export const environment = {
- production: true
+ production: true,
+ e2e: false
};
diff --git a/demo-shell/src/environments/environment.ts b/demo-shell/src/environments/environment.ts
index 15a3b4b68c..3461759621 100644
--- a/demo-shell/src/environments/environment.ts
+++ b/demo-shell/src/environments/environment.ts
@@ -21,5 +21,6 @@
// The list of which env maps to which file can be found in `.angular-cli.json`.
export const environment = {
- production: false
+ production: false,
+ e2e: false
};
diff --git a/demo-shell/src/favicon-96x96.png b/demo-shell/src/favicon-96x96.png
new file mode 100644
index 0000000000..d342b10ee0
Binary files /dev/null and b/demo-shell/src/favicon-96x96.png differ
diff --git a/demo-shell/src/index.html b/demo-shell/src/index.html
index 737233d32a..afe6a16bce 100644
--- a/demo-shell/src/index.html
+++ b/demo-shell/src/index.html
@@ -7,8 +7,6 @@
-
-