@websy/websy-designs 1.9.13 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -43,29 +43,45 @@ function APIRoutes (dbHelper, authHelper) {
43
43
  }
44
44
  }, err => res.json(err))
45
45
  })
46
+ router.post('/:entity/upsert', authHelper.checkPermissions, (req, res) => {
47
+ let user
48
+ if (req.session && req.session.user) {
49
+ user = req.session.user
50
+ }
51
+ const sql = dbHelper.buildUpsert(req.params.entity, req.body, user)
52
+ console.log('upsert sql', sql)
53
+ dbHelper.execute(sql).then(response => res.json(response), err => res.json(err))
54
+ })
46
55
  router.post('/:entity', authHelper.checkPermissions, (req, res) => {
47
56
  // const sql = dbHelper.buildInsert(req.params.entity, req.body, req.session.passport.user.id)
48
- console.log(req.body)
49
- console.log(req.session)
57
+ // console.log(req.body)
58
+ // console.log(req.session)
50
59
  let user
51
60
  if (req.session && req.session.user) {
52
61
  user = req.session.user
53
62
  }
54
63
  const sql = dbHelper.buildInsert(req.params.entity, req.body, user)
55
- console.log(sql)
64
+ // console.log(sql)
56
65
  dbHelper.execute(sql).then(response => res.json(response), err => {
57
66
  res.statusCode = 404
58
67
  res.json({err})
59
68
  })
60
- })
61
- console.log('defining put endpoint for /:entity/:id')
62
- router.put('/:entity/:id', (req, res) => {
63
- console.log('executing put')
64
- const sql = dbHelper.buildUpdateWithId(req.params.entity, req.params.id, req.body)
69
+ })
70
+ // console.log('defining put endpoint for /:entity/:id')
71
+ router.put('/:entity/:id', authHelper.checkPermissions, (req, res) => {
72
+ let user
73
+ if (req.session && req.session.user) {
74
+ user = req.session.user
75
+ }
76
+ const sql = dbHelper.buildUpdateWithId(req.params.entity, req.params.id, req.body, user)
65
77
  dbHelper.execute(sql).then(response => res.json(response), err => res.json(err))
66
78
  })
67
- router.put('/:entity', (req, res) => {
68
- const sql = dbHelper.buildUpdate(req.params.entity, req.query.where, req.body)
79
+ router.put('/:entity', authHelper.checkPermissions, (req, res) => {
80
+ let user
81
+ if (req.session && req.session.user) {
82
+ user = req.session.user
83
+ }
84
+ const sql = dbHelper.buildUpdate(req.params.entity, req.query.where, req.body, user)
69
85
  dbHelper.execute(sql).then(response => res.json(response), err => res.json(err))
70
86
  })
71
87
  return router
@@ -12,6 +12,6 @@ module.exports = {
12
12
  const rect = el.getBoundingClientRect()
13
13
  const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft
14
14
  const scrollTop = window.pageYOffset || document.documentElement.scrollTop
15
- return { top: rect.top + scrollTop, left: rect.left + scrollLeft }
15
+ return { top: rect.top + scrollTop, left: rect.left + scrollLeft, width: rect.width, height: rect.height }
16
16
  }
17
17
  }
@@ -55,6 +55,10 @@ class APIService {
55
55
  const url = this.buildUrl(entity, id)
56
56
  return this.run('DELETE', url)
57
57
  }
58
+ deleteMany (entity, query) {
59
+ const url = this.buildUrl(entity, null, query)
60
+ return this.run('DELETE', url)
61
+ }
58
62
  get (entity, id, query, offset, limit) {
59
63
  let url = this.buildUrl(entity, id, query)
60
64
  if (offset) {
@@ -65,12 +69,12 @@ class APIService {
65
69
  url += `?offset=${offset}`
66
70
  }
67
71
  }
68
- if (limit) {
72
+ if (limit || this.options.rowLimit) {
69
73
  if (url.indexOf('?') !== -1) {
70
- url += `&limit=${limit}`
74
+ url += `&limit=${limit || this.options.rowLimit}`
71
75
  }
72
76
  else {
73
- url += `?limit=${limit}`
77
+ url += `?limit=${limit || this.options.rowLimit}`
74
78
  }
75
79
  }
76
80
  return this.run('GET', url)
@@ -188,16 +192,51 @@ class ButtonGroup {
188
192
  this.render()
189
193
  }
190
194
  }
195
+ get value () {
196
+ if (this.options.activeItem > -1) {
197
+ return [this.options.items[this.options.activeItem]]
198
+ }
199
+ else if (this.options.multiSelect === true) {
200
+ return this.options.items.filter(d => d.selected)
201
+ }
202
+ return []
203
+ }
204
+ set value (value) {
205
+ let activeIndex = -1
206
+ if (this.options.multiSelect === true) {
207
+ if (Array.isArray(value)) {
208
+ this.options.items.forEach(d => {
209
+ if (value.indexOf(d.value) !== -1) {
210
+ d.selected = true
211
+ }
212
+ else {
213
+ d.selected = false
214
+ }
215
+ })
216
+ }
217
+ }
218
+ else {
219
+ for (let i = 0; i < this.options.items.length; i++) {
220
+ if ((this.options.items[i].value || this.options.items[i].label) === value) {
221
+ activeIndex = i
222
+ }
223
+ }
224
+ this.options.activeItem = activeIndex
225
+ }
226
+ this.render()
227
+ }
191
228
  handleClick (event) {
192
229
  if (event.target.classList.contains('websy-button-group-item')) {
193
230
  const index = +event.target.getAttribute('data-index')
194
231
  if (this.options.multiSelect === true) {
195
232
  if (event.target.classList.contains('active')) {
233
+ this.options.items[index].selected = false
196
234
  this.options.onDeactivate(this.options.items[index], index, event)
197
235
  event.target.classList.remove('active')
198
236
  event.target.classList.add('inactive')
199
237
  }
200
238
  else {
239
+ this.options.items[index].selected = true
201
240
  this.options.onActivate(this.options.items[index], index, event)
202
241
  event.target.classList.add('active')
203
242
  event.target.classList.remove('inactive')
@@ -248,7 +287,10 @@ class ButtonGroup {
248
287
  let activeClass = ''
249
288
  if (this.options.activeItem !== -1) {
250
289
  activeClass = i === this.options.activeItem ? 'active' : 'inactive'
251
- }
290
+ }
291
+ else if (this.options.multiSelect === true) {
292
+ activeClass = t.selected === true ? 'active' : 'inactive'
293
+ }
252
294
  return `
253
295
  <${this.options.tag} ${(t.attributes || []).join(' ')} data-id="${t.id || t.label}" data-index="${i}" class="websy-button-group-item ${(t.classes || []).join(' ')} ${this.options.style}-style ${activeClass}">${t.label}</${this.options.tag}>
254
296
  `
@@ -1696,7 +1738,20 @@ class WebsyDropdown {
1696
1738
  const maskEl = document.getElementById(`${this.elementId}_mask`)
1697
1739
  const contentEl = document.getElementById(`${this.elementId}_content`)
1698
1740
  const scrollEl = document.getElementById(`${this.elementId}_itemsContainer`)
1699
- const actionEl = document.getElementById(`${this.elementId}_actionContainer`)
1741
+ const actionEl = document.getElementById(`${this.elementId}_actionContainer`)
1742
+ const headerEl = document.getElementById(`${this.elementId}_header`)
1743
+ const headerPos = WebsyUtils.getElementPos(headerEl)
1744
+ const contentPos = WebsyUtils.getElementPos(contentEl)
1745
+ if (this.options.style === 'plain' && headerPos.width > 0 && headerPos.height > 0) {
1746
+ contentEl.style.right = 'unset'
1747
+ if (headerPos.bottom + contentPos.height > window.innerHeight) {
1748
+ // contentEl.classList.add('on-top')
1749
+ contentEl.style.bottom = 'unset'
1750
+ }
1751
+ else {
1752
+ contentEl.style.top = 'unset'
1753
+ }
1754
+ }
1700
1755
  if (actionEl) {
1701
1756
  actionEl.classList.remove('active')
1702
1757
  }
@@ -1720,7 +1775,7 @@ class WebsyDropdown {
1720
1775
  return
1721
1776
  }
1722
1777
  if (event.target.classList.contains('websy-dropdown-header')) {
1723
- this.open()
1778
+ this.open(event)
1724
1779
  }
1725
1780
  else if (event.target.classList.contains('websy-dropdown-mask')) {
1726
1781
  this.close()
@@ -1835,17 +1890,29 @@ class WebsyDropdown {
1835
1890
  }
1836
1891
  }
1837
1892
  }
1838
- open (options, override = false) {
1893
+ open (event, override = false) {
1839
1894
  const maskEl = document.getElementById(`${this.elementId}_mask`)
1840
1895
  const contentEl = document.getElementById(`${this.elementId}_content`)
1841
- const el = document.getElementById(this.elementId)
1842
- if (el) {
1843
- el.style.zIndex = 999
1844
- }
1896
+ const headerEl = document.getElementById(`${this.elementId}_header`)
1845
1897
  maskEl.classList.add('active')
1846
1898
  contentEl.classList.add('active')
1847
- if (WebsyUtils.getElementPos(contentEl).bottom > window.innerHeight) {
1848
- contentEl.classList.add('on-top')
1899
+ const headerPos = WebsyUtils.getElementPos(headerEl)
1900
+ const contentPos = WebsyUtils.getElementPos(contentEl)
1901
+ if (this.options.style === 'plain' && headerPos.width > 0 && headerPos.height > 0) {
1902
+ contentEl.style.right = `calc(100vw - ${headerPos.right}px)`
1903
+ contentEl.style.width = `${headerEl.clientWidth}px`
1904
+ if (headerPos.bottom + contentPos.height > window.innerHeight) {
1905
+ // contentEl.classList.add('on-top')
1906
+ contentEl.style.bottom = `calc(100vh - ${headerPos.top}px)`
1907
+ }
1908
+ else {
1909
+ contentEl.style.top = headerPos.bottom + 'px'
1910
+ }
1911
+ }
1912
+ else if (this.options.style === 'plain' && headerPos.width === 0 && headerPos.height === 0) {
1913
+ const targetPos = WebsyUtils.getElementPos(event.target)
1914
+ contentEl.style.right = `calc(100vw - ${targetPos.right}px)`
1915
+ contentEl.style.width = `${targetPos.width}px`
1849
1916
  }
1850
1917
  if (this.options.disableSearch !== true) {
1851
1918
  const searchEl = document.getElementById(`${this.elementId}_search`)
@@ -1857,6 +1924,19 @@ class WebsyDropdown {
1857
1924
  this.options.onOpen(this.elementId)
1858
1925
  }
1859
1926
  }
1927
+ set items (items) {
1928
+ this.options.items = [...items]
1929
+ if (this.options.items.length > 0) {
1930
+ this.options.items = this.options.items.map((d, i) => {
1931
+ if (typeof d.index === 'undefined') {
1932
+ d.index = i
1933
+ }
1934
+ return d
1935
+ })
1936
+ }
1937
+ this._originalData = [...this.options.items]
1938
+ this.render()
1939
+ }
1860
1940
  render () {
1861
1941
  if (!this.elementId) {
1862
1942
  console.log('No element Id provided for Websy Dropdown')
@@ -2055,9 +2135,7 @@ class WebsyForm {
2055
2135
  }
2056
2136
  GlobalPubSub.subscribe('recaptchaready', this.recaptchaReady.bind(this))
2057
2137
  this.recaptchaResult = null
2058
- this.options = Object.assign(defaults, {}, {
2059
- // defaults go here
2060
- }, options)
2138
+ this.options = Object.assign({}, defaults, options)
2061
2139
  if (!elementId) {
2062
2140
  console.log('No element Id provided')
2063
2141
  return
@@ -2125,8 +2203,27 @@ class WebsyForm {
2125
2203
  const data = {}
2126
2204
  const temp = new FormData(formEl)
2127
2205
  temp.forEach((value, key) => {
2128
- data[key] = value
2206
+ if (this.fieldMap[key] && this.fieldMap[key].type === 'checkbox') {
2207
+ data[key] = true
2208
+ }
2209
+ if (this.fieldMap[key] && this.fieldMap[key].instance && this.fieldMap[key].instance.value) {
2210
+ data[key] = this.fieldMap[key].instance.value
2211
+ }
2212
+ else {
2213
+ data[key] = value
2214
+ }
2129
2215
  })
2216
+ let keys = Object.keys(data)
2217
+ for (const key in this.fieldMap) {
2218
+ if (keys.indexOf(key) === -1) {
2219
+ if (this.fieldMap[key] && this.fieldMap[key].type === 'checkbox') {
2220
+ data[key] = false
2221
+ }
2222
+ else if (this.fieldMap[key] && this.fieldMap[key].instance && this.fieldMap[key].instance.value) {
2223
+ data[key] = this.fieldMap[key].instance.value
2224
+ }
2225
+ }
2226
+ }
2130
2227
  return data
2131
2228
  }
2132
2229
  set data (d) {
@@ -2184,6 +2281,7 @@ class WebsyForm {
2184
2281
  handleClick (event) {
2185
2282
  if (event.target.classList.contains('submit')) {
2186
2283
  event.preventDefault()
2284
+ event.stopPropagation()
2187
2285
  this.submitForm()
2188
2286
  }
2189
2287
  else if (event.target.classList.contains('cancel')) {
@@ -2356,6 +2454,7 @@ class WebsyForm {
2356
2454
  `
2357
2455
  this.options.fields.forEach((f, i) => {
2358
2456
  this.fieldMap[f.field] = f
2457
+ f.owningElement = this.elementId
2359
2458
  if (f.component) {
2360
2459
  componentsToProcess.push(f)
2361
2460
  html += `
@@ -2442,6 +2541,10 @@ class WebsyForm {
2442
2541
  const el = document.getElementById(`${this.elementId}_input_${field}`)
2443
2542
  if (el) {
2444
2543
  el.value = value
2544
+ el.setAttribute('value', value)
2545
+ if (this.fieldMap[field].type === 'checkbox') {
2546
+ el.checked = value
2547
+ }
2445
2548
  }
2446
2549
  else {
2447
2550
  console.error(`Input for ${field} does not exist in form.`)
@@ -2599,6 +2702,10 @@ class MultiForm {
2599
2702
  }
2600
2703
  this.render()
2601
2704
  }
2705
+ addData (data) {
2706
+ this.formData = this.formData.concat(data)
2707
+ this.render()
2708
+ }
2602
2709
  addEntry () {
2603
2710
  const el = document.getElementById(`${this.elementId}_container`)
2604
2711
  let newId = WebsyDesigns.Utils.createIdentity()
@@ -2616,7 +2723,7 @@ class MultiForm {
2616
2723
  </button>
2617
2724
  `
2618
2725
  el.appendChild(newFormEl)
2619
- let formOptions = Object.assign({}, this.options)
2726
+ let formOptions = Object.assign({}, this.options, { fields: [...this.options.fields.map(f => Object.assign({}, f))] })
2620
2727
  this.forms.push(new WebsyDesigns.Form(`${this.elementId}_${newId}_form`, formOptions))
2621
2728
  }
2622
2729
  clear () {
@@ -2630,14 +2737,20 @@ class MultiForm {
2630
2737
  }
2631
2738
  get data () {
2632
2739
  const d = this.forms.map(f => (f.data))
2633
- // we don't return the last form
2634
- d.pop()
2740
+ console.log('forms data', d)
2741
+ if (this.options.allowAdd !== false) {
2742
+ // we don't return the last form
2743
+ d.pop()
2744
+ }
2635
2745
  return d
2636
2746
  }
2637
2747
  set data (d) {
2638
2748
  this.formData = d
2639
2749
  this.render()
2640
2750
  }
2751
+ get deleted () {
2752
+ return this.formData.filter(d => this.recordsToDelete.includes(`${d.id}`))
2753
+ }
2641
2754
  handleClick (event) {
2642
2755
  if (event.target.classList.contains('websy-multi-form-add')) {
2643
2756
  let id = event.target.getAttribute('data-formid')
@@ -2717,15 +2830,17 @@ class MultiForm {
2717
2830
  `
2718
2831
  }
2719
2832
  el.innerHTML = html
2720
- this.formData.forEach(d => {
2721
- let formOptions = Object.assign({}, this.options)
2833
+ this.forms = new Array(this.formData.length)
2834
+ this.formData.forEach((d, i) => {
2835
+ let formOptions = Object.assign({}, this.options, { fields: [...this.options.fields.map(f => Object.assign({}, f))] })
2722
2836
  let formObject = new WebsyDesigns.Form(`${this.elementId}_${d.formId}_form`, formOptions)
2723
2837
  formObject.data = d
2724
- this.forms.push(formObject)
2838
+ this.forms[i] = formObject
2725
2839
  })
2726
2840
  if (this.options.allowAdd === true) {
2727
- let formOptions = Object.assign({}, this.options)
2728
- this.forms.push(new WebsyDesigns.Form(`${this.elementId}_${id}_form`, formOptions))
2841
+ let formOptions = Object.assign({}, this.options, { fields: [...this.options.fields.map(f => Object.assign({}, f))] })
2842
+ let formObject = new WebsyDesigns.Form(`${this.elementId}_${id}_form`, formOptions)
2843
+ this.forms.push(formObject)
2729
2844
  }
2730
2845
  }
2731
2846
  }
@@ -3671,6 +3786,9 @@ class WebsyPubSub {
3671
3786
  }
3672
3787
  }
3673
3788
  subscribe (id, method, fn) {
3789
+ if (!this.subscriptions) {
3790
+ this.subscriptions = {}
3791
+ }
3674
3792
  if (arguments.length === 3) {
3675
3793
  if (!this.subscriptions[id]) {
3676
3794
  this.subscriptions[id] = {}
@@ -5074,7 +5192,52 @@ class WebsyTemplate {
5074
5192
  return html
5075
5193
  }
5076
5194
  handleClick (event) {
5077
- //
5195
+ if (event.target.classList.contains('clickable')) {
5196
+ this.handleEvent(event, 'clickable', 'click')
5197
+ }
5198
+ }
5199
+ handleEvent (event, eventType, action) {
5200
+ let l = event.target.getAttribute('data-event')
5201
+ if (l) {
5202
+ l = l.split('(')
5203
+ let params = []
5204
+ const id = event.target.getAttribute('data-id')
5205
+ // const locator = event.target.getAttribute('data-locator')
5206
+ // if (l[1]) {
5207
+ // l[1] = l[1].replace(')', '')
5208
+ // params = l[1].split(',')
5209
+ // }
5210
+ // l = l[0]
5211
+ let data = this.options.data
5212
+ // if (locator !== '') {
5213
+ // let locatorItems = locator.split(';')
5214
+ // locatorItems.forEach(loc => {
5215
+ // let locatorParts = loc.split(':')
5216
+ // if (data[locatorParts[0]]) {
5217
+ // data = data[locatorParts[0]]
5218
+ // let parts = locatorParts[1].split('.')
5219
+ // parts.forEach(p => {
5220
+ // data = data[p]
5221
+ // })
5222
+ // }
5223
+ // })
5224
+ // }
5225
+ // params = params.map(p => {
5226
+ // if (typeof p !== 'string' && typeof p !== 'number') {
5227
+ // if (data[+id]) {
5228
+ // p = data[+id][p]
5229
+ // }
5230
+ // }
5231
+ // else if (typeof p === 'string') {
5232
+ // p = p.replace(/"/g, '').replace(/'/g, '')
5233
+ // }
5234
+ // return p
5235
+ // })
5236
+ if (event.target.classList.contains(eventType) && this.options.listeners[action] && this.options.listeners[action][l]) {
5237
+ event.stopPropagation()
5238
+ this.options.listeners[action][l].call(this, event, data[+id], ...params)
5239
+ }
5240
+ }
5078
5241
  }
5079
5242
  render () {
5080
5243
  this.resize()
@@ -5107,7 +5270,9 @@ const WebsyUtils = {
5107
5270
  top: rect.top + scrollTop,
5108
5271
  left: rect.left + scrollLeft,
5109
5272
  bottom: rect.top + scrollTop + el.clientHeight,
5110
- right: rect.left + scrollLeft + el.clientWidth
5273
+ right: rect.left + scrollLeft + el.clientWidth,
5274
+ width: rect.width,
5275
+ height: rect.height
5111
5276
  }
5112
5277
  },
5113
5278
  getLightDark: (backgroundColor, darkColor = '#000000', lightColor = '#ffffff') => {
@@ -6428,7 +6593,7 @@ class WebsyTable3 {
6428
6593
  row.forEach((cell, cellIndex) => {
6429
6594
  let sizeIndex = cell.level || cellIndex
6430
6595
  let colIndex = cell.index || cellIndex
6431
- if (typeof sizingColumns[sizeIndex] === 'undefined' || sizingColumns[sizeIndex].show === false) {
6596
+ if (typeof sizingColumns[sizeIndex] === 'undefined' || this.options.columns[this.options.columns.length - 1][colIndex].show === false) {
6432
6597
  return // need to revisit this logic
6433
6598
  }
6434
6599
  let style = ''
@@ -9420,6 +9585,14 @@ symbols
9420
9585
  if (this.options.data[xAxis].scale === 'Time') {
9421
9586
  xPos = this[`${xAxis}Axis`](this.parseX(d.x.value))
9422
9587
  }
9588
+ else {
9589
+ let xIndex = this[xAxis + 'Axis'].domain().indexOf(d.x.value)
9590
+ let xPos = this[`custom${xAxis.toInitialCaps()}Range`][xIndex]
9591
+ if (this[`custom${xAxis.toInitialCaps()}Range`][xIndex + 1]) {
9592
+ xPos = xPos + ((this[`custom${xAxis.toInitialCaps()}Range`][xIndex + 1] - xPos) / 2)
9593
+ }
9594
+ // return xPos
9595
+ }
9423
9596
  // return `translate(${this[`${xAxis}Axis`](this.parseX(d.x.value)) + adjustment}, ${this[`${yAxis}Axis`](isNaN(d.y.value) ? 0 : d.y.value)})`
9424
9597
  return `translate(${xPos}, ${this[`${yAxis}Axis`](isNaN(d.y.value) ? 0 : d.y.value)})`
9425
9598
  }
@@ -9446,6 +9619,14 @@ symbols.enter()
9446
9619
  if (this.options.data[xAxis].scale === 'Time') {
9447
9620
  xPos = this[`${xAxis}Axis`](this.parseX(d.x.value))
9448
9621
  }
9622
+ else {
9623
+ let xIndex = this[xAxis + 'Axis'].domain().indexOf(d.x.value)
9624
+ let xPos = this[`custom${xAxis.toInitialCaps()}Range`][xIndex]
9625
+ if (this[`custom${xAxis.toInitialCaps()}Range`][xIndex + 1]) {
9626
+ xPos = xPos + ((this[`custom${xAxis.toInitialCaps()}Range`][xIndex + 1] - xPos) / 2)
9627
+ }
9628
+ // return xPos
9629
+ }
9449
9630
  // return `translate(${this[`${xAxis}Axis`](this.parseX(d.x.value)) + adjustment}, ${this[`${yAxis}Axis`](isNaN(d.y.value) ? 0 : d.y.value)})`
9450
9631
  return `translate(${xPos}, ${this[`${yAxis}Axis`](isNaN(d.y.value) ? 0 : d.y.value)})`
9451
9632
  }
@@ -9696,8 +9877,12 @@ class WebsyKPI {
9696
9877
  constructor (elementId, options) {
9697
9878
  const DEFAULTS = {
9698
9879
  tooltip: {},
9699
- label: {},
9700
- value: {}
9880
+ label: {
9881
+ value: ''
9882
+ },
9883
+ value: {
9884
+ value: ''
9885
+ }
9701
9886
  }
9702
9887
  this.elementId = elementId
9703
9888
  this.options = Object.assign({}, DEFAULTS, options)
@@ -9733,7 +9918,7 @@ class WebsyKPI {
9733
9918
  html += `
9734
9919
  <div class="websy-kpi-info">
9735
9920
  <div class="websy-kpi-label ${this.options.label.classes.join(' ') || ''}">
9736
- ${this.options.label.value || ''}
9921
+ ${(this.options.label || {}).value || ''}
9737
9922
  `
9738
9923
  if (this.options.tooltip && this.options.tooltip.value) {
9739
9924
  html += `