diff options
| author | Hunternif | 2019-04-16 22:09:04 +0700 |
|---|---|---|
| committer | Hunternif | 2019-04-16 22:09:04 +0700 |
| commit | 9f673a39bfad299c101469f38d8838d7d266279e (patch) | |
| tree | 5741a2725cb456a848f3209b1079f9d01c91ba33 /client | |
| parent | 2307abc8aa27781a3e44930599141a778f09f800 (diff) | |
POC create metric in tag edit view.
Diffstat (limited to 'client')
| -rw-r--r-- | client/html/tag.tpl | 3 | ||||
| -rw-r--r-- | client/html/tag_metric.tpl | 24 | ||||
| -rw-r--r-- | client/js/controllers/tag_controller.js | 25 | ||||
| -rw-r--r-- | client/js/models/metric.js | 70 | ||||
| -rw-r--r-- | client/js/models/tag.js | 3 | ||||
| -rw-r--r-- | client/js/views/tag_metric_view.js | 53 | ||||
| -rw-r--r-- | client/js/views/tag_view.js | 13 |
7 files changed, 191 insertions, 0 deletions
diff --git a/client/html/tag.tpl b/client/html/tag.tpl index 497790e..fc3d81c 100644 --- a/client/html/tag.tpl +++ b/client/html/tag.tpl @@ -6,6 +6,9 @@ --><% if (ctx.canEditAnything) { %><!-- --><li data-name='edit'><a href='<%- ctx.formatClientLink('tag', ctx.tag.names[0], 'edit') %>'>Edit</a></li><!-- --><% } %><!-- + --><% if (ctx.tag.metric || ctx.canCreateMetric) { %><!-- + --><li data-name='merge'><a href='<%- ctx.formatClientLink('tag', ctx.tag.names[0], 'metric') %>'>Metric</a></li><!-- + --><% } %><!-- --><% if (ctx.canMerge) { %><!-- --><li data-name='merge'><a href='<%- ctx.formatClientLink('tag', ctx.tag.names[0], 'merge') %>'>Merge with…</a></li><!-- --><% } %><!-- diff --git a/client/html/tag_metric.tpl b/client/html/tag_metric.tpl new file mode 100644 index 0000000..b25ebff --- /dev/null +++ b/client/html/tag_metric.tpl @@ -0,0 +1,24 @@ +<div class='tag-metric'> + <form class='horizontal edit-metric'> + <%= ctx.makeNumericInput({ + text: 'Minimum', + name: 'metric-min', + value: ctx.metricMin, + enabled: ctx.canEditMetricBounds, + }) %> + <%= ctx.makeNumericInput({ + text: 'Maximum', + name: 'metric-max', + value: ctx.metricMax, + enabled: ctx.canEditMetricBounds, + }) %> + + <div class='buttons'> + <% if (!ctx.tag.metric && ctx.canCreateMetric) { %> + <input type='submit' >Create metric</input> + <% } else if (ctx.tag.metric && ctx.canEditMetricBounds) { %> + <input type='submit' >Update metric</input> + <% } %> + </div> + </form> +</div>
\ No newline at end of file diff --git a/client/js/controllers/tag_controller.js b/client/js/controllers/tag_controller.js index d64ab22..c3a4c91 100644 --- a/client/js/controllers/tag_controller.js +++ b/client/js/controllers/tag_controller.js @@ -6,6 +6,7 @@ const misc = require('../util/misc.js'); const uri = require('../util/uri.js'); const Tag = require('../models/tag.js'); const TagCategoryList = require('../models/tag_category_list.js'); +const Metric = require('../models/metric.js'); const topNavigation = require('../models/top_navigation.js'); const TagView = require('../views/tag_view.js'); const EmptyView = require('../views/empty_view.js'); @@ -44,6 +45,8 @@ class TagController { canEditImplications: api.hasPrivilege('tags:edit:implications'), canEditSuggestions: api.hasPrivilege('tags:edit:suggestions'), canEditDescription: api.hasPrivilege('tags:edit:description'), + canCreateMetric: api.hasPrivilege('metrics:create'), + canEditMetricBounds: api.hasPrivilege('metrics:edit:bounds'), canMerge: api.hasPrivilege('tags:merge'), canDelete: api.hasPrivilege('tags:delete'), categories: categories, @@ -54,6 +57,8 @@ class TagController { this._view.addEventListener('submit', e => this._evtUpdate(e)); this._view.addEventListener('merge', e => this._evtMerge(e)); this._view.addEventListener('delete', e => this._evtDelete(e)); + this._view.addEventListener('metricCreate', e => this._evtMetricCreate(e)); + this._view.addEventListener('metricUpdate', e => this._evtMetricUpdate(e)); }, error => { this._view = new EmptyView(); this._view.showError(error.message); @@ -94,6 +99,26 @@ class TagController { }); } + _evtMetricCreate(e) { + this._view.clearMessages(); + this._view.disableForm(); + const metric = new Metric(); + metric.min = e.detail.metricMin; + metric.max = e.detail.metricMax; + //TODO create metrics via updating tags instead + metric.save().then(() => { + this._view.showSuccess('Metric created.'); + this._view.enableForm(); + }, error => { + this._view.showError(error.message); + this._view.enableForm(); + }); + } + + _evtMetricUpdate(e) { + //TODO update metric + } + _evtMerge(e) { this._view.clearMessages(); this._view.disableForm(); diff --git a/client/js/models/metric.js b/client/js/models/metric.js new file mode 100644 index 0000000..2095999 --- /dev/null +++ b/client/js/models/metric.js @@ -0,0 +1,70 @@ +'use strict'; + +const api = require('../api.js'); +const uri = require('../util/uri.js'); +const events = require('../events.js'); +const misc = require('../util/misc.js'); + +class Metric extends events.EventTarget { + constructor() { + super(); + this._orig = {}; + + this._updateFromResponse({}); + } + + get min() { return this._min; } + get max() { return this._max; } + + set min(value) { this._min = value; } + set max(value) { this._max = value; } + + static fromResponse(response) { + const ret = new Metric(); + ret._updateFromResponse(response); + return ret; + } + + static get(name) { + //TODO get metric. Or only via tag? + return api.get(uri.formatApiLink('metric', name)) + .then(response => { + return Promise.resolve(Metric.fromResponse(response)); + }); + } + + save() { + const detail = {version: this._version}; + + if (this._min !== this._orig._min) { + detail.min = this._min; + } + if (this._max !== this._orig._max) { + detail.max = this._max; + } + + return api.post(uri.formatApiLink('metrics'), detail) + .then(response => { + this._updateFromResponse(response); + this.dispatchEvent(new CustomEvent('change', { + detail: { + metric: this, + }, + })); + return Promise.resolve(); + }); + } + + _updateFromResponse(response) { + const map = { + _version: response.version, + _min: response.min, + _max: response.max, + }; + + Object.assign(this, map); + Object.assign(this._orig, map); + } +} + +module.exports = Metric; diff --git a/client/js/models/tag.js b/client/js/models/tag.js index c743554..dcf95de 100644 --- a/client/js/models/tag.js +++ b/client/js/models/tag.js @@ -28,10 +28,12 @@ class Tag extends events.EventTarget { get postCount() { return this._postCount; } get creationTime() { return this._creationTime; } get lastEditTime() { return this._lastEditTime; } + get metric() { return this._metric; } set names(value) { this._names = value; } set category(value) { this._category = value; } set description(value) { this._description = value; } + set metric(value) { this._metric = value; } static fromResponse(response) { const ret = new Tag(); @@ -135,6 +137,7 @@ class Tag extends events.EventTarget { _creationTime: response.creationTime, _lastEditTime: response.lastEditTime, _postCount: response.usages || 0, + _metric: response.metric, }; for (let obj of [this, this._orig]) { diff --git a/client/js/views/tag_metric_view.js b/client/js/views/tag_metric_view.js new file mode 100644 index 0000000..01f2607 --- /dev/null +++ b/client/js/views/tag_metric_view.js @@ -0,0 +1,53 @@ +'use strict'; + +const events = require('../events.js'); +const api = require('../api.js'); +const views = require('../util/views.js'); +const Metric = require('../models/metric.js'); + +const template = views.getTemplate('tag-metric'); + +class TagMetricView extends events.EventTarget { + constructor(ctx) { + super(); + + this._tag = ctx.tag; + this._hostNode = ctx.hostNode; + + if (ctx.tag.metric) { + ctx.metricMin = ctx.tag.metric.min; + ctx.metricMax = ctx.tag.metric.max; + } else { + // default new values + ctx.metricMin = 0; + ctx.metricMax = 10; + } + + this._formNode.addEventListener('submit', e => this._evtSubmit(e)); + } + + _evtSubmit(e) { + e.preventDefault(); + this.dispatchEvent(new CustomEvent('submit', { + detail: { + tag: this._tag, + metricMin: this._minFieldNode.value, + metricMax: this._maxFieldNode.value, + }, + })); + } + + get _formNode() { + return this._hostNode.querySelector('form'); + } + + get _minFieldNode() { + return this._formNode.querySelector('input[name=metric-min]'); + } + + get _maxFieldNode() { + return this._formNode.querySelector('input[name=metric-max]'); + } +} + +module.exports = TagMetricView; diff --git a/client/js/views/tag_view.js b/client/js/views/tag_view.js index c3457bc..20a1a97 100644 --- a/client/js/views/tag_view.js +++ b/client/js/views/tag_view.js @@ -4,6 +4,7 @@ const events = require('../events.js'); const views = require('../util/views.js'); const TagSummaryView = require('./tag_summary_view.js'); const TagEditView = require('./tag_edit_view.js'); +const TagMetricView = require('./tag_metric_view.js'); const TagMergeView = require('./tag_merge_view.js'); const TagDeleteView = require('./tag_delete_view.js'); const EmptyView = require('../views/empty_view.js'); @@ -47,6 +48,18 @@ class TagView extends events.EventTarget { events.proxyEvent(this._view, this, 'submit'); } + } else if (ctx.section === 'metric') { + const metricExists = this._ctx.tag.metric; + if (!metricExists && !this._ctx.canCreateMetric) { + this._view = new EmptyView(); + this._view.showError( + 'You don\'t have privileges to create metrics.'); + } else { + this._view = new TagMetricView(ctx); + events.proxyEvent(this._view, this, 'submit', + metricExists ? 'metricUpdate' : 'metricCreate'); + } + } else if (ctx.section === 'merge') { if (!this._ctx.canMerge) { this._view = new EmptyView(); |