diff --git a/dashboard/src/theme.scss b/dashboard/src/theme.scss index a70c952dd..1cfee1c9b 100644 --- a/dashboard/src/theme.scss +++ b/dashboard/src/theme.scss @@ -687,7 +687,7 @@ multiselect { } .checklist-item-acknowledged { - border-left: 2px solid transparent; + border-left: 2px solid $brand-success; background-color: transparent; } diff --git a/dashboard/src/views/app.html b/dashboard/src/views/app.html index 089013743..2c17c1f9d 100644 --- a/dashboard/src/views/app.html +++ b/dashboard/src/views/app.html @@ -768,11 +768,22 @@ + +
-
- {{ item.message }} - +
+
+ {{ item.message }} + +
+
+ +
+
+ {{ item.message }} + +

diff --git a/dashboard/src/views/app.js b/dashboard/src/views/app.js index 32b5a787e..d4c1259f3 100644 --- a/dashboard/src/views/app.js +++ b/dashboard/src/views/app.js @@ -137,6 +137,9 @@ angular.module('Application').controller('AppController', ['$scope', '$location' }; $scope.info = { + checklist: [], + showDoneChecklist: false, + notes: { busy: false, editing: false, @@ -171,15 +174,18 @@ angular.module('Application').controller('AppController', ['$scope', '$location' }, show: function () { - $scope.info.notes.busy = false; + $scope.info.checklist = $scope.app.checklist; $scope.info.notes.content = $scope.app.notes; $scope.info.notes.editing = false; - - $scope.info.checklist = $scope.app.checklist; + $scope.info.notes.busy = false; }, - checklistAck: function () { + checklistAck(item) { + item.acknowledged = !item.acknowledged; + Client.configureApp($scope.app.id, 'checklist', { checklist: $scope.info.checklist }, function (error) { + if (error) return console.error('Failed to save checklist.', error); + }); } }; diff --git a/src/apps.js b/src/apps.js index c730ea24e..7c7935b17 100644 --- a/src/apps.js +++ b/src/apps.js @@ -32,6 +32,7 @@ exports = module.exports = { setIcon, setTags, setNotes, + setChecklist, setMemoryLimit, setCpuQuota, setMounts, @@ -1543,6 +1544,15 @@ async function setNotes(app, notes, auditSource) { await eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId: app.id, app, notes }); } +async function setChecklist(app, checklist, auditSource) { + assert.strictEqual(typeof app, 'object'); + assert.strictEqual(typeof checklist, 'object'); + assert.strictEqual(typeof auditSource, 'object'); + + await update(app.id, { checklist }); + await eventlog.add(eventlog.ACTION_APP_CONFIGURE, auditSource, { appId: app.id, app, checklist }); +} + async function setIcon(app, icon, auditSource) { assert.strictEqual(typeof app, 'object'); assert(icon === null || typeof icon === 'string'); diff --git a/src/routes/apps.js b/src/routes/apps.js index bf760a160..729e17303 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -24,6 +24,7 @@ exports = module.exports = { setLabel, setTags, setNotes, + setChecklist, setIcon, setTurn, setRedis, @@ -270,6 +271,18 @@ async function setNotes(req, res, next) { next(new HttpSuccess(200, {})); } +async function setChecklist(req, res, next) { + assert.strictEqual(typeof req.body, 'object'); + assert.strictEqual(typeof req.app, 'object'); + + if (typeof req.body.checklist !== 'object') return next(new HttpError(400, 'checklist must be an object')); + + const [error] = await safe(apps.setChecklist(req.app, req.body.checklist, AuditSource.fromRequest(req))); + if (error) return next(BoxError.toHttpError(error)); + + next(new HttpSuccess(200, {})); +} + async function setIcon(req, res, next) { assert.strictEqual(typeof req.body, 'object'); assert.strictEqual(typeof req.app, 'object'); diff --git a/src/server.js b/src/server.js index 3bc7fa4e2..89f734e19 100644 --- a/src/server.js +++ b/src/server.js @@ -244,6 +244,7 @@ async function initializeExpressSync() { router.post('/api/v1/apps/:id/configure/tags', json, token, routes.apps.load, authorizeOperator, routes.apps.setTags); router.post('/api/v1/apps/:id/configure/icon', json, token, routes.apps.load, authorizeOperator, routes.apps.setIcon); router.post('/api/v1/apps/:id/configure/notes', json, token, routes.apps.load, authorizeOperator, routes.apps.setNotes); + router.post('/api/v1/apps/:id/configure/checklist', json, token, routes.apps.load, authorizeOperator, routes.apps.setChecklist); router.post('/api/v1/apps/:id/configure/memory_limit', json, token, routes.apps.load, authorizeOperator, routes.apps.setMemoryLimit); router.post('/api/v1/apps/:id/configure/cpu_quota', json, token, routes.apps.load, authorizeOperator, routes.apps.setCpuQuota); router.post('/api/v1/apps/:id/configure/automatic_backup', json, token, routes.apps.load, authorizeOperator, routes.apps.setAutomaticBackup);