Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
feat(empty-state): Allow custom empty-states
Browse files Browse the repository at this point in the history
Enables the usage of custom empty states. This in turn makes empty states reusable.

Closes #528
  • Loading branch information
myieye committed Feb 7, 2020
1 parent 29c725f commit 1d30409
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 3 deletions.
19 changes: 19 additions & 0 deletions components/empty-state/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,23 @@ This is mainly used in an empty entity view.

## Empty state in use

<<<<<<< HEAD
<ba-ux-snippet name="empty-state-in-use"></ba-ux-snippet>
=======
The empty state is often used in combination with a card component (replaces the
deprecated CTA card) or in an empty table or chart.

<ba-live-example name="DtExampleEmptyStateInCard" background></ba-live-example>

The following example shows a CTA card with multiple empty state items.

<ba-live-example name="DtExampleEmptyStateMultipleItemsInCard" background></ba-live-example>

## Custom empty state

Custom/Reusable empty states are also supported using the `dtCustomEmptyState`
directive. The custom empty state must both extend and provide itself as a
`DtEmptyState`.

<ba-live-example name="DtExampleCustomEmptyStateTable" background></ba-live-example>
>>>>>>> feat(empty-state): Allow custom empty-states
2 changes: 2 additions & 0 deletions components/empty-state/src/empty-state-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
DtEmptyStateItem,
DtEmptyStateItemImage,
DtEmptyStateItemTitle,
DtCustomEmptyState,
} from './empty-state';

const EMPTY_STATE_DIRECTIVES = [
Expand All @@ -32,6 +33,7 @@ const EMPTY_STATE_DIRECTIVES = [
DtEmptyStateItemImage,
DtEmptyStateItemTitle,
DtEmptyStateFooterActions,
DtCustomEmptyState,
];

@NgModule({
Expand Down
9 changes: 9 additions & 0 deletions components/empty-state/src/empty-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,12 @@ export class DtEmptyState
}
}
}

/**
* Marks a custom empty state component to be used within, for example, `<dt-table>`.
* The custom empty state must both extend and provide itself as a DtEmptyState.
*/
@Directive({
selector: '[dtCustomEmptyState]',
})
export class DtCustomEmptyState {}
3 changes: 2 additions & 1 deletion components/table/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,8 @@ for the details column could look like this:
When there is no data to display an empty state is shown. It can consist of some
text that explains why there is no content and an illustration that helps to
visualize the problem. Pass an empty state to the table using the
`<dt-empty-state>` component.
`<dt-empty-state>` component or a
[custom empty state](/components/empty-state#custom-empty-state).

<ba-live-example name="DtExampleTableEmptyState" fullwidth></ba-live-example>

Expand Down
4 changes: 3 additions & 1 deletion components/table/src/table.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
<ng-container footerRowOutlet></ng-container>

<ng-template #emptyStateTemplate>
<ng-content select="[dtTableEmptyState], dt-empty-state"></ng-content>
<ng-content
select="[dtTableEmptyState], dt-empty-state, [dtCustomEmptyState]"
></ng-content>
</ng-template>

<ng-container cdkPortalOutlet></ng-container>
Expand Down
66 changes: 66 additions & 0 deletions components/table/src/table.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
import {
DtEmptyState,
DtEmptyStateModule,
DtCustomEmptyState,
} from '@dynatrace/barista-components/empty-state';
import {
DtLoadingDistractor,
Expand Down Expand Up @@ -75,6 +76,8 @@ describe('DtTable', () => {
TestAppMultiExpandableTable,
TestStickyHeader,
TestIndicatorApp,
CustomEmptyState,
TestCustomEmptyStateApp,
],
});

Expand Down Expand Up @@ -214,6 +217,33 @@ describe('DtTable', () => {
expect(fixture.debugElement.query(By.css('dt-empty-state'))).toBeTruthy();
});

it('Should render a provided custom empty-state marked with the DtEmptyStateDirective', () => {
const fixture = createComponent(TestCustomEmptyStateApp);

expect(
fixture.debugElement.query(By.directive(DtCustomEmptyState)),
).toBeFalsy();
expect(
fixture.debugElement.query(By.directive(CustomEmptyState)),
).toBeFalsy();
expect(
fixture.debugElement.query(By.directive(DtEmptyState)),
).toBeFalsy();

fixture.componentInstance.dataSource = [];
fixture.detectChanges();

expect(
fixture.debugElement.query(By.directive(DtCustomEmptyState)),
).toBeTruthy();
expect(
fixture.debugElement.query(By.directive(CustomEmptyState)),
).toBeTruthy();
expect(
fixture.debugElement.query(By.directive(DtEmptyState)),
).toBeTruthy();
});

it('Should render a LoadingComponent', () => {
const fixture = createComponent(TestApp);
fixture.componentInstance.loading = true;
Expand Down Expand Up @@ -826,3 +856,39 @@ class TestIndicatorApp {
color: 'error' | 'warning' = 'error';
active = true;
}

@Component({
selector: 'dt-test-app',
template: `
<dt-table [dataSource]="dataSource">
<ng-container dtColumnDef="host" dtColumnAlign="text">
<dt-header-cell *dtHeaderCellDef>Host</dt-header-cell>
<dt-cell *dtCellDef="let row">{{ row.host }}</dt-cell>
</ng-container>
<dt-header-row *dtHeaderRowDef="['host']"></dt-header-row>
<dt-row *dtRowDef="let row; columns: ['host']"></dt-row>
<custom-empty-state dtCustomEmptyState></custom-empty-state>
</dt-table>
`,
})
export class TestCustomEmptyStateApp {
dataSource: object[] = [{ host: 'host-1' }];
}

@Component({
selector: 'custom-empty-state',
providers: [
{
provide: DtEmptyState,
useExisting: CustomEmptyState,
},
],
template: `
<dt-empty-state-item>
<dt-empty-state-item-title>No host</dt-empty-state-item-title>
Test message
</dt-empty-state-item>
`,
})
export class CustomEmptyState extends DtEmptyState {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<dt-card>
<dt-table [dataSource]="[]">
<ng-container dtColumnDef="host" dtColumnAlign="text">
<dt-header-cell *dtHeaderCellDef>Host</dt-header-cell>
<dt-cell *dtCellDef="let row">{{ row.host }}</dt-cell>
</ng-container>

<dt-header-row *dtHeaderRowDef="['host']"></dt-header-row>
<dt-row *dtRowDef="let row; columns: ['host']"></dt-row>
<dt-example-custom-empty-state
dtCustomEmptyState
></dt-example-custom-empty-state>
</dt-table>
</dt-card>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* @license
* Copyright 2020 Dynatrace LLC
* 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 } from '@angular/core';
import { DtEmptyState } from 'components/empty-state/src/empty-state';

@Component({
templateUrl: 'empty-state-custom-empty-state-table-example.html',
})
export class DtExampleCustomEmptyStateTable {}

@Component({
selector: 'dt-example-custom-empty-state',
providers: [
{
provide: DtEmptyState,
useExisting: DtExampleCustomEmptyState,
},
],
template: `
<dt-empty-state-item>
<dt-empty-state-item-img>
<img src="/assets/cta-noagent.svg" alt="My Asset" />
</dt-empty-state-item-img>
<dt-empty-state-item-title
>Reusable empty state</dt-empty-state-item-title
>
Custom empty state message
</dt-empty-state-item>
`,
})
export class DtExampleCustomEmptyState extends DtEmptyState {}
15 changes: 14 additions & 1 deletion libs/examples/src/empty-state/empty-state-examples.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,29 @@ import { DtExampleEmptyStateDefault } from './empty-state-default-example/empty-
import { DtExampleEmptyStateInCard } from './empty-state-in-card-example/empty-state-in-card-example';
import { DtExampleEmptyStateMultipleItems } from './empty-state-multiple-items-example/empty-state-multiple-items-example';
import { DtExampleEmptyStateMultipleItemsInCard } from './empty-state-multiple-items-in-card-example/empty-state-multiple-items-in-card-example';
import {
DtExampleCustomEmptyStateTable,
DtExampleCustomEmptyState,
} from './empty-state-custom-empty-state-table-example/empty-state-custom-empty-state-table-example';
import { DtTableModule } from 'components/table/src/table-module';

export const DT_EMPTY_STATE_EXAMPLES = [
DtExampleEmptyStateDefault,
DtExampleEmptyStateInCard,
DtExampleEmptyStateMultipleItems,
DtExampleEmptyStateMultipleItemsInCard,
DtExampleCustomEmptyStateTable,
DtExampleCustomEmptyState,
];

@NgModule({
imports: [DtEmptyStateModule, DtIconModule, DtButtonModule, DtCardModule],
imports: [
DtEmptyStateModule,
DtIconModule,
DtButtonModule,
DtCardModule,
DtTableModule,
],
declarations: [...DT_EMPTY_STATE_EXAMPLES],
entryComponents: [...DT_EMPTY_STATE_EXAMPLES],
})
Expand Down

0 comments on commit 1d30409

Please sign in to comment.