alchemy_cms 5.3.0 → 5.3.1
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/CHANGELOG.md +14 -0
- data/app/assets/javascripts/alchemy/admin.js +0 -1
- data/app/assets/javascripts/alchemy/templates/index.js +1 -0
- data/app/assets/javascripts/alchemy/templates/page.hbs +17 -7
- data/app/assets/javascripts/alchemy/templates/page_folder.hbs +3 -0
- data/app/assets/stylesheets/alchemy/page-select.scss +29 -4
- data/app/assets/stylesheets/alchemy/sitemap.scss +2 -6
- data/app/controllers/alchemy/admin/pages_controller.rb +8 -12
- data/app/controllers/alchemy/api/pages_controller.rb +14 -4
- data/app/serializers/alchemy/page_serializer.rb +7 -1
- data/app/serializers/alchemy/page_tree_serializer.rb +3 -3
- data/app/views/alchemy/admin/pages/_page.html.erb +111 -133
- data/app/views/alchemy/admin/pages/_sitemap.html.erb +2 -8
- data/app/views/alchemy/admin/pages/_toolbar.html.erb +0 -12
- data/app/views/alchemy/admin/pages/index.html.erb +1 -1
- data/app/views/alchemy/admin/partials/_routes.html.erb +8 -1
- data/app/views/alchemy/essences/_essence_page_editor.html.erb +1 -1
- data/config/locales/alchemy.en.yml +0 -3
- data/config/routes.rb +4 -2
- data/lib/alchemy/permissions.rb +0 -1
- data/lib/alchemy/version.rb +1 -1
- data/package/src/page_sorter.js +68 -0
- data/package/src/sitemap.js +55 -36
- data/package.json +1 -1
- metadata +4 -6
- data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +0 -24
- data/app/views/alchemy/admin/pages/fold.js.erb +0 -2
- data/app/views/alchemy/admin/pages/sort.html.erb +0 -19
- data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +0 -434
@@ -292,7 +292,6 @@ en:
|
|
292
292
|
"Site successfully removed": "Website successfully removed."
|
293
293
|
"Site successfully updated": "Website successfully updated."
|
294
294
|
"Size": "Size"
|
295
|
-
"Sort pages": "Reorder pages"
|
296
295
|
"Successfully added content": "Successfully added %{content}"
|
297
296
|
"Successfully deleted content": "Successfully deleted %{content}"
|
298
297
|
"Tags": "Tags"
|
@@ -394,7 +393,6 @@ en:
|
|
394
393
|
enter_external_link: "Please enter the URL you want to link with"
|
395
394
|
explain_cropping: "<p>Move the frame and change its size with the mouse or arrow keys to adjust the image mask. Click on \"apply\" when you are satisfied with your selection.</p><p>If you want to return to the original centered image mask like it was defined in the layout, click \"reset\" and \"apply\" afterwards.</p>"
|
396
395
|
explain_publishing: "Publish the page and remove the cached version from the server."
|
397
|
-
explain_sitemap_dragndrop_sorting: "Tip: Drag the pages at the icon in order to sort them."
|
398
396
|
explain_unlocking: "Leave page and unlock it for other users."
|
399
397
|
external_link_notice_1: "Please enter the complete url with http:// or a similar protocol."
|
400
398
|
external_link_notice_2: "To refer a path from your website url, start with a /."
|
@@ -553,7 +551,6 @@ en:
|
|
553
551
|
robot_follow: "robot may follow links."
|
554
552
|
robot_index: "allow robot to index."
|
555
553
|
save: "Save"
|
556
|
-
"save order": "Save order"
|
557
554
|
saved_link: "Link saved."
|
558
555
|
search: "search"
|
559
556
|
search_engines: "Search engines"
|
data/config/routes.rb
CHANGED
@@ -28,13 +28,12 @@ Alchemy::Engine.routes.draw do
|
|
28
28
|
post :copy_language_tree
|
29
29
|
get :create_language
|
30
30
|
get :link
|
31
|
-
get :sort
|
32
31
|
get :tree
|
33
32
|
end
|
34
33
|
member do
|
35
34
|
post :unlock
|
36
35
|
post :publish
|
37
|
-
|
36
|
+
patch :fold
|
38
37
|
post :visit
|
39
38
|
get :configure
|
40
39
|
get :preview
|
@@ -145,6 +144,9 @@ Alchemy::Engine.routes.draw do
|
|
145
144
|
collection do
|
146
145
|
get :nested
|
147
146
|
end
|
147
|
+
member do
|
148
|
+
patch :move
|
149
|
+
end
|
148
150
|
end
|
149
151
|
|
150
152
|
get "/pages/*urlname(.:format)" => "pages#show", as: "page"
|
data/lib/alchemy/permissions.rb
CHANGED
data/lib/alchemy/version.rb
CHANGED
@@ -0,0 +1,68 @@
|
|
1
|
+
import Sortable from "sortablejs"
|
2
|
+
|
3
|
+
function onFinishDragging(evt) {
|
4
|
+
const pageId = evt.item.dataset.pageId
|
5
|
+
const url = Alchemy.routes.move_admin_page_path(pageId)
|
6
|
+
const data = {
|
7
|
+
target_parent_id: evt.to.dataset.parentId,
|
8
|
+
new_position: evt.newIndex
|
9
|
+
}
|
10
|
+
|
11
|
+
fetch(url, {
|
12
|
+
method: "PATCH",
|
13
|
+
headers: {
|
14
|
+
"Content-Type": "application/json",
|
15
|
+
Accept: "application/json"
|
16
|
+
},
|
17
|
+
body: JSON.stringify(data)
|
18
|
+
})
|
19
|
+
.then(async (response) => {
|
20
|
+
const pageData = await response.json()
|
21
|
+
const pageEl = document.getElementById(`page_${pageId}`)
|
22
|
+
const urlPathEl = pageEl.querySelector(".sitemap_url")
|
23
|
+
|
24
|
+
Alchemy.growl(Alchemy.t("Successfully moved page"))
|
25
|
+
urlPathEl.textContent = pageData.url_path
|
26
|
+
displayPageFolders()
|
27
|
+
})
|
28
|
+
.catch((error) => {
|
29
|
+
Alchemy.growl(error.message || error, "error")
|
30
|
+
})
|
31
|
+
}
|
32
|
+
|
33
|
+
export function displayPageFolders() {
|
34
|
+
document.querySelectorAll("li.sitemap-item").forEach((el) => {
|
35
|
+
const pageFolderEl = el.querySelector(".page_folder")
|
36
|
+
const list = el.querySelector(".children")
|
37
|
+
const page = {
|
38
|
+
folded: el.dataset.folded === "true",
|
39
|
+
id: el.dataset.pageId,
|
40
|
+
type: el.dataset.type
|
41
|
+
}
|
42
|
+
|
43
|
+
if (list.children.length > 0 || page.folded) {
|
44
|
+
pageFolderEl.outerHTML = HandlebarsTemplates.page_folder({ page })
|
45
|
+
} else {
|
46
|
+
pageFolderEl.innerHTML = ""
|
47
|
+
}
|
48
|
+
})
|
49
|
+
}
|
50
|
+
|
51
|
+
export function createSortables(sortables) {
|
52
|
+
sortables.forEach((el) => {
|
53
|
+
new Sortable(el, {
|
54
|
+
group: "pages",
|
55
|
+
animation: 150,
|
56
|
+
fallbackOnBody: true,
|
57
|
+
swapThreshold: 0.65,
|
58
|
+
handle: ".handle",
|
59
|
+
onEnd: onFinishDragging
|
60
|
+
})
|
61
|
+
})
|
62
|
+
}
|
63
|
+
|
64
|
+
export default function () {
|
65
|
+
const sortables = document.querySelectorAll("ul.children")
|
66
|
+
displayPageFolders()
|
67
|
+
createSortables(sortables)
|
68
|
+
}
|
data/package/src/sitemap.js
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
// The admin sitemap Alchemy class
|
2
|
+
import PageSorter from "./page_sorter"
|
3
|
+
import { on } from "./utils/events"
|
4
|
+
import { createSortables, displayPageFolders } from "./page_sorter"
|
2
5
|
|
3
6
|
export default class Sitemap {
|
4
7
|
// Storing some objects.
|
5
8
|
constructor(options) {
|
6
|
-
const list_template_regexp = new RegExp("/" + options.page_root_id, "g")
|
7
9
|
const list_template_html = document
|
8
10
|
.getElementById("sitemap-list")
|
9
|
-
.innerHTML.replace(
|
11
|
+
.innerHTML.replace(/__ID__/g, "{{id}}")
|
10
12
|
this.search_field = document.querySelector(".search_input_field")
|
11
13
|
this.filter_field_clear = document.querySelector(".search_field_clear")
|
12
14
|
this.filter_field_clear.removeAttribute("href")
|
@@ -24,56 +26,68 @@ export default class Sitemap {
|
|
24
26
|
|
25
27
|
// Loads the sitemap
|
26
28
|
load(pageId) {
|
27
|
-
const spinner =
|
29
|
+
const spinner = new Alchemy.Spinner("medium")
|
28
30
|
const spinTarget = this.sitemap_wrapper
|
29
31
|
spinTarget.innerHTML = ""
|
30
32
|
spinner.spin(spinTarget)
|
31
|
-
this.
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
fetch(`${this.options.url}?id=${pageId}`)
|
34
|
+
.then(async (response) => {
|
35
|
+
this.render(await response.json())
|
36
|
+
this.handlePageFolders()
|
37
|
+
spinner.stop()
|
38
|
+
})
|
39
|
+
.catch(this.errorHandler)
|
37
40
|
}
|
38
41
|
|
39
|
-
//
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
// Watch page folder clicks and re-render the page branch
|
43
|
+
handlePageFolders() {
|
44
|
+
on(
|
45
|
+
"click",
|
46
|
+
"#sitemap",
|
47
|
+
".page_folder",
|
48
|
+
function (evt) {
|
49
|
+
const spinner = new Alchemy.Spinner("small")
|
50
|
+
const pageFolder = evt.target.closest(".page_folder")
|
51
|
+
const pageId = pageFolder.dataset.pageId
|
52
|
+
pageFolder.innerHTML = ""
|
53
|
+
spinner.spin(pageFolder)
|
50
54
|
|
51
|
-
|
52
|
-
|
55
|
+
fetch(Alchemy.routes.fold_admin_page_path(pageId), {
|
56
|
+
method: "PATCH",
|
57
|
+
headers: {
|
58
|
+
Accept: "application/json"
|
59
|
+
}
|
60
|
+
})
|
61
|
+
.then(async (response) => {
|
62
|
+
this.reRender(pageId, await response.json())
|
63
|
+
spinner.stop()
|
64
|
+
})
|
65
|
+
.catch(this.errorHandler)
|
66
|
+
}.bind(this)
|
67
|
+
)
|
53
68
|
}
|
54
69
|
|
55
70
|
// Renders the sitemap
|
56
|
-
render(data
|
57
|
-
|
71
|
+
render(data) {
|
72
|
+
const renderTarget = this.sitemap_wrapper
|
73
|
+
const renderTemplate = this.template
|
58
74
|
|
59
|
-
|
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
|
-
}
|
75
|
+
renderTarget.innerHTML = renderTemplate({ children: data.pages })
|
68
76
|
this.items = document
|
69
77
|
.getElementById("sitemap")
|
70
78
|
.querySelectorAll(".sitemap_page")
|
71
79
|
this.sitemap_wrapper = document.getElementById("sitemap-wrapper")
|
72
80
|
this._observe()
|
81
|
+
PageSorter()
|
82
|
+
}
|
73
83
|
|
74
|
-
|
75
|
-
|
76
|
-
}
|
84
|
+
reRender(pageId, data) {
|
85
|
+
let pageEl = document.getElementById(`page_${pageId}`)
|
86
|
+
pageEl.outerHTML = this.list_template({ children: data.pages })
|
87
|
+
pageEl = document.getElementById(`page_${pageId}`)
|
88
|
+
const sortables = pageEl.querySelectorAll("ul.children")
|
89
|
+
createSortables(sortables)
|
90
|
+
displayPageFolders()
|
77
91
|
}
|
78
92
|
|
79
93
|
// Filters the sitemap
|
@@ -130,4 +144,9 @@ export default class Sitemap {
|
|
130
144
|
return false
|
131
145
|
})
|
132
146
|
}
|
147
|
+
|
148
|
+
errorHandler(error) {
|
149
|
+
Alchemy.growl(error.message || error, "error")
|
150
|
+
console.error(error)
|
151
|
+
}
|
133
152
|
}
|
data/package.json
CHANGED
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: 5.3.
|
4
|
+
version: 5.3.1
|
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: 2022-03-
|
16
|
+
date: 2022-03-11 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: active_model_serializers
|
@@ -633,7 +633,6 @@ files:
|
|
633
633
|
- app/assets/javascripts/alchemy/alchemy.initializer.js.coffee
|
634
634
|
- app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee
|
635
635
|
- app/assets/javascripts/alchemy/alchemy.list_filter.js.coffee
|
636
|
-
- app/assets/javascripts/alchemy/alchemy.page_sorter.js
|
637
636
|
- app/assets/javascripts/alchemy/alchemy.preview.js.coffee
|
638
637
|
- app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee
|
639
638
|
- app/assets/javascripts/alchemy/alchemy.spinner.js
|
@@ -650,6 +649,7 @@ files:
|
|
650
649
|
- app/assets/javascripts/alchemy/templates/node.hbs
|
651
650
|
- app/assets/javascripts/alchemy/templates/node_folder.hbs
|
652
651
|
- app/assets/javascripts/alchemy/templates/page.hbs
|
652
|
+
- app/assets/javascripts/alchemy/templates/page_folder.hbs
|
653
653
|
- app/assets/javascripts/alchemy/templates/spinner.hbs
|
654
654
|
- app/assets/javascripts/tinymce/plugins/alchemy_link/plugin.min.js
|
655
655
|
- app/assets/stylesheets/alchemy/_defaults.scss
|
@@ -927,7 +927,6 @@ files:
|
|
927
927
|
- app/views/alchemy/admin/pages/configure.html.erb
|
928
928
|
- app/views/alchemy/admin/pages/edit.html.erb
|
929
929
|
- app/views/alchemy/admin/pages/flush.js.erb
|
930
|
-
- app/views/alchemy/admin/pages/fold.js.erb
|
931
930
|
- app/views/alchemy/admin/pages/index.html.erb
|
932
931
|
- app/views/alchemy/admin/pages/info.html.erb
|
933
932
|
- app/views/alchemy/admin/pages/link.html.erb
|
@@ -935,7 +934,6 @@ files:
|
|
935
934
|
- app/views/alchemy/admin/pages/locked.html.erb
|
936
935
|
- app/views/alchemy/admin/pages/new.html.erb
|
937
936
|
- app/views/alchemy/admin/pages/show.html.erb
|
938
|
-
- app/views/alchemy/admin/pages/sort.html.erb
|
939
937
|
- app/views/alchemy/admin/pages/unlock.js.erb
|
940
938
|
- app/views/alchemy/admin/pages/update.js.erb
|
941
939
|
- app/views/alchemy/admin/partials/_autocomplete_tag_list.html.erb
|
@@ -1190,6 +1188,7 @@ files:
|
|
1190
1188
|
- package/src/i18n.js
|
1191
1189
|
- package/src/node_tree.js
|
1192
1190
|
- package/src/page_publication_fields.js
|
1191
|
+
- package/src/page_sorter.js
|
1193
1192
|
- package/src/sitemap.js
|
1194
1193
|
- package/src/translations.js
|
1195
1194
|
- package/src/utils/__tests__/ajax.spec.js
|
@@ -1215,7 +1214,6 @@ files:
|
|
1215
1214
|
- vendor/assets/javascripts/flatpickr/flatpickr.min.js
|
1216
1215
|
- vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js
|
1217
1216
|
- vendor/assets/javascripts/jquery_plugins/jquery.scrollTo.min.js
|
1218
|
-
- vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js
|
1219
1217
|
- vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js
|
1220
1218
|
- vendor/assets/javascripts/jquery_plugins/select2.js
|
1221
1219
|
- vendor/assets/javascripts/keymaster.js
|
@@ -1,24 +0,0 @@
|
|
1
|
-
Alchemy.PageSorter = function () {
|
2
|
-
var $sortables = $("ul#sitemap").find("ul.level_0_children")
|
3
|
-
|
4
|
-
$sortables.nestedSortable({
|
5
|
-
disableNesting: "no-nest",
|
6
|
-
forcePlaceholderSize: true,
|
7
|
-
handle: ".handle",
|
8
|
-
items: "li",
|
9
|
-
listType: "ul",
|
10
|
-
opacity: 0.5,
|
11
|
-
placeholder: "placeholder",
|
12
|
-
tabSize: 16,
|
13
|
-
tolerance: "pointer",
|
14
|
-
toleranceElement: "> div"
|
15
|
-
})
|
16
|
-
|
17
|
-
$("#save_page_order").click(function (e) {
|
18
|
-
e.preventDefault()
|
19
|
-
Alchemy.Buttons.disable(this)
|
20
|
-
$.post(Alchemy.routes.order_admin_pages_path, {
|
21
|
-
set: JSON.stringify($sortables.nestedSortable("toHierarchy"))
|
22
|
-
})
|
23
|
-
})
|
24
|
-
}
|
@@ -1,19 +0,0 @@
|
|
1
|
-
<% content_for :toolbar do %>
|
2
|
-
<div class="button_with_label">
|
3
|
-
<%= link_to alchemy.admin_pages_path, class: 'icon_button' do %>
|
4
|
-
<%= render_icon 'angle-double-left' %>
|
5
|
-
<% end %>
|
6
|
-
<label><%= Alchemy.t(:cancel) %></label>
|
7
|
-
</div>
|
8
|
-
<% end %>
|
9
|
-
|
10
|
-
<div id="sort_panel">
|
11
|
-
<%= render_message do %>
|
12
|
-
<%= Alchemy.t(:explain_sitemap_dragndrop_sorting) %>
|
13
|
-
<% end %>
|
14
|
-
<div class="buttons">
|
15
|
-
<%= button_tag Alchemy.t('save order'), id: 'save_page_order' %>
|
16
|
-
</div>
|
17
|
-
</div>
|
18
|
-
|
19
|
-
<%= render 'sitemap', page_partial: 'page', full: true %>
|