12479: Properties saving working. Remove tag button styling.
[arvados.git] / apps / workbench / app / assets / javascripts / components / edit_tags.js
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 window.SelectOrAutocomplete = {
6     view: function(vnode) {
7         return m("input", {
8             style: {
9                 width: '100%'
10             },
11             type: 'text',
12             value: vnode.attrs.value
13         }, vnode.attrs.value)
14     },
15     oncreate: function(vnode) {
16         vnode.state.selector = $(vnode.dom).selectize({
17             labelField: 'value',
18             valueField: 'value',
19             searchField: 'value',
20             sortField: 'value',
21             maxItems: 1,
22             create: vnode.attrs.create ? function(input) {
23                 return {value: input}
24             } : false,
25             items: [vnode.attrs.value()],
26             options: vnode.attrs.options.map(function(option) {
27                 return {value: option}
28             }),
29             onChange: function(val) {
30                 vnode.attrs.value(val)
31                 m.redraw()
32             }
33         }).data('selectize')
34     }
35 }
36
37 // When in edit mode, present a tag name selector and tag value
38 // selector/editor depending of the tag type.
39 window.TagEditorRow = {
40     view: function(vnode) {
41         // Value options list
42         valueOpts = []
43         if (vnode.attrs.name() in vnode.attrs.vocabulary().types &&
44             'options' in vnode.attrs.vocabulary().types[vnode.attrs.name()]) {
45                 valueOpts = vnode.attrs.vocabulary().types[vnode.attrs.name()].options
46         }
47         valueOpts.push(vnode.attrs.value())
48
49         return m("tr", [
50             // Erase tag
51             m("td",
52             vnode.attrs.editMode &&
53                 m('div.text-center', m('a.btn.btn-default.btn-sm', {
54                     style: {
55                         align: 'center'
56                     },
57                     onclick: function(e) { vnode.attrs.removeTag() }
58                 }, m('i.fa.fa-fw.fa-trash-o'))),
59             ),
60             // Tag name
61             m("td",
62             vnode.attrs.editMode ?
63             m("div", {key: 'name-'+vnode.attrs.name()},[m(SelectOrAutocomplete, {
64                 options: (vnode.attrs.name() in vnode.attrs.vocabulary().types)
65                     ? Object.keys(vnode.attrs.vocabulary().types)
66                     : Object.keys(vnode.attrs.vocabulary().types).concat(vnode.attrs.name()),
67                 value: vnode.attrs.name,
68                 create: vnode.attrs.vocabulary().strict
69             })])
70             : vnode.attrs.name),
71             // Tag value
72             m("td",
73             vnode.attrs.editMode ?
74             m("div", {key: 'value-'+vnode.attrs.name()}, [m(SelectOrAutocomplete, {
75                 options: valueOpts,
76                 value: vnode.attrs.value,
77                 create: (vnode.attrs.name() in vnode.attrs.vocabulary().types)
78                     ? (vnode.attrs.vocabulary().types[vnode.attrs.name()].type == 'text') || 
79                         vnode.attrs.vocabulary().types[vnode.attrs.name()].overridable || false
80                     : true, // If tag not in vocabulary, we should accept any value
81                 })
82             ])
83             : vnode.attrs.value)
84         ])
85     }
86 }
87
88 window.TagEditorTable = {
89     view: function(vnode) {
90         return m("table.table.table-condensed", {
91             border: "1"
92         }, [
93             m("colgroup", [
94                 m("col", {width:"5%"}),
95                 m("col", {width:"25%"}),
96                 m("col", {width:"70%"}),
97             ]),
98             m("thead", [
99                 m("tr", [
100                     m("th"),
101                     m("th", "Key"),
102                     m("th", "Value"),
103                 ])
104             ]),
105             m("tbody", [
106                 vnode.attrs.tags.map(function(tag, idx) {
107                     return m(TagEditorRow, {
108                         key: idx,
109                         removeTag: function() { vnode.attrs.tags.splice(idx, 1) },
110                         editMode: vnode.attrs.editMode,
111                         name: tag.name,
112                         value: tag.value,
113                         vocabulary: vnode.attrs.vocabulary
114                     })
115                 })
116             ]),
117         ])
118     }
119 }
120
121 window.TagEditorApp = {
122     oninit: function(vnode) {
123         vnode.state.saveLabel = m.stream(' Save ')
124         vnode.state.sessionDB = new SessionDB()
125         // Get vocabulary
126         vnode.state.vocabulary = m.stream({"strict":false, "types":{}})
127         m.request('/vocabulary.json').then(vnode.state.vocabulary)
128         vnode.state.editMode = vnode.attrs.targetEditable
129         // Get tags
130         vnode.state.tags = []
131         vnode.state.objPath = '/arvados/v1/'+vnode.attrs.targetController+'/'+vnode.attrs.targetUuid
132         vnode.state.sessionDB.request(
133             vnode.state.sessionDB.loadLocal(), vnode.state.objPath, {
134                 data: {
135                     select: JSON.stringify(['properties']) // FIXME: not working
136                 },
137             }).then(function(obj) {
138                 console.log(obj)
139                 Object.keys(obj.properties).forEach(function(k) {
140                     vnode.state.tags.push({
141                         name: m.stream(k),
142                         value: m.stream(obj.properties[k])
143                     })
144                 })
145                 vnode.state.dirty = m.stream(null)
146                 vnode.state.tags.map(function(tag) {
147                   tag.name.map(m.redraw)
148                   tag.name.map(vnode.state.dirty)
149                   tag.value.map(vnode.state.dirty)
150                 })
151             }
152         )
153     },
154     view: function(vnode) {
155         return [
156             // Tags table
157             m(TagEditorTable, {
158                 editMode: vnode.state.editMode,
159                 tags: vnode.state.tags,
160                 vocabulary: vnode.state.vocabulary
161             }),
162             vnode.state.editMode &&
163             m("div", [
164                 m("div.pull-left", [
165                     // Add tag button
166                     m("a.btn.btn-primary.btn-sm", {
167                         onclick: function(e) {
168                             vnode.state.tags.push({
169                                 name: m.stream('new tag'),
170                                 value: m.stream('new tag value')
171                             })
172                         }
173                     }, [
174                         m("i.glyphicon.glyphicon-plus"),
175                         " Add new tag "
176                     ])
177                 ]),
178                 m("div.pull-right", [
179                     // Save button
180                     m("a.btn.btn-primary.btn-sm", {
181                         onclick: function(e) {
182                             vnode.state.saveLabel('Saving...')
183                             var tags = {}
184                             vnode.state.tags.forEach(function(t) {
185                                 tags[t.name()] = t.value()
186                             })
187                             vnode.state.sessionDB.request(
188                                 vnode.state.sessionDB.loadLocal(),
189                                 vnode.state.objPath, {
190                                     method: "PUT",
191                                     data: {properties: JSON.stringify(tags)}
192                                 }
193                             ).then(function(v) {
194                                 vnode.state.saveLabel(' Save ')
195                                 console.log('ok!')
196                             })
197                         }
198                     }, vnode.state.saveLabel)
199                 ])
200             ])
201         ]
202     },
203 }