1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #9416: Dashboard widgets (#11823)

* Replace masonry with gridstack

* Initial work on dashboard widgets

* Implement function to save dashboard layout

* Define a default dashboard

* Clean up widgets

* Implement widget configuration views & forms

* Permit merging dict value with existing dict in user config

* Add widget deletion view

* Enable HTMX for widget configuration

* Implement view to add dashboard widgets

* ObjectCountsWidget: Identify models by app_label & name

* Add color customization to dashboard widgets

* Introduce Dashboard model to store user dashboard layout & config

* Clean up utility functions

* Remove hard-coded API URL

* Use fixed grid cell height

* Add modal close button

* Clean up dashboard views

* Rebuild JS
This commit is contained in:
Jeremy Stretch
2023-02-24 16:04:00 -05:00
committed by GitHub
parent 36771e821c
commit 084a2cc52c
40 changed files with 788 additions and 310 deletions

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

@@ -29,9 +29,9 @@
"color2k": "^2.0.0",
"dayjs": "^1.11.5",
"flatpickr": "4.6.13",
"gridstack": "^7.2.3",
"htmx.org": "^1.8.0",
"just-debounce-it": "^3.1.1",
"masonry-layout": "^4.2.2",
"query-string": "^7.1.1",
"sass": "^1.55.0",
"simplebar": "^5.3.9",
@@ -56,4 +56,4 @@
"resolutions": {
"@types/bootstrap/**/@popperjs/core": "^2.11.6"
}
}
}

View File

@@ -1,5 +1,4 @@
import { Collapse, Modal, Popover, Tab, Toast, Tooltip } from 'bootstrap';
import Masonry from 'masonry-layout';
import { createElement, getElements } from './util';
type ToastLevel = 'danger' | 'warning' | 'success' | 'info';
@@ -12,18 +11,6 @@ window.Popover = Popover;
window.Toast = Toast;
window.Tooltip = Tooltip;
/**
* Initialize masonry-layout for homepage (or any other masonry layout cards).
*/
function initMasonry(): void {
for (const grid of getElements<HTMLDivElement>('.masonry')) {
new Masonry(grid, {
itemSelector: '.masonry-item',
percentPosition: true,
});
}
}
function initTooltips() {
for (const tooltip of getElements('[data-bs-toggle="tooltip"]')) {
new Tooltip(tooltip, { container: 'body' });
@@ -194,7 +181,6 @@ export function initBootstrap(): void {
for (const func of [
initTooltips,
initModals,
initMasonry,
initTabs,
initImagePreview,
initSidebarAccordions,

View File

@@ -0,0 +1,41 @@
import { GridStack, GridStackOptions, GridStackWidget } from 'gridstack';
import { createToast } from './bs';
import { apiPatch, hasError } from './util';
async function saveDashboardLayout(
url: string,
gridData: GridStackWidget[] | GridStackOptions,
): Promise<APIResponse<APIUserConfig>> {
let data = {
layout: gridData
}
return await apiPatch<APIUserConfig>(url, data);
}
export function initDashboard(): void {
// Initialize the grid
let grid = GridStack.init({
cellHeight: 100,
});
// Create a listener for the dashboard save button
const gridSaveButton = document.getElementById('save_dashboard') as HTMLButtonElement;
if (gridSaveButton === null) {
return;
}
gridSaveButton.addEventListener('click', () => {
const url = gridSaveButton.getAttribute('data-url');
if (url == null) {
return;
}
let gridData = grid.save(false);
saveDashboardLayout(url, gridData).then(res => {
if (hasError(res)) {
const toast = createToast('danger', 'Error Saving Dashboard Config', res.error);
toast.show();
} else {
location.reload();
}
});
});
}

View File

@@ -10,6 +10,7 @@ import { initDateSelector } from './dateSelector';
import { initTableConfig } from './tableConfig';
import { initInterfaceTable } from './tables';
import { initSideNav } from './sidenav';
import { initDashboard } from './dashboard';
import { initRackElevation } from './racks';
import { initLinks } from './links';
import { initHtmx } from './htmx';
@@ -28,6 +29,7 @@ function initDocument(): void {
initTableConfig,
initInterfaceTable,
initSideNav,
initDashboard,
initRackElevation,
initLinks,
initHtmx,

View File

@@ -2,3 +2,4 @@
@import '../node_modules/@mdi/font/css/materialdesignicons.min.css';
@import '../node_modules/flatpickr/dist/flatpickr.css';
@import '../node_modules/simplebar/dist/simplebar.css';
@import 'gridstack/dist/gridstack.min.css';

View File

@@ -875,11 +875,6 @@ delegate@^3.1.2:
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
desandro-matches-selector@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/desandro-matches-selector/-/desandro-matches-selector-2.0.2.tgz#717beed4dc13e7d8f3762f707a6d58a6774218e1"
integrity sha1-cXvu1NwT59jzdi9wem1YpndCGOE=
diff@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
@@ -1411,11 +1406,6 @@ esutils@^2.0.2:
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
ev-emitter@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ev-emitter/-/ev-emitter-1.1.1.tgz#8f18b0ce5c76a5d18017f71c0a795c65b9138f2a"
integrity sha512-ipiDYhdQSCZ4hSbX4rMW+XzNKMD1prg/sTvoVmSLkuQ1MVlwjJQQA+sW8tMYR3BLUr9KjodFV4pvzunvRhd33Q==
event-target-shim@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
@@ -1496,13 +1486,6 @@ find-up@^5.0.0:
locate-path "^6.0.0"
path-exists "^4.0.0"
fizzy-ui-utils@^2.0.0:
version "2.0.7"
resolved "https://registry.yarnpkg.com/fizzy-ui-utils/-/fizzy-ui-utils-2.0.7.tgz#7df45dcc4eb374a08b65d39bb9a4beedf7330505"
integrity sha512-CZXDVXQ1If3/r8s0T+v+qVeMshhfcuq0rqIFgJnrtd+Bu8GmDmqMjntjUePypVtjHXKJ6V4sw9zeyox34n9aCg==
dependencies:
desandro-matches-selector "^2.0.0"
flat-cache@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
@@ -1582,11 +1565,6 @@ get-intrinsic@^1.1.3:
has "^1.0.3"
has-symbols "^1.0.3"
get-size@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/get-size/-/get-size-2.0.3.tgz#54a1d0256b20ea7ac646516756202769941ad2ef"
integrity sha512-lXNzT/h/dTjTxRbm9BXb+SGxxzkm97h/PCIKtlN/CBCxxmkkIVV21udumMS93MuVTDX583gqc94v3RjuHmI+2Q==
get-symbol-description@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
@@ -1784,6 +1762,11 @@ graphql-ws@^5.4.1:
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.0.tgz#39d19494dbe69d1ea719915b578bf920344a69d5"
integrity sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA==
gridstack@^7.2.3:
version "7.2.3"
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-7.2.3.tgz#bc04d3588eb5f2b7edd910e31fdac5bea8069ff2"
integrity sha512-1s4Fx+Hr4nKl064q/ygrd41XiZaC2gG6R+yz5nbOibP9vODJ6mOtjIM5x8qKN12FknakaMpVBnCa1T6V7H15hQ==
has-bigints@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
@@ -2163,14 +2146,6 @@ markdown-it@^10.0.0:
mdurl "^1.0.1"
uc.micro "^1.0.5"
masonry-layout@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/masonry-layout/-/masonry-layout-4.2.2.tgz#d57b44af13e601bfcdc423f1dd8348b5524de348"
integrity sha512-iGtAlrpHNyxaR19CvKC3npnEcAwszXoyJiI8ARV2ePi7fmYhIud25MHK8Zx4P0LCC4d3TNO9+rFa1KoK1OEOaA==
dependencies:
get-size "^2.0.2"
outlayer "^2.1.0"
mdurl@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
@@ -2341,15 +2316,6 @@ optionator@^0.9.1:
type-check "^0.4.0"
word-wrap "^1.2.3"
outlayer@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/outlayer/-/outlayer-2.1.1.tgz#29863b6de10ea5dadfffcadfa0d728907387e9a2"
integrity sha1-KYY7beEOpdrf/8rfoNcokHOH6aI=
dependencies:
ev-emitter "^1.0.0"
fizzy-ui-utils "^2.0.0"
get-size "^2.0.2"
p-limit@3.1.0, p-limit@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"