diff --git a/demo-shell/src/app/app.component.ts b/demo-shell/src/app/app.component.ts
index dae3d46971..a99aa77a79 100644
--- a/demo-shell/src/app/app.component.ts
+++ b/demo-shell/src/app/app.component.ts
@@ -16,30 +16,40 @@
*/
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
-import { SettingsService, PageTitleService, StorageService } from '@alfresco/adf-core';
+import { AlfrescoApiService, SettingsService, PageTitleService, StorageService } from '@alfresco/adf-core';
+import { Router } from '@angular/router';
@Component({
- selector: 'app-root',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.scss'],
- encapsulation: ViewEncapsulation.None
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.scss'],
+ encapsulation: ViewEncapsulation.None
})
export class AppComponent implements OnInit {
constructor(private settingsService: SettingsService,
private storage: StorageService,
- private pageTitleService: PageTitleService) {
+ private pageTitleService: PageTitleService,
+ private alfrescoApiService: AlfrescoApiService,
+ private router: Router) {
}
- ngOnInit() {
- this.setProvider();
+ ngOnInit() {
+ this.setProvider();
- this.pageTitleService.setTitle('title');
- }
+ this.pageTitleService.setTitle('title');
- private setProvider() {
- if (this.storage.hasItem(`providers`)) {
- this.settingsService.setProviders(this.storage.getItem(`providers`));
+ this.alfrescoApiService.getInstance().on('error', (error) => {
+
+ if (error.status === '404') {
+ this.router.navigate(['/error', error.status]);
+ }
+ });
+ }
+
+ private setProvider() {
+ if (this.storage.hasItem(`providers`)) {
+ this.settingsService.setProviders(this.storage.getItem(`providers`));
+ }
}
- }
}
diff --git a/demo-shell/src/app/app.routes.ts b/demo-shell/src/app/app.routes.ts
index f7ccfd73d5..3c945bc23b 100644
--- a/demo-shell/src/app/app.routes.ts
+++ b/demo-shell/src/app/app.routes.ts
@@ -17,7 +17,7 @@
import { ModuleWithProviders } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
-import { AuthGuard, AuthGuardBpm, AuthGuardEcm } from '@alfresco/adf-core';
+import { AuthGuard, AuthGuardBpm, AuthGuardEcm, ErrorContentComponent } from '@alfresco/adf-core';
import { AppLayoutComponent } from './components/app-layout/app-layout.component';
import { LoginComponent } from './components/login/login.component';
import { SettingsComponent } from './components/settings/settings.component';
@@ -51,7 +51,7 @@ import { BlobPreviewComponent } from './components/blob-preview/blob-preview.com
export const appRoutes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: 'settings', component: SettingsComponent },
- { path: 'files/:nodeId/view', component: FileViewComponent, canActivate: [ AuthGuardEcm ], outlet: 'overlay' },
+ { path: 'files/:nodeId/view', component: FileViewComponent, canActivate: [AuthGuardEcm], outlet: 'overlay' },
{ path: 'preview/blob', component: BlobPreviewComponent, outlet: 'overlay', pathMatch: 'full' },
{ path: 'preview/s/:id', component: SharedLinkViewComponent },
{
@@ -190,7 +190,16 @@ export const appRoutes: Routes = [
{
path: 'datatable-lazy',
loadChildren: 'app/components/lazy-loading/lazy-loading.module#LazyLoadingModule'
+ },
+ {
+ path: 'error/:id',
+ component: ErrorContentComponent
+ },
+ {
+ path: '**',
+ redirectTo: 'error/404'
}
+
]
}
];
diff --git a/demo-shell/src/app/components/files/files.component.ts b/demo-shell/src/app/components/files/files.component.ts
index 70bb53982d..a4490e678b 100644
--- a/demo-shell/src/app/components/files/files.component.ts
+++ b/demo-shell/src/app/components/files/files.component.ts
@@ -277,9 +277,9 @@ export class FilesComponent implements OnInit, OnChanges, OnDestroy {
}
}
- onNavigationError(err: any) {
- if (err) {
- this.errorMessage = err.message || 'Navigation error';
+ onNavigationError(error: any) {
+ if (error) {
+ this.router.navigate(['/error', error.status]);
}
}
diff --git a/docs/core/error-content.component.md b/docs/core/error-content.component.md
new file mode 100644
index 0000000000..5dbcd2645c
--- /dev/null
+++ b/docs/core/error-content.component.md
@@ -0,0 +1,63 @@
+# Error Content Component
+
+Displays info about a specific error.
+
+## Basic Usage
+
+Once you have catched the error in your server you will need to redirect to ```/error/errorCode``` to display information about that error.
+
+```ts
+this.router.navigate(['/error', errorCode]);
+```
+
+```html
+
+
{{ errorCode }}
+
+
{{ errorTitle | translate }}
+
{{ errorDescription | translate }}
+ {{ errorLinkText | translate }}
+
+
+```
+
+## Properties
+
+### Error Content Component
+
+| Name | Type | Description |
+| --- | --- | -- |
+| errorCode | string | Error code |
+| errorTitle | string | Error title |
+| errorDescription | string | Short description about the error |
+| errorLink | string | (Optional) This link will be attached at the end of the error description and itt will be highlighted.|
+
+
+## Details
+
+You can customize your errors by adding them to the tranlate files inside ```lib/core/i18n```.
+```json
+"ERROR_CONTENT": {
+ "HOME_BUTTON": "Back to home",
+ "403": {
+ "TITLE": "Error 403 forbidden!",
+ "DESCRIPTION": "Sorry, access to this resource on the server is denied. Either check URL or feel free to",
+ "LINK": {
+ "TEXT": "report this issue.",
+ "URL": ""
+ }
+ },
+ "404": {
+ "TITLE": "Whoops!",
+ "DESCRIPTION": "We couldn’t find the page you were looking for.",
+ "LINK": {
+ "TEXT": "",
+ "URL": ""
+ }
+ }
+ }
+```
+
+
+
diff --git a/lib/core/buttons-menu/buttons-menu.component.spec.ts b/lib/core/buttons-menu/buttons-menu.component.spec.ts
index 878f80e921..28b9e00c24 100644
--- a/lib/core/buttons-menu/buttons-menu.component.spec.ts
+++ b/lib/core/buttons-menu/buttons-menu.component.spec.ts
@@ -20,6 +20,7 @@ import { ButtonsMenuComponent } from './buttons-menu.component';
import { MenuButton } from './menu-button.model';
import { MaterialModule } from '../material.module';
import { CoreTestingModule } from '../testing/core.testing.module';
+import { setupTestBed } from '../testing/setupTestBed';
describe('ButtonsMenuComponent', () => {
@@ -27,14 +28,12 @@ describe('ButtonsMenuComponent', () => {
let buttonsMenuComponent: ButtonsMenuComponent;
let element: HTMLElement;
- beforeEach(async(() => {
- TestBed.configureTestingModule({
- imports: [
- MaterialModule,
- CoreTestingModule
- ]
- }).compileComponents();
- }));
+ setupTestBed({
+ imports: [
+ CoreTestingModule,
+ MaterialModule
+ ]
+ });
beforeEach(() => {
fixture = TestBed.createComponent(ButtonsMenuComponent);
diff --git a/lib/core/core.module.ts b/lib/core/core.module.ts
index cc28912336..99b73364ce 100644
--- a/lib/core/core.module.ts
+++ b/lib/core/core.module.ts
@@ -41,6 +41,7 @@ import { FormModule } from './form/form.module';
import { SidenavLayoutModule } from './sidenav-layout/sidenav-layout.module';
import { CommentsModule } from './comments/comments.module';
import { ButtonsMenuModule } from './buttons-menu/buttons-menu.module';
+import { TemplatetModule } from './templates/template.module';
import { DirectiveModule } from './directives/directive.module';
import { PipeModule } from './pipes/pipe.module';
@@ -80,7 +81,6 @@ import { UploadService } from './services/upload.service';
import { UserPreferencesService } from './services/user-preferences.service';
import { SearchConfigurationService } from './services/search-configuration.service';
import { startupServiceFactory } from './services/startup-service-factory';
-import { EmptyContentComponent } from './components/empty-content/empty-content.component';
import { SortingPickerComponent } from './components/sorting-picker/sorting-picker.component';
export function createTranslateLoader(http: HttpClient, logService: LogService) {
@@ -155,6 +155,7 @@ export function providers() {
DataColumnModule,
DataTableModule,
ButtonsMenuModule,
+ TemplatetModule,
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
@@ -190,7 +191,8 @@ export function providers() {
DataColumnModule,
DataTableModule,
TranslateModule,
- ButtonsMenuModule
+ ButtonsMenuModule,
+ TemplatetModule
]
})
export class CoreModuleLazy {
@@ -224,6 +226,7 @@ export class CoreModuleLazy {
DataColumnModule,
DataTableModule,
ButtonsMenuModule,
+ TemplatetModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
@@ -233,7 +236,6 @@ export class CoreModuleLazy {
})
],
declarations: [
- EmptyContentComponent,
SortingPickerComponent
],
exports: [
@@ -264,7 +266,7 @@ export class CoreModuleLazy {
DataTableModule,
TranslateModule,
ButtonsMenuModule,
- EmptyContentComponent,
+ TemplatetModule,
SortingPickerComponent
],
providers: [
diff --git a/lib/core/form/components/start-form.component.spec.ts b/lib/core/form/components/start-form.component.spec.ts
index 29f5ae72e9..7bf75ff22e 100644
--- a/lib/core/form/components/start-form.component.spec.ts
+++ b/lib/core/form/components/start-form.component.spec.ts
@@ -48,7 +48,6 @@ describe('StartFormComponent', () => {
});
beforeEach(() => {
-
fixture = TestBed.createComponent(StartFormComponent);
component = fixture.componentInstance;
formService = TestBed.get(FormService);
@@ -59,6 +58,10 @@ describe('StartFormComponent', () => {
}));
});
+ afterEach(() => {
+ fixture.destroy();
+ });
+
it('should load start form on change if processDefinitionId defined', () => {
component.processDefinitionId = exampleId1;
component.ngOnChanges({ processDefinitionId: new SimpleChange(exampleId1, exampleId2, true) });
diff --git a/lib/core/form/components/widgets/container/container.widget.scss b/lib/core/form/components/widgets/container/container.widget.scss
index d23cbb7e09..4a7cd091b1 100644
--- a/lib/core/form/components/widgets/container/container.widget.scss
+++ b/lib/core/form/components/widgets/container/container.widget.scss
@@ -89,6 +89,7 @@
.mat-grid-tile {
overflow: visible;
+ width: 80%;
}
}
diff --git a/lib/core/i18n/en.json b/lib/core/i18n/en.json
index 9271d64cad..efbbf1983e 100644
--- a/lib/core/i18n/en.json
+++ b/lib/core/i18n/en.json
@@ -262,5 +262,32 @@
"PLACEHOLDER": "Password",
"ERROR": "Password is wrong"
}
+ },
+ "ERROR_CONTENT": {
+ "HOME_BUTTON": "Back to home",
+ "UNKNOWN": {
+ "TITLE": "Oops!",
+ "DESCRIPTION": "Looks like something went wrong.",
+ "LINK": {
+ "TEXT": "",
+ "URL": ""
+ }
+ },
+ "403": {
+ "TITLE": "Error 403 forbidden!",
+ "DESCRIPTION": "Sorry, access to this resource on the server is denied. Either check URL or feel free to",
+ "LINK": {
+ "TEXT": "report this issue.",
+ "URL": ""
+ }
+ },
+ "404": {
+ "TITLE": "Whoops!",
+ "DESCRIPTION": "We couldn’t find the page you were looking for.",
+ "LINK": {
+ "TEXT": "",
+ "URL": ""
+ }
+ }
}
}
diff --git a/lib/core/index.ts b/lib/core/index.ts
index b262848dcd..8c6179a0b5 100644
--- a/lib/core/index.ts
+++ b/lib/core/index.ts
@@ -35,9 +35,9 @@ export * from './sidenav-layout/index';
export * from './comments/index';
export * from './buttons-menu/index';
-export * from './components/empty-content/empty-content.component';
export * from './components/sorting-picker/sorting-picker.component';
+export * from './templates/index';
export * from './pipes/index';
export * from './services/index';
export * from './directives/index';
diff --git a/lib/core/styles/_index.scss b/lib/core/styles/_index.scss
index 0fd157337c..48b2d2c9b5 100644
--- a/lib/core/styles/_index.scss
+++ b/lib/core/styles/_index.scss
@@ -26,7 +26,8 @@
@import '../comments/comment-list.component';
@import '../comments/comments.component';
@import '../sidenav-layout/components/layout-container/layout-container.component';
-@import "../components/empty-content/empty-content.component";
+@import "../templates/empty-content/empty-content.component";
+@import "../templates/error-content/error-content.component";
@mixin adf-core-theme($theme) {
@include adf-colors-theme($theme);
@@ -56,6 +57,7 @@
@include adf-task-list-comment-theme($theme);
@include adf-layout-container-theme($theme);
@include adf-empty-content-theme($theme);
+ @include adf-error-content-theme($theme);
}
diff --git a/lib/core/components/empty-content/empty-content.component.html b/lib/core/templates/empty-content/empty-content.component.html
similarity index 100%
rename from lib/core/components/empty-content/empty-content.component.html
rename to lib/core/templates/empty-content/empty-content.component.html
diff --git a/lib/core/components/empty-content/empty-content.component.scss b/lib/core/templates/empty-content/empty-content.component.scss
similarity index 100%
rename from lib/core/components/empty-content/empty-content.component.scss
rename to lib/core/templates/empty-content/empty-content.component.scss
diff --git a/lib/core/components/empty-content/empty-content.component.ts b/lib/core/templates/empty-content/empty-content.component.ts
similarity index 100%
rename from lib/core/components/empty-content/empty-content.component.ts
rename to lib/core/templates/empty-content/empty-content.component.ts
diff --git a/lib/core/templates/error-content/error-content.component.html b/lib/core/templates/error-content/error-content.component.html
new file mode 100644
index 0000000000..935ba2c2a0
--- /dev/null
+++ b/lib/core/templates/error-content/error-content.component.html
@@ -0,0 +1,9 @@
+
+
{{ errorCode }}
+
+
{{ errorTitle | translate }}
+
{{ errorDescription | translate }}
+ {{ errorLinkText | translate }}
+
{{ homeButton | translate}}
+
diff --git a/lib/core/templates/error-content/error-content.component.scss b/lib/core/templates/error-content/error-content.component.scss
new file mode 100644
index 0000000000..ae88b499a0
--- /dev/null
+++ b/lib/core/templates/error-content/error-content.component.scss
@@ -0,0 +1,72 @@
+@mixin adf-error-content-theme($theme) {
+
+ $primary: map-get($theme, primary);
+ $foreground: map-get($theme, foreground);
+
+ .adf-error-content {
+ color: mat-color($foreground, text, 0.54);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+
+ &-code {
+ font-size: 110px;
+ font-weight: 300;
+ margin-top: 200px;
+ margin-bottom: 45px;
+ }
+
+ &-shadow {
+ width: 170px;
+ height: 3px;
+ opacity: 0.54;
+ box-shadow: 0 10px 15px 0 rgba(0, 0, 0, 0.39);
+ }
+
+ &-title {
+ font-size: 46px;
+ font-weight: normal;
+ margin-top: 40px;
+ margin-bottom: 10px;
+ }
+
+ &-description {
+ font-size: 24px;
+ font-weight: normal;
+ text-align: center;
+ width: 50%;
+ min-width: 250px;
+ margin-bottom: 60px;
+ line-height: 30px;
+
+ &-link{
+ color: mat-color($primary);
+ text-decoration: none;
+ }
+ }
+ }
+
+ @media screen and ($mat-small) {
+ .adf-error-content {
+
+ &-code {
+ margin-top: 100px;
+ font-size: 50px;
+ margin-bottom: 25px;
+ }
+
+ &-shadow {
+ width: 100px;
+ }
+
+ &-title {
+ font-size: 24px;
+ }
+
+ &-description {
+ font-size: 17px;
+ }
+ }
+ }
+}
diff --git a/lib/core/templates/error-content/error-content.component.spec.ts b/lib/core/templates/error-content/error-content.component.spec.ts
new file mode 100644
index 0000000000..53514cc7d5
--- /dev/null
+++ b/lib/core/templates/error-content/error-content.component.spec.ts
@@ -0,0 +1,100 @@
+/*!
+ * @license
+ * Copyright 2016 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.
+ */
+
+/*tslint:disable:ban*/
+
+import { TestBed, async } from '@angular/core/testing';
+import { CoreTestingModule } from '../../testing/core.testing.module';
+import { ErrorContentComponent } from './error-content.component';
+import { TranslationService } from '../../services/translation.service';
+import { TranslationMock } from '../../mock/translation.service.mock';
+import { setupTestBed } from '../../testing/setupTestBed';
+
+describe('ErrorContentComponent', () => {
+
+ let fixture;
+ let errorContentComponent: ErrorContentComponent;
+ let element: HTMLElement;
+ let translateService: TranslationService;
+
+ setupTestBed({
+ imports: [CoreTestingModule],
+ providers: [
+ { provide: TranslationService, useClass: TranslationMock }
+ ]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(ErrorContentComponent);
+ element = fixture.nativeElement;
+ errorContentComponent = fixture.debugElement.componentInstance;
+ translateService = TestBed.get(TranslationService);
+ });
+
+ afterEach(() => {
+ fixture.destroy();
+ TestBed.resetTestingModule();
+ });
+
+ it('should create error component', async(() => {
+ fixture.detectChanges();
+ expect(errorContentComponent).toBeTruthy();
+ }));
+
+ it('should render error code', async(() => {
+ fixture.detectChanges();
+ const errorContentElement = element.querySelector('.adf-error-content-code');
+ expect(errorContentElement).not.toBeNull();
+ expect(errorContentElement).toBeDefined();
+ }));
+
+ it('should render error title', async(() => {
+ fixture.detectChanges();
+ const errorContentElement = element.querySelector('.adf-error-content-title');
+ expect(errorContentElement).not.toBeNull();
+ expect(errorContentElement).toBeDefined();
+ }));
+
+ it('should render error description', async(() => {
+ fixture.detectChanges();
+ const errorContentElement = element.querySelector('.adf-error-content-description');
+ expect(errorContentElement).not.toBeNull();
+ expect(errorContentElement).toBeDefined();
+ }));
+
+ it('should render report issue links', async(() => {
+ errorContentComponent.errorLinkUrl = '403 Link';
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ const errorContentElement = element.querySelector('.adf-error-content-description-link');
+ expect(errorContentElement).not.toBeNull();
+ expect(errorContentElement).toBeDefined();
+ });
+ }));
+
+ it('should hide link if this one is empty', async(() => {
+ spyOn(translateService, 'instant').and.callFake((inputString) => {
+ return '';
+ } );
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ const errorContentElement = element.querySelector('.adf-error-content-description-link');
+ expect(errorContentElement).toBeNull();
+ });
+ }));
+
+});
diff --git a/lib/core/templates/error-content/error-content.component.ts b/lib/core/templates/error-content/error-content.component.ts
new file mode 100644
index 0000000000..3eb3d6b268
--- /dev/null
+++ b/lib/core/templates/error-content/error-content.component.ts
@@ -0,0 +1,79 @@
+/*!
+ * @license
+ * Copyright 2016 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 { Component, ChangeDetectionStrategy, ViewEncapsulation, OnInit } from '@angular/core';
+import { Params, ActivatedRoute } from '@angular/router';
+import { TranslationService } from '../../services/translation.service';
+
+@Component({
+ selector: 'adf-error-content',
+ templateUrl: './error-content.component.html',
+ styleUrls: ['./error-content.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ encapsulation: ViewEncapsulation.None,
+ host: { class: 'adf-error-content' }
+})
+export class ErrorContentComponent implements OnInit {
+
+ errorCode: string;
+
+ errorTitle: string;
+ errorDescription: string;
+ errorLinkText: string;
+ errorLinkUrl: string;
+
+ homeButton: string;
+
+ constructor(private route: ActivatedRoute,
+ private translateService: TranslationService) {
+ }
+
+ ngOnInit() {
+ if (this.route) {
+ this.route.params.forEach((params: Params) => {
+ if (params['id']) {
+ this.errorCode = params['id'];
+ }
+ });
+ }
+
+ this.getData();
+
+ }
+
+ getData() {
+ this.errorTitle = this.translateService.instant(
+ 'ERROR_CONTENT.' + this.errorCode + '.TITLE');
+
+ if (this.errorTitle === 'ERROR_CONTENT.' + this.errorCode + '.TITLE') {
+ this.errorCode = 'UNKNOWN';
+ this.errorTitle = this.translateService.instant(
+ 'ERROR_CONTENT.' + this.errorCode + '.TITLE');
+ }
+
+ this.errorDescription = this.translateService.instant(
+ 'ERROR_CONTENT.' + this.errorCode + '.DESCRIPTION');
+ this.errorLinkText = this.translateService.instant(
+ 'ERROR_CONTENT.' + this.errorCode + '.LINK.TEXT');
+ this.errorLinkUrl = this.translateService.instant(
+ 'ERROR_CONTENT.' + this.errorCode + '.LINK.URL');
+
+ this.homeButton = this.translateService.instant(
+ 'ERROR_CONTENT.HOME_BUTTON').toUpperCase();
+
+ }
+}
diff --git a/lib/core/templates/index.ts b/lib/core/templates/index.ts
new file mode 100644
index 0000000000..4c6ac1d58f
--- /dev/null
+++ b/lib/core/templates/index.ts
@@ -0,0 +1,18 @@
+/*!
+ * @license
+ * Copyright 2016 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.
+ */
+
+export * from './public-api';
diff --git a/lib/core/templates/public-api.ts b/lib/core/templates/public-api.ts
new file mode 100644
index 0000000000..182c2242ab
--- /dev/null
+++ b/lib/core/templates/public-api.ts
@@ -0,0 +1,21 @@
+/*!
+ * @license
+ * Copyright 2016 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.
+ */
+
+export * from './error-content/error-content.component';
+export * from './empty-content/empty-content.component';
+
+export * from './template.module';
diff --git a/lib/core/templates/template.module.ts b/lib/core/templates/template.module.ts
new file mode 100644
index 0000000000..e357ac560c
--- /dev/null
+++ b/lib/core/templates/template.module.ts
@@ -0,0 +1,40 @@
+/*!
+ * @license
+ * Copyright 2016 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 { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { TranslateModule } from '@ngx-translate/core';
+import { MaterialModule } from '../material.module';
+import { ErrorContentComponent } from './error-content/error-content.component';
+import { EmptyContentComponent } from './empty-content/empty-content.component';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ MaterialModule,
+ TranslateModule
+ ],
+ declarations: [
+ ErrorContentComponent,
+ EmptyContentComponent
+ ],
+ exports: [
+ ErrorContentComponent,
+ EmptyContentComponent
+ ]
+})
+export class TemplatetModule {}