diff --git a/bower.json b/bower.json
index 40d25d80..2fee9681 100644
--- a/bower.json
+++ b/bower.json
@@ -34,7 +34,7 @@
"angular-translate-interpolation-messageformat": "^2.14.0",
"angular-sanitize": "^1.6.2",
"angular-message-format": "^1.6.2",
- "impac-angular": "~1.7.0",
+ "impac-angular": "~1.8.5",
"angular-bootstrap-toggle": "^0.1.2"
},
"devDependencies": {
diff --git a/src/app/components/mnoe-api/admin/dashboard.svc.coffee b/src/app/components/mnoe-api/admin/dashboard.svc.coffee
new file mode 100644
index 00000000..efc6ab2b
--- /dev/null
+++ b/src/app/components/mnoe-api/admin/dashboard.svc.coffee
@@ -0,0 +1,18 @@
+# Service for managing staff dashboards
+@App.service 'MnoeDashboards', (MnoeAdminApiSvc, MnoeCurrentUser) ->
+ _self = @
+
+ # List the staff dashboard for the current user
+ @getStaffDashboards = (organizationUid, limit, offset, sort) ->
+ MnoeAdminApiSvc.all("/impac/dashboards").getList({
+ order_by: sort,
+ limit: limit,
+ offset: offset,
+ 'where[data_sources]': [organizationUid]
+ })
+
+ # Delete a dashboard
+ @delete = (dashboardId) ->
+ MnoeAdminApiSvc.one("/impac/dashboards", dashboardId).remove()
+
+ return @
diff --git a/src/app/components/mnoe-config/mnoe-admin-config.svc.coffee b/src/app/components/mnoe-config/mnoe-admin-config.svc.coffee
index 30b87efb..42466f28 100644
--- a/src/app/components/mnoe-config/mnoe-admin-config.svc.coffee
+++ b/src/app/components/mnoe-config/mnoe-admin-config.svc.coffee
@@ -97,4 +97,7 @@
@dashboardTemplatesDatesFormat = ->
ADMIN_PANEL_CONFIG.dashboard_templates? && ADMIN_PANEL_CONFIG.dashboard_templates.dates_format || 'L'
+ @isStaffDashboardsEnabled = ->
+ ADMIN_PANEL_CONFIG.staff_dashboards? && ADMIN_PANEL_CONFIG.staff_dashboards.enabled
+
return @
diff --git a/src/app/components/mnoe-staff-dashboards-list/mnoe-staff-dashboards-list.coffee b/src/app/components/mnoe-staff-dashboards-list/mnoe-staff-dashboards-list.coffee
new file mode 100644
index 00000000..d6b80170
--- /dev/null
+++ b/src/app/components/mnoe-staff-dashboards-list/mnoe-staff-dashboards-list.coffee
@@ -0,0 +1,109 @@
+#
+# Mnoe staff dashboards list.
+#
+@App.component('mnoeStaffDashboardsList', {
+ templateUrl: 'app/components/mnoe-staff-dashboards-list/mnoe-staff-dashboards-list.html'
+ bindings: {
+ organization: '<'
+ }
+
+ controller: (toastr, MnoConfirm, MnoeDashboards, ImpacDashboardsSvc, ImpacConfigSvc) ->
+ vm = this
+
+ vm.$onChanges = (changes) ->
+ if changes.organization && vm.organization
+ fetchDashboards()
+
+ vm.dashboards =
+ sort: "created_at"
+ nbItems: 5
+ page: 1
+ offset: 0
+ nbItemsValues: [5, 10, 20]
+ pageChangedCb: (nbItems, page) ->
+ vm.dashboards.nbItems = nbItems
+ vm.dashboards.page = page
+ offset = (page - 1) * nbItems
+ fetchDashboards(nbItems, offset)
+
+ vm.callServer = (tableState) ->
+ sort = updateSort(tableState.sort)
+ fetchDashboards(vm.dashboards.nbItems, vm.dashboards.offset, sort)
+
+ # Update sorting parameters
+ updateSort = (sortState = {}) ->
+ sort = "name"
+ if sortState.predicate
+ sort = sortState.predicate
+ if sortState.reverse
+ sort += ".desc"
+ else
+ sort += ".asc"
+
+ # Update dashboards sort
+ vm.dashboards.sort = sort
+
+ #====================================
+ # Reconfigure Impac!
+ #====================================
+ ImpacConfigSvc.disableDashboardDesigner()
+
+ #====================================
+ # Retrieve Staff Dashboard
+ #====================================
+ fetchDashboards = (limit = vm.dashboards.nbItems, offset = vm.dashboards.offset, sort = vm.dashboards.sort) ->
+ vm.dashboards.loading = true
+ return unless vm.organization
+ return MnoeDashboards.getStaffDashboards(vm.organization.uid, limit, offset, sort).then(
+ (response) ->
+ vm.dashboards.totalItems = response.headers('x-total-count')
+ vm.dashboards.list = response.data
+ ).finally(-> vm.dashboards.loading = false)
+
+ #====================================
+ # Staff dashboard deletion Modal
+ #====================================
+ vm.openDeleteModal = (dashboardId) ->
+
+ modalOptions =
+ type: 'danger'
+ closeButtonText: 'mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.cancel'
+ actionButtonText: 'mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.action'
+ headerText: 'mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.proceed'
+ bodyText: 'mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.perform'
+ MnoConfirm.showModal(modalOptions).then(
+ ->
+ MnoeDashboards.delete(dashboardId).then(
+ (success) ->
+ toastr.success('mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.toastr.success')
+ # Reload list if the user deleted a dashboard
+ fetchDashboards()
+ (error) ->
+ toastr.error('mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.toastr.error')
+ )
+ ->
+ # Cancel
+ )
+
+ # -----------------------------------------------------------
+ # Advisor Dashboard
+ # -----------------------------------------------------------
+ vm.createDashboard = (dashboard) ->
+ angular.merge(dashboard, { organization_ids: [vm.organization.id] })
+
+ # TODO: bug when creating after copying (also present on frontend)
+ promise = if dashboard.id
+ ImpacDashboardsSvc.copy(dashboard)
+ else
+ ImpacDashboardsSvc.create(dashboard)
+
+ # TODO: toaster
+ # refresh dashboard list OR redirect to created dashboard
+ promise.then(
+ (savedDhb) ->
+ fetchDashboards()
+ # $state.go('dashboard.staff-dashboard-show', dashboardId: dashboard.id, orgId: vm.organization.id)
+ )
+
+ return
+})
diff --git a/src/app/components/mnoe-staff-dashboards-list/mnoe-staff-dashboards-list.html b/src/app/components/mnoe-staff-dashboards-list/mnoe-staff-dashboards-list.html
new file mode 100644
index 00000000..1df22124
--- /dev/null
+++ b/src/app/components/mnoe-staff-dashboards-list/mnoe-staff-dashboards-list.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ mnoe_admin_panel.dashboard.staff_dashboards.widget.list.name |
+ |
+
+
+
+
+
+
+
+ {{ dashboard.name }}
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/components/mnoe-staff-dashboards-list/mnoe-staff-dashboards-list.less b/src/app/components/mnoe-staff-dashboards-list/mnoe-staff-dashboards-list.less
new file mode 100644
index 00000000..6ae1a958
--- /dev/null
+++ b/src/app/components/mnoe-staff-dashboards-list/mnoe-staff-dashboards-list.less
@@ -0,0 +1,11 @@
+.nested-table-one-header:first-of-type {
+ font-weight: bold;
+}
+
+.nested-table-one-header > td:first-of-type {
+ padding-left: 16px !important;
+}
+
+.nested-table-one-body > td:first-of-type {
+ padding-left: 24px !important;
+}
diff --git a/src/app/impac.config.coffee b/src/app/impac.config.coffee
index 890b9ba2..df9544d9 100644
--- a/src/app/impac.config.coffee
+++ b/src/app/impac.config.coffee
@@ -9,9 +9,6 @@ angular.module 'frontendAdmin'
data =
mnoHub: mnoHub
impacApi: "#{IMPAC_CONFIG.protocol}://#{IMPAC_CONFIG.host}/api"
- dashboards:
- index: "#{mnoHub}/admin/impac/dashboard_templates"
- show: "#{mnoHub}/admin/impac/dashboard_templates/:id"
widgets:
update: "#{mnoHub}/admin/impac/widgets/:id"
del: "#{mnoHub}/admin/impac/widgets/:id"
@@ -30,7 +27,9 @@ angular.module 'frontendAdmin'
options =
# link to the marketplace
dataNotFoundConfig:
- mainMessage: 'mnoe_admin_panel.impac.data_not_found_config.custom_message'
+ content:
+ mainMessage: 'mnoe_admin_panel.impac.data_not_found_config.custom_message'
+ linkMessage: null
linkUrl: '#!/marketplace'
linkTarget: '_self'
dhbConfig:
@@ -44,8 +43,6 @@ angular.module 'frontendAdmin'
# configurations for the dashboard selector feature.
dhbSelectorConfig:
pdfModeEnabled: false
- addDhbEnabled: false
- deleteDhbEnabled: false
selectorType: 'dropdown'
dhbSettings:
syncApps:
diff --git a/src/app/index.route.coffee b/src/app/index.route.coffee
index d4d38a3c..4542fa45 100644
--- a/src/app/index.route.coffee
+++ b/src/app/index.route.coffee
@@ -157,6 +157,8 @@
if adminConfig.isDashboardTemplatesEnabled
$stateProvider.state 'dashboard.dashboard-templates',
+ data:
+ dashboardDesigner: true
url: '/dashboard-templates'
templateUrl: 'app/views/dashboard-templates/dashboard-templates.html'
controller: 'DashboardTemplatesController'
@@ -164,6 +166,8 @@
ncyBreadcrumb:
label: 'mnoe_admin_panel.dashboard.dashboard_templates.title'
.state 'dashboard.dashboard-templates-show',
+ data:
+ dashboardDesigner: true
url: '/dashboard-templates/:dashboardId'
templateUrl: 'app/views/impac/impac.html'
controller: 'ImpacController'
@@ -171,4 +175,15 @@
ncyBreadcrumb:
label: 'mnoe_admin_panel.dashboard.impac.title'
+ if adminConfig.isStaffDashboardsEnabled()
+ $stateProvider.state 'dashboard.staff-dashboard-show',
+ data:
+ dashboardDesigner: false
+ url: '^/organization/:orgId/staff-dashboard/:dashboardId'
+ templateUrl: 'app/views/impac/impac.html'
+ controller: 'ImpacController'
+ controllerAs: 'vm'
+ ncyBreadcrumb:
+ label: 'mnoe_admin_panel.dashboard.staff_dashboards.title'
+
$urlRouterProvider.otherwise '/home'
diff --git a/src/app/services/impac-config/impac-config.coffee b/src/app/services/impac-config/impac-config.coffee
index ba26294b..cde52db0 100644
--- a/src/app/services/impac-config/impac-config.coffee
+++ b/src/app/services/impac-config/impac-config.coffee
@@ -1,19 +1,94 @@
-@App.service 'ImpacConfigSvc' , ($log, $q, MnoeCurrentUser, MnoeOrganizations) ->
+@App.service 'ImpacConfigSvc' , ($state, $stateParams, $log, $q, MnoeCurrentUser, MnoeOrganizations, ImpacMainSvc, ImpacRoutes, ImpacTheming, IMPAC_CONFIG) ->
_self = @
+ # Keep track of dashboard designer mode
+ _self.dashboardDesigner = null
+
+ # Used to control Impac Angular UI in staff dashboard mode
+ # We want to remove the create/delete dashboard butttons as this is managed through
+ # the staff-dashboard-list component.
+ defaultACL = {
+ self: {show: true, update: true, destroy: true},
+ related: {
+ impac: {show: true},
+ dashboards: {show: true, create: false, update: true, destroy: false},
+ widgets: {show: true, create: true, update: true, destroy: true},
+ kpis: {show: false, create: false, update: false, destroy: false}
+ }
+ }
+
@getUserData = ->
MnoeCurrentUser.getUser()
@getOrganizations = ->
- userOrgsPromise = MnoeCurrentUser.getUser().then(
- (user) ->
- userOrgs = user.organizations
- if _.isEmpty(userOrgs)
- $log.error(err = { message: "Unable to retrieve user organizations" })
- $q.reject(err)
- else
- firstOrgId = userOrgs[0].id
- $q.resolve({ organizations: userOrgs, currentOrgId: firstOrgId })
- )
+ if _self.dashboardDesigner
+ MnoeCurrentUser.getUser().then(
+ (user) ->
+ userOrgs = user.organizations
+ if _.isEmpty(userOrgs)
+ $log.error(err = { message: "Unable to retrieve user organizations" })
+ $q.reject(err)
+ else
+ firstOrgId = userOrgs[0].id
+ $q.resolve({ organizations: userOrgs, currentOrgId: firstOrgId })
+ )
+ else if $stateParams.orgId
+ # Staff dashboard mode, returns the current organization
+ $log.info('getOrganizations', 'Loading customer org')
+ MnoeOrganizations.get($stateParams.orgId).then(
+ (response) ->
+ currentOrganization = response.data.plain()
+ angular.extend(currentOrganization, {acl: defaultACL})
+ $q.resolve(
+ organizations: [currentOrganization],
+ currentOrgId: currentOrganization.id
+ )
+ )
+ else
+ $log.warn('ImpacConfigSvc.getOrganizations: Designer disabled and orgId specified')
+ $log.error(err = { message: "Unable to retrieve user organizations" })
+ $q.reject(err)
+
+ @configureDashboardDesigner = (enabled) ->
+ _self.dashboardDesigner = enabled
+
+ $log.info('Configuring dashboard designer', enabled, _self.dashboardDesigner)
+
+ # Reconfigure Impac routes to use templates or dashboards
+ mnoHub = IMPAC_CONFIG.paths.mnohub_api
+
+ if _self.dashboardDesigner
+ data =
+ dashboards:
+ index: "#{mnoHub}/admin/impac/dashboard_templates"
+ show: "#{mnoHub}/admin/impac/dashboard_templates/:id"
+ else
+ data =
+ dashboards:
+ index: "#{mnoHub}/admin/impac/dashboards"
+ show: "#{mnoHub}/admin/impac/dashboards/:id"
+ create: "#{mnoHub}/admin/impac/dashboards"
+
+ ImpacRoutes.configureRoutes(data)
+
+ # Configure Dashboard Designer
+ options =
+ dhbConfig:
+ designerMode:
+ enabled: enabled
+ # For now do not allow to create templates from templates
+ dhbSettings:
+ createFromTemplateEnabled: !enabled
+ # Disable PDF mode in designer mode
+ dhbSelectorConfig:
+ pdfModeEnabled: !enabled
+
+ ImpacTheming.configure(options)
+
+ @enableDashboardDesigner = ->
+ _self.configureDashboardDesigner(true)
+
+ @disableDashboardDesigner = ->
+ _self.configureDashboardDesigner(false)
return
diff --git a/src/app/views/dashboard-templates/dasboard-templates.controller.coffee b/src/app/views/dashboard-templates/dasboard-templates.controller.coffee
index 302b1e2a..b0a4f1b5 100644
--- a/src/app/views/dashboard-templates/dasboard-templates.controller.coffee
+++ b/src/app/views/dashboard-templates/dasboard-templates.controller.coffee
@@ -1,7 +1,10 @@
-@App.controller 'DashboardTemplatesController', ($state, ImpacDashboardsSvc) ->
+@App.controller 'DashboardTemplatesController', ($state, ImpacDashboardsSvc, ImpacConfigSvc) ->
'ngInject'
vm = this
+ # Reconfigure Impac to enable the dashboard designer
+ ImpacConfigSvc.enableDashboardDesigner()
+
vm.createDashboard = (dashboard) ->
angular.merge(dashboard, { published: false })
ImpacDashboardsSvc.create(dashboard).then(
diff --git a/src/app/views/impac/impac.coffee b/src/app/views/impac/impac.coffee
index 9164e44d..d65885a6 100644
--- a/src/app/views/impac/impac.coffee
+++ b/src/app/views/impac/impac.coffee
@@ -1,8 +1,17 @@
-@App.controller 'ImpacController', ($rootScope, $stateParams, MnoeDashboardTemplates, ImpacDashboardsSvc) ->
+@App.controller 'ImpacController', (
+ $rootScope, $state, $stateParams
+ MnoeDashboardTemplates, MnoeOrganizations, ImpacConfigSvc, ImpacDashboardsSvc
+) ->
'ngInject'
vm = this
vm.dashboardLoaded = false
+ vm.designerMode = $state.current.data.dashboardDesigner
+ vm.orgId = $stateParams.orgId
+
+ if vm.designerMode != ImpacConfigSvc.dashboardDesigner
+ ImpacConfigSvc.configureDashboardDesigner(vm.designerMode)
+
$rootScope.$watch(
->
vm.dashboardLoaded
diff --git a/src/app/views/impac/impac.html b/src/app/views/impac/impac.html
index b6079c1a..67b7e1ce 100644
--- a/src/app/views/impac/impac.html
+++ b/src/app/views/impac/impac.html
@@ -1,9 +1,13 @@
+
diff --git a/src/locales/en-AU.json b/src/locales/en-AU.json
index ef037ba6..53ffefc4 100644
--- a/src/locales/en-AU.json
+++ b/src/locales/en-AU.json
@@ -91,6 +91,16 @@
"mnoe_admin_panel.dashboard.customers.connect_app.myob.cancel": "Cancel",
"mnoe_admin_panel.dashboard.customers.connect_app.myob.close": "Close",
"mnoe_admin_panel.dashboard.customers.connect_app.myob.connect": "Connect",
+ "mnoe_admin_panel.dashboard.staff_dashboards.title": "Staff Dashboard",
+ "mnoe_admin_panel.dashboard.staff_dashboards.back_link": "Back to organization",
+ "mnoe_admin_panel.dashboard.staff_dashboards.widget.list.title": "Staff dashboards",
+ "mnoe_admin_panel.dashboard.staff_dashboards.widget.list.name": "Name",
+ "mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.cancel": "Cancel",
+ "mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.action": "Delete",
+ "mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.proceed": "Delete Staff Dashboard",
+ "mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.perform": "Are you sure you want to delete this staff dashboard?",
+ "mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.toastr.success": "Staff dashboard deleted successfully",
+ "mnoe_admin_panel.dashboard.staff_dashboards.delete_dashboard.toastr.error": "The staff dashboard could not be deleted",
"mnoe_admin_panel.dashboard.dashboard_templates.title": "Dashboard Templates",
"mnoe_admin_panel.dashboard.dashboard_templates.back_link": "Back to templates list",
"mnoe_admin_panel.dashboard.dashboard_templates.published": "Published",