alchemy_cms 5.3.0 → 5.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 %>
|