Skip to content

Commit

Permalink
feat(datagrid): style
Browse files Browse the repository at this point in the history
  • Loading branch information
aesteves60 committed Oct 4, 2023
1 parent d8851ab commit 05c0793
Show file tree
Hide file tree
Showing 12 changed files with 218 additions and 26 deletions.
2 changes: 2 additions & 0 deletions packages/components/datagrid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
"@ovhcloud/ods-common-core": "16.1.1",
"@ovhcloud/ods-common-stencil": "16.1.1",
"@ovhcloud/ods-common-theming": "16.1.1",
"@ovhcloud/ods-component-icon": "16.1.1",
"@ovhcloud/ods-component-text": "16.1.1",
"tabulator-tables": "5.5.2"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const DEFAULT_ATTRIBUTE: OdsDatagridAttribute = Object.freeze({
columns: [],
rows: [],
isSelectable: false,
placeholder: 'No Data Set',
});

export {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,36 +44,36 @@ describe('spec:ods-select-controller', () => {
it('should mapped column to a Tabular column', () => {
setup({ });
const column = { title: 'Name', field: 'name' };
const tabulartorColumn = controller.toTabulatorColumn(column);
expect(tabulartorColumn.title).toBe(column.title);
expect(tabulartorColumn.field).toBe(column.field);
expect(tabulartorColumn.headerSort).toBe(false);
const tabulatorColumn = controller.toTabulatorColumn(column);
expect(tabulatorColumn.title).toBe(column.title);
expect(tabulatorColumn.field).toBe(column.field);
expect(tabulatorColumn.headerSort).toBe(false);
});

it('should mapped column to a Tabular column with isSortable', () => {
setup({ });
const column = { title: 'Name', field: 'name', isSortable: true };
const tabulartorColumn = controller.toTabulatorColumn(column);
expect(tabulartorColumn.title).toBe(column.title);
expect(tabulartorColumn.field).toBe(column.field);
expect(tabulartorColumn.headerSort).toBe(true);
const tabulatorColumn = controller.toTabulatorColumn(column);
expect(tabulatorColumn.title).toBe(column.title);
expect(tabulatorColumn.field).toBe(column.field);
expect(tabulatorColumn.headerSort).toBe(true);
});

it('should get columns with selections columns', () => {
setup({ isSelectable: true });
const columns = [{ title: 'Name', field: 'name' }];
const tabulartorColumns = controller.getTabulatorColumns(columns);
expect(tabulartorColumns[0].formatter).toBe('rowSelection');
expect(tabulartorColumns[0].titleFormatter).toBe('rowSelection');
const tabulatorColumns = controller.getTabulatorColumns(columns);
expect(tabulatorColumns[0].formatter).toBe('rowSelection');
expect(tabulatorColumns[0].titleFormatter).toBe('rowSelection');
});

it('should get columns without selections columns', () => {
setup({ isSelectable: false });
const columns = [{ title: 'Name', field: 'name' }];
const tabulartorColumns = controller.getTabulatorColumns(columns);
expect(tabulartorColumns[0].title).toBe(columns[0].title);
expect(tabulartorColumns[0].field).toBe(columns[0].field);
expect(tabulartorColumns[0].headerSort).toBe(false);
const tabulatorColumns = controller.getTabulatorColumns(columns);
expect(tabulatorColumns[0].title).toBe(columns[0].title);
expect(tabulatorColumns[0].field).toBe(columns[0].field);
expect(tabulatorColumns[0].headerSort).toBe(false);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { OsdsDatagrid } from "../osds-datagrid";
import type { CellComponent, ColumnDefinition } from 'tabulator-tables';
import { OdsDatagridColumn, OdsDatagridRow } from "../interfaces/attributes";
import { parseStringToArray } from '@ovhcloud/ods-common-core';
import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming';
import { ODS_TEXT_SIZE } from '@ovhcloud/ods-component-text'

class OdsDatagridController {

Expand All @@ -13,7 +15,11 @@ class OdsDatagridController {
return {
title: column.title,
field: column.field,
headerSort: column.isSortable ?? false,
headerSort: column.isSortable ?? false,
headerHozAlign: 'center',
titleFormatter: (cell: CellComponent) => this.getOdsText(cell.getValue(), ODS_TEXT_SIZE._500),
formatter: (cell: CellComponent) => this.getOdsText(cell.getValue(), ODS_TEXT_SIZE._400),
hozAlign: 'center',
}
}

Expand All @@ -24,9 +30,11 @@ class OdsDatagridController {
formatter: 'rowSelection' as const,
titleFormatter: 'rowSelection' as const,
headerSort: false,
resizable: false,
cssClass: 'ods-selectable__input-checkbox',
cellClick: (_e: UIEvent, cell: CellComponent) => cell.getRow().toggleSelect(),
width: '40',
}] || []),
} as ColumnDefinition] || []),
...columns.map((column) => this.toTabulatorColumn(column)),
];
}
Expand All @@ -40,6 +48,14 @@ class OdsDatagridController {
const onError = () => { this.component.logger.warn('[OsdsDatagrid] rows string could not be parsed.');};
return parseStringToArray(this.component.rows, onError);
}

private getOdsText(text: string, size: ODS_TEXT_SIZE): string {
return `<osds-text
size="${size}"
color="${ODS_THEME_COLOR_INTENT.text}">
${text}
</osds-text>`
}
}

export {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ interface OdsDatagridAttribute {
rows: OdsDatagridRow[] | string;
/** The rows can be selectable */
isSelectable?: boolean
/** Text when the datagrid was no rows */
placeholder?: string;
}

export {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,134 @@
@import '~@ovhcloud/ods-common-theming/color/ods-theming-color';
@import '~@ovhcloud/ods-common-theming/ods-theme';
@import "~tabulator-tables/dist/css/tabulator.min.css";

@mixin ods-input-checkbox {
input[type="checkbox"] {
appearance: none;
border-radius: var(--ods-size-border-radius-01);
border: solid 3px var(--ods-color-primary-500);
margin: 0;
width: 20px;
height: 20px;

&::before {
content: "";
display: block;
width: 15px;
height: 15px;
mask-position: center;
mask-repeat: no-repeat;
}

&:checked::before {
background-color: var(--ods-color-primary-500);
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='15' viewBox='0 0 24 24'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath stroke-linecap='round' stroke-width='2' d='M4 13l5 5M20 7L9 18'/%3E%3Cpath fill='%23000000' d='M19.293 6.293a1 1 0 011.414 1.414l-11 11a.995.995 0 01-.53.277l-.118.014h-.118a.996.996 0 01-.648-.29l-5-5a1 1 0 011.414-1.415L9 16.585z'/%3E%3C/g%3E%3C/svg%3E");
}

&:indeterminate::before {
background-color: var(--ods-color-primary-500);
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24'%3E%3Cpath fill='%23000000' fill-rule='evenodd' d='M20 11a1 1 0 010 2H4a1 1 0 010-2h16z'/%3E%3C/svg%3E");
}
}
}

.tabulator {
border: none;
background-color: #FFF;

.tabulator-tableholder {
border: solid 1px var(--ods-color-blue-200);
box-sizing: border-box;
overflow-x: hidden;

.tabulator-row {
border-bottom: solid 1px var(--ods-color-blue-200);
background-color: #FFF;

&:last-child {
border-bottom: 0;
}

&:hover {
background-color: #FFF;
}
}

.tabulator-cell {
border-right: none;
height: unset !important;
}

.ods-selectable__input-checkbox {
&.tabulator-cell {
padding-left: 9px;
}
&.tabulator-cell {
@include ods-input-checkbox;
}
}

.tabulator-placeholder {

.tabulator-placeholder-contents {
color: var(--ods-color-text-500);
font-size: var(--ods-typography-body-500-font-size);
font-weight: var(--ods-typography-body-500-font-weight);
font-family: var(--ods-typography-body-500-font-family);
font-style: var(--ods-typography-body-500-font-style);
letter-spacing: var(--ods-typography-body-500-letter-spacing);
line-height: var(--ods-typography-body-500-line-height);
}
}
}

.tabulator-header {
background-color: #FFF;
border-bottom: none;
height: unset !important;

.tabulator-headers {
height: unset !important;

.tabulator-col {
background-color: #FFF;
border: none;
height: unset !important;

&.tabulator-sortable {

& .tabulator-col-title {
padding-right: 10px;
}
&:hover {
background-color: #FFF;
}
}
&.ods-selectable__input-checkbox {
@include ods-input-checkbox;

.tabulator-col-content {
padding: 0;
}
}

.tabulator-col-content {

.tabulator-col-title-holder {
display: flex;
justify-content: center;
align-items: flex-end;

.tabulator-col-title {
width: unset;
}

.tabulator-col-sorter {
position: inherit;
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,16 @@ describe('spec:osds-datagrid', () => {
});
});

describe('placeholder', () => {
odsUnitTestAttribute<OdsDatagridAttribute, 'placeholder'>({
name: 'placeholder',
defaultValue: DEFAULT_ATTRIBUTE.placeholder,
newValue: 'Aucune données de renseignée',
value: '',
setup: (value) => setup({ attributes: { ['placeholder']: value } }),
...config,
});
});

});
});
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { OdsDatagridAttribute, OdsDatagridColumn, OdsDatagridRow } from './interfaces/attributes';
import { Component, Element, Host, h, Prop, Watch } from '@stencil/core';
import { DEFAULT_ATTRIBUTE } from './constants/default-attributes';
import { TabulatorFull as Tabulator } from 'tabulator-tables';
import { ColumnComponent, TabulatorFull as Tabulator } from 'tabulator-tables';
import { OdsDatagridController } from './core/controller';
import { OdsLogger } from '@ovhcloud/ods-common-core';

import { ODS_ICON_SIZE, ODS_ICON_NAME } from '@ovhcloud/ods-component-icon'
import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming';
@Component({
tag: 'osds-datagrid',
styleUrl: 'osds-datagrid.scss',
Expand All @@ -27,6 +28,9 @@ export class OsdsDatagrid implements OdsDatagridAttribute {
/** @see OdsDatagridAttribute.isSelectable */
@Prop({ reflect: true }) public isSelectable?: boolean = DEFAULT_ATTRIBUTE.isSelectable;

/** @see OdsDatagridAttribute.placeholder */
@Prop({ reflect: true }) public placeholder?: string = DEFAULT_ATTRIBUTE.placeholder;

componentDidLoad(): void {
if (!this.grid) {
return;
Expand All @@ -35,10 +39,24 @@ export class OsdsDatagrid implements OdsDatagridAttribute {
const rows = this.controler.getRows();

this.table = new Tabulator(this.grid, {
height: "100%",
height: '100%',
data: rows,
layout: "fitColumns",
layout: 'fitColumns',
placeholder: this.placeholder,
columns: this.controler.getTabulatorColumns(columns),
headerSortElement: (_column: ColumnComponent, dir: 'asc' | 'desc' | 'none') => {
const getIcon = () => {
if (dir === 'none') {
return ODS_ICON_NAME.SORT;
}
return dir === 'desc' ? ODS_ICON_NAME.SORT_UP : ODS_ICON_NAME.SORT_DOWN;
}
return `<osds-icon
name="${getIcon()}"
size="${ODS_ICON_SIZE.sm}"
color="${ODS_THEME_COLOR_INTENT.primary}">
</osds-icon>`
},
});
}

Expand Down
2 changes: 2 additions & 0 deletions packages/components/datagrid/src/global.dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import './components';
import './global';
import { OdsLogger } from '@ovhcloud/ods-common-core';
import '@ovhcloud/ods-component-icon';
import '@ovhcloud/ods-component-text';

const logger = new OdsLogger('global-dev');
logger.log('init');
Expand Down
13 changes: 10 additions & 3 deletions packages/components/datagrid/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,22 @@

<h1>With sorted column</h1>
<osds-datagrid
columns='[{"title":"Name", "field":"name", "isSortable": true}, {"title":"Firstname", "field":"firstname"}]'
rows='[{"name":"Homer", "firstname":"Simpson"}, {"name":"Marge", "firstname":"Simpson"}]'>
columns='[{"title":"Name", "field":"name", "isSortable": true}, {"title":"Firstname", "field":"firstname"}, {"title":"Gender", "field":"gender"}]'
rows='[{"name":"Homer", "firstname":"Simpson", "gender": "Male"}, {"name":"Marge", "firstname":"Simpson", "gender": "Female"}]'>
</osds-datagrid>

<h1>With selectable columns</h1>
<osds-datagrid
is-selectable
columns='[{"title":"Name", "field":"name"}, {"title":"Firstname", "field":"firstname"}]'
rows='[{"name":"Homer", "firstname":"Simpson"}]'>
rows='[{"name":"Homer", "firstname":"Simpson"}, {"name":"Marge", "firstname":"Simpson"}]'>
</osds-datagrid>

<h1>Empty state</h1>
<osds-datagrid
columns='[{"title":"Name", "field":"name", "isSortable": true}, {"title":"Firstname", "field":"firstname"}]'
rows='[]'
placeholder="Aucune données de renseignée">
</osds-datagrid>

</body>
Expand Down
4 changes: 2 additions & 2 deletions packages/components/datagrid/stencil.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ export const config: Config = getStencilConfig({
jestConfig: jestConfig.default,
reactOutput: {
componentCorePackage: '@ovhcloud/ods-component-datagrid',
excludeComponents: []
excludeComponents: ['osds-icon', 'osds-text']
},
vueOutput: {
componentCorePackage: '@ovhcloud/ods-component-datagrid',
excludeComponents: []
excludeComponents: ['osds-icon', 'osds-text']
},
dev: {
globalScript: 'src/global.dev.ts',
Expand Down
2 changes: 2 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4684,6 +4684,8 @@ __metadata:
"@ovhcloud/ods-common-stencil": 16.1.1
"@ovhcloud/ods-common-testing": 16.1.1
"@ovhcloud/ods-common-theming": 16.1.1
"@ovhcloud/ods-component-icon": 16.1.1
"@ovhcloud/ods-component-text": 16.1.1
"@ovhcloud/ods-stencil-dev": 16.1.1
"@types/tabulator-tables": 5.5.2
tabulator-tables: 5.5.2
Expand Down

0 comments on commit 05c0793

Please sign in to comment.