@nova-ui/dashboards
Version:
Nova Dashboards is a framework designed to provide feature developers with a common solution for presenting data coming from various sources within a single view, as well as a set of predefined widget visualizations that are 100% configuration-driven and
254 lines • 11.2 kB
JavaScript
;
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
Object.defineProperty(exports, "__esModule", { value: true });
exports.DashboardComponent = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@angular/core");
const angular_gridster2_1 = require("angular-gridster2");
const defaultsDeep_1 = tslib_1.__importDefault(require("lodash/defaultsDeep"));
const bits_1 = require("@nova-ui/bits");
const default_gridster_config_1 = require("./default-gridster-config");
const types_1 = require("../../services/types");
const types_2 = require("../../types");
let DashboardComponent = class DashboardComponent {
get dashboard() {
return this.dashboardBuffer || this._dashboard;
}
set dashboard(value) {
this._dashboard = value;
this.dashboardBuffer = null;
}
get hostClass() {
return true;
}
constructor(eventBus) {
this.eventBus = eventBus;
this.editMode = false;
this.gridsterConfigChange = new core_1.EventEmitter();
this.dashboardChange = new core_1.EventEmitter();
this.gridsterItemsVisibilityMap = {};
this.orderWidgets = (a, b) => {
const nextWidget = this.dashboard.positions[a.key];
const currentWidget = this.dashboard.positions[b.key];
return nextWidget.y - currentWidget.y || nextWidget.x - currentWidget.x;
};
this.trackByFn = (index, item) => item.key;
this.updateWidgetPosition = (item, itemComponent) => {
const widgetId = String(itemComponent.widgetId);
const dashboard = (0, bits_1.immutableSet)(this.dashboard, "positions." + widgetId, item);
this.dashboardChange.emit(dashboard);
this.eventBus.getStream(types_1.WIDGET_POSITION_CHANGE).next({
widgetId,
payload: item,
});
};
this.emitWidgetResize = (item, itemComponent) => {
const widgetId = itemComponent.widgetId;
this.eventBus.getStream(types_1.WIDGET_RESIZE).next({
widgetId,
payload: {
widgetId,
height: itemComponent.height,
width: itemComponent.width,
},
});
};
}
ngAfterViewInit() {
// need to wait till DOM is rendered because of "getBoundingClientRect" under the hood
setTimeout(() => this.calculateWidgetsVisibility());
}
onGridsterScroll() {
this.calculateWidgetsVisibility();
}
ngOnChanges(changes) {
if (changes.gridsterConfig) {
if (changes.gridsterConfig.isFirstChange()) {
const gridsterConfig = (0, defaultsDeep_1.default)(this.gridsterConfig || {}, default_gridster_config_1.DEFAULT_GRIDSTER_CONFIG);
this.hookEvent(gridsterConfig, "itemChangeCallback", this.updateWidgetPosition);
this.hookEvent(gridsterConfig, "itemResizeCallback", this.emitWidgetResize);
this.gridsterConfigChange.emit(gridsterConfig);
}
if (this.gridsterConfig?.api) {
this.gridsterConfig.api.optionsChanged?.();
}
}
if (changes.editMode) {
if (!this.gridsterConfig.resizable) {
throw new Error(`Gridster's resizable prop is undefined`);
}
this.gridsterConfig.resizable.enabled = this.editMode;
if (!this.gridsterConfig.draggable) {
throw new Error(`Gridster's draggable prop is undefined`);
}
this.gridsterConfig.draggable.enabled = this.editMode;
this.gridsterConfigChange.emit(Object.assign({}, this.gridsterConfig));
this.eventBus
.getStream(types_1.DASHBOARD_EDIT_MODE)
.next({ payload: this.editMode });
}
// TODO: position doesn't update on external change of position
// if (!changes.dashboard.isFirstChange() &&
// changes.dashboard.currentValue.positions !== changes.dashboard.previousValue.positions) {
// if (this.gridsterConfig.api) {
// this.gridsterConfig.api.optionsChanged();
// }
// }
}
onWidgetChange(widget) {
// this could happen when changes are being made on a widget that is being removed
if (!this.dashboard.widgets[widget.id]) {
return;
}
this.updateWidget(widget);
}
updateWidget(widget) {
let dashboard = this.dashboard;
if (!this.dashboard.positions[widget.id] && this.gridsterConfig?.api) {
const gridsterItem = this.gridsterConfig.api.getFirstPossiblePosition?.({
x: 0,
y: 0,
rows: this.gridsterConfig?.defaultItemRows,
cols: this.gridsterConfig?.defaultItemCols,
});
dashboard = (0, bits_1.immutableSet)(dashboard, `positions.${widget.id}`, gridsterItem);
}
dashboard = (0, bits_1.immutableSet)(dashboard, `widgets.${widget.id}`, widget);
this.dashboardBuffer = dashboard;
this.dashboardChange.emit(dashboard);
}
removeWidget(widgetId, removePosition = true) {
let dashboard = this.dashboard;
if (!dashboard.widgets[widgetId]) {
return;
}
const widgetsClone = Object.assign({}, dashboard.widgets);
delete widgetsClone[widgetId];
dashboard = (0, bits_1.immutableSet)(dashboard, "widgets", widgetsClone);
if (removePosition) {
const positionsClone = Object.assign({}, dashboard.positions);
delete positionsClone[widgetId];
dashboard = (0, bits_1.immutableSet)(dashboard, "positions", positionsClone);
}
this.dashboardChange.emit(dashboard);
}
shouldWidgetRender(key) {
return this.belowFoldLazyLoadingConfig?.enabled
? this.gridsterItemsVisibilityMap[key]
: true;
}
hookEvent(options, eventName, invoke) {
const prevEvent = options[eventName];
options[eventName] = (item, itemComponent) => {
invoke(item, itemComponent);
if (prevEvent) {
prevEvent(item, itemComponent);
}
};
}
calculateWidgetsVisibility() {
if (!this.belowFoldLazyLoadingConfig?.enabled) {
return;
}
const gridsterRect = this.gridster.el.getBoundingClientRect();
this.gridsterItemsVisibilityMap = this.gridsterItems.reduce((acc, next) => {
const { el } = next;
const idx = next.widgetId;
// if widget is already loaded don't hide it
if (!this.belowFoldLazyLoadingConfig.configuration
?.reloadWidgetsOnScroll) {
const prevVisibility = acc[idx];
if (prevVisibility) {
return acc;
}
}
const rect = el.getBoundingClientRect();
const getHeightVisibility = () => (rect.top > gridsterRect.top &&
rect.top < gridsterRect.bottom) ||
(rect.bottom > gridsterRect.top &&
rect.bottom < gridsterRect.bottom);
const getWidthVisibility = () => (rect.left > gridsterRect.left &&
rect.left < gridsterRect.right) ||
(rect.right > gridsterRect.left &&
rect.right < gridsterRect.right);
const isVisible = getHeightVisibility() && getWidthVisibility();
acc[idx] = isVisible;
return acc;
}, this.gridsterItemsVisibilityMap);
}
};
exports.DashboardComponent = DashboardComponent;
tslib_1.__decorate([
(0, core_1.Input)(),
tslib_1.__metadata("design:type", Object)
], DashboardComponent.prototype, "gridsterConfig", void 0);
tslib_1.__decorate([
(0, core_1.Input)(),
tslib_1.__metadata("design:type", Object),
tslib_1.__metadata("design:paramtypes", [Object])
], DashboardComponent.prototype, "dashboard", null);
tslib_1.__decorate([
(0, core_1.Input)(),
tslib_1.__metadata("design:type", Object)
], DashboardComponent.prototype, "editMode", void 0);
tslib_1.__decorate([
(0, core_1.Input)(),
tslib_1.__metadata("design:type", Object)
], DashboardComponent.prototype, "belowFoldLazyLoadingConfig", void 0);
tslib_1.__decorate([
(0, core_1.Output)(),
tslib_1.__metadata("design:type", Object)
], DashboardComponent.prototype, "gridsterConfigChange", void 0);
tslib_1.__decorate([
(0, core_1.Output)(),
tslib_1.__metadata("design:type", Object)
], DashboardComponent.prototype, "dashboardChange", void 0);
tslib_1.__decorate([
(0, core_1.HostBinding)("class.nui-dashboard"),
tslib_1.__metadata("design:type", Boolean),
tslib_1.__metadata("design:paramtypes", [])
], DashboardComponent.prototype, "hostClass", null);
tslib_1.__decorate([
(0, core_1.ViewChild)(angular_gridster2_1.GridsterComponent),
tslib_1.__metadata("design:type", angular_gridster2_1.GridsterComponent)
], DashboardComponent.prototype, "gridster", void 0);
tslib_1.__decorate([
(0, core_1.ViewChildren)(angular_gridster2_1.GridsterItemComponent),
tslib_1.__metadata("design:type", core_1.QueryList)
], DashboardComponent.prototype, "gridsterItems", void 0);
exports.DashboardComponent = DashboardComponent = tslib_1.__decorate([
(0, core_1.Component)({
selector: "nui-dashboard",
templateUrl: "./dashboard.component.html",
styleUrls: ["./dashboard.component.less"],
encapsulation: core_1.ViewEncapsulation.None,
providers: [
{
provide: types_2.DASHBOARD_EVENT_BUS,
useClass: bits_1.EventBus,
},
],
standalone: false,
}),
tslib_1.__param(0, (0, core_1.Inject)(types_2.DASHBOARD_EVENT_BUS)),
tslib_1.__metadata("design:paramtypes", [bits_1.EventBus])
], DashboardComponent);
//# sourceMappingURL=dashboard.component.js.map