├── src
├── scss
│ ├── main.scss
│ ├── mobile.scss
│ ├── breakpoints.scss
│ ├── date-picker.scss
│ ├── themes
│ │ └── deepblue.scss
│ └── gridster.scss
├── assets
│ ├── .gitkeep
│ ├── img
│ │ ├── bg.jpg
│ │ ├── logo.png
│ │ ├── map-marker-red.png
│ │ ├── icons
│ │ │ ├── done-black-18dp.svg
│ │ │ ├── check-black-18dp.svg
│ │ │ ├── checkbox.svg
│ │ │ ├── chevron_left-black-18dp.svg
│ │ │ ├── menu.svg
│ │ │ ├── check.svg
│ │ │ ├── close-black-18dp.svg
│ │ │ ├── view-2colums.svg
│ │ │ ├── burger-menu-gray.svg
│ │ │ ├── undo-black-18dp.svg
│ │ │ ├── icon-filter.svg
│ │ │ ├── view-3colums.svg
│ │ │ ├── top-records.svg
│ │ │ ├── search-black-18dp.svg
│ │ │ ├── filter_alt-black-18dp.svg
│ │ │ ├── palette-icon.svg
│ │ │ ├── view-2columns.svg
│ │ │ ├── text.svg
│ │ │ ├── view-5columns.svg
│ │ │ ├── reset.svg
│ │ │ ├── icon-reload.svg
│ │ │ ├── icon-copy.svg
│ │ │ ├── settings-black-24dp.svg
│ │ │ ├── icon-check.svg
│ │ │ ├── legend-toggle.svg
│ │ │ ├── language-24px.svg
│ │ │ ├── icon-close.svg
│ │ │ ├── close.svg
│ │ │ ├── table.svg
│ │ │ ├── icon-next.svg
│ │ │ ├── icon-next-blue.svg
│ │ │ ├── next.svg
│ │ │ ├── pen.svg
│ │ │ ├── icon-edit.svg
│ │ │ ├── view-list.svg
│ │ │ ├── view-3columns.svg
│ │ │ ├── icon-logout.svg
│ │ │ ├── icon-search.svg
│ │ │ ├── view-6columns.svg
│ │ │ └── icon-settings.svg
│ │ ├── widget-icons
│ │ │ ├── dashboard-1.svg
│ │ │ ├── widget-4.svg
│ │ │ ├── folder-1.svg
│ │ │ ├── widget-3.svg
│ │ │ ├── back-1.svg
│ │ │ ├── widget-1.svg
│ │ │ └── widget-2.svg
│ │ ├── traffic-light
│ │ │ ├── green.svg
│ │ │ ├── red.svg
│ │ │ └── yellow.svg
│ │ ├── spinner.svg
│ │ ├── smiley
│ │ │ ├── smile-red.svg
│ │ │ ├── smile-green.svg
│ │ │ └── smile-yellow.svg
│ │ └── map-pin-icon.svg
│ └── fonts
│ │ ├── Oxygen-Bold.ttf
│ │ ├── Oxygen-Light.ttf
│ │ ├── Oxygen-Regular.ttf
│ │ ├── RobotoCondensed-Bold.woff2
│ │ ├── RobotoCondensed-Italic.woff2
│ │ ├── RobotoCondensed-Light.woff2
│ │ ├── RobotoCondensed-Regular.woff2
│ │ ├── RobotoCondensed-BoldItalic.woff2
│ │ └── RobotoCondensed-LightItalic.woff2
├── app
│ ├── components
│ │ ├── widgets
│ │ │ ├── wpivot
│ │ │ │ ├── pivot.component.html
│ │ │ │ └── pivot.component.scss
│ │ │ ├── smiley
│ │ │ │ ├── smiley.component.html
│ │ │ │ ├── smiley.component.ts
│ │ │ │ └── smiley.component.scss
│ │ │ ├── traffic-light
│ │ │ │ ├── traffic-light.component.html
│ │ │ │ ├── traffic-light.component.ts
│ │ │ │ └── traffic-light.component.scss
│ │ │ ├── map-widget
│ │ │ │ └── map-widget.component.html
│ │ │ ├── map-widget-old
│ │ │ │ ├── map-widget.component.html
│ │ │ │ └── map-widget.component.scss
│ │ │ ├── light-bar
│ │ │ │ ├── light-bar.component.html
│ │ │ │ ├── light-bar.component.ts
│ │ │ │ └── light-bar.component.scss
│ │ │ ├── text
│ │ │ │ ├── wtext.component.html
│ │ │ │ └── wtext.component.scss
│ │ │ ├── charts
│ │ │ │ ├── bar-chart.component.ts
│ │ │ │ ├── column-chart.component.ts
│ │ │ │ ├── area-chart.component.ts
│ │ │ │ └── line-chart.component.ts
│ │ │ └── base
│ │ │ │ ├── widget
│ │ │ │ ├── widget.component.scss
│ │ │ │ └── widget.component.html
│ │ │ │ └── widget-filter
│ │ │ │ └── widget-filter.component.html
│ │ ├── ui
│ │ │ ├── date-picker
│ │ │ │ ├── date-picker.component.html
│ │ │ │ └── date-picker.component.scss
│ │ │ ├── error
│ │ │ │ ├── error.component.html
│ │ │ │ └── error.component.scss
│ │ │ ├── text-area
│ │ │ │ ├── text-area.component.html
│ │ │ │ ├── text-area.component.scss
│ │ │ │ └── text-area.component.ts
│ │ │ ├── sidebar
│ │ │ │ ├── sidebar.component.html
│ │ │ │ └── sidebar.component.scss
│ │ │ ├── input
│ │ │ │ └── input
│ │ │ │ │ ├── input.component.html
│ │ │ │ │ ├── input.component.scss
│ │ │ │ │ └── input.component.ts
│ │ │ ├── language-selector
│ │ │ │ ├── language-selector.component.html
│ │ │ │ └── language-selector.component.ts
│ │ │ ├── search
│ │ │ │ └── search-input
│ │ │ │ │ ├── search-input.component.html
│ │ │ │ │ └── search-input.component.scss
│ │ │ ├── about
│ │ │ │ ├── about.component.html
│ │ │ │ ├── about.component.scss
│ │ │ │ └── about.component.ts
│ │ │ ├── color-picker
│ │ │ │ ├── color-picker.component.html
│ │ │ │ └── color-picker.component.scss
│ │ │ ├── namespace-selector
│ │ │ │ ├── namespace-selector.component.html
│ │ │ │ └── namespace-selector.component.ts
│ │ │ ├── app-settings
│ │ │ │ ├── app-settings.component.scss
│ │ │ │ └── app-settings.component.html
│ │ │ ├── date-filter
│ │ │ │ ├── date-filter.component.html
│ │ │ │ └── date-filter.component.scss
│ │ │ ├── menu
│ │ │ │ ├── menu-settings
│ │ │ │ │ ├── menu-settings.component.html
│ │ │ │ │ └── menu-settings.component.ts
│ │ │ │ └── menu.component.html
│ │ │ ├── theme-settings
│ │ │ │ ├── theme-settings.component.scss
│ │ │ │ └── theme-settings.component.html
│ │ │ ├── chart-colors-config
│ │ │ │ └── chart-colors-config.component.scss
│ │ │ ├── home-editor
│ │ │ │ └── home-editor.component.scss
│ │ │ ├── share-dashboard
│ │ │ │ └── share-dashboard
│ │ │ │ │ ├── share-dashboard.component.html
│ │ │ │ │ └── share-dashboard.component.scss
│ │ │ ├── sidebar-actions
│ │ │ │ ├── sidebar-actions.component.html
│ │ │ │ └── sidebar-actions.component.ts
│ │ │ ├── tabs
│ │ │ │ └── tabs.component.html
│ │ │ └── modal
│ │ │ │ └── modal.component.html
│ │ ├── editor
│ │ │ ├── widget-editor
│ │ │ │ └── widget-editor.component.scss
│ │ │ ├── type-and-datasource
│ │ │ │ ├── type-and-datasource.component.scss
│ │ │ │ └── type-and-datasource.component.html
│ │ │ └── datasource-selector-dialog
│ │ │ │ ├── datasource-selector-dialog.html
│ │ │ │ └── datasource-selector-dialog.scss
│ │ └── screens
│ │ │ ├── main-screen
│ │ │ ├── main-screen.component.scss
│ │ │ ├── main-screen.component.html
│ │ │ └── main-screen.component.ts
│ │ │ └── folder-screen
│ │ │ └── folder-screen.component.html
│ ├── services
│ │ ├── menu.service.ts
│ │ ├── widget.service.ts
│ │ ├── broadcast.service.ts
│ │ ├── variables.service.ts
│ │ ├── header.service.ts
│ │ ├── lpt.types.ts
│ │ └── error.service.ts
│ ├── app.component.scss
│ ├── directives
│ │ ├── focus-next.directive.ts
│ │ └── auto-focus.directive.ts
│ ├── app.component.html
│ └── app.routes.ts
├── environments
│ ├── environment.prod.ts
│ ├── environment.ts
│ └── dsw.ts
├── main.ts
├── addons
│ ├── tsconfig.json
│ └── htmlViewer.ts
├── test.ts
└── manifest.webmanifest
├── screenshot.png
├── dist
├── assets
│ ├── img
│ │ ├── bg.jpg
│ │ ├── logo.png
│ │ ├── map-marker-red.png
│ │ ├── icons
│ │ │ ├── done-black-18dp.svg
│ │ │ ├── check-black-18dp.svg
│ │ │ ├── checkbox.svg
│ │ │ ├── chevron_left-black-18dp.svg
│ │ │ ├── menu.svg
│ │ │ ├── check.svg
│ │ │ ├── close-black-18dp.svg
│ │ │ ├── view-2colums.svg
│ │ │ ├── burger-menu-gray.svg
│ │ │ ├── undo-black-18dp.svg
│ │ │ ├── icon-filter.svg
│ │ │ ├── view-3colums.svg
│ │ │ ├── top-records.svg
│ │ │ ├── search-black-18dp.svg
│ │ │ ├── filter_alt-black-18dp.svg
│ │ │ ├── palette-icon.svg
│ │ │ ├── view-2columns.svg
│ │ │ ├── text.svg
│ │ │ ├── view-5columns.svg
│ │ │ ├── reset.svg
│ │ │ ├── icon-reload.svg
│ │ │ ├── icon-copy.svg
│ │ │ ├── settings-black-24dp.svg
│ │ │ ├── icon-check.svg
│ │ │ ├── legend-toggle.svg
│ │ │ ├── language-24px.svg
│ │ │ ├── icon-close.svg
│ │ │ ├── close.svg
│ │ │ ├── table.svg
│ │ │ ├── icon-next.svg
│ │ │ ├── icon-next-blue.svg
│ │ │ ├── next.svg
│ │ │ ├── pen.svg
│ │ │ ├── icon-edit.svg
│ │ │ ├── view-list.svg
│ │ │ ├── view-3columns.svg
│ │ │ ├── icon-logout.svg
│ │ │ ├── icon-search.svg
│ │ │ ├── view-6columns.svg
│ │ │ └── icon-settings.svg
│ │ ├── widget-icons
│ │ │ ├── dashboard-1.svg
│ │ │ ├── widget-4.svg
│ │ │ ├── folder-1.svg
│ │ │ ├── widget-3.svg
│ │ │ ├── back-1.svg
│ │ │ ├── widget-1.svg
│ │ │ └── widget-2.svg
│ │ ├── traffic-light
│ │ │ ├── green.svg
│ │ │ ├── red.svg
│ │ │ └── yellow.svg
│ │ ├── spinner.svg
│ │ ├── smiley
│ │ │ ├── smile-red.svg
│ │ │ ├── smile-green.svg
│ │ │ └── smile-yellow.svg
│ │ └── map-pin-icon.svg
│ └── fonts
│ │ ├── Oxygen-Bold.ttf
│ │ ├── Oxygen-Light.ttf
│ │ ├── Oxygen-Regular.ttf
│ │ ├── RobotoCondensed-Bold.woff2
│ │ ├── RobotoCondensed-Italic.woff2
│ │ ├── RobotoCondensed-Light.woff2
│ │ ├── RobotoCondensed-Regular.woff2
│ │ ├── RobotoCondensed-BoldItalic.woff2
│ │ └── RobotoCondensed-LightItalic.woff2
├── config.json
├── media
│ ├── fontawesome-webfont-FMJ3VJ65.eot
│ ├── fontawesome-webfont-RJ6LE7IU.ttf
│ ├── fontawesome-webfont-5GKVPAEF.woff2
│ └── fontawesome-webfont-Z4ARLA73.woff
├── chunk-N4BXP7J5.js
├── chunk-CBDZIDUZ.js
├── chunk-RU73HBGW.js
├── chunk-QDTU75BJ.js
├── chunk-NHWJ6QQD.js
├── chunk-XEMLRN7T.js
├── chunk-QT4NCOPW.js
├── chunk-HFC6Q7LK.js
├── chunk-23TAPEHU.js
├── chunk-MDOQS4TE.js
├── chunk-G7BOERRR.js
├── chunk-YE4HGH46.js
├── chunk-MG3ERZGY.js
├── chunk-ZMZIHCGB.js
├── manifest.webmanifest
└── chunk-NF3Y2YSA.js
├── public
└── config.json
├── oauth.json
├── docker-compose.yml
├── .editorconfig
├── tsconfig.app.json
├── proxy.conf.samples-bi.js
├── proxy.conf.local.js
├── proxy.conf.js
├── module.xml
├── iris.script
├── .github
├── sync-zpm-version.js
└── workflows
│ ├── test-ui.yml
│ └── angular-build.yml
├── .gitignore
├── Installer.cls
├── karma.conf.js
├── LICENSE
├── Dockerfile
├── tsconfig.json
└── ngsw-config.json
/src/scss/main.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/components/widgets/wpivot/pivot.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/components/ui/date-picker/date-picker.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/components/editor/widget-editor/widget-editor.component.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/components/editor/type-and-datasource/type-and-datasource.component.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/components/ui/error/error.component.html:
--------------------------------------------------------------------------------
1 | {{error.message}}
2 |
--------------------------------------------------------------------------------
/src/scss/mobile.scss:
--------------------------------------------------------------------------------
1 | [desktop-hidden] {
2 | display: initial !important;
3 | }
4 |
--------------------------------------------------------------------------------
/src/app/components/widgets/wpivot/pivot.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | height: 100%;
3 | }
4 |
--------------------------------------------------------------------------------
/src/app/components/ui/date-picker/date-picker.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 |
4 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/screenshot.png
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/src/app/components/ui/text-area/text-area.component.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/assets/img/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/img/bg.jpg
--------------------------------------------------------------------------------
/dist/assets/img/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/img/bg.jpg
--------------------------------------------------------------------------------
/src/assets/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/img/logo.png
--------------------------------------------------------------------------------
/dist/assets/img/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/img/logo.png
--------------------------------------------------------------------------------
/dist/assets/fonts/Oxygen-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/fonts/Oxygen-Bold.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Oxygen-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/fonts/Oxygen-Bold.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Oxygen-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/fonts/Oxygen-Light.ttf
--------------------------------------------------------------------------------
/src/assets/img/map-marker-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/img/map-marker-red.png
--------------------------------------------------------------------------------
/dist/assets/fonts/Oxygen-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/fonts/Oxygen-Light.ttf
--------------------------------------------------------------------------------
/dist/assets/fonts/Oxygen-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/fonts/Oxygen-Regular.ttf
--------------------------------------------------------------------------------
/dist/assets/img/map-marker-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/img/map-marker-red.png
--------------------------------------------------------------------------------
/src/assets/fonts/Oxygen-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/fonts/Oxygen-Regular.ttf
--------------------------------------------------------------------------------
/src/app/components/screens/main-screen/main-screen.component.scss:
--------------------------------------------------------------------------------
1 | :host {
2 | display: block;
3 | width: 100%;
4 | height: 100%;
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/components/ui/sidebar/sidebar.component.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "namespace": "MDX2JSON",
3 | "endpoints": {
4 | "mdx2json": "MDX2JSON"
5 | },
6 | "defaultApp": ""
7 | }
8 |
--------------------------------------------------------------------------------
/dist/media/fontawesome-webfont-FMJ3VJ65.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/media/fontawesome-webfont-FMJ3VJ65.eot
--------------------------------------------------------------------------------
/dist/media/fontawesome-webfont-RJ6LE7IU.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/media/fontawesome-webfont-RJ6LE7IU.ttf
--------------------------------------------------------------------------------
/public/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "namespace": "MDX2JSON",
3 | "endpoints": {
4 | "mdx2json": "MDX2JSON"
5 | },
6 | "defaultApp": ""
7 | }
8 |
--------------------------------------------------------------------------------
/src/assets/fonts/RobotoCondensed-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/fonts/RobotoCondensed-Bold.woff2
--------------------------------------------------------------------------------
/dist/assets/fonts/RobotoCondensed-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/fonts/RobotoCondensed-Bold.woff2
--------------------------------------------------------------------------------
/dist/assets/fonts/RobotoCondensed-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/fonts/RobotoCondensed-Italic.woff2
--------------------------------------------------------------------------------
/dist/assets/fonts/RobotoCondensed-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/fonts/RobotoCondensed-Light.woff2
--------------------------------------------------------------------------------
/dist/media/fontawesome-webfont-5GKVPAEF.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/media/fontawesome-webfont-5GKVPAEF.woff2
--------------------------------------------------------------------------------
/dist/media/fontawesome-webfont-Z4ARLA73.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/media/fontawesome-webfont-Z4ARLA73.woff
--------------------------------------------------------------------------------
/src/assets/fonts/RobotoCondensed-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/fonts/RobotoCondensed-Italic.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/RobotoCondensed-Light.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/fonts/RobotoCondensed-Light.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/RobotoCondensed-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/fonts/RobotoCondensed-Regular.woff2
--------------------------------------------------------------------------------
/dist/assets/fonts/RobotoCondensed-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/fonts/RobotoCondensed-Regular.woff2
--------------------------------------------------------------------------------
/dist/chunk-N4BXP7J5.js:
--------------------------------------------------------------------------------
1 | import{a as e}from"./chunk-YE4HGH46.js";import"./chunk-MG3ERZGY.js";var o=class extends e{decodeBlock(r){return r}};export{o as default};
2 |
--------------------------------------------------------------------------------
/dist/assets/fonts/RobotoCondensed-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/fonts/RobotoCondensed-BoldItalic.woff2
--------------------------------------------------------------------------------
/dist/assets/fonts/RobotoCondensed-LightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/dist/assets/fonts/RobotoCondensed-LightItalic.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/RobotoCondensed-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/fonts/RobotoCondensed-BoldItalic.woff2
--------------------------------------------------------------------------------
/src/assets/fonts/RobotoCondensed-LightItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/intersystems-community/DeepSeeWeb/master/src/assets/fonts/RobotoCondensed-LightItalic.woff2
--------------------------------------------------------------------------------
/dist/chunk-CBDZIDUZ.js:
--------------------------------------------------------------------------------
1 | import{a}from"./chunk-XC5FPF3U.js";import"./chunk-XVF25FWQ.js";import"./chunk-YZADXMU6.js";import"./chunk-ZEAAPN4P.js";import"./chunk-MG3ERZGY.js";export{a as ShareDashboardComponent};
2 |
--------------------------------------------------------------------------------
/dist/chunk-RU73HBGW.js:
--------------------------------------------------------------------------------
1 | import{S as r,ba as o,c as n,oa as s,xa as i}from"./chunk-ZEAAPN4P.js";function c(t){t||(s(c),t=o(i));let u=new n(e=>t.onDestroy(e.next.bind(e)));return e=>e.pipe(r(u))}export{c as a};
2 |
--------------------------------------------------------------------------------
/src/app/components/screens/main-screen/main-screen.component.html:
--------------------------------------------------------------------------------
1 | @if (isFolder) {
2 |
3 | }
4 | @if (!isFolder) {
5 |
6 | }
7 |
--------------------------------------------------------------------------------
/src/app/components/ui/text-area/text-area.component.scss:
--------------------------------------------------------------------------------
1 | @import "breakpoints";
2 |
3 | textarea {
4 | min-width: 500px;
5 | min-height: 150px;
6 |
7 | @include sm {
8 | min-width: auto;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/dist/chunk-QDTU75BJ.js:
--------------------------------------------------------------------------------
1 | import{a as e}from"./chunk-PZJJYAMS.js";import{a as r}from"./chunk-YE4HGH46.js";import"./chunk-MG3ERZGY.js";var o=class extends r{decodeBlock(t){return e(new Uint8Array(t)).buffer}};export{o as default};
2 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/done-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/icons/done-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/check-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/icons/check-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/icons/checkbox.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/checkbox.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/chevron_left-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/icons/chevron_left-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/icons/menu.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/menu.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/check.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/oauth.json:
--------------------------------------------------------------------------------
1 | {
2 | "auth": {
3 | "socialKeys": {
4 | "github": "c59b1f8a0a798a43513a",
5 | "intersystems": "9M-iTne2oe6ckE4_MZ92TaQCffzzDdf8SNmnD8HAV1U"
6 | },
7 | "redirect": "localhost/redirect.html",
8 | "proxy": "localhost/oauthproxy"
9 | }
10 | }
--------------------------------------------------------------------------------
/src/assets/img/icons/check.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/close-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/view-2colums.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/img/icons/close-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/icons/view-2colums.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/dist/chunk-NHWJ6QQD.js:
--------------------------------------------------------------------------------
1 | import{X as o,za as e}from"./chunk-ZEAAPN4P.js";var s=(()=>{class t{constructor(){this.onEditDashboard=new e,this.onSetTitle=new e}static{this.\u0275fac=function(r){return new(r||t)}}static{this.\u0275prov=o({token:t,factory:t.\u0275fac,providedIn:"root"})}}return t})();export{s as a};
2 |
--------------------------------------------------------------------------------
/src/app/components/ui/input/input/input.component.html:
--------------------------------------------------------------------------------
1 |
8 | @if (chooseButton) {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/app/components/widgets/smiley/smiley.component.html:
--------------------------------------------------------------------------------
1 | @for (d of data; track d) {
2 |
3 |
![]()
5 |
6 |
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/burger-menu-gray.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/app/components/widgets/traffic-light/traffic-light.component.html:
--------------------------------------------------------------------------------
1 | @for (d of data; track d) {
2 |
3 |
![]()
5 |
6 |
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/src/assets/img/icons/burger-menu-gray.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/app/components/ui/language-selector/language-selector.component.html:
--------------------------------------------------------------------------------
1 |
2 | @for (lang of languages; track lang) {
3 | -
4 |
5 | {{ i18n.getLanguageName(lang) }}
6 |
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/src/app/components/widgets/map-widget/map-widget.component.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/undo-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/icons/undo-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/components/ui/search/search-input/search-input.component.html:
--------------------------------------------------------------------------------
1 |
2 |
10 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/icon-filter.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon-filter.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/dist/assets/img/widget-icons/dashboard-1.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/img/widget-icons/dashboard-1.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.6'
2 | services:
3 | iris:
4 | build:
5 | context: .
6 | dockerfile: Dockerfile
7 | restart: always
8 | command: --check-caps false
9 | ports:
10 | - "1972:1972"
11 | - "52773:52773"
12 | - "53773:53773"
13 | volumes:
14 | - ./:/home/irisowner/irisdev
15 |
--------------------------------------------------------------------------------
/src/app/components/widgets/map-widget-old/map-widget.component.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.ts]
12 | quote_type = single
13 |
14 | [*.md]
15 | max_line_length = off
16 | trim_trailing_whitespace = false
17 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/view-3colums.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/app/components/ui/about/about.component.html:
--------------------------------------------------------------------------------
1 | DeepSeeWeb is an Angular UI layer for IRIS BI (DeepSee) dashboards.
2 |
3 | More info at: Github DeepSeeWeb repository
4 |
5 | Changelog
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/assets/img/icons/view-3colums.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/app/components/ui/about/about.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | :host {
4 | font-family: $font;
5 | max-width: 50vw;
6 |
7 | & h2 {
8 | font-size: 18px;
9 | margin-bottom: 20px;
10 | font-weight: normal;
11 | }
12 | }
13 |
14 |
15 | a {
16 | color: var(--cl-accent);
17 | text-decoration: none;
18 | cursor: pointer;
19 | }
20 |
--------------------------------------------------------------------------------
/src/app/services/menu.service.ts:
--------------------------------------------------------------------------------
1 | import {EventEmitter, Injectable} from '@angular/core';
2 |
3 | @Injectable({
4 | providedIn: 'root'
5 | })
6 | export class MenuService {
7 | // Triggers dashboard editing mode on/off
8 | public onEditDashboard = new EventEmitter();
9 | onSetTitle = new EventEmitter();
10 |
11 | constructor() {
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/dist/chunk-XEMLRN7T.js:
--------------------------------------------------------------------------------
1 | import{a as l}from"./chunk-YE4HGH46.js";import"./chunk-MG3ERZGY.js";var i=class extends l{decodeBlock(s){let o=new DataView(s),r=[];for(let e=0;e
7 | @if (!isImmediate) {
8 |
9 | }
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/components/ui/namespace-selector/namespace-selector.component.html:
--------------------------------------------------------------------------------
1 | @if (isLoading) {
2 |
3 | }
4 |
5 | @for (ns of items; track ns) {
6 | -
7 |
8 | {{ ns }}
9 |
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/src/app/components/ui/app-settings/app-settings.component.scss:
--------------------------------------------------------------------------------
1 | .actions {
2 | display: flex;
3 | justify-content: space-between;
4 | margin-top: 20px;
5 | margin-bottom: 10px;
6 |
7 | & > button {
8 | width: 100%;
9 |
10 | &:first-child {
11 | margin-right: 5px;
12 | }
13 |
14 | &:last-child {
15 | margin-left: 5px;
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/top-records.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/img/icons/top-records.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": [
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "src/main.ts"
12 | ],
13 | "include": [
14 | "src/**/*.d.ts"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/app.component.scss:
--------------------------------------------------------------------------------
1 | @import "breakpoints";
2 |
3 | :host {
4 | display: flex;
5 | flex-direction: column;
6 | height: 100%;
7 | }
8 |
9 | .content {
10 | display: flex;
11 | flex: 1 1 100%;
12 | height: 100%;
13 | min-height: 0;
14 |
15 | /* @include sm {
16 | position: absolute;
17 | top: var(--header-height);
18 | bottom: var(--header-height);
19 | }*/
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/components/widgets/light-bar/light-bar.component.html:
--------------------------------------------------------------------------------
1 | @for (d of data; track d) {
2 |
3 |
4 | @for (idx of dots; track idx) {
5 |
= (idx + 1)">
6 | }
7 |
8 |
9 |
10 | }
11 |
12 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/search-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/assets/img/widget-icons/widget-4.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/assets/img/icons/search-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/widget-icons/widget-4.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/filter_alt-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/icons/filter_alt-black-18dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/app/components/ui/date-filter/date-filter.component.html:
--------------------------------------------------------------------------------
1 |
2 | @for (f of filters; track f; let idx = $index) {
3 | - {{ f.label }}
7 |
8 | }
9 |
10 |
11 |
17 |
18 |
--------------------------------------------------------------------------------
/proxy.conf.samples-bi.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "/configs": {
3 | "target": "https://samples-bi-demo.demo.community.intersystems.com/dsw/",
4 | "secure": false,
5 | "logLevel": "debug",
6 | "changeOrigin": true
7 | },
8 | "/MDX2JSON": {
9 | "target": "https://samples-bi-demo.demo.community.intersystems.com/",
10 | "secure": false,
11 | "logLevel": "debug",
12 | "changeOrigin": true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/dist/assets/img/traffic-light/green.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/dist/assets/img/traffic-light/red.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/assets/img/traffic-light/green.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/assets/img/traffic-light/red.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/assets/img/traffic-light/yellow.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/dist/assets/img/traffic-light/yellow.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/app/components/ui/menu/menu-settings/menu-settings.component.html:
--------------------------------------------------------------------------------
1 |
2 | -
3 |
4 | Application
5 |
6 | -
7 |
8 | Theme
9 |
10 | -
11 |
12 | Charts
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import {bootstrapApplication} from '@angular/platform-browser';
2 | import {appConfig} from './app/app.config';
3 | import {AppComponent} from './app/app.component';
4 | import {environment} from './environments/environment';
5 | import {enableProdMode} from '@angular/core';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | bootstrapApplication(AppComponent, appConfig)
12 | .catch((err) => console.error(err));
13 |
--------------------------------------------------------------------------------
/src/app/components/ui/sidebar/sidebar.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | :host {
4 | display: block;
5 | height: 100%;
6 | width: var(--sidebar-width);
7 | max-width: var(--sidebar-width);
8 | background-color: var(--cl-sidebar-bg);
9 | color: var(--cl-sidebar-txt);
10 | flex: 0 0 var(--sidebar-width);
11 | border-right: 1px solid var(--cl-sidebar-border);
12 | z-index: 3;
13 |
14 | position: relative;
15 | overflow: hidden;
16 | }
17 |
--------------------------------------------------------------------------------
/src/app/components/ui/theme-settings/theme-settings.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | table {
4 | font-size: 12px;
5 |
6 | & > thead {
7 | opacity: 0.7;
8 | }
9 |
10 | & td {
11 | width: 50%;
12 | }
13 | }
14 |
15 | .color {
16 | height: 14px;
17 | cursor: pointer;
18 | }
19 |
20 | .input {
21 | height: 14px;
22 | }
23 |
24 | .btn-success {
25 | margin-top: 10px;
26 | }
27 |
28 | dsw-color-picker {
29 | height: 20px;
30 | }
31 |
--------------------------------------------------------------------------------
/dist/chunk-QT4NCOPW.js:
--------------------------------------------------------------------------------
1 | import{I as c}from"./chunk-YZADXMU6.js";import{Ea as o,bb as i,ha as r}from"./chunk-ZEAAPN4P.js";var a=(()=>{class t{constructor(s,e){this.el=s,this.us=e}ngAfterViewInit(){this.el.nativeElement.attributes.getNamedItem("dswAutoFocus").value==="desktop"&&this.us.isMobile()||this.el.nativeElement.focus()}static{this.\u0275fac=function(e){return new(e||t)(i(o),i(c))}}static{this.\u0275dir=r({type:t,selectors:[["","dswAutoFocus",""]],standalone:!0})}}return t})();export{a};
2 |
--------------------------------------------------------------------------------
/src/app/components/ui/chart-colors-config/chart-colors-config.component.scss:
--------------------------------------------------------------------------------
1 |
2 | .color-small {
3 | display: inline-block;
4 | width: 32px;
5 | height: 32px;
6 | min-width: 32px;
7 | flex-shrink: 0;
8 | }
9 |
10 | .series-colors {
11 | display: flex;
12 | flex-wrap: wrap;
13 | gap: 8px;
14 | }
15 |
16 | label + .color-small {
17 | margin-left: 0;
18 | }
19 |
20 | .color {
21 | display: inline-flex;
22 | }
23 |
24 | .divider {
25 | margin-bottom: 10px;
26 | }
27 |
--------------------------------------------------------------------------------
/src/app/components/ui/color-picker/color-picker.component.scss:
--------------------------------------------------------------------------------
1 | $size: 32px;
2 |
3 | :host {
4 | display: block;
5 | width: 100%;
6 | height: $size;
7 | cursor: pointer;
8 | border: 1px solid rgb(210, 210,210);
9 | }
10 |
11 | chrome-picker {
12 | position: fixed;
13 | transform: translateY($size);
14 | cursor: default;
15 | z-index: 2;
16 | }
17 |
18 | .btn-primary {
19 | width: 100%;
20 | border-radius: 0;
21 | }
22 |
23 | .top {
24 | transform: translateY(-100%);
25 | }
26 |
--------------------------------------------------------------------------------
/proxy.conf.local.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "/config.json": {
3 | "target": "http://127.0.0.1:52773/dsw/",
4 | "secure": false,
5 | "logLevel": "debug",
6 | "changeOrigin": true
7 | },
8 | "/configs": {
9 | "target": "http://127.0.0.1:52773/dsw/",
10 | "secure": false,
11 | "logLevel": "debug",
12 | "changeOrigin": true
13 | },
14 | "/MDX2JSON": {
15 | "target": "http://127.0.0.1:52773/",
16 | "secure": false,
17 | "logLevel": "debug",
18 | "changeOrigin": true
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/components/ui/home-editor/home-editor.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | // Upload control
4 | input[type=file] {
5 | &::-webkit-file-upload-button {
6 | // color: red;
7 | }
8 | }
9 |
10 | // Checkbox, must be placed inside label
11 | input[type=checkbox] {
12 | cursor: pointer;
13 | outline: none;
14 | display: inline;
15 | &:focus, &:active {
16 | outline: none;
17 | }
18 | }
19 |
20 | .divider {
21 | display: block;
22 | width: 100%;
23 | clear: both;
24 | }
25 |
--------------------------------------------------------------------------------
/src/app/components/widgets/text/wtext.component.html:
--------------------------------------------------------------------------------
1 | @for (item of textData; track item; let idx = $index) {
2 |
3 |
9 |
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/src/app/services/widget.service.ts:
--------------------------------------------------------------------------------
1 | import {EventEmitter, Injectable} from '@angular/core';
2 |
3 | import {IWidgetDesc} from "./dsw.types";
4 |
5 | export interface IButtonToggle {
6 | widget: IWidgetDesc;
7 | name: string;
8 | state: boolean;
9 | }
10 |
11 | @Injectable({
12 | providedIn: 'root'
13 | })
14 | export class WidgetService {
15 |
16 | onToggleHeaderButton = new EventEmitter();
17 |
18 | constructor() {
19 | }
20 |
21 | toggleButton(btn: IButtonToggle) {
22 | this.onToggleHeaderButton.emit(btn);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/assets/img/widget-icons/folder-1.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/widget-icons/folder-1.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/palette-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/icons/palette-icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/proxy.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "/config.json": {
3 | "target": "https://startup-dev.community.intersystems.com/dsw/",
4 | "secure": false,
5 | "logLevel": "debug",
6 | "changeOrigin": true
7 | },
8 | "/configs": {
9 | "target": "https://startup-dev.community.intersystems.com/dsw/",
10 | "secure": false,
11 | "logLevel": "debug",
12 | "changeOrigin": true
13 | },
14 | "/MDX2JSON": {
15 | "target": "https://startup-dev.community.intersystems.com/",
16 | "secure": false,
17 | "logLevel": "debug",
18 | "changeOrigin": true
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/app/directives/focus-next.directive.ts:
--------------------------------------------------------------------------------
1 | import {Directive, ElementRef, HostListener} from '@angular/core';
2 |
3 | @Directive({
4 | selector: '[dswFocusNext]',
5 | standalone: true
6 | })
7 | export class FocusNextDirective {
8 |
9 | constructor(private el: ElementRef) {
10 | }
11 |
12 | @HostListener('keydown.enter', ['$event'])
13 | onReturnPressed(e: KeyboardEvent) {
14 | e.preventDefault();
15 | const focusEl = document.getElementById(this.el.nativeElement.attributes.dswFocusNext.value);
16 | if (focusEl) {
17 | focusEl.focus();
18 | }
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/view-2columns.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/app/components/widgets/charts/bar-chart.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {BaseChartClass} from './base-chart.class';
3 |
4 | @Component({
5 | selector: 'dsw-bar-chart',
6 | template: '',
7 | standalone: true
8 | })
9 | export class BarChartComponent extends BaseChartClass implements OnInit {
10 |
11 | ngOnInit(): void {
12 | super.ngOnInit();
13 | this.widget.isBtnZero = true;
14 | this.widget.isBtnValues = true;
15 |
16 | if (this.widget.type.toLowerCase() === 'barchartstacked') {
17 | this.enableStacking();
18 | }
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/assets/img/icons/view-2columns.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/app/components/widgets/charts/column-chart.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {BaseChartClass} from './base-chart.class';
3 |
4 | @Component({
5 | selector: 'dsw-column-chart',
6 | template: '',
7 | standalone: true
8 | })
9 | export class ColumnChartComponent extends BaseChartClass implements OnInit {
10 |
11 | ngOnInit(): void {
12 | super.ngOnInit();
13 | this.widget.isBtnZero = true;
14 | this.widget.isBtnValues = true;
15 |
16 | if (this.widget.type.toLowerCase() === "columnchartstacked") {
17 | this.enableStacking();
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/dist/assets/img/spinner.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/img/spinner.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/dist/assets/img/widget-icons/widget-3.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/img/widget-icons/widget-3.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/widget-icons/back-1.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/widget-icons/back-1.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/text.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/view-5columns.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/assets/img/icons/text.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/img/icons/view-5columns.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/assets/img/icons/reset.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/reset.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/icon-reload.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon-reload.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 | @if (hs.visible$ | async) {
2 |
3 | }
4 |
5 | @if (isSidebar) {
6 |
7 | }
8 |
9 |
10 |
11 |
12 | @for (modal of ms.modals(); track $index) {
13 |
14 | }
15 |
16 |
17 | @for (err of es.errors$ | async; track trackError(idx, err); let idx = $index) {
18 |
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/app/directives/auto-focus.directive.ts:
--------------------------------------------------------------------------------
1 | import {AfterViewInit, Directive, ElementRef} from '@angular/core';
2 | import {UtilService} from '../services/util.service';
3 |
4 | @Directive({
5 | selector: '[dswAutoFocus]',
6 | standalone: true
7 | })
8 | export class AutoFocusDirective implements AfterViewInit {
9 |
10 | constructor(private el: ElementRef, private us: UtilService) {
11 | }
12 |
13 | ngAfterViewInit() {
14 | if (this.el.nativeElement.attributes.getNamedItem('dswAutoFocus').value === 'desktop') {
15 | // Focus only for desktop and ignore mobile
16 | if (this.us.isMobile()) {
17 | return;
18 | }
19 | }
20 | this.el.nativeElement.focus();
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/app/components/ui/error/error.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | :host {
4 | font-family: $font;
5 | cursor: pointer;
6 | position: absolute;
7 | padding: 4px 10px;
8 | height: 32px;
9 | color: white;
10 | background-color: red;
11 | display: flex;
12 | justify-content: flex-start;
13 | align-items: center;
14 | border-radius: 4px;
15 | right: 10px;
16 | white-space: nowrap;
17 | max-width: 50%;
18 | transition: bottom 0.1s linear;
19 | z-index: 100;
20 | // Flex fix to show ellipsis on text
21 | & > span {
22 | min-width: 0;
23 | overflow: hidden;
24 | text-overflow: ellipsis;
25 | }
26 |
27 | &.left {
28 | right: auto;
29 | left: 10px;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/icon-copy.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/settings-black-24dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon-copy.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/img/icons/settings-black-24dp.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/chunk-HFC6Q7LK.js:
--------------------------------------------------------------------------------
1 | import{a as o}from"./chunk-YE4HGH46.js";import{h as n}from"./chunk-MG3ERZGY.js";var i=class extends o{constructor(){if(super(),typeof createImageBitmap>"u")throw new Error("Cannot decode WebImage as `createImageBitmap` is not available");if(typeof document>"u"&&typeof OffscreenCanvas>"u")throw new Error("Cannot decode WebImage as neither `document` nor `OffscreenCanvas` is not available")}decode(s,r){return n(this,null,function*(){let d=new Blob([r]),e=yield createImageBitmap(d),t;typeof document<"u"?(t=document.createElement("canvas"),t.width=e.width,t.height=e.height):t=new OffscreenCanvas(e.width,e.height);let a=t.getContext("2d");return a.drawImage(e,0,0),a.getImageData(0,0,e.width,e.height).data.buffer})}};export{i as default};
2 |
--------------------------------------------------------------------------------
/src/app/components/ui/text-area/text-area.component.ts:
--------------------------------------------------------------------------------
1 | import {AfterViewInit, Component, ElementRef, Input, ViewChild} from '@angular/core';
2 | import {FormsModule} from '@angular/forms';
3 |
4 | @Component({
5 | selector: 'dsw-text-area',
6 | templateUrl: './text-area.component.html',
7 | styleUrls: ['./text-area.component.scss'],
8 | standalone: true,
9 | imports: [FormsModule]
10 | })
11 | export class TextAreaComponent implements AfterViewInit {
12 | @Input() value = '';
13 | @ViewChild('input') input!: ElementRef;
14 |
15 | constructor() {
16 | }
17 |
18 | ngAfterViewInit() {
19 | setTimeout(() => {
20 | this.input.nativeElement.focus();
21 | this.input.nativeElement.select();
22 | });
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/icon-check.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/app/services/broadcast.service.ts:
--------------------------------------------------------------------------------
1 | import {EventEmitter, Injectable} from '@angular/core';
2 | import {Subscription} from 'rxjs';
3 |
4 | interface IBroadcast {
5 | message: string;
6 | value: any;
7 | }
8 |
9 | @Injectable({
10 | providedIn: 'root'
11 | })
12 | export class BroadcastService {
13 |
14 | private emitter = new EventEmitter();
15 |
16 | constructor() {
17 | }
18 |
19 | broadcast(message: string, value?: any) {
20 | this.emitter.emit({message, value});
21 | }
22 |
23 | subscribe(message: string, callback: (value: any) => void): Subscription {
24 | return this.emitter.subscribe((b: IBroadcast) => {
25 | if (b.message === message) {
26 | callback(b.value);
27 | }
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon-check.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/chunk-23TAPEHU.js:
--------------------------------------------------------------------------------
1 | import{X as o,g as i,za as e}from"./chunk-ZEAAPN4P.js";var m=(()=>{class t{constructor(){this.visible$=new i(!1),this.onSearch=new i(""),this.onSearchReset=new e,this.shareDashboardEmitter=new e,this.gotoZenDeepSeeEmitter=new e,this.mobileFilterToggle=new e,this.mobileFilterDialogToggle=new e}resetSearch(){this.onSearchReset.emit()}shareDashboard(){this.shareDashboardEmitter.emit()}gotoZenDeepSee(){this.gotoZenDeepSeeEmitter.emit()}showMobileFilterButton(){this.mobileFilterToggle.emit(!0)}hideMobileFilterButton(){this.mobileFilterToggle.emit(!1)}toggleMobileFilterDialog(){this.mobileFilterDialogToggle.emit()}static{this.\u0275fac=function(r){return new(r||t)}}static{this.\u0275prov=o({token:t,factory:t.\u0275fac,providedIn:"root"})}}return t})();export{m as a};
2 |
--------------------------------------------------------------------------------
/src/app/components/ui/about/about.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, input, OnInit} from '@angular/core';
2 | import {DataService} from '../../../services/data.service';
3 | import {DomSanitizer, SafeHtml} from '@angular/platform-browser';
4 | import markdownit from 'markdown-it';
5 |
6 | @Component({
7 | selector: 'dsw-about',
8 | templateUrl: './about.component.html',
9 | styleUrls: ['./about.component.scss'],
10 | standalone: true
11 | })
12 | export class AboutComponent implements OnInit {
13 | html = input.required();
14 | protected changelog?: SafeHtml;
15 |
16 | constructor(private ds: DataService,
17 | private san: DomSanitizer) {
18 | }
19 |
20 | ngOnInit() {
21 | this.changelog = markdownit({html: true}).render(this.html());
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/app/components/ui/search/search-input/search-input.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 | @import "breakpoints";
3 |
4 | :host {
5 | position: relative;
6 | display: block;
7 |
8 | & > input {
9 | @include reset-input-styles;
10 | }
11 | }
12 |
13 | // Search input
14 | input {
15 | border: none;
16 | color: #606367;
17 | height: 24px;
18 | border-bottom: 1px solid #EBEBEA;
19 | padding-left: 16px;
20 | border-radius: 0;
21 |
22 | &:focus, &:active {
23 | border: none;
24 | border-bottom: 1px solid var(--cl-accent);
25 | outline: none;
26 | }
27 |
28 | &::placeholder {
29 | color: var(--cl-header-txt);
30 | opacity: 0.5;
31 | }
32 | }
33 |
34 | img {
35 | position: absolute;
36 | pointer-events: none;
37 | top: 5px;
38 | }
39 |
--------------------------------------------------------------------------------
/src/app/components/ui/share-dashboard/share-dashboard/share-dashboard.component.html:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | dsw
6 | 4.0.27
7 | module
8 | DeepSeeWeb (DSW) is an Angular UI layer for IRIS BI (DeepSee) dashboards
9 |
10 |
11 | MDX2JSON
12 | 3.*
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/dist/chunk-MDOQS4TE.js:
--------------------------------------------------------------------------------
1 | import{X as c,ib as r}from"./chunk-ZEAAPN4P.js";import{h as o}from"./chunk-MG3ERZGY.js";var u=[{label:"OK",default:!0,autoClose:!0}],a=(()=>{class e{#t;constructor(){this.#t=r([]),this.modals=this.#t.asReadonly()}show(t,s){return o(this,null,function*(){if(typeof t=="string"&&(t={message:t}),t.buttons||(t.buttons=JSON.parse(JSON.stringify(u)),s&&t.buttons&&(t.buttons[0].click=s)),t.inputs||(t.inputs={}),t.component&&t.component.then){yield t.component;let n=yield t.component;t.component=n[Object.keys(n)[0]]}this.#t.update(n=>[...n,t])})}close(t){let n=this.#t().indexOf(t);n!==-1&&(this.#t.update(i=>(i.splice(n,1),[...i])),t.onClose&&t.onClose())}static{this.\u0275fac=function(s){return new(s||e)}}static{this.\u0275prov=c({token:e,factory:e.\u0275fac,providedIn:"root"})}}return e})();export{a};
2 |
--------------------------------------------------------------------------------
/iris.script:
--------------------------------------------------------------------------------
1 | // Unexpire passwords to simplify dev mode. Comment these two lines for Production use
2 | zn "%SYS"
3 | Do ##class(Security.Users).UnExpireUserPasswords("*")
4 |
5 | ; enabling callin for Embedded Python
6 | do ##class(Security.Services).Get("%Service_CallIn",.prop)
7 | set prop("Enabled")=1
8 | set prop("AutheEnabled")=48
9 | do ##class(Security.Services).Modify("%Service_CallIn",.prop)
10 |
11 | // create IRISAPP namespace
12 | do $SYSTEM.OBJ.Load("/home/irisowner/irisdev/Installer.cls", "ck")
13 | set sc = ##class(App.Installer).setup()
14 |
15 | // Install samples BI
16 | zn "IRISAPP"
17 | zpm "install samples-bi"
18 |
19 | // load all the code of the project as a ZPM package
20 | zn "IRISAPP"
21 | zpm "load /home/irisowner/irisdev/ -v":1:1
22 | halt
23 |
--------------------------------------------------------------------------------
/src/addons/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "forceConsistentCasingInFileNames": false,
4 | "strict": false,
5 | "noImplicitOverride": false,
6 | "noImplicitAny": false,
7 | "noPropertyAccessFromIndexSignature": false,
8 | "noImplicitReturns": false,
9 | "noFallthroughCasesInSwitch": false,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "sourceMap": false,
13 | "declaration": false,
14 | "experimentalDecorators": true,
15 | "moduleResolution": "node",
16 | "resolveJsonModule": true,
17 | "importHelpers": true,
18 | "target": "ES2022",
19 | "module": "CommonJS",
20 | "useDefineForClassFields": false,
21 | "lib": [
22 | "ES2022",
23 | "dom"
24 | ],
25 | "outDir": "../../dist-addons/",
26 | "types": []
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/app/components/widgets/smiley/smiley.component.ts:
--------------------------------------------------------------------------------
1 | import {ChangeDetectionStrategy, Component, HostBinding, Input} from '@angular/core';
2 | import {WMeterComponent} from '../base/meter-widget.class';
3 | import {IWidgetDesc} from "../../../services/dsw.types";
4 |
5 |
6 | @Component({
7 | selector: 'dsw-wsmiley',
8 | templateUrl: './smiley.component.html',
9 | styleUrls: ['./smiley.component.scss'],
10 | changeDetection: ChangeDetectionStrategy.OnPush,
11 | standalone: true,
12 | imports: []
13 | })
14 | export class WSmileyComponent extends WMeterComponent {
15 | @Input() widget: IWidgetDesc = {} as IWidgetDesc;
16 | ;
17 |
18 | @HostBinding('style.grid-template-columns')
19 | get gridColumns() {
20 | return 'repeat(' + (this.data?.length >= 3 ? 3 : (this.data?.length || 0)).toString() + ', 1fr)';
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/legend-toggle.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/app/components/ui/sidebar-actions/sidebar-actions.component.html:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
22 |
--------------------------------------------------------------------------------
/src/assets/img/icons/legend-toggle.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: {
11 | context(path: string, deep?: boolean, filter?: RegExp): {
12 | keys(): string[];
13 | (id: string): T;
14 | };
15 | };
16 |
17 | // First, initialize the Angular testing environment.
18 | getTestBed().initTestEnvironment(
19 | BrowserDynamicTestingModule,
20 | platformBrowserDynamicTesting()
21 | );
22 | // Then we find all the tests.
23 | const context = require.context('./', true, /\.spec\.ts$/);
24 | // And load the modules.
25 | context.keys().map(context);
26 |
--------------------------------------------------------------------------------
/src/app/components/widgets/traffic-light/traffic-light.component.ts:
--------------------------------------------------------------------------------
1 | import {ChangeDetectionStrategy, Component, HostBinding, Input} from '@angular/core';
2 | import {WMeterComponent} from '../base/meter-widget.class';
3 | import {IWidgetDesc} from "../../../services/dsw.types";
4 |
5 |
6 | @Component({
7 | selector: 'dsw-traffic-light',
8 | templateUrl: './traffic-light.component.html',
9 | styleUrls: ['./traffic-light.component.scss'],
10 | changeDetection: ChangeDetectionStrategy.OnPush,
11 | standalone: true,
12 | imports: []
13 | })
14 | export class WTrafficLightComponent extends WMeterComponent {
15 | @Input() widget: IWidgetDesc = {} as IWidgetDesc;
16 |
17 | @HostBinding('style.grid-template-columns')
18 | get gridColumns() {
19 | return 'repeat(' + (this.data?.length >= 3 ? 3 : (this.data?.length || 0)).toString() + ', 1fr)';
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/app/components/widgets/charts/area-chart.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {BaseChartClass} from './base-chart.class';
3 |
4 | @Component({
5 | selector: 'dsw-area-chart',
6 | template: '',
7 | standalone: true
8 | })
9 | export class AreaChartComponent extends BaseChartClass implements OnInit {
10 |
11 | ngOnInit(): void {
12 | super.ngOnInit();
13 | this.widget.isBtnZero = true;
14 | this.widget.isBtnValues = true;
15 |
16 | const ex = {
17 | plotOptions: {
18 | series: {
19 | colorByPoint: false
20 | },
21 | area: {
22 | //stacking: 'percent',
23 | stacking: 'normal',
24 | marker: {
25 | enabled: false
26 | }
27 | }
28 | }
29 | };
30 | this.us.mergeRecursive(this.chartConfig, ex);
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/.github/sync-zpm-version.js:
--------------------------------------------------------------------------------
1 | const pkg = require('./../package.json');
2 | const fs = require('fs');
3 | const xml2js = require('xml2js');
4 | const util = require('util');
5 |
6 | const parser = new xml2js.Parser();
7 | const xmlBuilder = new xml2js.Builder();
8 |
9 | const data = fs.readFileSync('./module.xml');
10 |
11 |
12 | parser.parseString(data, function (err, result) {
13 | const ver = result.Export.Document[0].Module[0].Version[0];
14 | if (ver === pkg.version) {
15 | console.log('Versiona are equal: ' + pkg.version);
16 | return;
17 | }
18 | result.Export.Document[0].Module[0].Version[0] = pkg.version;
19 |
20 | const xml = xmlBuilder.buildObject(result, {xmldec: { 'version': '1.0', 'encoding': 'UTF-8' }});
21 |
22 | console.log('Changing version of Module.xml to: ' + pkg.version);
23 | fs.writeFileSync('module.xml', xml);
24 | });
25 |
26 |
--------------------------------------------------------------------------------
/dist/chunk-G7BOERRR.js:
--------------------------------------------------------------------------------
1 | import{X as c,g as i,za as o}from"./chunk-ZEAAPN4P.js";import{h as s}from"./chunk-MG3ERZGY.js";var d=(()=>{class e{constructor(){this.sidebarToggle=new i(void 0),this.onAnimStart=new o,this.onAnimEnd=new o,this.stack=[]}hide(){this.resetComponentStack(),this.sidebarToggle.next(void 0)}showComponent(t){return s(this,null,function*(){if(!t){this.hide();return}if(t.component&&t.component.then){yield t.component;let n=yield t.component;t.component=n[Object.keys(n)[0]]}if(t?.single&&this.stack.find(r=>r.component===t?.component)){this.sidebarToggle.next(t);return}t?.component&&this.stack.push(t),t&&this.sidebarToggle.next(t)})}popComponent(){this.stack.pop();let t=this.stack.pop()||null;this.showComponent(t)}resetComponentStack(){this.stack=[]}static{this.\u0275fac=function(n){return new(n||e)}}static{this.\u0275prov=c({token:e,factory:e.\u0275fac,providedIn:"root"})}}return e})();export{d as a};
2 |
--------------------------------------------------------------------------------
/src/app/app.routes.ts:
--------------------------------------------------------------------------------
1 | import {Routes} from '@angular/router';
2 | import {LoginScreenComponent} from './components/screens/login-screen/login-screen.component';
3 | import {MainScreenComponent} from './components/screens/main-screen/main-screen.component';
4 | import {NamespaceService} from './services/namespace.service';
5 | import {ConfigResolver} from './services/config-resolver';
6 |
7 | export const routes: Routes = [
8 | {path: '', component: LoginScreenComponent, resolve: {model: NamespaceService}},
9 | {path: 'login', component: LoginScreenComponent},
10 | {
11 | path: ':ns', resolve: {model: ConfigResolver}, runGuardsAndResolvers: 'always', children: [
12 | {
13 | path: '**',
14 | component: MainScreenComponent,
15 | data: {isDashboard: true},
16 | resolve: {model: ConfigResolver},
17 | runGuardsAndResolvers: 'always'
18 | }
19 | ]
20 | },
21 | ];
22 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/language-24px.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/img/icons/language-24px.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/scss/breakpoints.scss:
--------------------------------------------------------------------------------
1 | // Small tablets and large smartphones (landscape view)
2 | $screen-sm-min: 576px;
3 |
4 | // Small tablets (portrait view)
5 | $screen-md-min: 768px;
6 |
7 | // Tablets and small desktops
8 | $screen-lg-min: 992px;
9 |
10 | // Large tablets and desktops
11 | $screen-xl-min: 1200px;
12 |
13 | // Small devices
14 | @mixin sm {
15 | @media (max-width: #{$screen-sm-min}) {
16 | @content;
17 | }
18 | }
19 |
20 | // Medium devices
21 | @mixin md {
22 | @media (max-width: #{$screen-md-min}) {
23 | @content;
24 | }
25 | }
26 |
27 | // Large devices
28 | @mixin lg {
29 | @media (max-width: #{$screen-lg-min}) {
30 | @content;
31 | }
32 | }
33 |
34 | // Extra large devices
35 | @mixin xl {
36 | @media (max-width: #{$screen-xl-min}) {
37 | @content;
38 | }
39 | }
40 |
41 | @mixin only-sm {
42 | @media (min-width: #{$screen-sm-min}) {
43 | display: none !important;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/icon-close.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon-close.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /tmp
5 | /out-tsc
6 | # Only exists if Bazel was run
7 | /bazel-out
8 |
9 | # dependencies
10 | /node_modules
11 |
12 | # profiling files
13 | chrome-profiler-events*.json
14 | speed-measure-plugin*.json
15 |
16 | # IDEs and editors
17 | /.idea
18 | .project
19 | .classpath
20 | .c9/
21 | *.launch
22 | .settings/
23 | *.sublime-workspace
24 |
25 | # IDE - VSCode
26 | .vscode/*
27 | !.vscode/settings.json
28 | !.vscode/tasks.json
29 | !.vscode/launch.json
30 | !.vscode/extensions.json
31 | .history/*
32 |
33 | # misc
34 | .angular
35 | /.sass-cache
36 | /connect.lock
37 | /coverage
38 | /libpeerconnection.log
39 | npm-debug.log
40 | yarn-error.log
41 | testem.log
42 | /typings
43 |
44 | # System Files
45 | .DS_Store
46 | Thumbs.db
47 |
48 | # addons compilation modules
49 | /dist/commonjs
50 | /dist-addons
51 | /e2e/screenshots
52 |
--------------------------------------------------------------------------------
/src/assets/img/icons/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.github/workflows/test-ui.yml:
--------------------------------------------------------------------------------
1 | # on: push
2 | on:
3 | workflow_run:
4 | workflows: ["Build Angular"]
5 | types:
6 | - completed
7 | name: Test UI
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | strategy:
12 | matrix:
13 | node-version: [20.14.0]
14 | steps:
15 | - uses: actions/checkout@v4
16 |
17 | - name: Build the docker
18 | run: |
19 | docker compose build
20 | docker compose up -d
21 |
22 | - name: Check running containers
23 | run: docker ps -a
24 |
25 | - name: Create directory for artifacts
26 | run: mkdir -p ./e2e/screenshots
27 |
28 | - name: Install node modules
29 | run: npm i
30 |
31 | - name: Running test
32 | run: npm test
33 |
34 | - name: Archive artifacts
35 | if: always()
36 | uses: actions/upload-artifact@v4
37 | with:
38 | name: screenshots
39 | path: ./e2e/screenshots
40 |
--------------------------------------------------------------------------------
/src/app/components/ui/menu/menu-settings/menu-settings.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {SidebarService} from '../../../../services/sidebar.service';
3 |
4 | @Component({
5 | selector: 'dsw-menu-settings',
6 | templateUrl: './menu-settings.component.html',
7 | styleUrls: ['./../menu.component.scss'],
8 | standalone: true
9 | })
10 | export class MenuSettingsComponent implements OnInit {
11 |
12 | constructor(private sbs: SidebarService) {
13 | }
14 |
15 | ngOnInit(): void {
16 | }
17 |
18 | showThemeSettings() {
19 | this.sbs.showComponent({component: import('./../../theme-settings/theme-settings.component')});
20 | }
21 |
22 | showAppSettings() {
23 | this.sbs.showComponent({component: import('./../../app-settings/app-settings.component')});
24 | }
25 |
26 | showChartsSettings() {
27 | this.sbs.showComponent({component: import('../../chart-colors-config/chart-colors-config.component')});
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/services/variables.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 |
3 | @Injectable({
4 | providedIn: 'root'
5 | })
6 | export class VariablesService {
7 |
8 | items: any[] = [];
9 | widgets: any[] = [];
10 |
11 | constructor() {
12 | }
13 |
14 | /**
15 | * Initialize service
16 | */
17 | init(result) {
18 | this.items = [];
19 | this.widgets = [];
20 | if (!result.widgets) {
21 | return;
22 | }
23 | for (let i = 0; i < result.widgets.length; i++) {
24 | const w: any = result.widgets[i];
25 | this.widgets.push(w);
26 | for (let j = 0; j < w.controls.length; j++) {
27 | if (w.controls[j].action.toLowerCase() === 'applyvariable') {
28 | this.items.push(w.controls[j]);
29 | }
30 | }
31 | }
32 | }
33 |
34 | /**
35 | * Clear all variables
36 | */
37 | clear() {
38 | this.items = [];
39 | }
40 |
41 | isExists(): boolean {
42 | return this.items.length !== 0;
43 | }
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/table.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/img/icons/table.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/widget-icons/widget-1.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/img/widget-icons/widget-1.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/Installer.cls:
--------------------------------------------------------------------------------
1 | Class App.Installer
2 | {
3 |
4 | XData setup
5 | {
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 | }
22 |
23 | ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 3, pInstaller As %Installer.Installer, pLogger As %Installer.AbstractLogger) As %Status [ CodeMode = objectgenerator, Internal ]
24 | {
25 | #; Let XGL document generate code for this method.
26 | Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "setup")
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/app/components/widgets/base/widget/widget.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | :host {
4 | display: flex;
5 | flex-direction: column;
6 | width: 100%;
7 | height: 100%;
8 | min-height: 0;
9 | overflow: hidden;
10 | background-color: var(--cl-widget-bg);
11 | padding: 20px;
12 | }
13 |
14 | .error {
15 | font-family: $font;
16 | position: absolute;
17 | inset: 0;
18 | color: rgb(215 7 2 / 58%);
19 | background-color: transparent;
20 | text-align: center;
21 | background: var(--cl-widget-bg);
22 | display: flex;
23 | align-items: center;
24 | justify-content: center;
25 | padding: 20px;
26 | z-index: 10;
27 | }
28 |
29 | .spinner {
30 | position: absolute;
31 | left: 0;
32 | right: 0;
33 | top: 44px;
34 | bottom: 0;
35 | z-index: 3;
36 | display: flex;
37 | justify-content: center;
38 | align-items: center;
39 | background-color: rgba(255, 255, 255, 0.9);
40 | backdrop-filter: blur(2px);
41 | height: auto;
42 | }
43 |
44 | dsw-widget-filter {
45 | z-index: 4;
46 | }
47 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon-next.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/icon-next.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon-next-blue.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/icon-next-blue.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/next.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
43 |
--------------------------------------------------------------------------------
/src/app/components/widgets/smiley/smiley.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | :host {
4 | // display: flex;
5 | display: grid;
6 | width: 100%;
7 | height: 100%;
8 | font-family: $font;
9 | -webkit-user-select: initial;
10 | user-select: initial;
11 | align-items: center;
12 | justify-content: center;
13 | }
14 |
15 | img {
16 | width: 100%;
17 |
18 | max-height: calc(100% - 24px);
19 | max-width: 100%;
20 | /* width: 100%;
21 | height: 100%;*/
22 | }
23 |
24 | .card {
25 | width: 100%;
26 | height: 100%;
27 | flex: 1 1 100%;
28 | min-width: 0;
29 | min-height: 0;
30 | display: flex;
31 | flex-direction: column;
32 | align-items: center;
33 | justify-content: center;
34 |
35 | & > div {
36 | height: 100%;
37 | }
38 | }
39 |
40 | label {
41 | width: 100%;
42 | font-family: $font;
43 | color: gray;
44 | font-size: 14px;
45 | text-align: center;
46 | height: 24px;
47 | max-height: 24px;
48 | white-space: nowrap;
49 | overflow: hidden;
50 | text-overflow: ellipsis;
51 | }
52 |
--------------------------------------------------------------------------------
/src/assets/img/icons/next.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
43 |
--------------------------------------------------------------------------------
/dist/assets/img/widget-icons/widget-2.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/img/widget-icons/widget-2.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/app/components/widgets/traffic-light/traffic-light.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | :host {
4 | // display: flex;
5 | display: grid;
6 | width: 100%;
7 | height: 100%;
8 | font-family: $font;
9 | -webkit-user-select: initial;
10 | user-select: initial;
11 | align-items: center;
12 | justify-content: center;
13 | gap: 20px;
14 | }
15 |
16 | img {
17 | width: 100%;
18 |
19 | max-height: calc(100% - 24px);
20 | max-width: 100%;
21 | /* width: 100%;
22 | height: 100%;*/
23 | }
24 |
25 | .card {
26 | width: 100%;
27 | height: 100%;
28 | flex: 1 1 100%;
29 | min-width: 0;
30 | min-height: 0;
31 | display: flex;
32 | flex-direction: column;
33 | align-items: center;
34 | justify-content: center;
35 |
36 | & > div {
37 | height: 100%;
38 | }
39 | }
40 |
41 | label {
42 | width: 100%;
43 | font-family: $font;
44 | color: gray;
45 | font-size: 14px;
46 | text-align: center;
47 | height: 24px;
48 | max-height: 24px;
49 | white-space: nowrap;
50 | overflow: hidden;
51 | text-overflow: ellipsis;
52 | }
53 |
--------------------------------------------------------------------------------
/src/app/components/ui/app-settings/app-settings.component.html:
--------------------------------------------------------------------------------
1 | Settings
2 |
27 |
--------------------------------------------------------------------------------
/src/app/components/widgets/charts/line-chart.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {BaseChartClass} from './base-chart.class';
3 |
4 | @Component({
5 | selector: 'dsw-line-chart',
6 | template: '',
7 | standalone: true
8 | })
9 | export class LineChartComponent extends BaseChartClass implements OnInit {
10 |
11 | ngOnInit() {
12 | super.ngOnInit();
13 | this.widget.isBtnZero = true;
14 | this.widget.isBtnValues = true;
15 | let ex = {};
16 | if (this.widget.type.toLowerCase() !== 'combochart') {
17 | ex = {
18 | plotOptions: {
19 | series: {
20 | lineWidth: 3,
21 | marker: {
22 | enabled: false
23 | }
24 | }
25 | },
26 | };
27 | }
28 |
29 | if (this.widget.type.toLowerCase() === 'linechartmarkers') {
30 | ex = {
31 | series: {
32 | marker: {
33 | enabled: true
34 | }
35 | }
36 | };
37 | }
38 | this.us.mergeRecursive(this.chartConfig, ex);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/pen.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/assets/img/icons/pen.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/app/components/ui/tabs/tabs.component.html:
--------------------------------------------------------------------------------
1 | @for (tab of tabs; track trackByIdentity($index, tab)) {
2 |
9 |
12 | {{ tab.text }}
13 |
14 | }
15 | @if (isMoreButtonVisible) {
16 |
17 |

18 |
19 | }
20 |
21 | @if (isOpened) {
22 |
23 | @for (tab of hiddenTabs; track trackByIdentity($index, tab)) {
24 |
31 | {{ tab.text }}
32 |
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/app/components/ui/modal/modal.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | @if (data.title) {
4 |
5 | {{ data.title }}
6 |
7 | }
8 |
9 |
10 |
11 | {{ data.message }}
12 |
13 | @if (isInitialized) {
14 |
15 | }
16 |
17 |
18 |
19 | @if (data.buttons?.length) {
20 |
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/src/environments/dsw.ts:
--------------------------------------------------------------------------------
1 | import pkg from './../../package.json';
2 |
3 | interface IDSWConfig {
4 | addons: string[];
5 | mobile: boolean;
6 | desktop: boolean;
7 | const: any;
8 | }
9 |
10 | export const dsw: IDSWConfig = {
11 | // TODO: add type for addons
12 | addons: [],
13 | mobile: false, // TODO: add to init = screen.availWidth <= 600;
14 | desktop: true,
15 | const: {
16 | themes: [
17 | {text: 'Default', file: ''},
18 | {text: 'Contrast', file: 'contrast.css'}
19 | // {text: 'Metro', file: 'themes/metro.css'},
20 | // {text: 'Black', file: 'themes/black.css'}
21 | ],
22 | bgColorClasses: ['', 'cl1', 'cl2', 'cl3', 'cl4', 'cl5', 'cl6', 'cl7', 'cl8', 'cl9'],
23 | fontColors: ['fc0', 'fc1', 'fc2', 'fc3', 'fc4', 'fc5'],
24 | icons: ['', 'ico-widget-back', 'ico-widget-folder', 'ico-widget-1', 'ico-widget-dashboard', 'ico-widget-2', 'ico-widget-3', 'ico-widget-4'],
25 | timeout: 60000,
26 | ver: pkg.version,
27 | emptyWidgetClass: 'MDX2JSON.EmptyPortlet'.toLowerCase()
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/src/scss/date-picker.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | // Change selection color
4 | .air-datepicker-cell.-selected- {
5 | --adp-background-color-selected-other-month: var(--cl-accent);
6 | --adp-cell-background-color-selected: var(--cl-accent);
7 | --adp-cell-background-color-in-range: var(--cl-hover);
8 | --adp-cell-border-radius: 40px;
9 | }
10 |
11 | // Change font and color
12 | .air-datepicker {
13 | --adp-color: #1C1D20;
14 | font-family: $font;
15 | --adp-color-current-date: var(--cl-accent);
16 | --adp-width: 224px;
17 | }
18 |
19 | // Day names
20 | .air-datepicker-body--day-name {
21 | --adp-day-name-color: var(--cl-widget-filter-txt);
22 | }
23 |
24 | // Day names background
25 | .air-datepicker-body--day-names {
26 | background-color: #EBEBEA;
27 | padding: 0;
28 | margin: 0;
29 | // margin-bottom: 4px;
30 |
31 | padding-top: 6px;
32 | padding-bottom: 6px;
33 | /* padding-left: 4px;
34 | padding-right: 4px;*/
35 | }
36 |
37 | .air-datepicker-body--cells.-days- {
38 | /*padding-left: 4px;
39 | padding-right: 4px;*/
40 | }
41 |
42 | .air-datepicker--content {
43 | padding: 0;
44 | }
45 |
--------------------------------------------------------------------------------
/src/scss/themes/deepblue.scss:
--------------------------------------------------------------------------------
1 | @import "../variables";
2 |
3 | :root {
4 | --cl-main: #2a3f54;
5 | --cl-accent: #0258f6;
6 |
7 | --cl-btn-main: #5c79b8;
8 | --cl-btn-main-txt: #fff;
9 | --cl-btn-main-border: #4c6bae;
10 | --cl-btn-main-hover: #6e8bca;
11 |
12 | --cl-btn-secondary-border: #3f2222;
13 | --cl-btn-secondary-hover: #3f3f3f;
14 |
15 |
16 | --cl-header-bg: var(--cl-main);
17 | --cl-header-border: var(--cl-main);
18 | --cl-header-txt: white;
19 | --cl-header-ico: white;
20 | --cl-sidebar-txt: white;
21 |
22 | --cl-text-widget-font: #000;
23 | --cl-widget-filter-txt: #fff;
24 | --cl-widget-filter-bg: #364d64;
25 | --widget-header-btn-opacity: 1;
26 | --widget-header-btn-filter: invert(1);
27 | --widget-header-btn-active-filter: contrast(0.2) sepia(1) brightness(1.1) hue-rotate(-655deg) contrast(4);
28 |
29 | --cl-header-btn-hover: #445a70;
30 | --cl-header-btn-active: #364d64;
31 |
32 | --cl-sidebar-bg: #364d64;
33 | --menu-item-icon-filter: invert(1);
34 | --icon-filter: invert(1);
35 |
36 |
37 | }
38 |
39 |
40 | //@import "../main";
41 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, './coverage/DeepSeeWeb'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | restartOnFileChange: true
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 InterSystems Corp.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/src/app/components/ui/date-filter/date-filter.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | :host {
4 | font-family: $font;
5 | font-size: 14px;
6 | color: var(--cl-widget-filter-txt);
7 | display: flex;
8 | align-items: flex-start;
9 | overflow: auto;
10 |
11 | &::-webkit-scrollbar {
12 | width: 5px;
13 | height: 8px;
14 | background-color: #eee; /* or add it to the track */
15 | }
16 |
17 | &::-webkit-scrollbar-thumb {
18 | background: #aaa;
19 | }
20 | }
21 |
22 | ul {
23 | border-right: 1px solid var(--cl-input-border);
24 | padding: 20px;
25 | margin: 0;
26 | list-style-type: none;
27 | }
28 |
29 | li {
30 | white-space: nowrap;
31 | cursor: pointer;
32 |
33 | &:not(:last-child) {
34 | margin-bottom: 12px;
35 | }
36 |
37 | &.selected {
38 | position: relative;
39 | color: var(--cl-accent);
40 |
41 | &:before {
42 | position: absolute;
43 | left: -20px;
44 | top: 0;
45 | height: 100%;
46 | width: 2px;
47 | content: "";
48 | background-color: var(--cl-accent);
49 | }
50 | }
51 | }
52 |
53 | dsw-date-picker::ng-deep.air-datepicker {
54 | border: none;
55 | }
56 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG IMAGE=intersystemsdc/irishealth-community:2020.3.0.200.0-zpm
2 | ARG IMAGE=intersystemsdc/iris-community:2020.4.0.547.0-zpm
3 | ARG IMAGE=containers.intersystems.com/intersystems/iris:2021.1.0.215.0
4 | ARG IMAGE=intersystemsdc/iris-community:preview
5 | ARG IMAGE=intersystemsdc/irishealth-community
6 | ARG IMAGE=intersystemsdc/iris-community
7 | FROM $IMAGE
8 |
9 | WORKDIR /home/irisowner/irisdev
10 |
11 | ## install git
12 | ## USER root
13 | ##RUN apt update && apt-get -y install git
14 | ##USER ${ISC_PACKAGE_MGRUSER}
15 |
16 | ARG TESTS=0
17 | ARG MODULE="dc-sample"
18 | ARG NAMESPACE="IRISAPP"
19 |
20 | ## Embedded Python environment
21 | ENV IRISUSERNAME "_SYSTEM"
22 | ENV IRISPASSWORD "SYS"
23 | ENV IRISNAMESPACE $NAMESPACE
24 | ENV PYTHON_PATH=/usr/irissys/bin/
25 | ENV PATH "/usr/irissys/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/irisowner/bin"
26 |
27 |
28 | RUN --mount=type=bind,src=.,dst=. \
29 | iris start IRIS && \
30 | iris session IRIS < iris.script && \
31 | ([ $TESTS -eq 0 ] || iris session iris -U $NAMESPACE "##class(%ZPM.PackageManager).Shell(\"test $MODULE -v -only\",1,1)") && \
32 | iris stop IRIS quietly
33 |
--------------------------------------------------------------------------------
/src/app/components/ui/share-dashboard/share-dashboard/share-dashboard.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | :host {
4 | z-index: 4;
5 | text-align: left;
6 | padding: 20px;
7 | // background: red;
8 | // background: red;
9 | }
10 |
11 | div {
12 | background: #FFFFFF;
13 | box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
14 | border-radius: 10px;
15 | padding: 20px;
16 | }
17 |
18 | p {
19 | font-family: $font;
20 | font-weight: 500;
21 | font-size: 14px;
22 | line-height: 16px;
23 | color: var(--cl-header-txt);
24 | margin-top: 0;
25 | margin-bottom: 20px;
26 | }
27 |
28 | input, textarea {
29 | margin-bottom: 10px;
30 | min-width: 200px;
31 | color: var(--cl-header-txt);
32 | font-size: 12px;
33 | line-height: 14px;
34 | }
35 |
36 | textarea {
37 | min-height: 120px;
38 |
39 | &.small {
40 | min-height: 80px;
41 | }
42 | }
43 |
44 | button {
45 | width: 100%;
46 | }
47 |
48 | input {
49 | min-width: 16px;
50 | width: 16px;
51 | display: inline-block;
52 | margin: 0;
53 | margin-right: 4px;
54 | vertical-align: bottom
55 | }
56 |
57 | label {
58 | display: block;
59 | margin-bottom: 10px;
60 | font-weight: normal;
61 | }
62 |
--------------------------------------------------------------------------------
/src/app/services/header.service.ts:
--------------------------------------------------------------------------------
1 | import {EventEmitter, Injectable} from '@angular/core';
2 | import {BehaviorSubject} from 'rxjs';
3 |
4 |
5 | @Injectable({
6 | providedIn: 'root'
7 | })
8 | export class HeaderService {
9 | visible$ = new BehaviorSubject(false);
10 | onSearch = new BehaviorSubject('');
11 | onSearchReset = new EventEmitter();
12 | shareDashboardEmitter = new EventEmitter();
13 | gotoZenDeepSeeEmitter = new EventEmitter();
14 | mobileFilterToggle = new EventEmitter();
15 | mobileFilterDialogToggle = new EventEmitter();
16 |
17 | // onSetTitle = new BehaviorSubject('');
18 |
19 | constructor() {
20 |
21 | }
22 |
23 | resetSearch() {
24 | this.onSearchReset.emit();
25 | }
26 |
27 | shareDashboard() {
28 | this.shareDashboardEmitter.emit();
29 | }
30 |
31 | gotoZenDeepSee() {
32 | this.gotoZenDeepSeeEmitter.emit();
33 | }
34 |
35 | showMobileFilterButton() {
36 | this.mobileFilterToggle.emit(true);
37 | }
38 |
39 | hideMobileFilterButton() {
40 | this.mobileFilterToggle.emit(false);
41 | }
42 |
43 | toggleMobileFilterDialog() {
44 | this.mobileFilterDialogToggle.emit();
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/app/components/widgets/base/widget/widget.component.html:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
22 |
23 |
24 | @if (widgetType && widgetType.class) {
25 |
26 | }
27 |
28 |
29 | @if (model.error) {
30 | {{ model.error }}
31 | }
32 |
33 |
34 | @if (component?.isSpinner && !model.error) {
35 |
36 |
![]()
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "outDir": "./dist/out-tsc",
6 | "forceConsistentCasingInFileNames": true,
7 | "strict": true,
8 | "noImplicitOverride": false,
9 | "noImplicitAny": false,
10 | "noPropertyAccessFromIndexSignature": false,
11 | "noImplicitReturns": true,
12 | "noFallthroughCasesInSwitch": true,
13 | "skipLibCheck": true,
14 | "esModuleInterop": true,
15 | "sourceMap": true,
16 | "declaration": false,
17 | "experimentalDecorators": true,
18 | "moduleResolution": "node",
19 | "resolveJsonModule": true,
20 | "importHelpers": true,
21 | "target": "ES2022",
22 | "module": "ES2022",
23 | "useDefineForClassFields": false,
24 | "lib": [
25 | "ES2022",
26 | "dom"
27 | ]
28 | },
29 | "angularCompilerOptions": {
30 | "enableI18nLegacyMessageIdFormat": false,
31 | "strictInjectionParameters": true,
32 | "strictInputAccessModifiers": true,
33 | "strictTemplates": true
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/icon-edit.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon-edit.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/smiley/smile-red.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/img/smiley/smile-red.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/dist/assets/img/smiley/smile-green.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/dist/chunk-YE4HGH46.js:
--------------------------------------------------------------------------------
1 | import{h}from"./chunk-MG3ERZGY.js";function g(o,n){let e=o.length-n,i=0;do{for(let a=n;a>0;a--)o[i+n]+=o[i],i++;e-=n}while(e>0)}function u(o,n,e){let i=0,a=o.length,l=a/e;for(;a>n;){for(let t=n;t>0;--t)o[i+n]+=o[i],++i;a-=n}let c=o.slice();for(let t=0;t=o.byteLength);++r){let s;if(n===2){switch(a[0]){case 8:s=new Uint8Array(o,r*t*e*c,t*e*c);break;case 16:s=new Uint16Array(o,r*t*e*c,t*e*c/2);break;case 32:s=new Uint32Array(o,r*t*e*c,t*e*c/4);break;default:throw new Error(`Predictor 2 not allowed with ${a[0]} bits per sample.`)}g(s,t,c)}else n===3&&(s=new Uint8Array(o,r*t*e*c,t*e*c),u(s,t,c))}return o}var d=class{decode(n,e){return h(this,null,function*(){let i=yield this.decodeBlock(e),a=n.Predictor||1;if(a!==1){let l=!n.StripOffsets,c=l?n.TileWidth:n.ImageWidth,t=l?n.TileLength:n.RowsPerStrip||n.ImageLength;return f(i,a,c,t,n.BitsPerSample,n.PlanarConfiguration)}return i})}};export{d as a};
2 |
--------------------------------------------------------------------------------
/src/assets/img/smiley/smile-green.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/img/smiley/smile-yellow.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/dist/assets/img/smiley/smile-yellow.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/img/map-pin-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/assets/img/map-pin-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/app/components/ui/language-selector/language-selector.component.ts:
--------------------------------------------------------------------------------
1 | import {Component} from '@angular/core';
2 | import {I18nService} from '../../../services/i18n.service';
3 | import {SidebarService} from '../../../services/sidebar.service';
4 | import {StorageService} from '../../../services/storage.service';
5 |
6 |
7 | @Component({
8 | selector: 'dsw-language-selector',
9 | templateUrl: './language-selector.component.html',
10 | styleUrls: ['./../menu/menu.component.scss'],
11 | standalone: true,
12 | imports: []
13 | })
14 | export class LanguageSelectorComponent {
15 |
16 | languages: string[];
17 |
18 | constructor(public i18n: I18nService,
19 | private storage: StorageService,
20 | private ss: SidebarService) {
21 | this.languages = this.i18n.getLanguages();
22 | }
23 |
24 | selectLanguage(lang: any) {
25 | const settings = this.storage.getAppSettings();
26 | this.i18n.current = lang;
27 | settings.language = lang;
28 | this.storage.setAppSettings(settings);
29 | window.location.reload();
30 |
31 | this.ss.hide();
32 | }
33 |
34 | /**
35 | * Returns true if language is selected
36 | * @param lang
37 | */
38 | isSelected(lang: string) {
39 | return this.i18n.current === lang;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/app/components/ui/input/input/input.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | $border-radius: 4px;
4 |
5 | :host {
6 | position: relative;
7 | display: block;
8 |
9 | &.choose > input {
10 | // padding-right: calc(10px + var(--cl-input-height));
11 | width: calc(100% - var(--cl-input-height));
12 | border-radius: $border-radius 0 0 $border-radius;
13 | }
14 |
15 | &.invalid {
16 | & input {
17 | border-color: red;
18 | }
19 | }
20 | }
21 |
22 | input {
23 | font-family: $font;
24 | font-size: 13px;
25 | border-radius: $border-radius;
26 | height: var(--cl-input-height);
27 | text-overflow: ellipsis;
28 | }
29 |
30 | button {
31 | position: absolute;
32 | top: 0;
33 | right: 0;
34 | width: var(--cl-input-height);
35 | height: var(--cl-input-height);
36 | padding: 0;
37 | border: 1px solid var(--cl-input-border);
38 | border-left: none;
39 | background-color: var(--cl-input-bg);
40 | cursor: pointer;
41 | font-family: $font;
42 | color: var(--cl-input-text);
43 | font-size: 16px;
44 | border-radius: 0 $border-radius $border-radius 0;
45 | transition: background-color 0.2s linear;
46 |
47 | &:hover {
48 | background-color: var(--cl-hover);
49 | }
50 |
51 | &:active {
52 | transform: translateY(1px);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/app/components/screens/folder-screen/folder-screen.component.html:
--------------------------------------------------------------------------------
1 |
2 | @for (tile of data$ | async; track tile) {
3 | @let desc = itemDesc[tile.idx];
4 |
5 |
13 |
14 | @if (desc) {
15 |
16 | }
17 |
18 | @if (!desc && model.icons[tile.icon]; as icon) {
19 |
20 | }
21 |
22 | @if (!tile.hideTitle) {
23 |
26 | }
27 |
28 | }
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/app/components/widgets/light-bar/light-bar.component.ts:
--------------------------------------------------------------------------------
1 | import {ChangeDetectionStrategy, Component, HostBinding, Input} from '@angular/core';
2 | import {IMeterWidgetData, WMeterComponent} from '../base/meter-widget.class';
3 | import {IWidgetDesc} from "../../../services/dsw.types";
4 |
5 |
6 | interface ILightbarData extends IMeterWidgetData {
7 | progress: number;
8 | }
9 |
10 | @Component({
11 | selector: 'dsw-light-bar',
12 | templateUrl: './light-bar.component.html',
13 | styleUrls: ['./light-bar.component.scss'],
14 | changeDetection: ChangeDetectionStrategy.OnPush,
15 | standalone: true,
16 | imports: []
17 | })
18 | export class WLightBarComponent extends WMeterComponent {
19 | @Input() widget: IWidgetDesc = {} as IWidgetDesc;
20 | data: ILightbarData[] = [];
21 | dots = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
22 |
23 | @HostBinding('style.grid-template-columns')
24 | get gridColumns() {
25 | return 'repeat(' + (this.data?.length >= 5 ? 2 : 1).toString() + ', 1fr)';
26 | }
27 |
28 | prepareMeterData(result: any) {
29 | super.prepareMeterData(result);
30 | this.data.forEach(d => {
31 | d.progress = (d.value - d.min) / (d.max - d.min) * 10;
32 | if (isNaN(d.progress)) {
33 | d.progress = 0;
34 | }
35 | });
36 | console.log(this.data);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/view-list.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/img/icons/view-list.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/app/components/widgets/map-widget-old/map-widget.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | ;
4 | :host {
5 | position: relative;
6 | }
7 |
8 | .tooltip {
9 | margin-top: 24px;
10 | z-index: 1000;
11 | position: absolute;
12 | border: solid 1px #000000;
13 | color: #000000;
14 | background-color: #ffffe1;
15 | white-space: nowrap;
16 | font-family: $font;
17 | font-size: 13px;
18 | -moz-box-shadow: 2px 2px 4px #7f7f7f;
19 | box-shadow: 2px 2px 4px #7f7f7f;
20 | padding: 2px 3px;
21 | }
22 |
23 | .map-popup {
24 | transform: translateY(-100%) translateX(-50%);
25 | z-index: 1;
26 | position: absolute;
27 | background-color: var(--cl-widget-filter-bg);
28 | margin-bottom: 0px;
29 | border-color: rgb(176, 176, 176);
30 | padding: 4px;
31 | -webkit-box-shadow: 1px 1px 9px 0px rgba(50, 50, 50, 0.5);
32 | -moz-box-shadow: 1px 1px 9px 0px rgba(50, 50, 50, 0.5);
33 | box-shadow: 1px 1px 9px 0px rgba(50, 50, 50, 0.5);
34 | color: var(--cl-widget-header-txt);
35 | }
36 |
37 | .map-popup:after {
38 | content: " ";
39 | display: block;
40 | width: 0;
41 | height: 0;
42 | border-style: solid;
43 | border-width: 8px 4px 0 4px;
44 | bottom: -8px;
45 | left: calc(50% - 4px);
46 | position: absolute;
47 | border-color: var(--cl-widget-filter-bg) transparent transparent transparent;
48 | }
49 |
--------------------------------------------------------------------------------
/src/scss/gridster.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 | @import "breakpoints";
3 |
4 | .no-anim {
5 | -webkit-transition: none !important;
6 | transition: none !important;
7 | }
8 |
9 | //// Gridster without animation
10 | gridster.no-anim-g .gridster-column,
11 | gridster.no-anim-g .gridster-row,
12 | gridster.no-anim-g gridster-item,
13 | gridster.no-anim-g gridster-item.gridster-item-resizing,
14 | gridster.no-anim-g gridster-item.gridster-item-moving {
15 | transition: unset !important;
16 | }
17 |
18 | gridster-item {
19 | transition-property: width, height, transform !important;
20 | }
21 |
22 | // Gridster resize handler
23 | gridster-item:hover .gridster-item-resizable-handler.handle-se {
24 | border-color: transparent transparent var(--cl-accent) !important;
25 | z-index: 10;
26 | }
27 |
28 | // Needed to make greater than LPT zindex, so user can resize widget
29 | .gridster-item:hover .gridster-item-resizable-handler.handle-se {
30 | z-index: 1000;
31 | }
32 |
33 | // Mobile item height
34 | .gridster.mobile gridster-item {
35 | @include sm {
36 | height: $mobile-folder-height !important; // Because gridster uses inline styles
37 | margin-bottom: 0 !important;
38 | }
39 | }
40 |
41 | // Remove padding for mobile
42 | .gridster.mobile {
43 | @include sm {
44 | padding: 0 !important;
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/src/app/services/lpt.types.ts:
--------------------------------------------------------------------------------
1 | import {IMDXData} from './dsw.types';
2 |
3 | export interface ILPTConfig {
4 | initialData?: IMDXData;
5 | }
6 |
7 | export interface ILPTControls {
8 | back: () => void;
9 | }
10 |
11 | export interface ILPTView {
12 | displayMessage: (msg: string) => void;
13 | }
14 |
15 | export interface ILPTDataSource {
16 | FILTERS: string;
17 | _convert: (data: IMDXData) => ILPTData;
18 | }
19 |
20 | export interface ILPTDataRow {
21 |
22 | }
23 |
24 | export interface ILPTColumnProp {
25 |
26 | }
27 |
28 | export interface ILPTData {
29 | columnProps: ILPTColumnProp[];
30 | dataArray: number[];
31 | dimensions: string[];
32 | }
33 |
34 | export interface ILPTDataController {
35 | setData: (data: ILPTData) => void;
36 | getData: () => ILPTData;
37 | }
38 |
39 | export interface ILPDDataSourceStack {
40 | BASIC_MDX: string;
41 | }
42 |
43 | export interface ILightPivotTable {
44 | DRILL_LEVEL: number;
45 | CONFIG: ILPTConfig;
46 | CONTROLS: ILPTControls;
47 | pivotView: ILPTView;
48 | dataSource: ILPTDataSource;
49 | dataController: ILPTDataController;
50 | updateSizes: () => void;
51 | changeBasicMDX: (newMdx: string) => void;
52 | isListing: () => boolean;
53 | getActualMDX: () => string;
54 | getSelectedRows: () => number[];
55 | _dataSourcesStack: ILPDDataSourceStack[];
56 | }
57 |
--------------------------------------------------------------------------------
/dist/chunk-MG3ERZGY.js:
--------------------------------------------------------------------------------
1 | var q=Object.create;var h=Object.defineProperty,r=Object.defineProperties,s=Object.getOwnPropertyDescriptor,t=Object.getOwnPropertyDescriptors,u=Object.getOwnPropertyNames,g=Object.getOwnPropertySymbols,m=Object.getPrototypeOf,k=Object.prototype.hasOwnProperty,n=Object.prototype.propertyIsEnumerable,v=Reflect.get;var l=(a,b,c)=>b in a?h(a,b,{enumerable:!0,configurable:!0,writable:!0,value:c}):a[b]=c,x=(a,b)=>{for(var c in b||={})k.call(b,c)&&l(a,c,b[c]);if(g)for(var c of g(b))n.call(b,c)&&l(a,c,b[c]);return a},y=(a,b)=>r(a,t(b));var z=(a,b)=>{var c={};for(var d in a)k.call(a,d)&&b.indexOf(d)<0&&(c[d]=a[d]);if(a!=null&&g)for(var d of g(a))b.indexOf(d)<0&&n.call(a,d)&&(c[d]=a[d]);return c};var A=(a,b)=>()=>(b||a((b={exports:{}}).exports,b),b.exports),B=(a,b)=>{for(var c in b)h(a,c,{get:b[c],enumerable:!0})},w=(a,b,c,d)=>{if(b&&typeof b=="object"||typeof b=="function")for(let e of u(b))!k.call(a,e)&&e!==c&&h(a,e,{get:()=>b[e],enumerable:!(d=s(b,e))||d.enumerable});return a};var C=(a,b,c)=>(c=a!=null?q(m(a)):{},w(b||!a||!a.__esModule?h(c,"default",{value:a,enumerable:!0}):c,a));var D=(a,b,c)=>v(m(a),c,b);var E=(a,b,c)=>new Promise((d,e)=>{var o=f=>{try{i(c.next(f))}catch(j){e(j)}},p=f=>{try{i(c.throw(f))}catch(j){e(j)}},i=f=>f.done?d(f.value):Promise.resolve(f.value).then(o,p);i((c=c.apply(a,b)).next())});export{x as a,y as b,z as c,A as d,B as e,C as f,D as g,E as h};
2 |
--------------------------------------------------------------------------------
/dist/chunk-ZMZIHCGB.js:
--------------------------------------------------------------------------------
1 | import{a as k}from"./chunk-YE4HGH46.js";import"./chunk-MG3ERZGY.js";var x=9,E=256,b=257,B=12;function C(c,o,r){let i=o%8,n=Math.floor(o/8),h=8-i,g=o+r-(n+1)*8,l=8*(n+2)-(o+r),w=(n+2)*8-o;if(l=Math.max(0,l),n>=c.length)return console.warn("ran off the end of the buffer before finding EOI_CODE (end on input code)"),b;let u=c[n]&2**(8-i)-1;u<<=r-h;let s=u;if(n+1>>l;f<<=Math.max(0,r-w),s+=f}if(g>8&&n+2>>f;s+=t}return s}function p(c,o){for(let r=o.length-1;r>=0;r--)c.push(o[r]);return c}function D(c){let o=new Uint16Array(4093),r=new Uint8Array(4093);for(let e=0;e<=257;e++)o[e]=4096,r[e]=e;let i=258,n=x,h=0;function g(){i=258,n=x}function l(e){let a=C(e,h,n);return h+=n,a}function w(e,a){return r[i]=a,o[i]=e,i++,i-1}function u(e){let a=[];for(let y=e;y!==4096;y=o[y])a.push(r[y]);return a}let s=[];g();let f=new Uint8Array(c),t=l(f),d;for(;t!==b;){if(t===E){for(g(),t=l(f);t===E;)t=l(f);if(t===b)break;if(t>E)throw new Error(`corrupted code at scanline ${t}`);{let e=u(t);p(s,e),d=t}}else if(t=2**n&&(n===B?d=void 0:n++),t=l(f)}return new Uint8Array(s)}var A=class extends k{decodeBlock(o){return D(o,!1).buffer}};export{A as default};
2 |
--------------------------------------------------------------------------------
/src/app/components/editor/type-and-datasource/type-and-datasource.component.html:
--------------------------------------------------------------------------------
1 |
6 | Type & Datasource
7 |
8 |
9 | @if (model) {
10 |
11 |
12 |
21 |
22 |
23 |
30 |
31 |
32 |
42 |
43 |
44 |
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/app/components/ui/menu/menu.component.html:
--------------------------------------------------------------------------------
1 |
45 | v.{{ version }}
46 |
--------------------------------------------------------------------------------
/src/app/components/editor/datasource-selector-dialog/datasource-selector-dialog.html:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 | @for (d of data; track trackByIndex($index, d)) {
13 |
14 | @if (d.children?.length) {
15 |

16 | }
17 | {{ d.name }}
18 |
19 | }
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | @for (sel of selected; track trackByIndex(idx, sel); let idx = $index) {
30 |
31 |
32 |
33 | }
34 |
35 |
36 | @if (isLoading) {
37 |
38 |

39 |
40 | }
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/app/components/screens/main-screen/main-screen.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnDestroy, OnInit} from '@angular/core';
2 | import {ActivatedRoute} from '@angular/router';
3 | import {combineLatest, Subscription} from 'rxjs';
4 | import {HeaderService} from '../../../services/header.service';
5 | import {DashboardScreenComponent} from '../dashboard-screen/dashboard-screen.component';
6 | import {FolderScreenComponent} from '../folder-screen/folder-screen.component';
7 |
8 | @Component({
9 | selector: 'dsw-main-screen',
10 | templateUrl: './main-screen.component.html',
11 | styleUrls: ['./main-screen.component.scss'],
12 | standalone: true,
13 | imports: [FolderScreenComponent, DashboardScreenComponent]
14 | })
15 | export class MainScreenComponent implements OnInit, OnDestroy {
16 | isFolder = true;
17 | private subRoutechange: Subscription;
18 |
19 | constructor(private route: ActivatedRoute, private hs: HeaderService) {
20 | this.hs.visible$.next(true);
21 | this.subRoutechange = combineLatest([
22 | this.route.url,
23 | this.route.params
24 | ]).subscribe(([segments, params]) => {
25 | const path = [params.name, ...segments.map(s => s.path)].join('/');
26 | this.isFolder = path.indexOf('.dashboard') === -1;
27 | });
28 | }
29 |
30 | ngOnInit(): void {
31 | }
32 |
33 | ngOnDestroy(): void {
34 | this.subRoutechange.unsubscribe();
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/view-3columns.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/assets/img/icons/view-3columns.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/app/components/ui/theme-settings/theme-settings.component.html:
--------------------------------------------------------------------------------
1 | Theme settings
2 |
3 |
4 |
11 |
12 |
13 |
14 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/ngsw-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/service-worker/config/schema.json",
3 | "index": "/index.html",
4 | "dataGroups": [
5 | {
6 | "name": "api",
7 | "urls": [
8 | "/MDX2JSON",
9 | "/MDX2JSON/**",
10 | "/MDX2JSON/*",
11 | "/mdx2json",
12 | "/mdx2json/*",
13 | "/mdx2json/**"
14 | ],
15 | "cacheConfig": {
16 | "maxSize": 0,
17 | "maxAge": "0u",
18 | "strategy": "freshness"
19 | }
20 | }
21 | ],
22 | "assetGroups": [
23 | {
24 | "name": "app",
25 | "installMode": "prefetch",
26 | "resources": {
27 | "files": [
28 | "/favicon.ico",
29 | "/index.html",
30 | "/manifest.webmanifest",
31 | "/*.css",
32 | "/*.js"
33 | ]
34 | }
35 | },
36 | {
37 | "name": "assets",
38 | "installMode": "lazy",
39 | "updateMode": "prefetch",
40 | "resources": {
41 | "files": [
42 | "/assets/**",
43 | "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
44 | ]
45 | }
46 | }
47 | ]
48 | }
49 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon-logout.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/icon-logout.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/dist/manifest.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "DeepSeeWeb",
3 | "short_name": "DeepSeeWeb",
4 | "theme_color": "#1976d2",
5 | "background_color": "#fafafa",
6 | "display": "standalone",
7 | "scope": "./",
8 | "start_url": "index.html",
9 | "icons": [
10 | {
11 | "src": "assets/img/logo.png",
12 | "sizes": "72x72",
13 | "type": "image/png",
14 | "purpose": "any"
15 | },
16 | {
17 | "src": "assets/img/logo.png",
18 | "sizes": "96x96",
19 | "type": "image/png",
20 | "purpose": "any"
21 | },
22 | {
23 | "src": "assets/img/logo.png",
24 | "sizes": "128x128",
25 | "type": "image/png",
26 | "purpose": "any"
27 | },
28 | {
29 | "src": "assets/img/logo.png",
30 | "sizes": "144x144",
31 | "type": "image/png",
32 | "purpose": "any"
33 | },
34 | {
35 | "src": "assets/img/logo.png",
36 | "sizes": "152x152",
37 | "type": "image/png",
38 | "purpose": "any"
39 | },
40 | {
41 | "src": "assets/img/logo.png",
42 | "sizes": "192x192",
43 | "type": "image/png",
44 | "purpose": "any"
45 | },
46 | {
47 | "src": "assets/img/logo.png",
48 | "sizes": "384x384",
49 | "type": "image/png",
50 | "purpose": "any"
51 | },
52 | {
53 | "src": "assets/img/logo.png",
54 | "sizes": "512x512",
55 | "type": "image/png",
56 | "purpose": "any"
57 | }
58 | ]
59 | }
60 |
--------------------------------------------------------------------------------
/src/manifest.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "DeepSeeWeb",
3 | "short_name": "DeepSeeWeb",
4 | "theme_color": "#1976d2",
5 | "background_color": "#fafafa",
6 | "display": "standalone",
7 | "scope": "./",
8 | "start_url": "index.html",
9 | "icons": [
10 | {
11 | "src": "assets/img/logo.png",
12 | "sizes": "72x72",
13 | "type": "image/png",
14 | "purpose": "any"
15 | },
16 | {
17 | "src": "assets/img/logo.png",
18 | "sizes": "96x96",
19 | "type": "image/png",
20 | "purpose": "any"
21 | },
22 | {
23 | "src": "assets/img/logo.png",
24 | "sizes": "128x128",
25 | "type": "image/png",
26 | "purpose": "any"
27 | },
28 | {
29 | "src": "assets/img/logo.png",
30 | "sizes": "144x144",
31 | "type": "image/png",
32 | "purpose": "any"
33 | },
34 | {
35 | "src": "assets/img/logo.png",
36 | "sizes": "152x152",
37 | "type": "image/png",
38 | "purpose": "any"
39 | },
40 | {
41 | "src": "assets/img/logo.png",
42 | "sizes": "192x192",
43 | "type": "image/png",
44 | "purpose": "any"
45 | },
46 | {
47 | "src": "assets/img/logo.png",
48 | "sizes": "384x384",
49 | "type": "image/png",
50 | "purpose": "any"
51 | },
52 | {
53 | "src": "assets/img/logo.png",
54 | "sizes": "512x512",
55 | "type": "image/png",
56 | "purpose": "any"
57 | }
58 | ]
59 | }
60 |
--------------------------------------------------------------------------------
/src/app/components/widgets/text/wtext.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | :host {
4 | display: flex;
5 | //flex-direction: column;
6 | flex-display: row;
7 | width: 100%;
8 | height: 100%;
9 | font-family: $font;
10 | -webkit-user-select: initial;
11 | user-select: initial;
12 |
13 | // No background for labels on tiles
14 | &.inline label {
15 | background-color: transparent;
16 | background-image: none;
17 | }
18 | }
19 |
20 | .item {
21 | display: flex;
22 | flex-direction: column;
23 | height: 100%;
24 | min-height: 0;
25 | }
26 |
27 | label {
28 | display: block;
29 | flex-shrink: 0;
30 | height: 16px;
31 | background-image: linear-gradient(to bottom, #f5f5f5 0, #e8e8e8 100%);
32 | width: 100%;
33 | text-align: center;
34 | font-family: monospace;
35 | white-space: nowrap;
36 | overflow: hidden;
37 | text-overflow: ellipsis;
38 | }
39 |
40 | .item2 {
41 | display: flex;
42 | flex-direction: column;
43 | flex: 1 1 100%;
44 | justify-content: center;
45 | align-items: center;
46 | margin: 10px;
47 | background-color: #fafafa;
48 | padding: 10px;
49 | min-height: 0;
50 | min-width: 0;
51 |
52 | &.clickable {
53 | cursor: pointer;
54 | }
55 |
56 | & > label {
57 | height: auto;
58 | background: transparent;
59 | color: gray;
60 | font-size: 19px;
61 | }
62 |
63 | & > svg {
64 | height: 50%;
65 | width: 100%;
66 | display: block;
67 | }
68 | }
69 |
70 | .text-widget {
71 | height: 100%;
72 | }
73 |
--------------------------------------------------------------------------------
/dist/chunk-NF3Y2YSA.js:
--------------------------------------------------------------------------------
1 | import{F as c,J as f}from"./chunk-YZADXMU6.js";import{X as o,aa as n,g as r,za as l}from"./chunk-ZEAAPN4P.js";var p=(()=>{class e{constructor(){this.emitter=new l}broadcast(t,s){this.emitter.emit({message:t,value:s})}subscribe(t,s){return this.emitter.subscribe(i=>{i.message===t&&s(i.value)})}static{this.\u0275fac=function(s){return new(s||e)}}static{this.\u0275prov=o({token:e,factory:e.\u0275fac,providedIn:"root"})}}return e})();var v=(()=>{class e{constructor(t){this.ss=t,this.current=new r(""),this.dashboard=new r(null),this.widgets=[],this.allWidgets=[]}setWidgets(t){this.widgets=t}getWidgets(){return this.widgets}getWidgetsWithoutEmpty(t=[]){return this.widgets.filter(s=>s.type!==c.const.emptyWidgetClass&&!t.includes(s.name))}setAllWidgets(t){this.allWidgets=t}getAllWidgets(){return this.allWidgets}saveWidgetPositionAndSize(t){let s=this.ss.getWidgetsSettings(t.dashboard),i=t.name;s[i]||(s[i]={}),isNaN(t.x)||(s[i].col=t.x),isNaN(t.y)||(s[i].row=t.y),isNaN(t.cols)||(s[i].sizeX=t.cols),isNaN(t.rows)||(s[i].sizeY=t.rows),this.ss.setWidgetsSettings(s,t.dashboard)}generateDisplayInfo(t){if(t.displayInfo)return;let s=1,i=1,a=this.dashboard.value;a&&(s=Math.floor(12/a.displayInfo.gridCols),s<1&&(s=1),i<1&&(i=1));let h={topCol:Math.floor((t.x||0)/s),leftRow:Math.floor((t.y||0)/i),colWidth:Math.floor((t.cols||1)/s),rowHeight:Math.floor(t.rows||1)};t.displayInfo=h}static{this.\u0275fac=function(s){return new(s||e)(n(f))}}static{this.\u0275prov=o({token:e,factory:e.\u0275fac,providedIn:"root"})}}return e})();export{p as a,v as b};
2 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/icon-search.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon-search.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/app/components/widgets/base/widget-filter/widget-filter.component.html:
--------------------------------------------------------------------------------
1 |
2 | @for (v of widget().pvItems; track v) {
3 |
4 |
5 |
6 |
7 | }
8 |
9 |
10 | @for (chooser of widget().dsItems; track chooser) {
11 |
12 |
13 | @if (chooser.field === 'select') {
14 |
19 | }
20 | @if (chooser.field === 'input') {
21 |
23 | }
24 |
25 | }
26 |
27 |
28 | @for (action of widget().acItems; track action) {
29 |
30 |
31 |
32 | }
33 |
34 |
35 | @for (flt of filters(); track flt) {
36 |
37 |
38 |
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/view-6columns.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/src/assets/img/icons/view-6columns.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/.github/workflows/angular-build.yml:
--------------------------------------------------------------------------------
1 | on: push
2 | name: Build Angular
3 | jobs:
4 | build:
5 | runs-on: ubuntu-latest
6 | strategy:
7 | matrix:
8 | node-version: [20.14.0]
9 |
10 | steps:
11 | - uses: actions/checkout@v2
12 | with:
13 | #persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token
14 | fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
15 |
16 | - name: Cache node modules
17 | uses: actions/cache@v3
18 | with:
19 | path: ~/.npm
20 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
21 | restore-keys: |
22 | ${{ runner.os }}-node-
23 | - name: Node ${{ matrix.node-version }}
24 | uses: actions/setup-node@v1
25 | with:
26 | node-version: ${{ matrix.node-version }}
27 |
28 | - name: Installing modules (npm i)
29 | run: |
30 | npm i
31 |
32 | - name: Updating version for ZPM
33 | run: |
34 | node ./.github/sync-zpm-version
35 |
36 | - name: Building DSW and addons
37 | run: |
38 | npm run build:addons
39 | npm run build
40 |
41 | - name: Deploying dist to master
42 | continue-on-error: true
43 | run: |
44 | git config --local user.email "action@github.com"
45 | git config --local user.name "GitHub Action"
46 | git add ./dist/*
47 | git add ./module.xml
48 | git commit -am "Automated commit of dist"
49 | git push
50 |
51 |
--------------------------------------------------------------------------------
/src/app/components/ui/input/input/input.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, EventEmitter, forwardRef, HostBinding, Input, Output} from '@angular/core';
2 | import {ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR} from "@angular/forms";
3 |
4 | @Component({
5 | selector: 'dsw-input',
6 | templateUrl: './input.component.html',
7 | styleUrls: ['./input.component.scss'],
8 | providers: [
9 | {
10 | provide: NG_VALUE_ACCESSOR,
11 | useExisting: forwardRef(() => InputComponent),
12 | multi: true
13 | }
14 | ],
15 | standalone: true,
16 | imports: [FormsModule]
17 | })
18 | export class InputComponent implements ControlValueAccessor {
19 | @Input() model = '';
20 | @Input() type = 'text';
21 | @Input() required = false;
22 | @HostBinding('class.choose')
23 | @Input() chooseButton = false;
24 | @Output() choose = new EventEmitter();
25 |
26 | constructor() {
27 | }
28 |
29 | @HostBinding('class.invalid')
30 | get isInvalid() {
31 | return this.required && !this.model;
32 | }
33 |
34 | onChange = (_) => {
35 | };
36 | onTouched = () => {
37 | };
38 |
39 | writeValue(value: any): void {
40 | this.model = value;
41 | }
42 |
43 | registerOnChange(fn: any): void {
44 | this.onChange = fn;
45 | }
46 |
47 | registerOnTouched(fn: any): void {
48 | this.onTouched = fn;
49 | }
50 |
51 | setDisabledState?(isDisabled: boolean): void {
52 | return;
53 | }
54 |
55 | onSelectButtonClick() {
56 | this.choose.emit();
57 | }
58 |
59 | onModelChange(txt: any) {
60 | this.writeValue(txt);
61 | this.onChange(txt);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/app/services/error.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import {BehaviorSubject} from 'rxjs';
3 |
4 | const DEFAULT_ERROR_DELAY = 5000;
5 |
6 | export interface IError {
7 | id: number;
8 | message?: string;
9 | delay: number;
10 | isLeft?: boolean;
11 | }
12 |
13 | @Injectable({
14 | providedIn: 'root'
15 | })
16 | export class ErrorService {
17 | errors$ = new BehaviorSubject([]);
18 | private lastId = 0;
19 | private errors: IError[] = [];
20 |
21 | constructor() {
22 | }
23 |
24 | /**
25 | * Returns error index
26 | */
27 | getIndex(error: IError): number {
28 | return this.errors.indexOf(error);
29 | }
30 |
31 | /**
32 | * Closes error
33 | */
34 | close(error: IError) {
35 | const idx = this.errors.findIndex(e => e === error);
36 | if (idx !== -1) {
37 | this.errors.splice(idx, 1);
38 | this.emit();
39 | }
40 | }
41 |
42 | /**
43 | * Shows error
44 | */
45 | show(message: string, isLeft = false, delay: number = DEFAULT_ERROR_DELAY) {
46 | // Generate id
47 | this.lastId++;
48 |
49 | // Add new error
50 | const error = {
51 | id: this.lastId,
52 | message,
53 | delay,
54 | isLeft
55 | };
56 | this.errors.push(error);
57 |
58 | // Remove error after delay
59 | if (delay !== 0) {
60 | setTimeout(() => {
61 | this.close(error);
62 | }, delay);
63 | }
64 |
65 | // Emit errors array
66 | this.emit();
67 | }
68 |
69 | /**
70 | * Emit new state of errors array
71 | */
72 | private emit() {
73 | this.errors$.next([...this.errors]);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/app/components/ui/sidebar-actions/sidebar-actions.component.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ChangeDetectionStrategy,
3 | ChangeDetectorRef,
4 | Component,
5 | EventEmitter,
6 | Input,
7 | OnDestroy,
8 | OnInit,
9 | Output
10 | } from '@angular/core';
11 | import {SidebarService} from "../../../services/sidebar.service";
12 | import {EditorService} from "../../../services/editor.service";
13 | import {Subscription} from "rxjs";
14 | import {I18nPipe} from '../../../services/i18n.service';
15 |
16 |
17 | @Component({
18 | selector: 'dsw-sidebar-actions',
19 | templateUrl: './sidebar-actions.component.html',
20 | styleUrls: ['./sidebar-actions.component.scss'],
21 | changeDetection: ChangeDetectionStrategy.OnPush,
22 | standalone: true,
23 | imports: [I18nPipe]
24 | })
25 | export class SidebarActionsComponent implements OnInit, OnDestroy {
26 | @Input() isBack = false;
27 | @Input() isWidgetEditorWarning = false;
28 | @Output() cancel = new EventEmitter();
29 | @Output() apply = new EventEmitter();
30 |
31 | isWidgetEditorWarningVisible = false;
32 | private subOnUnsavedChanged?: Subscription;
33 |
34 | constructor(private sbs: SidebarService,
35 | private eds: EditorService,
36 | private cd: ChangeDetectorRef) {
37 | }
38 |
39 | ngOnInit(): void {
40 | this.subOnUnsavedChanged = this.eds.onUnsavedChanged.subscribe(state => {
41 | this.isWidgetEditorWarningVisible = state;
42 | this.cd.detectChanges();
43 | });
44 | }
45 |
46 | onCloseClick() {
47 | if (this.isBack) {
48 | this.sbs.popComponent();
49 | }
50 | this.cancel.emit();
51 | }
52 |
53 | ngOnDestroy() {
54 | this.subOnUnsavedChanged?.unsubscribe();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/app/components/widgets/light-bar/light-bar.component.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | :host {
4 | // display: flex;
5 | display: grid;
6 | width: 100%;
7 | height: 100%;
8 | font-family: $font;
9 | -webkit-user-select: initial;
10 | user-select: initial;
11 | align-items: center;
12 | justify-content: center;
13 | gap: 20px;
14 | }
15 |
16 | .holder {
17 | width: 100%;
18 | height: 100%;
19 | flex: 1 1 100%;
20 | min-width: 0;
21 | min-height: 0;
22 | display: flex;
23 | flex-direction: column;
24 | align-items: center;
25 | justify-content: center;
26 | }
27 |
28 | label {
29 | width: 100%;
30 | font-family: $font;
31 | color: gray;
32 | font-size: 14px;
33 | text-align: center;
34 | height: 24px;
35 | max-height: 24px;
36 | white-space: nowrap;
37 | overflow: hidden;
38 | text-overflow: ellipsis;
39 | }
40 |
41 | .bar {
42 | display: flex;
43 | width: 100%;
44 | height: 24px;
45 | // height: calc(100% - 24px);
46 | border: 1px solid var(--cl-accent);
47 | border-radius: 1000px;
48 | padding-left: 3px;
49 | padding-right: 3px;
50 | gap: 4px;
51 | justify-content: space-between;
52 | align-items: center;
53 | }
54 |
55 | .dot {
56 | background: var(--cl-hover);
57 | border-radius: 1000px;
58 | /* flex: 1 1 100%;
59 | max-width: 100%;
60 | max-height: 100%;
61 | aspect-ratio: 1;*/
62 | width: 100%;
63 | height: 100%;
64 |
65 | max-width: 18px;
66 | max-height: 18px;
67 |
68 | &.filled {
69 | background: var(--cl-accent);
70 | }
71 | }
72 |
73 |
74 | .bar.high > .dot:last-child {
75 | background-color: rgba(224, 125, 134, 1);
76 | }
77 |
78 | .bar.low > .dot:first-child {
79 | background-color: #175ab8;
80 | }
81 |
--------------------------------------------------------------------------------
/dist/assets/img/icons/icon-settings.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon-settings.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/addons/htmlViewer.ts:
--------------------------------------------------------------------------------
1 | import {Component, inject, OnDestroy, OnInit} from '@angular/core';
2 | import {Subscription} from 'rxjs';
3 | import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';
4 | import {BaseWidget} from "../app/components/widgets/base-widget.class";
5 | import {IAddonInfo} from "../app/services/dsw.types";
6 |
7 | @Component({
8 | standalone: true,
9 | template: `
10 | `
11 | })
12 | export class HtmlViewer extends BaseWidget implements OnInit, OnDestroy {
13 | static AddonInfo: IAddonInfo = {
14 | // Version of addon system, should be specified manually as number, not reference
15 | // version always should be equal to BaseWidget.CURRENT_ADDON_VERSION
16 | // used to compare unsupported addons when breaking changes are made into BaseWidget
17 | // Note: do not use reference to BaseWidget.CURRENT_ADDON_VERSIO here!
18 | // specify number MANUALLY
19 | version: 1,
20 | // Widget type
21 | // 'custom' for all non-standard widgets
22 | // 'chart' for highcharts widget
23 | type: 'custom'
24 | };
25 | isSpinner = false;
26 | url: SafeResourceUrl;
27 | private san = inject(DomSanitizer);
28 | private subOnFilter: Subscription;
29 |
30 |
31 | ngOnInit(): void {
32 | this.url = this.san.bypassSecurityTrustResourceUrl(this.getUrl());
33 |
34 | this.subOnFilter = this.fs.onApplyFilter.subscribe(flt => {
35 | this.url = this.san.bypassSecurityTrustResourceUrl(this.getUrl().replace('$$$FILTERS', encodeURIComponent(flt.value)));
36 | });
37 | }
38 |
39 | getUrl(): string {
40 | return this.widget?.properties?.Data || '';
41 | }
42 |
43 | ngOnDestroy() {
44 | this.subOnFilter.unsubscribe();
45 | super.ngOnDestroy();
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/app/components/ui/namespace-selector/namespace-selector.component.ts:
--------------------------------------------------------------------------------
1 | import {ChangeDetectionStrategy, ChangeDetectorRef, Component} from '@angular/core';
2 | import {SidebarService} from '../../../services/sidebar.service';
3 | import {CURRENT_NAMESPACE, NamespaceService} from '../../../services/namespace.service';
4 | import {Router} from '@angular/router';
5 | import {DataService} from '../../../services/data.service';
6 |
7 | @Component({
8 | selector: 'dsw-namespace-selector',
9 | templateUrl: './namespace-selector.component.html',
10 | styleUrls: ['./../menu/menu.component.scss'],
11 | standalone: true,
12 | imports: [],
13 | changeDetection: ChangeDetectionStrategy.OnPush
14 | })
15 | export class NamespaceSelectorComponent {
16 |
17 | items: string[] = [];
18 | isLoading = true;
19 |
20 | constructor(private ss: SidebarService,
21 | private ns: NamespaceService,
22 | private ds: DataService,
23 | private cdr: ChangeDetectorRef,
24 | private router: Router) {
25 | this.requestData();
26 | }
27 |
28 | /**
29 | * Select namespace callback
30 | */
31 | selectNamespace(ns: string) {
32 | this.ns.setCurrent(ns);
33 | void this.router.navigateByUrl(ns);
34 | this.ss.hide();
35 | }
36 |
37 | /**
38 | * Returs true if namespace selected
39 | */
40 | isSelected(ns: string) {
41 | return ns.toLowerCase() === CURRENT_NAMESPACE.toLowerCase();
42 | }
43 |
44 | private requestData() {
45 | this.ds.getSettings(CURRENT_NAMESPACE)
46 | .then((settings: any) => {
47 | this.ns.setNamespaces(settings.Mappings.Mapped);
48 | })
49 | .finally(() => {
50 | this.isLoading = false;
51 | this.items = this.ns.getNamespaces();
52 | this.cdr.detectChanges();
53 | });
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/app/components/editor/datasource-selector-dialog/datasource-selector-dialog.scss:
--------------------------------------------------------------------------------
1 | @import "variables";
2 |
3 | :host {
4 | display: flex;
5 | flex-direction: column;
6 | height: 100%;
7 | overflow: hidden;
8 | }
9 |
10 | .header {
11 | flex-shrink: 0;
12 | }
13 |
14 | .table {
15 | position: relative;
16 | flex: 1 1 100%;
17 | min-width: 800px;
18 | min-height: 0;
19 | display: flex;
20 | white-space: nowrap;
21 | overflow: hidden;
22 |
23 | & > div {
24 | flex-shrink: 0;
25 | flex-grow: 1;
26 | flex-basis: 25%;
27 | border-right: 1px solid var(--cl-input-border);
28 | overflow: auto;
29 | min-width: 25%;
30 | width: 25%;
31 | @include dsw-scrollbar-v;
32 |
33 | &:first-child {
34 | position: sticky;
35 | left: 0;
36 | z-index: 2;
37 | background: white;
38 | }
39 | }
40 | }
41 |
42 | .row {
43 | user-select: none;
44 | padding: 5px 4px;
45 | cursor: pointer;
46 | align-items: center;
47 | color: var(--cl-widget-filter-txt);
48 | max-width: 25em;
49 | overflow: hidden;
50 | white-space: nowrap;
51 | text-overflow: ellipsis;
52 | position: relative;
53 | // padding-right: 20px;
54 |
55 | &:hover {
56 | background-color: var(--cl-hover);
57 | color: var(--cl-header-txt);
58 | }
59 |
60 | &.selected {
61 | color: var(--cl-accent);
62 | background-color: var(--cl-sidebar-bg);
63 | }
64 |
65 | & > img {
66 | height: 18px;
67 | vertical-align: text-top;
68 | margin-right: 2px;
69 | }
70 |
71 | /* &:after {
72 | position: absolute;
73 | right: 0;
74 | content: "»";
75 | }*/
76 | }
77 |
78 | /*
79 | .no-data {
80 | display: flex;
81 | align-items: center;
82 | justify-content: center;
83 | color: var(--cl-txt);
84 | min-height: 400px;
85 | }
86 | */
87 |
--------------------------------------------------------------------------------