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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +0 -7
- data/CHANGELOG.md +26 -0
- data/alchemy_cms.gemspec +1 -1
- data/app/assets/javascripts/alchemy/admin.js +0 -2
- data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +6 -1
- data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +2 -2
- data/app/assets/stylesheets/alchemy/_extends.scss +4 -4
- data/app/assets/stylesheets/alchemy/flatpickr.scss +182 -232
- data/app/assets/stylesheets/alchemy/sitemap.scss +7 -1
- data/app/controllers/alchemy/admin/base_controller.rb +9 -3
- data/app/controllers/alchemy/admin/pages_controller.rb +1 -3
- data/app/models/alchemy/page.rb +9 -3
- data/app/services/alchemy/tag_validations.rb +21 -0
- data/app/views/alchemy/admin/pages/_sitemap.html.erb +8 -8
- data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
- data/app/views/alchemy/admin/pages/fold.js.erb +1 -1
- data/app/views/alchemy/admin/pages/update.js.erb +0 -5
- data/config/locales/alchemy.en.yml +0 -1
- data/config/routes.rb +0 -1
- data/db/migrate/20200226213334_alchemy_four_point_four.rb +30 -30
- data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +1 -1
- data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +1 -1
- data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +1 -1
- data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +1 -1
- data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +1 -1
- data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +1 -1
- data/db/migrate/20200617110713_create_alchemy_picture_thumbs.rb +1 -1
- data/db/migrate/20200907111332_remove_tri_state_booleans.rb +1 -1
- data/db/migrate/20201207131309_create_page_versions.rb +1 -1
- data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +1 -1
- data/lib/alchemy/engine.rb +5 -4
- data/lib/alchemy/error_tracking.rb +14 -0
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy_cms.rb +1 -0
- data/package/admin.js +7 -1
- data/package/src/datepicker.js +39 -0
- data/package/src/page_publication_fields.js +27 -0
- data/package/src/sitemap.js +133 -0
- data/package.json +2 -1
- metadata +11 -8
- data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +0 -29
- 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-
|
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.
|
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:
|
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.
|
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.
|
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
|