{"version":3,"sources":["webpack:///./src/pages/dashboard-manager/dashboard-manager.ts","webpack:///./src/pages/dashboard-manager/dashboard-manager.html","webpack:///./src/pages/dashboard-manager/routes/dashboard-edit/dashboard-edit.ts","webpack:///./src/pages/dashboard-manager/routes/dashboard-edit/dashboard-edit.html","webpack:///./src/pages/dashboard-manager/routes/dashboard-list/dashboard-list.ts","webpack:///./src/pages/dashboard-manager/routes/dashboard-list/dashboard-list.html","webpack:///./src/pages/dashboard-manager/routes/data-store-list/data-store-list.ts","webpack:///./src/pages/dashboard-manager/routes/data-store-list/data-store-list.html"],"names":["DashboardManager","api","stores","program","recentPrograms","Object","keys","this","router","currentInstruction","params","length","config","programId","id","fetchProgram","settings","map","route","redirect","name","label","moduleId","fallbackRoute","auth","me","managementOrganizationId","activate","manageActivity","title","tabs","routes","filter","load","module","exports","logger","getLogger","DashboardEdit","alerts","ea","dialogs","resizing","resizeWidth","startWidth","resize","e","clientX","touches","diff","startLocation","Math","min","max","stopTrack","window","removeEventListener","newValue","editItem","type","publish","openEditor","create","level","dismissable","button","preventDefault","stopPropagation","forEach","event","addEventListener","editEnabled","closeEditor","configId","dashboardId","Boolean","edit","programConfigs","get","then","catch","description","program_id","data","items","x","y","w","h","getId","chartOptions","labels","datasets","backgroundColor","options","plugins","attachTo","dismissible","open","debug","some","item","noneField","storeId","undefined","customTitle","datalabels","percentLabels","categoryField","splitField","statsFields","field","stat","stacked","timeInterval","dateRange","push","cleanConfig","highlight","advancedEditor","patch","result","navigateToRoute","message","isDashboard","viewModel","model","whenClosed","wasCancelled","delete","remove","Promise","resolve","i","DashboardList","eaw","onDashboardCreated","dashboard","fetchDashboards","loading","find","query","orgId","matchingOrg","organizationId","isAdmin","dashboards","gadgets","getGadgetDisplay","mapping","reduce","obj","charAt","toUpperCase","slice","entries","count","join","events","eventEmitter","fn","DataStoreList","dataStoreDetails","loadStores","updateDataStoreDetails","programSurveys","$select","res","serviceTypeMapping","store","surveyTitle","sv","survey_id","fieldSelection","$modify","geometry","toGeoJSON","loadOffline","$client","dataType","service","path","survey","metadata","status","checkboxQuery","numberQuery","updatePromises","flatMap","updated","storeIds","includes","mapOptions","layers","layer","all","updateMapGadgets","updateConfigs"],"mappings":"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","file":"app~2814b46f.2c5c10cb1a4972799eba.chunk.js","sourcesContent":["import { PLATFORM } from 'aurelia-pal';\nimport { Router, RouterConfiguration, RouteConfig, Redirect } from 'aurelia-router';\nimport { autoinject, computedFrom } from 'aurelia-framework';\nimport { Program } from '../../types/Program';\nimport { ensureNumber } from '../../util/numbers/ensureNumber';\nimport { hasOrgPermission } from '../../util/orgs/hasOrgPermission';\nimport { DatafiProAPI } from '../../services/api/DatafiProAPI';\nimport { ActiveProgram } from '../../services/util/ActiveProgram';\nimport { ProgramActivity, RecentPrograms } from '../../services/util/RecentPrograms';\nimport { StoreManager } from 'services/util/StoreManager';\n\n@autoinject\nexport class DashboardManager {\n    programId: number;\n    router: Router;\n    tabs: RouteConfig[];\n\n    constructor(\n        private api: DatafiProAPI,\n        private stores: StoreManager,\n        private program: ActiveProgram,\n        private recentPrograms: RecentPrograms,\n    ) { }\n\n    @computedFrom('router.currentInstruction')\n    get showTabs(): boolean {\n        return !Object.keys(this.router.currentInstruction.params).length;\n    }\n\n    async configureRouter(config: RouterConfiguration, router: Router, params) {\n        const programId = ensureNumber(params.id);\n        await this.fetchProgram(programId);\n\n        const settings = { program: this.program, programId: this.programId };\n\n        config.map([\n            { route: '', redirect: 'data-stores' },\n            { name: 'data-stores', route: 'data-stores', label: 'Data Stores', moduleId: PLATFORM.moduleName('pages/dashboard-manager/routes/data-store-list/data-store-list'), settings },\n            { name: 'data-store-edit', route: 'data-stores/:configId', moduleId: PLATFORM.moduleName('pages/dashboard-program-edit/routes/configs-edit'), settings },\n            { name: 'dashboards', route: 'dashboards', label: 'Dashboards', moduleId: PLATFORM.moduleName('pages/dashboard-manager/routes/dashboard-list/dashboard-list'), settings },\n            { name: 'dashboard-edit', route: 'dashboards/:dashboardId', moduleId: PLATFORM.moduleName('pages/dashboard-manager/routes/dashboard-edit/dashboard-edit'), settings },\n        ]);\n\n        config.fallbackRoute('home');\n        this.router = router;\n    }\n\n    async canActivate(params) {\n        const programId = ensureNumber(params.id);\n\n        if (programId !== this.programId) await this.fetchProgram(programId);\n\n        if (!this.program) new Redirect('/not-found');\n        if (!hasOrgPermission(this.api.auth.me, { id: this.programId, managementOrganizationId: this.program.managementOrganizationId } as Program)) return new Redirect('/not-found');\n    }\n\n    async activate(params) {\n        if (!this.program) return;\n        await this.stores.activate(this.programId);\n        if (this.programId) this.recentPrograms.manageActivity({ id: this.programId, title: this.program.title, managementOrganizationId: this.program.managementOrganizationId } as ProgramActivity);\n    }\n\n    attached() {\n        this.tabs = this.router.routes.filter((route) => !!route.label);\n    }\n\n    async fetchProgram(programId: number) {\n        this.programId = programId;\n        await this.program.load(programId, true);\n    }\n}\n","// Module\nvar code = \"<template> <require from=\\\"../../components/dashboard-layout/dashboard-layout\\\"></require> <div class=\\\"h-100 d-flex flex-column\\\"> <mdc-tab-bar class=\\\"d-block mt-4\\\" if.bind=\\\"showTabs\\\"> <mdc-tab repeat.for=\\\"tab of tabs\\\" active.bind=\\\"tab.navModel.isActive\\\" label.bind=\\\"tab.label\\\" click.delegate=\\\"router.navigateToRoute(tab.route)\\\"></mdc-tab> </mdc-tab-bar> <div slot=\\\"main\\\" class=\\\"w-100 p-6 flex-grow-1\\\"> <router-view class=\\\"h-100 d-block\\\"></router-view> </div> </div> </template> \";\n// Exports\nmodule.exports = code;","import { Field, ProgramConfig } from '@wsb_dev/datafi-shared/lib/types';\nimport { autoinject, bindable, LogManager } from 'aurelia-framework';\nimport { Router } from 'aurelia-router';\nimport { DatafiProAPI } from '../../../../services/api/DatafiProAPI';\nimport { AlertService } from '../../../../services/util/Alert';\nimport { ValidatedProgramConfig } from '../../../../types/ProgramConfig';\nimport { ensureNumber } from '../../../../util/numbers/ensureNumber';\nimport { v4 as uuidv4 } from 'uuid';\nimport { EventAggregator } from 'aurelia-event-aggregator';\nimport { MDCDrawer } from '@material/drawer';\nimport { IDashboardConfig, IDashboardItem } from '../../../../types/Dashboards';\nimport { DialogService } from 'aurelia-dialog';\nimport { ConfirmDialog } from '../../../../components/confirm-dialog/confirm-dialog';\nimport cloneDeep from 'lodash.clonedeep';\n\nconst logger = LogManager.getLogger('dfp:dashboards');\n@autoinject\nexport class DashboardEdit {\n    config: ProgramConfig<IDashboardConfig>;\n    configId: number;\n    guid: string;\n    resizing = false;\n    resizeWidth = 275;\n    startWidth = 275;\n    startLocation: number;\n\n    @bindable editItem: any;\n\n    editItemChanged(newValue) {\n\n        if (!this.editItem) {\n            return;\n        }\n        if (this.editItem.type) {\n            // publish the new edit item\n            this.ea.publish('edit-item', newValue);\n            this.openEditor();\n        } else {\n            this.alerts.create({ label: 'Unknown Widget Type', level: 'warning', dismissable: true });\n        }\n    }\n\n    startTrack(e) {\n        if (e.button !== 0 && e.type === 'mousedown') {\n            return;\n        }\n        e.preventDefault();\n        e.stopPropagation();\n\n        this.startLocation = e.clientX || e.touches[0].clientX;\n        this.resizing = true;\n        ['mouseup', 'touchend'].forEach((event) => window.addEventListener(event, this.stopTrack));\n        ['mousemove', 'touchmove'].forEach((event) => window.addEventListener(event, this.resize));\n    }\n\n    // needs to be an arrow function for \"this\" to be the dashboard and not the window\n    resize = (e) => {\n        if (this.resizing) {\n            const clientX = e.clientX || e.touches[0].clientX;\n            const diff = this.startLocation - clientX;\n            this.resizeWidth = Math.min(Math.max(this.startWidth + diff, 275), 718);\n        }\n    }\n\n    // needs to be an arrow function for \"this\" to be the dashboard and not the window\n    stopTrack = (e) => {\n        if (this.resizing) {\n            this.resizing = false;\n            this.startWidth = this.resizeWidth;\n            window.removeEventListener('mouseup', this.stopTrack);\n            window.removeEventListener('mousemove', this.resize);\n        }\n    }\n\n    @bindable editEnabled: boolean;\n    editEnabledChanged() {\n        if (!this.editEnabled) {\n            this.closeEditor();\n        }\n    }\n\n    dismissible: HTMLDivElement;\n\n    constructor(\n        private api: DatafiProAPI,\n        private alerts: AlertService,\n        private router: Router,\n        private ea: EventAggregator,\n        private dialogs: DialogService,\n    ) {\n    }\n\n    async activate(params, config) {\n        this.configId = ensureNumber(params.dashboardId);\n        this.editEnabled = Boolean(params.edit);\n        this.config = await (\n            this.configId ?\n                this.api.programConfigs.get(this.configId)\n                    .then((config) => new ValidatedProgramConfig(config))\n                    // not found\n                    .catch(() => undefined) :\n                new ValidatedProgramConfig({\n                    label: 'New Dashboard',\n                    description: 'A nifty little dashboard',\n                    type: 'dashboard',\n                    program_id: config.settings.program.id,\n                    data: {\n                        items: [\n                            {\n                                x: 0, y: 0, w: 6, h: 5, id: this.getId(), type: 'chart', config: {\n                                    chartOptions: {\n                                        type: 'bar',\n                                        data: {\n                                            labels: ['a', 'b', 'c'],\n                                            datasets: [{\n                                                label: 'Sample Dataset',\n                                                data: [10, 20, 15],\n                                                backgroundColor: []\n                                                ,\n                                            }],\n                                        },\n                                        options: {},\n                                        plugins: [],\n                                    },\n                                },\n                            },\n                        ],\n                    },\n                })\n        );\n\n        // if we are creating a new dashboard, display the edit dialog for\n        // the new dashboard\n        if (!this.configId) {\n            this.editItem = this.config;\n        }\n    }\n\n    attached() {\n        if (this.editEnabled) {\n            this.openEditor();\n        }\n    }\n\n    closeEditor() {\n        this.editItem = null;\n        const drawer = MDCDrawer.attachTo(this.dismissible);\n        drawer.open = false;\n    }\n\n    openEditor() {\n        const drawer = MDCDrawer.attachTo(this.dismissible);\n        drawer.open = true;\n    }\n\n    addItem(type, config) {\n        logger.debug(type, config);\n        // only allow one global filter gadget to exist\n        if (type === 'filter') {\n            if (this.config.data.items.some((item) => item.type == 'filter')) {\n                return this.alerts.create({\n                    label: 'A global filter already exists',\n                    level: 'warning',\n                    dismissable: true,\n                });\n            }\n        }\n        if (type == 'chart') {\n            const noneField: Field = { label: 'None', name: 'none' };\n            // pass a default config to initialize the chart\n            const type = config.type;\n            const chartConfig = {\n                type: type,\n                data: {\n                    labels: ['a', 'b', 'c'],\n                    datasets: [{\n                        label: 'Sample Dataset',\n                        data: [10, 20, 15],\n                        backgroundColor: ['rgb(250, 175, 63)']\n                        ,\n                    }],\n                },\n                options: {},\n            };\n            config = {\n                storeId: undefined,\n                chartOptions: chartConfig,\n                customTitle: false,\n                title: undefined,\n                datalabels: false,\n                percentLabels: false,\n                categoryField: noneField, splitField: noneField,\n                statsFields: [{ field: noneField, stat: 'Count' }],\n                stacked: false, timeInterval: 'day', dateRange: '',\n            };\n\n        }\n\n        this.config.data.items.push({ x: 0, y: 0, w: 6, h: 5, type, config, id: this.getId() });\n\n        this.editItem = this.config.data.items[this.config.data.items.length - 1];\n        this.openEditor();\n    }\n\n    getId() {\n        const guid = uuidv4();\n        return guid;\n    }\n\n    save() {\n        const cleanConfig = cloneDeep(this.config);\n        cleanConfig.data.items.forEach((item) => {\n            item.highlight = false;\n        });\n        delete cleanConfig.advancedEditor;\n\n        const id = cleanConfig.id;\n        const promise = id ?\n            this.api.programConfigs.patch(id, cleanConfig) :\n            this.api.programConfigs.create(cleanConfig);\n\n        return promise.then((result) => {\n            this.alerts.create({\n                label: 'Dashboard saved',\n                level: 'success',\n                dismissable: true,\n            });\n            if (!id) {\n                this.router.navigateToRoute('dashboard-edit', { dashboardId: result.id });\n                this.ea.publish('new-dashboard', result);\n            }\n        }).catch((e) => {\n            this.alerts.create({ label: `Error: ${e.message}`, level: 'error', dismissable: true });\n        });\n    }\n\n    async deleteDialog(item: IDashboardItem | ProgramConfig) {\n        const isDashboard = (item as ProgramConfig).type === 'dashboard';\n\n        if (isDashboard) {\n            if (!item.id) {\n                this.alerts.create({\n                    label: 'Item is not yet saved',\n                    level: 'warning',\n                    dismissable: true,\n                });\n                return;\n            }\n        }\n\n        return this.dialogs.open({\n            viewModel: ConfirmDialog,\n            model: {\n                title: 'Delete',\n                message: isDashboard ?\n                    'Are you sure you want to delete this dashboard and all of its gadgets?' :\n                    'Are you sure you want to remove this gadget?',\n\n            },\n        }).whenClosed((result) => {\n            if (result.wasCancelled) {\n                return;\n            }\n            this.delete(item, isDashboard);\n\n        });\n    }\n\n    delete(item, isDashboard) {\n\n        const promise = isDashboard ?\n            this.api.programConfigs.remove(item.id) :\n            Promise.resolve(this.config.data.items = this.config.data.items.filter((i) => i.id !== item.id));\n\n        return promise.then(() => {\n            this.closeEditor();\n\n            this.alerts.create({\n                label: 'Item removed',\n                level: 'success',\n                dismissable: true,\n            });\n\n            if (isDashboard) {\n                this.router.navigateToRoute('program/dashboard-manager', { id: this.config.program_id });\n            }\n        });\n    }\n}\n","// Module\nvar code = \"<template> <require from=\\\"../../../../components/dashboard-grid/dashboard-grid\\\"></require> <require from=\\\"../../../../components/gadget-editor/gadget-editor\\\"></require> <require from=\\\"../../../../components/mdc-json-field/mdc-json-field\\\"></require> <p if.bind=\\\"!config\\\">This dashboard could not be found</p> <div class=\\\"grid-container\\\" if.bind=\\\"config\\\"> <aside ref=\\\"dismissible\\\" class=\\\"mdc-drawer mdc-drawer--dismissible drawer-from-right float-right scroll-y-hidden edit-drawer\\\" css=\\\"width: ${resizeWidth}px;\\\"> <div class=\\\"mdc-drawer-content\\\" dir=\\\"ltr\\\"> <button class=\\\"button--color--secondary d-inline-flex float-right m-4\\\" icon=\\\"close\\\" mdc-icon-button click.trigger=\\\"closeEditor()\\\"></button> <gadget-editor if.bind=\\\"editItem\\\" edit-item.two-way=\\\"editItem\\\" edit-item.trigger=\\\"editItemChanged($event.detail)\\\"> </gadget-editor> <span if.bind=\\\"config.id\\\"> <button click.delegate=\\\"deleteDialog(editItem)\\\" class=\\\"button--color--danger my-8 p-centered\\\" mdc-button raised> <mdc-icon>delete</mdc-icon> Delete </button> </span> </div> </aside> <div if.bind=\\\"editItem\\\" class=\\\"resize-handle d-flex align-center\\\" mousedown.delegate=\\\"startTrack($event)\\\" touchstart.trigger=\\\"startTrack($event)\\\"> <div class=\\\"handle-bar d-flex align-center justify-center flex-column\\\"> <span></span> <span></span> <span></span> </div> </div> <div class=\\\"d-block p-2 main-content\\\"> <div class=\\\"header d-flex mx-2\\\"> <div class=\\\"d-flex align-center\\\"> <a mdc-icon-button class=\\\"button--color--grey--primary\\\" route-href=\\\"route: dashboards\\\" mdc-tooltip=\\\"Back\\\" icon=\\\"arrow_back\\\"></a> <span class=\\\"text-bold text-large ml-5\\\">${config.label}</span> </div> <div if.bind=\\\"editEnabled\\\"> <button if.bind=\\\"!config.advancedEditor\\\" mdc-elevation.bind=\\\"0\\\" ref=\\\"hierarchicalAnchor\\\" mdc-fab extended icon=\\\"dashboard_customize\\\" label=\\\"New Gadget\\\" click.trigger=\\\"(hierarchical.open = !hierarchical.open)\\\" class=\\\"button--color--grey--primary m-2\\\"></button> <mdc-menu anchor-corner=\\\"BOTTOM_LEFT\\\" view-model.ref=\\\"hierarchical\\\" anchor.bind=\\\"hierarchicalAnchor\\\" hoist-to-body> <mdc-list> <mdc-list-item click.trigger=\\\"addItem('chart', {type: 'bar'})\\\" value=\\\"list\\\" mdclistitem:action.trigger=\\\"hierarchical.open = false\\\"> <span class=\\\"d-flex\\\"> <mdc-icon class=\\\"mr-2\\\">view_column</mdc-icon>Bar Chart </span> </mdc-list-item> <mdc-list-item click.trigger=\\\"addItem('chart', {type: 'pie'})\\\" value=\\\"list\\\" mdclistitem:action.trigger=\\\"hierarchical.open = false\\\"> <span class=\\\"d-flex\\\"> <mdc-icon class=\\\"mr-2\\\">pie_chart</mdc-icon>Pie Chart </span> </mdc-list-item> <mdc-list-item click.trigger=\\\"addItem('summary', {label: 'New summary'})\\\" value=\\\"gallery\\\" mdclistitem:action.trigger=\\\"hierarchical.open = false\\\"> <span class=\\\"d-flex\\\"> <mdc-icon class=\\\"mr-2\\\">pin</mdc-icon>Summary </span> </mdc-list-item> <mdc-list-item click.trigger=\\\"addItem('map', {\\n                                storeIds: [], \\n                                mapOptions: { \\n                                    type: 'ol/Map',\\n                                    view: { type: 'ol/View' },\\n                                    layers: [{\\n                                        id: 'OpenStreetMapDefault',\\n                                        label: 'Basemap',\\n                                        type: 'ol/layer/Tile',\\n                                        source: { type: 'ol/source/OSM' },\\n                                    }]\\n                                }})\\\"> <span class=\\\"d-flex\\\"> <mdc-icon class=\\\"mr-2\\\">place</mdc-icon>Map </span> </mdc-list-item> <mdc-list-item click.delegate=\\\"addItem('table')\\\"> <span class=\\\"d-flex\\\"> <mdc-icon class=\\\"mr-2\\\">table_rows</mdc-icon>Table </span> </mdc-list-item> <mdc-list-item click.trigger=\\\"addItem('text', {data: {innerHTML: '<div>Edit me to modify text.</div>'}})\\\" value=\\\"list\\\" mdclistitem:action.trigger=\\\"hierarchical.open = false\\\"> <span class=\\\"d-flex\\\"> <mdc-icon class=\\\"mr-2\\\">text_fields</mdc-icon>Text </span> </mdc-list-item> <mdc-list-item click.trigger=\\\"addItem('filter')\\\" value=\\\"list\\\" mdclistitem:action.trigger=\\\"hierarchical.open = false\\\"> <span class=\\\"d-flex\\\"> <mdc-icon class=\\\"mr-2\\\">filter_alt</mdc-icon>Global Filter </span> </mdc-list-item> </mdc-list> </mdc-menu> <button class=\\\"button--color--grey--primary\\\" mdc-tooltip=\\\"Settings\\\" mdc-icon-button icon=\\\"settings\\\" click.trigger=\\\"editItem = config\\\"></button> <a mdc-icon-button class=\\\"button--color--grey--primary ml-2\\\" route-href=\\\"route: dashboard-share; params.bind: {configId: configId, programId: config.program_id}\\\" target=\\\"_blank\\\" mdc-tooltip=\\\"Open Sharable Tab\\\" icon=\\\"ios_share\\\"></a> <button mdc-icon-button class=\\\"button--color--grey--primary m-2\\\" mdc-tooltip=\\\"Save Changes\\\" click.trigger=\\\"save()\\\" icon=\\\"save\\\"></button> <button mdc-icon-button class=\\\"button--color--grey--primary\\\" mdc-tooltip=\\\"Stop Editing\\\" click.delegate=\\\"editEnabled = false\\\" icon=\\\"edit_off\\\"></button> </div> <div else> <a mdc-icon-button class=\\\"button--color--grey--primary m-2\\\" route-href=\\\"route: dashboard-share; params.bind: {configId: configId, programId: config.program_id}\\\" target=\\\"_blank\\\" mdc-tooltip=\\\"Open Sharable Tab\\\" icon=\\\"ios_share\\\"></a> <button mdc-icon-button class=\\\"button--color--grey--primary\\\" click.delegate=\\\"editEnabled = true\\\" mdc-tooltip=\\\"Start Editing\\\" icon=\\\"edit_square\\\"></button> </div> </div> <div class=\\\"d-flex\\\"> <div class=\\\"w-100\\\" if.bind=\\\"config\\\"> <mdc-json-field show.bind=\\\"config.advancedEditor\\\" label=\\\"Dashboard Configuration\\\" value.two-way=\\\"config.data\\\" class=\\\"mt-8\\\"></mdc-json-field> <dashboard-grid show.bind=\\\"!config.advancedEditor\\\" class=\\\"dashboard-content w-100\\\" edit-item.two-way=\\\"editItem\\\" config.two-way=\\\"config\\\" edit-enabled.bind=\\\"editEnabled\\\" edit-item.trigger=\\\"editItem = $event.detail\\\"> </dashboard-grid> </div> <p else>Loading...</p> </div> </div> </div> </template> \";\n// Exports\nmodule.exports = code;","import { autoinject } from 'aurelia-framework';\nimport { DialogService } from 'aurelia-dialog';\nimport { Paginated } from '@feathersjs/feathers';\nimport { userHasPermission } from '@wsb_dev/datafi-shared/lib/util/users/userHasPermission';\nimport { ensureNumber } from '../../../../util/numbers/ensureNumber';\nimport { subscribe } from '../../../../util/decorators/subscribe';\nimport { EventAggregatorWrapper } from '../../../../util/events/eventAggregatorWrapper';\nimport { ProgramConfig } from '@wsb_dev/datafi-shared/lib/types';\nimport { ValidatedProgramConfig } from '../../../../types/ProgramConfig';\nimport { IDashboardItem } from '../../../../types/Dashboards';\nimport { DatafiProAPI } from '../../../../services/api/DatafiProAPI';\nimport { ActiveProgram } from '../../../../services/util/ActiveProgram';\nimport { AlertService } from '../../../../services/util/Alert';\nimport { ConfirmDialog } from '../../../../components/confirm-dialog/confirm-dialog';\n\n@subscribe({\n    events: [\n        { eventEmitter: 'eaw', event: 'new-dashboard', fn: 'onDashboardCreated' },\n    ],\n})\n\n@autoinject\nexport class DashboardList {\n    loading: boolean;\n    programId: number;\n    dashboards: ProgramConfig[];\n\n    constructor(\n        private api: DatafiProAPI,\n        private program: ActiveProgram,\n        private eaw: EventAggregatorWrapper,\n        private dialogs: DialogService,\n        private alerts: AlertService,\n    ) {\n        this.eaw = eaw;\n    }\n\n    async activate() {\n        await this.program.load();\n        this.programId = ensureNumber(this.program.id);\n        this.fetchDashboards();\n    }\n\n    fetchDashboards() {\n        this.loading = true;\n\n        this.api.programConfigs.find({\n            query: { program_id: this.programId, type: 'dashboard' },\n        }).then((result: Paginated<ProgramConfig>) => {\n            const orgId = this.program?.managementOrganizationId;\n\n            if (orgId) {\n                const matchingOrg = this.api.auth.me.organizationId === orgId;\n                const isAdmin = userHasPermission(this.api.auth.me, '*', '*');\n                if (!matchingOrg && !isAdmin) {\n                    return;\n                }\n            }\n\n            this.dashboards = result.data.map((config) => {\n                return {\n                    ...new ValidatedProgramConfig(config),\n                    gadgets: this.getGadgetDisplay(config.data.items),\n                };\n            });\n            this.loading = false;\n        });\n    }\n\n    getGadgetDisplay(items) {\n        const mapping = items.reduce((obj, item) => {\n            const type = item.type.charAt(0).toUpperCase() + item.type.slice(1);\n            obj[type] = (obj[type] || 0) + 1;\n            return obj;\n        }, {});\n\n        return Object.entries(mapping).map(([type, count]) => `${type} (${count})`).join(', ');\n    }\n\n    deleteDialog(id: number) {\n        return this.dialogs.open({\n            viewModel: ConfirmDialog,\n            model: {\n                message: 'Are you sure you want to delete this dashboard and all of its gadgets?',\n                title: 'Delete',\n            } as Partial<ConfirmDialog>,\n        }).whenClosed((result) => {\n            if (result.wasCancelled) {\n                return;\n            }\n            this.delete(id);\n        });\n    }\n\n    async delete(id: number) {\n        await this.api.programConfigs.remove(id)\n            .then(() => {\n                this.alerts.create({\n                    label: 'Dashboard removed',\n                    level: 'success',\n                    dismissable: true,\n                });\n                this.fetchDashboards();\n            })\n            .catch((e) => {\n                this.alerts.create({\n                    label: `Error: ${e.message}`,\n                    level: 'error',\n                    dismissable: true,\n                });\n            });\n    }\n\n    onDashboardCreated = (dashboard: IDashboardItem) => {\n        if (dashboard) {\n            this.fetchDashboards();\n        }\n    }\n\n}\n","// Module\nvar code = \"<template> <mdc-data-table class=\\\"w-100\\\"> <table> <thead> <th> <a mdc-button raised route-href=\\\"route: dashboard-edit; params.bind: {\\n                        dashboardId: 0, \\n                        edit: true\\n                    }\\\"><mdc-icon>add</mdc-icon> New</a> </th> <th>Title</th> <th>Description</th> <th>Gadgets</th> <th>Date Created</th> <th>Created By</th> <th>Date Updated</th> <th>Updated By</th> <th>ID</th> <th></th> </thead> <tbody> <tr mdc-data-table-row repeat.for=\\\"dash of dashboards\\\"> <td> <a route-href=\\\"route: dashboard-edit; params.bind: {dashboardId: dash.id}\\\" mdc-icon-button class=\\\"button--color--primary\\\" icon=\\\"edit\\\"> </a> </td> <td>${dash.label}</td> <td>${dash.description}</td> <td>${dash.gadgets}</td> <td>${dash.createdAt | date}</td> <td>${dash.createdBy}</td> <td>${dash.updatedAt | date}</td> <td>${dash.modifiedBy}</td> <td>${dash.id}</td> <td> <button class=\\\"button--color--danger\\\" mdc-icon-button click.delegate=\\\"deleteDialog(dash.id)\\\" icon=\\\"delete\\\"> </button> </td> </tr> </tbody> </table> <mdc-linear-progress if.bind=\\\"loading === true\\\" open.bind=\\\"true\\\"></mdc-linear-progress> </mdc-data-table> </template> \";\n// Exports\nmodule.exports = code;","import { autoinject } from 'aurelia-framework';\nimport { DialogService } from 'aurelia-dialog';\nimport { ensureNumber } from '../../../../util/numbers/ensureNumber';\nimport { ProgramConfig } from '@wsb_dev/datafi-shared/lib/types';\nimport { ConfirmDialog } from '../../../../components/confirm-dialog/confirm-dialog';\nimport { DatafiProAPI } from '../../../../services/api/DatafiProAPI';\nimport { AlertService } from '../../../../services/util/Alert';\nimport { StoreManager } from '../../../../services/util/StoreManager';\nimport { ActiveProgram } from '../../../../services/util/ActiveProgram';\n\nexport interface DataStoreDetails {\n    id: number;\n    name: string;\n    dataType: string;\n    loadOffline: boolean;\n    filter: boolean;\n    survey?: string;\n    fieldSelection?: string;\n    geometry?: boolean;\n}\n\n@autoinject\nexport class DataStoreList {\n    loading: boolean;\n    programId: number;\n    dataStoreDetails: DataStoreDetails[] = [];\n\n    constructor(\n        private api: DatafiProAPI,\n        private program: ActiveProgram,\n        private stores: StoreManager,\n        private dialogs: DialogService,\n        private alerts: AlertService,\n    ) { }\n\n    async activate() {\n        await this.program.load();\n        this.programId = ensureNumber(this.program.id);\n        this.loadStores();\n    }\n\n    async loadStores() {\n        this.loading = true;\n        await this.updateDataStoreDetails();\n        this.loading = false;\n    }\n\n    async updateDataStoreDetails() {\n        this.dataStoreDetails = [];\n        const programSurveys = await this.api.programSurveys.find({\n            query: {\n                program_id: this.programId,\n                $select: ['id', 'title'],\n            },\n        }).then((res: any) => res.data);\n\n        const serviceTypeMapping = {\n            'api/v1/form-submissions': 'Survey',\n            'api/v1/projects-files': 'Project Files',\n            'api/v1/projects': 'Projects',\n            'api/v1/programs-users-roles': 'User Location',\n        };\n\n        this.stores?.stores.map(async (store) => {\n            const surveyTitle = programSurveys.find((sv) => sv.id === store.query?.survey_id)?.title;\n            const fieldSelection = store.query?.$modify?.fieldSelection?.length;\n            const geometry = store?.query?.$modify?.toGeoJSON;\n            const loadOffline = store.query?.$client;\n\n            this.dataStoreDetails.push({\n                id: store.id,\n                name: store.name,\n                dataType: serviceTypeMapping[store.service.path] || store.service.path,\n                survey: surveyTitle ? `: ${surveyTitle}` : '',\n                fieldSelection: fieldSelection ? `${fieldSelection} of 15 selected` : 'All',\n                geometry: geometry ? true : false,\n                loadOffline: loadOffline ? false : true,\n                filter: store.query?.metadata || store.query?.status || store.query?.$modify?.checkboxQuery || store.query?.$modify?.numberQuery ? true : false,\n            });\n        });\n    }\n\n    async updateMapGadgets(id: number) {\n        const dashboards = await this.api.programConfigs.find({ query: { program_id: this.programId, type: 'dashboard' } }) as ProgramConfig;\n        const updatePromises = dashboards.data.flatMap((dashboard) => {\n            let updated = false;\n            dashboard.data.items.forEach((item) => {\n                if (item.config?.storeIds?.includes(id)) {\n                    item.config.storeIds = item.config.storeIds.filter((storeId) => storeId !== id);\n                    updated = true;\n                }\n                if (item.config?.mapOptions?.layers) {\n                    item.config.mapOptions.layers = item.config.mapOptions.layers.filter((layer) => layer.id !== `store-${id}`);\n                    updated = true;\n                }\n            });\n\n            if (updated) {\n                return [this.api.programConfigs.patch(dashboard.id, dashboard)];\n            }\n            return [];\n        });\n\n        await Promise.all(updatePromises);\n    }\n\n    deleteDialog(id: number) {\n        return this.dialogs.open({\n            viewModel: ConfirmDialog,\n            model: {\n                message: 'Are you sure you want to delete this data store? Dashboard gadgets will need to be updated to remove datastore.',\n                title: 'Confirm Delete',\n            } as Partial<ConfirmDialog>,\n        })\n            .whenClosed((result) => {\n                if (result.wasCancelled) {\n                    return;\n                }\n\n                this.updateMapGadgets(id);\n                this.delete(id);\n\n            })\n            .catch((e) => {\n                this.alerts.create({\n                    label: `Error: ${e.message}`,\n                    level: 'error',\n                    dismissable: true,\n                });\n            });\n    }\n\n    delete(id) {\n        return this.api.programConfigs.remove(id).then(() => {\n            this.alerts.create({\n                label: 'Data store removed',\n                level: 'success',\n                dismissable: true,\n            });\n            return this.stores.updateConfigs().then(() => {\n                this.updateDataStoreDetails();\n            });\n        });\n    }\n\n}\n","// Module\nvar code = \"<template> <mdc-data-table class=\\\"w-100\\\"> <table> <thead> <th> <a mdc-button raised route-href=\\\"route: data-store-edit; params.bind: {\\n                        configId: 0, \\n                        defaults: {type: 'data-store'}\\n                    }\\\"><mdc-icon>add</mdc-icon> New</a> </th> <th>Title</th> <th>Store Type</th> <th>Filter Active</th> <th>Field Selection</th> <th>Include Map Data</th> <th>Loads Offline</th> <th>ID</th> <th></th> </thead> <tbody> <tr mdc-data-table-row repeat.for=\\\"store of dataStoreDetails\\\"> <td> <a route-href=\\\"route: data-store-edit; params.bind: {configId: store.id}\\\" mdc-icon-button class=\\\"button--color--primary\\\" icon=\\\"edit\\\"> </a> </td> <td>${store.name}</td> <td>${store.dataType} ${store.survey ? `${store.survey}` : ''}</td> <td> <mdc-icon if.bind=\\\"store.filter\\\">check</mdc-icon> </td> <td>${store.fieldSelection}</td> <td> <mdc-icon if.bind=\\\"store.geometry\\\">check</mdc-icon> </td> <td> <mdc-icon if.bind=\\\"store.loadOffline\\\">check</mdc-icon> </td> <td>${store.id}</td> <td> <button class=\\\"button--color--danger\\\" mdc-icon-button click.delegate=\\\"deleteDialog(store.id)\\\" icon=\\\"delete\\\"> </button> </td> </tr> </tbody> </table> <mdc-linear-progress if.bind=\\\"loading === true\\\" open.bind=\\\"true\\\"></mdc-linear-progress> </mdc-data-table>  </template> \";\n// Exports\nmodule.exports = code;"],"sourceRoot":""}