Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): add "Empty Data" warning message when grid is empty #155

Merged
merged 15 commits into from
Nov 9, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ export class Example11 {

pushNewFilterToSelectPreFilter(predefinedFilters: FilterPreset | FilterPreset[], isOptionSelected = false) {
if (isOptionSelected) {
this.resetPredefinedFilterSelection(this.predefinedPresets);
this.predefinedPresets.forEach(preFilter => preFilter.isSelected = false); // reset selection
}
const presetFilters: FilterPreset[] = Array.isArray(predefinedFilters) ? predefinedFilters : [predefinedFilters];
const filterSelect = document.querySelector('.selected-filter');
Expand Down Expand Up @@ -611,6 +611,7 @@ export class Example11 {
event.stopPropagation();
return;
}
this.predefinedPresets.forEach(preFilter => preFilter.isSelected = false); // reset selection
const currentFilters = this.sgb.filterService.getCurrentLocalFilters();

const filterName = await prompt('Please provide a name for the new Filter.');
Expand Down Expand Up @@ -665,7 +666,7 @@ export class Example11 {
}

usePredefinedFilter(filterValue: string) {
this.resetPredefinedFilterSelection(this.predefinedPresets);
this.predefinedPresets.forEach(preFilter => preFilter.isSelected = false); // reset selection
const selectedFilter = this.predefinedPresets.find(preset => preset.value === filterValue);
if (selectedFilter) {
selectedFilter.isSelected = true;
Expand All @@ -681,10 +682,6 @@ export class Example11 {
this.currentSelectedFilterPreset = selectedFilter;
}

resetPredefinedFilterSelection(predefinedFilters: FilterPreset[]) {
predefinedFilters.forEach(preFilter => preFilter.isSelected = false);
}

mockProducts() {
return [
{
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/editors/dateEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ export class DateEditor implements Editor {
if (this.flatInstance.element) {
setTimeout(() => destroyObjectDomElementProps(this.flatInstance));
}
this.flatInstance = null;
}
if (this._$editorInputElm?.remove) {
this._$editorInputElm.remove();
Expand All @@ -178,6 +177,7 @@ export class DateEditor implements Editor {
this._$inputWithData.remove();
this._$inputWithData = null;
}
this._$input.remove();
}

disable(isDisabled = true) {
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/filters/compoundDateFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export class CompoundDateFilter implements Filter {
this.$filterElm = null;
}
if (this.$selectOperatorElm) {
this.$selectOperatorElm.off('change').remove()
this.$selectOperatorElm.off('change').remove();
}
}

Expand Down
7 changes: 7 additions & 0 deletions packages/common/src/global-grid-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ export const GlobalGridOptions: GridOption = {
defaultSlickgridEventPrefix: '',
editable: false,
editorTypingDebounce: 450,
enableEmptyDataWarningMessage: true,
emptyDataWarning: {
class: 'slick-empty-data-warning',
message: 'No data to display.',
marginTop: 100,
marginLeft: 10
},
enableAutoResize: true,
enableAutoSizeColumns: true,
enableCellNavigation: false,
Expand Down
13 changes: 13 additions & 0 deletions packages/common/src/interfaces/emptyWarning.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export interface EmptyWarning {
/** Empty data warning message, defaults to "No Records Found." */
message?: string;

/** DOM Element class name, defaults to "empty-data-warning" */
class?: string;

/** Top margin position, number in pixel, of where the warning message will be displayed, default calculation is (header title row + filter row + 5px) */
marginTop?: number;

/** Left margin position, number in pixel, of where the warning message will be displayed, defaults to 10px */
marginLeft?: number;
}
10 changes: 10 additions & 0 deletions packages/common/src/interfaces/gridOption.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
DataViewOption,
DraggableGrouping,
EditCommand,
EmptyWarning,
ExcelCopyBufferOption,
ExcelExportOption,
ExportOption,
Expand Down Expand Up @@ -170,6 +171,15 @@ export interface GridOption {
/** Default to 450ms and only applies to Composite Editor, how long to wait until we start validating the editor changes on Editor that support it (integer, float, text, longText). */
editorTypingDebounce?: number;

emptyDataWarning?: EmptyWarning;

/**
* Defaults to true, will display a warning message positioned inside the grid when there's no data returned.
* When using local (in-memory) dataset, it will show the message when there's no filtered data returned.
* When using backend Pagination it will display the message as soon as the total row count is 0.
*/
enableEmptyDataWarningMessage?: boolean;

/** Do we want to emulate paging when we are scrolling? */
emulatePagingWhenScrolling?: boolean;

Expand Down
1 change: 1 addition & 0 deletions packages/common/src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export * from './editorValidationResult.interface';
export * from './editorValidator.interface';
export * from './editUndoRedoBuffer.interface';
export * from './elementPosition.interface';
export * from './emptyWarning.interface';
export * from './excelCellFormat.interface';
export * from './excelCopyBufferOption.interface';
export * from './excelExportOption.interface';
Expand Down
8 changes: 8 additions & 0 deletions packages/common/src/styles/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -861,3 +861,11 @@ $footer-right-float: right !default;
$footer-right-text-align: right !default;
$footer-right-text-color: $footer-text-color !default;
$footer-right-width: 50% !default;

/** Empty Data Warning element */
$empty-data-warning-color: $cell-text-color !default;
$empty-data-warning-font-family: $font-family !default;
$empty-data-warning-font-size: calc(#{$font-size-base} + 2px) !default;
$empty-data-warning-font-style: italic !default;
$empty-data-warning-line-height: 18px !default;
$empty-data-warning-z-index: 9999 !default;
Original file line number Diff line number Diff line change
@@ -1,7 +1,64 @@
/* pagination/pagination variables */
@import './variables';

/* Pagination styling */
// ----------------------------------------------
// Slick Footer Component
// ----------------------------------------------

.slick-custom-footer {
color: $footer-text-color;
padding: $footer-padding;
background-color: $footer-bg-color;
font-size: $footer-font-size;
font-style: $footer-font-style;
font-weight: $footer-font-weight;
height: $footer-height;

.left-footer {
color: $footer-left-text-color;
font-style: $footer-left-font-style;
font-weight: $footer-left-font-weight;
text-align: $footer-left-text-align;
padding: $footer-left-padding;
width: $footer-left-width;
float: $footer-left-float;
}

.right-footer.metrics {
color: $footer-right-text-color;
text-align: $footer-right-text-align;
font-style: $footer-right-font-style;
font-weight: $footer-right-font-weight;
text-align: $footer-right-text-align;
padding: $footer-right-padding;
width: $footer-right-width;
float: $footer-right-float;
.separator {
margin: $footer-right-separator-margin;
}
}
}


// ----------------------------------------------
// Slick Empty Data Warning Component
// ----------------------------------------------

.slick-empty-data-warning {
position: absolute;
color: $empty-data-warning-color;
font-family: $empty-data-warning-font-family;
font-size: $empty-data-warning-font-size;
font-style: $empty-data-warning-font-style;
line-height: $empty-data-warning-line-height;
z-index: $empty-data-warning-z-index;
}


// ----------------------------------------------
// Slick Pagination Component
// ----------------------------------------------

.slick-pagination {
border-top: $pagination-border-top;
border-right: $pagination-border-right;
Expand Down
35 changes: 0 additions & 35 deletions packages/common/src/styles/slick-footer.scss

This file was deleted.

3 changes: 1 addition & 2 deletions packages/common/src/styles/slickgrid-theme-bootstrap.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
@import './slick-controls';
@import './slick-editors';
@import './slick-plugins';
@import './slick-pagination';
@import './slick-footer';
@import './slick-component';
@import './slickgrid-examples';
@import './slick-bootstrap';
@import './ui-autocomplete';
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
@import './slick-controls';
@import './slick-editors';
@import './slick-plugins';
@import './slick-pagination';
@import './slick-footer';
@import './slick-component';
@import './slickgrid-examples';
@import './slick-bootstrap';
@import './ui-autocomplete';
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
@import './slick-controls';
@import './slick-editors';
@import './slick-plugins';
@import './slick-pagination';
@import './slick-footer';
@import './slick-component';
@import './slickgrid-examples';
@import './slick-bootstrap';
@import './ui-autocomplete';
Expand Down
3 changes: 1 addition & 2 deletions packages/common/src/styles/slickgrid-theme-material.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
@import './slick-controls';
@import './slick-editors';
@import './slick-plugins';
@import './slick-pagination';
@import './slick-footer';
@import './slick-component';
@import './slickgrid-examples';
@import './slick-bootstrap';
@import './ui-autocomplete';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
@import './slick-controls';
@import './slick-editors';
@import './slick-plugins';
@import './slick-pagination';
@import './slick-footer';
@import './slick-component';
@import './slickgrid-examples';
@import './slick-bootstrap';
@import './ui-autocomplete';
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
@import './slick-controls';
@import './slick-editors';
@import './slick-plugins';
@import './slick-pagination';
@import './slick-footer';
@import './slick-component';
@import './slickgrid-examples';
@import './slick-bootstrap';
@import './ui-autocomplete';
Expand Down
3 changes: 1 addition & 2 deletions packages/common/src/styles/slickgrid-theme-salesforce.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
@import './slick-controls';
@import './slick-editors';
@import './slick-plugins';
@import './slick-pagination';
@import './slick-footer';
@import './slick-component';
@import './slickgrid-examples';
@import './slick-bootstrap';
@import './ui-autocomplete';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { EmptyWarning, GridOption, sanitizeTextByAvailableSanitizer, SlickGrid } from '@slickgrid-universal/common';

export class SlickEmptyWarningComponent {
private _warningElement: HTMLDivElement | null;

/** Getter for the Grid Options pulled through the Grid Object */
get gridOptions(): GridOption {
return (this.grid && this.grid.getOptions) ? this.grid.getOptions() : {};
}

constructor(private grid: SlickGrid) { }

dispose() {
this._warningElement?.remove();
}

/**
this.angularGrid.destroy(); * Display a warning of empty data when the filtered dataset is empty
* NOTE: to make this code reusable, you could (should) move this code into a utility service
* @param gridSelector - HTML Selector of the grid <div>
* @param emptyMessage - empty data message to display in the <span>
* @param isShowing - are we showing the message?
* @param options - any styling options you'd like to pass like the text color
*/
showEmptyDataMessage(gridSelector: string, isShowing = true, emptyMessage?: string, options?: EmptyWarning) {
const gridUid = this.grid.getUID();
const mergedOptions = { ...this.gridOptions.emptyDataWarning, options };
const emptyDataClassName = mergedOptions.class || 'slick-empty-data-warning';
const finalClassNames = [gridUid, emptyDataClassName];
this._warningElement = document.querySelector<HTMLDivElement>(`.${finalClassNames.join('.')}`);
const gridElm = document.querySelector<HTMLDivElement>(gridSelector);
ghiscoding marked this conversation as resolved.
Show resolved Hide resolved

// calculate margins
const gridHeaderFilterRowHeight = this.gridOptions?.headerRowHeight ?? 30; // filter row height
const headerRowCount = 2; // header title row is calculated by SASS and defined as (17px * headerRowCount + paddingTopBottom)
const headerRowPaddingTopBottom = 10; // 5px (2x for both top/bottom), this is different in each SASS Theme
const headerRowHeight = 17 * headerRowCount + headerRowPaddingTopBottom;
const warningMessage = emptyMessage ?? mergedOptions.message ?? 'No data to display.';
const preHeaderRowHeight = this.gridOptions.showPreHeaderPanel && this.gridOptions.preHeaderPanelHeight || 0;
const marginTop = (mergedOptions.marginTop ?? (headerRowHeight + gridHeaderFilterRowHeight + 5)) + preHeaderRowHeight;
const marginLeft = mergedOptions.marginLeft ?? 10;

if (!this._warningElement) {
const sanitizedOptions = this.gridOptions && this.gridOptions.sanitizeHtmlOptions || {};
const sanitizedText = sanitizeTextByAvailableSanitizer(this.gridOptions, warningMessage, sanitizedOptions);

this._warningElement = document.createElement('div');
this._warningElement.className = finalClassNames.join(' ');
this._warningElement.innerHTML = sanitizedText;
document.body.appendChild(this._warningElement);
}

if (gridElm && this._warningElement) {
if (isShowing) {
const gridPosition = gridElm.getBoundingClientRect();
this._warningElement.style.top = `${gridPosition.top + marginTop}px`;
this._warningElement.style.left = `${gridPosition.left + marginLeft}px`;
}
this._warningElement.style.display = isShowing ? 'inline' : 'none';
}
}
}
Loading