Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[KAPP-175] Staff Dashboards #353

Merged
merged 13 commits into from
Apr 8, 2019
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
18 changes: 18 additions & 0 deletions src/app/components/mnoe-api/admin/dashboard.svc.coffee
Original file line number Diff line number Diff line change
@@ -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 @
3 changes: 3 additions & 0 deletions src/app/components/mnoe-config/mnoe-admin-config.svc.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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 @
Original file line number Diff line number Diff line change
@@ -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
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<mno-widget icon="fa-bar-chart" is-loading="$ctrl.dashboards.loading" heading="{{ 'mnoe_admin_panel.dashboard.staff_dashboards.widget.list.title' | translate}}">
<mno-widget-header>
<div class="btn-group pull-right">
<impac-dashboard-create on-create-dashboard="$ctrl.createDashboard(dashboard)" btn-class="btn-primary" />
</div>
</mno-widget-header>
<mno-widget-body class="no-padding">
<div>
<table st-pipe="$ctrl.callServer" class="table table-striped" st-table="$ctrl.dashboards.list">

<!-- Dashboard list header -->
<thead>
<tr>
<th st-sort="name" class="col-lg-3" translate>mnoe_admin_panel.dashboard.staff_dashboards.widget.list.name</th>
<th st-sort="created_at" class="col-lg-2" translate></th>
</tr>
</thead>

<!-- Dashboard list -->
<tbody ng-repeat="dashboard in $ctrl.dashboards.list">
<tr>
<td title="{{ dashboard.full_name }}">
<a ui-sref="dashboard.staff-dashboard-show({ dashboardId: dashboard.id, orgId: $ctrl.organization.id })">{{ dashboard.name }}</a>
</td>
<td>
<div class="pull-right">
<div class="btn-group" ng-click="$ctrl.openDeleteModal(dashboard.id)">
<a type="button" class="btn btn-primary" >
<i class="fa fa-trash-o" aria-hidden="true"></i>
</a>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</mno-widget-body>
<mno-widget-footer ng-show="$ctrl.dashboards.list">
<mno-pagination
page="$ctrl.dashboards.page"
nb-items="$ctrl.dashboards.nbItems"
total-items="$ctrl.dashboards.totalItems"
on-change-cb="$ctrl.dashboards.pageChangedCb(nbItems, page)"
is-loading="$ctrl.dashboards.loading"
nb-items-values="$ctrl.dashboards.nbItemsValues"
>
</mno-pagination>
</mno-widget-footer>
</mno-widget>
Original file line number Diff line number Diff line change
@@ -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;
}
9 changes: 3 additions & 6 deletions src/app/impac.config.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ angular.module 'frontendAdmin'
data =
mnoHub: mnoHub
impacApi: "#{IMPAC_CONFIG.protocol}://#{IMPAC_CONFIG.host}/api"
dashboards:
ouranos marked this conversation as resolved.
Show resolved Hide resolved
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"
Expand All @@ -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:
Expand All @@ -44,8 +43,6 @@ angular.module 'frontendAdmin'
# configurations for the dashboard selector feature.
dhbSelectorConfig:
pdfModeEnabled: false
addDhbEnabled: false
deleteDhbEnabled: false
selectorType: 'dropdown'
dhbSettings:
syncApps:
Expand Down
15 changes: 15 additions & 0 deletions src/app/index.route.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -157,18 +157,33 @@

if adminConfig.isDashboardTemplatesEnabled
$stateProvider.state 'dashboard.dashboard-templates',
data:
dashboardDesigner: true
url: '/dashboard-templates'
templateUrl: 'app/views/dashboard-templates/dashboard-templates.html'
controller: 'DashboardTemplatesController'
controllerAs: 'vm'
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'
controllerAs: 'vm'
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'
97 changes: 86 additions & 11 deletions src/app/services/impac-config/impac-config.coffee
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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(
Expand Down
Loading