alchemy_cms 6.0.0.pre.rc3 → 6.0.0.pre.rc6

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.

Potentially problematic release.


This version of alchemy_cms might be problematic. Click here for more details.

Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +0 -7
  3. data/CHANGELOG.md +26 -0
  4. data/alchemy_cms.gemspec +1 -1
  5. data/app/assets/javascripts/alchemy/admin.js +0 -2
  6. data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +6 -1
  7. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +2 -2
  8. data/app/assets/stylesheets/alchemy/_extends.scss +4 -4
  9. data/app/assets/stylesheets/alchemy/flatpickr.scss +182 -232
  10. data/app/assets/stylesheets/alchemy/sitemap.scss +7 -1
  11. data/app/controllers/alchemy/admin/base_controller.rb +9 -3
  12. data/app/controllers/alchemy/admin/pages_controller.rb +1 -3
  13. data/app/models/alchemy/page.rb +9 -3
  14. data/app/services/alchemy/tag_validations.rb +21 -0
  15. data/app/views/alchemy/admin/pages/_sitemap.html.erb +8 -8
  16. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  17. data/app/views/alchemy/admin/pages/fold.js.erb +1 -1
  18. data/app/views/alchemy/admin/pages/update.js.erb +0 -5
  19. data/config/locales/alchemy.en.yml +0 -1
  20. data/config/routes.rb +0 -1
  21. data/db/migrate/20200226213334_alchemy_four_point_four.rb +30 -30
  22. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +1 -1
  23. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +1 -1
  24. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +1 -1
  25. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +1 -1
  26. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +1 -1
  27. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +1 -1
  28. data/db/migrate/20200617110713_create_alchemy_picture_thumbs.rb +1 -1
  29. data/db/migrate/20200907111332_remove_tri_state_booleans.rb +1 -1
  30. data/db/migrate/20201207131309_create_page_versions.rb +1 -1
  31. data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +1 -1
  32. data/lib/alchemy/engine.rb +5 -4
  33. data/lib/alchemy/error_tracking.rb +14 -0
  34. data/lib/alchemy/version.rb +1 -1
  35. data/lib/alchemy_cms.rb +1 -0
  36. data/package/admin.js +7 -1
  37. data/package/src/datepicker.js +39 -0
  38. data/package/src/page_publication_fields.js +27 -0
  39. data/package/src/sitemap.js +133 -0
  40. data/package.json +2 -1
  41. metadata +11 -8
  42. data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +0 -29
  43. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +0 -119
@@ -0,0 +1,27 @@
1
+ // Handles the page publication date fields
2
+ export default function () {
3
+ document.addEventListener("DialogReady.Alchemy", function (evt) {
4
+ const dialog = evt.detail.body
5
+ const public_on_field = dialog.querySelector("#page_public_on")
6
+ const public_until_field = dialog.querySelector("#page_public_until")
7
+ const publication_date_fields = dialog.querySelector(
8
+ ".page-publication-date-fields"
9
+ )
10
+
11
+ dialog
12
+ .querySelector("#page_public")
13
+ .addEventListener("click", function (evt) {
14
+ const checkbox = evt.target
15
+ const now = new Date()
16
+
17
+ if (checkbox.checked) {
18
+ publication_date_fields.classList.remove("hidden")
19
+ public_on_field._flatpickr.setDate(now)
20
+ } else {
21
+ publication_date_fields.classList.add("hidden")
22
+ public_on_field.value = ""
23
+ }
24
+ public_until_field.value = ""
25
+ })
26
+ })
27
+ }
@@ -0,0 +1,133 @@
1
+ // The admin sitemap Alchemy class
2
+
3
+ export default class Sitemap {
4
+ // Storing some objects.
5
+ constructor(options) {
6
+ const list_template_regexp = new RegExp("/" + options.page_root_id, "g")
7
+ const list_template_html = document
8
+ .getElementById("sitemap-list")
9
+ .innerHTML.replace(list_template_regexp, "/{{id}}")
10
+ this.search_field = document.querySelector(".search_input_field")
11
+ this.filter_field_clear = document.querySelector(".search_field_clear")
12
+ this.filter_field_clear.removeAttribute("href")
13
+ this.display = document.getElementById("page_filter_result")
14
+ this.sitemap_wrapper = document.getElementById("sitemap-wrapper")
15
+ this.template = Handlebars.compile(
16
+ document.getElementById("sitemap-template").innerHTML
17
+ )
18
+ this.list_template = Handlebars.compile(list_template_html)
19
+ this.items = null
20
+ this.options = options
21
+ Handlebars.registerPartial("list", list_template_html)
22
+ this.load(options.page_root_id)
23
+ }
24
+
25
+ // Loads the sitemap
26
+ load(pageId) {
27
+ const spinner = this.options.spinner || new Alchemy.Spinner("medium")
28
+ const spinTarget = this.sitemap_wrapper
29
+ spinTarget.innerHTML = ""
30
+ spinner.spin(spinTarget)
31
+ this.fetch(
32
+ `${this.options.url}?id=${pageId}&full=${this.options.full}`
33
+ ).then(async (response) => {
34
+ this.render(await response.json())
35
+ spinner.stop()
36
+ })
37
+ }
38
+
39
+ // Reload the sitemap for a specific branch
40
+ reload(pageId) {
41
+ const spinner = new Alchemy.Spinner("small")
42
+ const spinTarget = document.getElementById(`fold_button_${pageId}`)
43
+ spinTarget.querySelector(".far").remove()
44
+ spinner.spin(spinTarget)
45
+ this.fetch(`${this.options.url}?id=${pageId}`).then(async (response) => {
46
+ this.render(await response.json(), pageId)
47
+ spinner.stop()
48
+ })
49
+ }
50
+
51
+ fetch(url) {
52
+ return fetch(url).catch((error) => console.warn(`Request failed: ${error}`))
53
+ }
54
+
55
+ // Renders the sitemap
56
+ render(data, foldingId) {
57
+ let renderTarget, renderTemplate
58
+
59
+ if (foldingId) {
60
+ renderTarget = document.getElementById(`page_${foldingId}`)
61
+ renderTemplate = this.list_template
62
+ renderTarget.outerHTML = renderTemplate({ children: data.pages })
63
+ } else {
64
+ renderTarget = this.sitemap_wrapper
65
+ renderTemplate = this.template
66
+ renderTarget.innerHTML = renderTemplate({ children: data.pages })
67
+ }
68
+ this.items = document
69
+ .getElementById("sitemap")
70
+ .querySelectorAll(".sitemap_page")
71
+ this.sitemap_wrapper = document.getElementById("sitemap-wrapper")
72
+ this._observe()
73
+
74
+ if (this.options.ready) {
75
+ this.options.ready()
76
+ }
77
+ }
78
+
79
+ // Filters the sitemap
80
+ filter(term) {
81
+ const results = []
82
+
83
+ this.items.forEach(function (item) {
84
+ if (
85
+ term !== "" &&
86
+ item.getAttribute("name").toLowerCase().indexOf(term) !== -1
87
+ ) {
88
+ item.classList.add("highlight")
89
+ item.classList.remove("no-match")
90
+ results.push(item)
91
+ } else {
92
+ item.classList.add("no-match")
93
+ item.classList.remove("highlight")
94
+ }
95
+ })
96
+ this.filter_field_clear.style.display = "inline-block"
97
+ const { length } = results
98
+
99
+ if (length === 1) {
100
+ this.display.style.display = "block"
101
+ this.display.innerText = `1 ${Alchemy.t("page_found")}`
102
+ results[0].scrollIntoView({ behavior: "smooth", block: "center" })
103
+ } else if (length > 1) {
104
+ this.display.style.display = "block"
105
+ this.display.innerText = `${length} ${Alchemy.t("pages_found")}`
106
+ } else {
107
+ this.items.forEach((item) =>
108
+ item.classList.remove("no-match", "highlight")
109
+ )
110
+ this.display.style.display = "none"
111
+ window.scrollTo({
112
+ top: 0,
113
+ left: 0,
114
+ behavior: "smooth"
115
+ })
116
+ this.filter_field_clear.style.display = "none"
117
+ }
118
+ }
119
+
120
+ // Adds onkey up observer to search field
121
+ _observe() {
122
+ this.search_field.addEventListener("keyup", (evt) => {
123
+ const term = evt.target.value
124
+ this.filter(term.toLowerCase())
125
+ })
126
+ this.search_field.addEventListener("focus", () => key.setScope("search"))
127
+ this.filter_field_clear.addEventListener("click", () => {
128
+ this.search_field.value = ""
129
+ this.filter("")
130
+ return false
131
+ })
132
+ }
133
+ }
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alchemy_cms/admin",
3
- "version": "6.0.0-rc3",
3
+ "version": "6.0.0-rc6",
4
4
  "description": "AlchemyCMS",
5
5
  "browser": "package/admin.js",
6
6
  "files": [
@@ -24,6 +24,7 @@
24
24
  },
25
25
  "homepage": "https://github.com/AlchemyCMS/alchemy_cms#readme",
26
26
  "dependencies": {
27
+ "flatpickr": "^4.6.9",
27
28
  "lodash-es": "^4.17.21",
28
29
  "sortablejs": "^1.10.2"
29
30
  },
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alchemy_cms
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.0.pre.rc3
4
+ version: 6.0.0.pre.rc6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas von Deyen
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2021-11-24 00:00:00.000000000 Z
16
+ date: 2022-03-05 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: actionmailer
@@ -408,9 +408,9 @@ dependencies:
408
408
  - - ">="
409
409
  - !ruby/object:Gem::Version
410
410
  version: '1.8'
411
- - - "<"
411
+ - - "<="
412
412
  - !ruby/object:Gem::Version
413
- version: 2.4.2
413
+ version: 2.5.0
414
414
  type: :runtime
415
415
  prerelease: false
416
416
  version_requirements: !ruby/object:Gem::Requirement
@@ -418,9 +418,9 @@ dependencies:
418
418
  - - ">="
419
419
  - !ruby/object:Gem::Version
420
420
  version: '1.8'
421
- - - "<"
421
+ - - "<="
422
422
  - !ruby/object:Gem::Version
423
- version: 2.4.2
423
+ version: 2.5.0
424
424
  - !ruby/object:Gem::Dependency
425
425
  name: request_store
426
426
  requirement: !ruby/object:Gem::Requirement
@@ -757,7 +757,6 @@ files:
757
757
  - app/assets/javascripts/alchemy/alchemy.buttons.js.coffee
758
758
  - app/assets/javascripts/alchemy/alchemy.char_counter.js.coffee
759
759
  - app/assets/javascripts/alchemy/alchemy.confirm_dialog.js.coffee
760
- - app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee
761
760
  - app/assets/javascripts/alchemy/alchemy.dialog.js.coffee
762
761
  - app/assets/javascripts/alchemy/alchemy.dirty.js.coffee
763
762
  - app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee
@@ -776,7 +775,6 @@ files:
776
775
  - app/assets/javascripts/alchemy/alchemy.page_sorter.js
777
776
  - app/assets/javascripts/alchemy/alchemy.preview.js.coffee
778
777
  - app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee
779
- - app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee
780
778
  - app/assets/javascripts/alchemy/alchemy.spinner.js
781
779
  - app/assets/javascripts/alchemy/alchemy.string_extension.js.coffee
782
780
  - app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee
@@ -1008,6 +1006,7 @@ files:
1008
1006
  - app/serializers/alchemy/picture_serializer.rb
1009
1007
  - app/services/alchemy/delete_elements.rb
1010
1008
  - app/services/alchemy/duplicate_element.rb
1009
+ - app/services/alchemy/tag_validations.rb
1011
1010
  - app/views/alchemy/_edit_mode.html.erb
1012
1011
  - app/views/alchemy/_menubar.html.erb
1013
1012
  - app/views/alchemy/_preview_mode_code.html.erb
@@ -1308,6 +1307,7 @@ files:
1308
1307
  - lib/alchemy/element_definition.rb
1309
1308
  - lib/alchemy/elements_finder.rb
1310
1309
  - lib/alchemy/engine.rb
1310
+ - lib/alchemy/error_tracking.rb
1311
1311
  - lib/alchemy/errors.rb
1312
1312
  - lib/alchemy/essence.rb
1313
1313
  - lib/alchemy/filetypes.rb
@@ -1424,12 +1424,15 @@ files:
1424
1424
  - package.json
1425
1425
  - package/admin.js
1426
1426
  - package/src/__tests__/i18n.spec.js
1427
+ - package/src/datepicker.js
1427
1428
  - package/src/file_editors.js
1428
1429
  - package/src/i18n.js
1429
1430
  - package/src/image_cropper.js
1430
1431
  - package/src/image_loader.js
1431
1432
  - package/src/node_tree.js
1433
+ - package/src/page_publication_fields.js
1432
1434
  - package/src/picture_editors.js
1435
+ - package/src/sitemap.js
1433
1436
  - package/src/translations.js
1434
1437
  - package/src/utils/__tests__/ajax.spec.js
1435
1438
  - package/src/utils/__tests__/events.spec.js
@@ -1,29 +0,0 @@
1
- window.Alchemy = {} if typeof(window.Alchemy) is 'undefined'
2
-
3
- $.extend Alchemy,
4
-
5
- Datepicker: (scope) ->
6
- $datepicker_inputs = $('input[data-datepicker-type]', scope)
7
-
8
- # Initializes the datepickers on the text inputs and sets the proper type
9
- # to enable browsers default datepicker if the current OS is iOS.
10
- if Alchemy.isiOS
11
- $datepicker_inputs.prop "type", ->
12
- return $(this).data('datepicker-type')
13
- else
14
- $datepicker_inputs.each ->
15
- type = $(this).data('datepicker-type')
16
- options =
17
- # alchemy_i18n supports `zh_CN` etc., but flatpickr only has two-letter codes (`zh`)
18
- locale: Alchemy.locale.slice(0, 2)
19
- altInput: true
20
- altFormat: Alchemy.t("formats.#{type}")
21
- altInputClass: ""
22
- enableTime: /time/.test(type)
23
- noCalendar: type == "time"
24
- time_24hr: Alchemy.t("formats.time_24hr")
25
- onValueUpdate: (_selectedDates, _dateStr, instance) ->
26
- Alchemy.setElementDirty $(instance.element).closest(".element-editor")
27
- $(this).flatpickr(options)
28
-
29
- return
@@ -1,119 +0,0 @@
1
- window.Alchemy = {} if typeof(window.Alchemy) is 'undefined'
2
-
3
- # The admin sitemap Alchemy module
4
- Alchemy.Sitemap =
5
-
6
- # Storing some objects.
7
- init: (options) ->
8
- @search_field = $(".search_input_field")
9
- @filter_field_clear = $('.search_field_clear')
10
- @display = $('#page_filter_result')
11
- @sitemap_wrapper = $('#sitemap-wrapper p.loading')
12
- @template = Handlebars.compile($('#sitemap-template').html())
13
- list_template_regexp = new RegExp '\/' + options.page_root_id, 'g'
14
- list_template_html = $('#sitemap-list').html().replace(list_template_regexp, '/{{id}}')
15
- @list_template = Handlebars.compile(list_template_html)
16
- @items = null
17
- @options = options
18
- @watchPagePublicationState()
19
- true
20
-
21
- Handlebars.registerPartial('list', list_template_html)
22
-
23
- @fetch()
24
-
25
- # Fetches the sitemap from JSON
26
- fetch: (foldingId) ->
27
- self = Alchemy.Sitemap
28
-
29
- if foldingId
30
- spinner = new Alchemy.Spinner('small')
31
- spinTarget = $('#fold_button_' + foldingId)
32
- renderTarget = $('#page_' + foldingId)
33
- renderTemplate = @list_template
34
- pageId = foldingId
35
- else
36
- spinner = @options.spinner || new Alchemy.Spinner('medium')
37
- spinTarget = @sitemap_wrapper
38
- renderTarget = @sitemap_wrapper
39
- renderTemplate = @template
40
- pageId = @options.page_root_id
41
-
42
- spinner.spin(spinTarget[0])
43
-
44
- request = $.ajax url: @options.url, data:
45
- id: pageId
46
- full: @options.full
47
-
48
- request.done (data) ->
49
- # This will also remove the spinner
50
- renderTarget.replaceWith(renderTemplate({children: data.pages}))
51
- self.items = $(".sitemap_page", '#sitemap')
52
- self._observe()
53
-
54
- if self.options.ready
55
- self.options.ready()
56
-
57
- request.fail (jqXHR, status) ->
58
- console.warn("Request failed: " + status)
59
-
60
- # Filters the sitemap
61
- filter: (term) ->
62
- results = []
63
- self = Alchemy.Sitemap
64
- self.items.map ->
65
- item = $(this)
66
- if term != '' && item.attr('name').toLowerCase().indexOf(term) != -1
67
- item.addClass('highlight')
68
- item.removeClass('no-match')
69
- results.push item
70
- else
71
- item.addClass('no-match')
72
- item.removeClass('highlight')
73
- self.filter_field_clear.show()
74
- length = results.length
75
- if length == 1
76
- self.display.show().text("1 #{Alchemy.t('page_found')}")
77
- $.scrollTo(results[0], {duration: 400, offset: -80})
78
- else if length > 1
79
- self.display.show().text("#{length} #{Alchemy.t('pages_found')}")
80
- else
81
- self.items.removeClass('no-match highlight')
82
- self.display.hide()
83
- $.scrollTo('0', 400)
84
- self.filter_field_clear.hide()
85
-
86
- # Adds onkey up observer to search field
87
- _observe: ->
88
- filter = @filter
89
- @search_field.on 'keyup', ->
90
- term = $(this).val()
91
- filter(term.toLowerCase())
92
- @search_field.on 'focus', ->
93
- key.setScope('search')
94
- @filter_field_clear.click =>
95
- @search_field.val('')
96
- filter('')
97
- false
98
-
99
- # Handles the page publication date fields
100
- watchPagePublicationState: ->
101
- $(document).on 'DialogReady.Alchemy', (e, $dialog) ->
102
- $public_on_field = $('#page_public_on', $dialog)
103
- $public_until_field = $('#page_public_until', $dialog)
104
- $publication_date_fields = $('.page-publication-date-fields', $dialog)
105
-
106
- $('#page_public', $dialog).click ->
107
- $checkbox = $(this)
108
- format = $checkbox.data('date-format')
109
- now = new Date()
110
- if $checkbox.is(':checked')
111
- $publication_date_fields.removeClass('hidden')
112
- $public_on_field[0]._flatpickr.setDate(now)
113
- else
114
- $publication_date_fields.addClass('hidden')
115
- $public_on_field.val('')
116
- $public_until_field.val('')
117
- true
118
-
119
- return