Files: c391dccdd6de62d41151a763ea688e5244384f94 / modules / sheet / tags.js
5579 bytesRaw
1 | var {h, when, map, computed, Value, lookup} = require('mutant') |
2 | var nest = require('depnest') |
3 | var catchLinks = require('../../lib/catch-links') |
4 | |
5 | exports.needs = nest({ |
6 | 'sheet.display': 'first', |
7 | 'keys.sync.id': 'first', |
8 | 'contact.obs.following': 'first', |
9 | 'contact.html.followToggle': 'first', |
10 | 'profile.obs.rank': 'first', |
11 | 'about.html.image': 'first', |
12 | 'about.obs.name': 'first', |
13 | 'app.navigate': 'first', |
14 | 'intl.sync.i18n': 'first', |
15 | 'tag.obs.messageTaggers': 'first' |
16 | }) |
17 | |
18 | exports.gives = nest('sheet.tags') |
19 | |
20 | exports.create = function (api) { |
21 | const i18n = api.intl.sync.i18n |
22 | const displayTags = Value(true) |
23 | const selectedTag = Value() |
24 | return nest('sheet.tags', function (msgId, ids) { |
25 | api.sheet.display(close => { |
26 | const content = computed([displayTags, selectedTag], (displayTags, selectedTag) => { |
27 | if (displayTags) { |
28 | return renderTags(ids) |
29 | } else { |
30 | return renderTaggers(msgId, selectedTag) |
31 | } |
32 | }) |
33 | const back = computed(displayTags, (display) => { |
34 | if (display) { |
35 | return |
36 | } else { |
37 | return h('button -close', { |
38 | 'ev-click': () => { |
39 | displayTags.set(true) |
40 | selectedTag.set() |
41 | } |
42 | }, i18n('Back')) |
43 | } |
44 | }) |
45 | return { |
46 | content, |
47 | footer: [ |
48 | back, |
49 | h('button -close', { |
50 | 'ev-click': () => { |
51 | close() |
52 | displayTags.set(true) |
53 | selectedTag.set() |
54 | } |
55 | }, i18n('Close')) |
56 | ] |
57 | } |
58 | }) |
59 | }) |
60 | |
61 | function renderTags (ids) { |
62 | var currentFilter = Value() |
63 | var tagLookup = lookup(ids, (id) => { |
64 | return [id, api.about.obs.name(id)] |
65 | }) |
66 | var filteredIds = computed([ids, tagLookup, currentFilter], (ids, tagLookup, filter) => { |
67 | if (filter) { |
68 | var result = [] |
69 | for (var k in tagLookup) { |
70 | if ((tagLookup[k] && tagLookup[k].toLowerCase().includes(filter.toLowerCase())) || k === filter) { |
71 | result.push(k) |
72 | } |
73 | } |
74 | return result |
75 | } else { |
76 | return ids |
77 | } |
78 | }) |
79 | var content = h('div', { |
80 | style: { padding: '20px' } |
81 | }, [ |
82 | h('h2', { |
83 | style: { 'font-weight': 'normal' } |
84 | }, [ |
85 | i18n('Applied Tags'), |
86 | h('input', { |
87 | type: 'search', |
88 | placeholder: 'filter tags', |
89 | 'ev-input': function (ev) { |
90 | currentFilter.set(ev.target.value) |
91 | }, |
92 | hooks: [FocusHook()], |
93 | style: { |
94 | 'float': 'right', |
95 | 'font-size': '100%' |
96 | } |
97 | }) |
98 | ]), |
99 | renderTagBlock(filteredIds) |
100 | ]) |
101 | |
102 | catchLinks(content, (href, external, anchor) => { |
103 | if (!external) { |
104 | api.app.navigate(href, anchor) |
105 | close() |
106 | } |
107 | }) |
108 | |
109 | return content |
110 | } |
111 | |
112 | function renderTagBlock (tags) { |
113 | var yourId = api.keys.sync.id() |
114 | return [ |
115 | h('div', { |
116 | classList: 'TagList' |
117 | }, [ |
118 | map(tags, (id) => { |
119 | return h('a.tag', { |
120 | href: `/tags/${id}`, |
121 | title: id |
122 | }, [ |
123 | h('div.main', [ |
124 | h('div.name', [ api.about.obs.name(id) ]) |
125 | ]), |
126 | h('div.buttons', [ |
127 | h('a.ToggleButton', { |
128 | 'ev-click': () => { |
129 | selectedTag.set(id) |
130 | displayTags.set(false) |
131 | } |
132 | }, i18n('View Taggers')) |
133 | ]) |
134 | ]) |
135 | }, { idle: true, maxTime: 2 }) |
136 | ]) |
137 | ] |
138 | } |
139 | |
140 | function renderTaggers (msgId, tagId) { |
141 | var taggerIds = api.tag.obs.messageTaggers(msgId, tagId) |
142 | var currentFilter = Value() |
143 | var taggerLookup = lookup(taggerIds, (id) => { |
144 | return [id, api.about.obs.name(id)] |
145 | }) |
146 | var filteredIds = computed([taggerIds, taggerLookup, currentFilter], (ids, taggerLookup, filter) => { |
147 | if (filter) { |
148 | var result = [] |
149 | for (var k in taggerLookup) { |
150 | if ((taggerLookup[k] && taggerLookup[k].toLowerCase().includes(filter.toLowerCase())) || k === filter) { |
151 | result.push(k) |
152 | } |
153 | } |
154 | return result |
155 | } else { |
156 | return ids |
157 | } |
158 | }) |
159 | return h('div', { |
160 | style: { padding: '20px' } |
161 | }, [ |
162 | h('h2', { |
163 | style: { 'font-weight': 'normal' } |
164 | }, [ |
165 | api.about.obs.name(tagId), |
166 | i18n(' Taggers'), |
167 | h('input', { |
168 | type: 'search', |
169 | placeholder: 'filter names', |
170 | 'ev-input': function (ev) { |
171 | currentFilter.set(ev.target.value) |
172 | }, |
173 | hooks: [FocusHook()], |
174 | style: { |
175 | 'float': 'right', |
176 | 'font-size': '100%' |
177 | } |
178 | }) |
179 | ]), |
180 | renderTaggersBlock(filteredIds) |
181 | ]) |
182 | } |
183 | |
184 | function renderTaggersBlock (profiles) { |
185 | var yourId = api.keys.sync.id() |
186 | profiles = api.profile.obs.rank(profiles) |
187 | return [ |
188 | h('div', { |
189 | classList: 'ProfileList' |
190 | }, [ |
191 | map(profiles, (id) => { |
192 | return h('a.profile', { |
193 | href: id, |
194 | title: id |
195 | }, [ |
196 | h('div.avatar', [api.about.html.image(id)]), |
197 | h('div.main', [ |
198 | h('div.name', [ api.about.obs.name(id) ]) |
199 | ]), |
200 | h('div.buttons', [ |
201 | api.contact.html.followToggle(id, {block: false}) |
202 | ]) |
203 | ]) |
204 | }, { idle: true, maxTime: 2 }) |
205 | ]) |
206 | ] |
207 | } |
208 | } |
209 | |
210 | function FocusHook () { |
211 | return function (element) { |
212 | setTimeout(() => { |
213 | element.focus() |
214 | element.select() |
215 | }, 5) |
216 | } |
217 | } |
Built with git-ssb-web