iurynogueira/ion

View on GitHub
stories/Table.stories.ts

Summary

Maintainability
C
1 day
Test Coverage
import { Meta, Story } from '@storybook/angular';

import { IonTableComponent } from '../projects/ion/src/lib/table/table.component';
import { SafeAny } from '../projects/ion/src/lib/utils/safe-any';
import {
  ColumnType,
  IonTableModule,
  TooltipPosition,
  TooltipTrigger,
} from '../projects/ion/src/public-api';

export default {
  title: 'Ion/Data Display/Table',
  component: IonTableComponent,
} as Meta;

const Template: Story<IonTableComponent<unknown>> = (
  args: IonTableComponent<unknown>
) => ({
  component: IonTableComponent,
  props: args,
  moduleMetadata: {
    imports: [IonTableModule],
  },
});

const data = [
  { id: 1, name: 'Meteora', deleted: false, year: 2003 },
  { id: 2, name: 'One More Light', deleted: false, year: 2017 },
  {
    id: 3,
    name: 'Hybrid Theory',
    deleted: true,
    year: 2000,
    icon: 'star-solid',
    status: 'warning',
  },
  {
    id: 4,
    name: 'Minutes to Midnight',
    deleted: false,
    year: 2007,
    icon: 'union',
    status: 'info',
  },
  {
    id: 5,
    name: 'A Thousand Suns',
    deleted: false,
    year: 2010,
    icon: 'union',
    status: 'info',
  },
  {
    id: 6,
    name: 'Living Things',
    deleted: false,
    year: 2012,
    icon: 'union',
    status: 'info',
  },
  {
    id: 7,
    name: 'The Hunting Party',
    deleted: false,
    year: 2014,
    icon: 'union',
    status: 'info',
  },
  {
    id: 8,
    name: 'Hybrid Theory',
    deleted: true,
    year: 2000,
    icon: 'star-solid',
    status: 'warning',
  },
  {
    id: 9,
    name: 'Minutes to Midnight',
    deleted: false,
    year: 2007,
  },
  {
    id: 10,
    name: 'A Thousand Suns',
    deleted: false,
    year: 2010,
  },
  {
    id: 11,
    name: 'Living Things',
    deleted: false,
    year: 2012,
  },
  {
    id: 12,
    name: 'The Hunting Party',
    deleted: false,
    year: 2014,
  },
];

const dataWithLink = [
  {
    id: 1,
    name: 'Meteora',
    deleted: false,
    year: 2003,
  },
  {
    id: 2,
    name: 'One More Light',
    deleted: false,
    year: 2017,
  },
  {
    id: 3,
    name: 'Hybrid Theory',
    deleted: true,
    year: 2000,
  },
  {
    id: 4,
    name: 'Minutes to Midnight',
    deleted: false,
    year: 2007,
  },
  {
    id: 5,
    name: 'A Thousand Suns',
    deleted: false,
    year: 2010,
  },
  {
    id: 6,
    name: 'Living Things',
    deleted: false,
    year: 2012,
  },
  {
    id: 7,
    name: 'The Hunting Party',
    deleted: false,
    year: 2014,
  },
  {
    id: 8,
    name: 'Hybrid Theory',
    deleted: true,
    year: 2000,
  },
  {
    id: 9,
    name: 'Minutes to Midnight',
    deleted: false,
    year: 2007,
  },
  {
    id: 10,
    name: 'A Thousand Suns',
    deleted: false,
    year: 2010,
  },
  {
    id: 11,
    name: 'Living Things',
    deleted: false,
    year: 2012,
  },
  {
    id: 12,
    name: 'The Hunting Party',
    deleted: false,
    year: 2014,
  },
];

const columns = [
  {
    key: 'id',
    label: 'Código',
    sort: true,
  },
  {
    key: 'name',
    label: 'Name',
    sort: true,
  },
];

const dataWithColumnBoolean = [
  { id: 1, name: 'Meteora', available: true },
  { id: 2, name: 'One More Light', available: false },
  {
    id: 3,
    name: 'Hybrid Theory',
    available: true,
    icon: 'star-solid',
    status: 'warning',
  },
  {
    id: 4,
    name: 'Minutes to Midnight',
    available: false,
    icon: 'union',
    status: 'info',
  },
  {
    id: 5,
    name: 'A Thousand Suns',
    available: true,
    icon: 'union',
    status: 'info',
  },
  {
    id: 6,
    name: 'Living Things',
    available: false,
    icon: 'union',
    status: 'info',
  },
  {
    id: 7,
    name: 'The Hunting Party',
    available: false,
    icon: 'union',
    status: 'info',
  },
  {
    id: 8,
    name: 'Hybrid Theory',
    available: false,
    icon: 'star-solid',
    status: 'warning',
  },
  {
    id: 9,
    name: 'Minutes to Midnight',
    available: true,
  },
  {
    id: 10,
    name: 'A Thousand Suns',
    available: true,
  },
  {
    id: 11,
    name: 'Living Things',
    available: false,
  },
  {
    id: 12,
    name: 'The Hunting Party',
    available: true,
  },
];

const columnsWithBooleanDefault = [
  {
    key: 'id',
    label: 'Código',
    sort: true,
  },
  {
    key: 'name',
    label: 'Nome',
    sort: true,
  },
  {
    key: 'available',
    label: 'Disponível',
    sort: true,
    type: ColumnType.BOOLEAN,
  },
];

const columnsWithBooleanCustom = [
  {
    key: 'id',
    label: 'Código',
    sort: true,
  },
  {
    key: 'name',
    label: 'Nome',
    sort: true,
  },
  {
    key: 'available',
    label: 'Disponível',
    sort: true,
    type: ColumnType.BOOLEAN,
    booleanText: {
      truthy: 'disponível',
      falsy: 'indisponível',
    },
  },
];

const columnsWithLink = [
  {
    key: 'id',
    label: 'Código',
    sort: true,
  },
  {
    key: 'name',
    label: 'Name',
    sort: true,
  },
  {
    key: 'link',
    label: 'URL',
    sort: true,
    type: 'link',
    link: {
      label: (row): string => row.name,
      icon: 'access2',
      iconKey: 'icon',
      bold: true,
      disabled: (): boolean => false,
    },
  },
];

const actions = [
  {
    label: 'Excluir',
    icon: 'trash',
    show: (row: SafeAny): boolean => {
      return !row.deleted;
    },
    call: (row: SafeAny): void => {
      row.name += ' DELETED';
    },
    confirm: {
      title: 'Você realmente deseja deletar?',
    },
  },
  {
    label: 'Editar',
    icon: 'pencil',
  },
];

const actionsWithLabel = [
  {
    label: 'Excluir',
    icon: 'trash',
    show: (row: SafeAny): boolean => {
      return !row.deleted;
    },
    call: (row: SafeAny): void => {
      row.name += ' DELETED';
    },
    confirm: {
      title: 'Você realmente deseja deletar?',
    },
    showLabel: true,
    rightSideIcon: false,
  },
  {
    label: 'Editar',
    icon: 'pencil',
    showLabel: true,
    rightSideIcon: false,
  },
];

const mockTooltip = {
  ionTooltipTitle: 'Eu sou um tooltip',
  ionTooltipPosition: TooltipPosition.DEFAULT,
  ionTooltipTrigger: TooltipTrigger.DEFAULT,
  ionTooltipColorScheme: 'dark',
  ionTooltipShowDelay: 1000,
  ionTooltipArrowPointAtCenter: true,
};

const columnsWithTooltip = [
  {
    key: 'id',
    label: 'Código',
    sort: true,
    configTooltip: { ...mockTooltip },
  },
  {
    key: 'name',
    label: 'Nome',
    sort: false,
    configTooltip: { ...mockTooltip },
  },
];

export const Basic = Template.bind({});
Basic.args = {
  config: {
    data,
    columns,
  },
};

export const NoData = Template.bind({});
NoData.args = {
  config: {
    data: [],
    columns,
  },
};

export const WithActions = Template.bind({});
WithActions.args = {
  config: {
    data,
    columns,
    actions,
  },
};

export const WithActionsWithLabel = Template.bind({});
WithActionsWithLabel.args = {
  config: {
    data,
    columns,
    actions: actionsWithLabel,
  },
};

export const WithCheck = Template.bind({});
WithCheck.args = {
  config: {
    data,
    columns,
    check: true,
  },
};

export const CustomWidthCell = Template.bind({});
const customWidth = JSON.parse(JSON.stringify(columns));
customWidth[1].width = 90;
CustomWidthCell.args = {
  config: {
    data,
    columns: customWidth,
  },
};

export const ColumnWithBoolean = Template.bind({});
ColumnWithBoolean.args = {
  config: {
    data: dataWithColumnBoolean,
    columns: columnsWithBooleanDefault,
  },
};

export const ColumnWithBooleanCustom = Template.bind({});
ColumnWithBooleanCustom.args = {
  config: {
    data: dataWithColumnBoolean,
    columns: columnsWithBooleanCustom,
  },
};

export const WithTagByColumn = Template.bind({});
WithTagByColumn.args = {
  config: {
    data,
    columns: [
      ...columns,
      {
        key: 'year',
        label: 'Year',
        sort: true,
        type: 'tag',
        tag: {
          icon: 'check',
          status: 'success',
        },
      },
    ],
  },
};

export const ColumnHeaderWithTooltip = Template.bind({});
ColumnHeaderWithTooltip.args = {
  config: {
    data,
    columns: columnsWithTooltip,
    actions,
  },
};

export const WithTagByRow = Template.bind({});
const customDataWithIcon = JSON.parse(JSON.stringify(data));

WithTagByRow.args = {
  config: {
    data: customDataWithIcon,
    columns: [
      ...columns,
      {
        key: 'year',
        label: 'Year',
        sort: true,
        type: 'tag',
        tag: {
          iconKey: 'icon',
          statusKey: 'status',
        },
      },
    ],
  },
};

export const WithPagination = Template.bind({});
WithPagination.args = {
  config: {
    data: [...data, ...data, ...data, ...data],
    columns,
    pagination: {
      total: 46,
      itemsPerPage: 2,
    },
    actions,
  },
};

export const CustomItemsPerPage = Template.bind({});
CustomItemsPerPage.args = {
  config: {
    data: [
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
      ...data,
    ],
    columns,
    pagination: {
      total: 3000,
      itemsPerPage: 7,
    },
  },
};

export const ActionWithDanger = Template.bind({});
ActionWithDanger.args = {
  config: {
    data,
    columns,
    actions: [{ ...actions[0], danger: true }],
    pagination: { total: 2, itemsPerPage: 2 },
  },
};

export const PopConfirmDynamicDescription = Template.bind({});
PopConfirmDynamicDescription.args = {
  config: {
    data,
    columns,
    actions: [
      {
        ...actions[0],
        confirm: {
          ...actions[0].confirm,
          description: undefined,
          dynamicDescription: (row: SafeAny): string => {
            return `Você estará excluindo o disco ${row.name} da sua base de dados!`;
          },
        },
      },
    ],
    pagination: { total: 2, itemsPerPage: 2 },
  },
};

export const TableCustomRow = Template.bind({});
TableCustomRow.args = {
  config: {
    columns,
  },
};

TableCustomRow.parameters = {
  docs: {
    description: {
      story: `Passos para customizar a linha da tabela.
    1. No HTML do seu componente, crie um ng-template com a diretiva 'let-row' e realize as customizações desejadas.
    A diretiva 'let-row' permite acessar os dados da linha através da identificação do objeto passado na configuração
    da tabela. Veja o exemplo abaixo:

    <ng-template #customTemplate let-row>
      <td>{{row.id}}</td>
      <td>{{ row.name }}</td>
      <td><ion-icon [type]="row.active ? 'check' : 'close'"></ion-icon></td>
      <td>
        <ion-icon
          type="info"
          (click)="onDetails(row)"
          style="cursor: pointer"
        ></ion-icon>
      </td>
    </ng-template>

    2. No arquivo .ts do seu componente, utilize o decorator '@ViewChild' para obter a referência do template customizado
    criado no arquivo HTML.

    export class AppComponent implements OnInit {
      @ViewChild("customTemplate", { static: true })
      customTemplate: TemplateRef<HTMLElement>;

      ...
    }

    3. Passe a referência do template customizado para o atributo customRowTemplate da configuração da tabela.

    export class AppComponent implements OnInit {
      ...

      ngOnInit(): void {
        this.config = {
          data,
          columns,
          customRowTemplate:  this.customTemplate,
        }
      }
    }
      `,
    },
  },
};

export const TableWithLinkInCell = Template.bind({});
TableWithLinkInCell.args = {
  config: {
    data: dataWithLink,
    columns: columnsWithLink,
  },
};