alchemy_cms 5.2.7 → 5.3.2

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.rspec +1 -0
  4. data/CHANGELOG.md +19 -0
  5. data/Rakefile +18 -0
  6. data/alchemy_cms.gemspec +1 -1
  7. data/app/assets/javascripts/alchemy/admin.js +0 -2
  8. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +5 -2
  9. data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +6 -1
  10. data/app/assets/javascripts/alchemy/page_select.js +13 -8
  11. data/app/assets/javascripts/alchemy/templates/index.js +1 -0
  12. data/app/assets/javascripts/alchemy/templates/page.hbs +17 -7
  13. data/app/assets/javascripts/alchemy/templates/page_folder.hbs +3 -0
  14. data/app/assets/stylesheets/alchemy/archive.scss +4 -0
  15. data/app/assets/stylesheets/alchemy/page-select.scss +29 -4
  16. data/app/assets/stylesheets/alchemy/sitemap.scss +9 -7
  17. data/app/controllers/alchemy/admin/pages_controller.rb +10 -13
  18. data/app/controllers/alchemy/api/pages_controller.rb +14 -4
  19. data/app/serializers/alchemy/page_serializer.rb +7 -1
  20. data/app/serializers/alchemy/page_tree_serializer.rb +3 -3
  21. data/app/views/alchemy/admin/pages/_form.html.erb +19 -0
  22. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +16 -5
  23. data/app/views/alchemy/admin/pages/_page.html.erb +111 -133
  24. data/app/views/alchemy/admin/pages/_sitemap.html.erb +10 -16
  25. data/app/views/alchemy/admin/pages/_toolbar.html.erb +0 -12
  26. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  27. data/app/views/alchemy/admin/pages/index.html.erb +1 -1
  28. data/app/views/alchemy/admin/pages/update.js.erb +7 -0
  29. data/app/views/alchemy/admin/partials/_routes.html.erb +8 -1
  30. data/app/views/alchemy/essences/_essence_page_editor.html.erb +1 -1
  31. data/config/locales/alchemy.en.yml +0 -3
  32. data/config/routes.rb +4 -2
  33. data/lib/alchemy/permissions.rb +0 -1
  34. data/lib/alchemy/version.rb +1 -1
  35. data/package/admin.js +5 -1
  36. data/package/src/node_tree.js +3 -3
  37. data/package/src/page_publication_fields.js +27 -0
  38. data/package/src/page_sorter.js +62 -0
  39. data/package/src/sitemap.js +148 -0
  40. data/package/src/utils/__tests__/ajax.spec.js +61 -15
  41. data/package/src/utils/ajax.js +12 -0
  42. data/package.json +1 -1
  43. metadata +9 -9
  44. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +0 -24
  45. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +0 -119
  46. data/app/views/alchemy/admin/pages/fold.js.erb +0 -2
  47. data/app/views/alchemy/admin/pages/sort.html.erb +0 -19
  48. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +0 -434
@@ -0,0 +1,148 @@
1
+ // The admin sitemap Alchemy class
2
+ import PageSorter from "./page_sorter"
3
+ import { on } from "./utils/events"
4
+ import { patch } from "./utils/ajax"
5
+ import { createSortables, displayPageFolders } from "./page_sorter"
6
+
7
+ export default class Sitemap {
8
+ // Storing some objects.
9
+ constructor(options) {
10
+ const list_template_html = document
11
+ .getElementById("sitemap-list")
12
+ .innerHTML.replace(/__ID__/g, "{{id}}")
13
+ this.search_field = document.querySelector(".search_input_field")
14
+ this.filter_field_clear = document.querySelector(".search_field_clear")
15
+ this.filter_field_clear.removeAttribute("href")
16
+ this.display = document.getElementById("page_filter_result")
17
+ this.sitemap_wrapper = document.getElementById("sitemap-wrapper")
18
+ this.template = Handlebars.compile(
19
+ document.getElementById("sitemap-template").innerHTML
20
+ )
21
+ this.list_template = Handlebars.compile(list_template_html)
22
+ this.items = null
23
+ this.options = options
24
+ Handlebars.registerPartial("list", list_template_html)
25
+ this.load(options.page_root_id)
26
+ }
27
+
28
+ // Loads the sitemap
29
+ load(pageId) {
30
+ const spinner = new Alchemy.Spinner("medium")
31
+ const spinTarget = this.sitemap_wrapper
32
+ spinTarget.innerHTML = ""
33
+ spinner.spin(spinTarget)
34
+ fetch(`${this.options.url}?id=${pageId}`)
35
+ .then(async (response) => {
36
+ this.render(await response.json())
37
+ this.handlePageFolders()
38
+ spinner.stop()
39
+ })
40
+ .catch(this.errorHandler)
41
+ }
42
+
43
+ // Watch page folder clicks and re-render the page branch
44
+ handlePageFolders() {
45
+ on(
46
+ "click",
47
+ "#sitemap",
48
+ ".page_folder",
49
+ function (evt) {
50
+ const spinner = new Alchemy.Spinner("small")
51
+ const pageFolder = evt.target.closest(".page_folder")
52
+ const pageId = pageFolder.dataset.pageId
53
+ pageFolder.innerHTML = ""
54
+ spinner.spin(pageFolder)
55
+
56
+ patch(Alchemy.routes.fold_admin_page_path(pageId))
57
+ .then(async (response) => {
58
+ this.reRender(pageId, await response.json())
59
+ spinner.stop()
60
+ })
61
+ .catch(this.errorHandler)
62
+ }.bind(this)
63
+ )
64
+ }
65
+
66
+ // Renders the sitemap
67
+ render(data) {
68
+ const renderTarget = this.sitemap_wrapper
69
+ const renderTemplate = this.template
70
+
71
+ renderTarget.innerHTML = renderTemplate({ children: data.pages })
72
+ this.items = document
73
+ .getElementById("sitemap")
74
+ .querySelectorAll(".sitemap_page")
75
+ this.sitemap_wrapper = document.getElementById("sitemap-wrapper")
76
+ this._observe()
77
+ PageSorter()
78
+ }
79
+
80
+ reRender(pageId, data) {
81
+ let pageEl = document.getElementById(`page_${pageId}`)
82
+ pageEl.outerHTML = this.list_template({ children: data.pages })
83
+ pageEl = document.getElementById(`page_${pageId}`)
84
+ const sortables = pageEl.querySelectorAll("ul.children")
85
+ createSortables(sortables)
86
+ displayPageFolders()
87
+ }
88
+
89
+ // Filters the sitemap
90
+ filter(term) {
91
+ const results = []
92
+
93
+ this.items.forEach(function (item) {
94
+ if (
95
+ term !== "" &&
96
+ item.getAttribute("name").toLowerCase().indexOf(term) !== -1
97
+ ) {
98
+ item.classList.add("highlight")
99
+ item.classList.remove("no-match")
100
+ results.push(item)
101
+ } else {
102
+ item.classList.add("no-match")
103
+ item.classList.remove("highlight")
104
+ }
105
+ })
106
+ this.filter_field_clear.style.display = "inline-block"
107
+ const { length } = results
108
+
109
+ if (length === 1) {
110
+ this.display.style.display = "block"
111
+ this.display.innerText = `1 ${Alchemy.t("page_found")}`
112
+ results[0].scrollIntoView({ behavior: "smooth", block: "center" })
113
+ } else if (length > 1) {
114
+ this.display.style.display = "block"
115
+ this.display.innerText = `${length} ${Alchemy.t("pages_found")}`
116
+ } else {
117
+ this.items.forEach((item) =>
118
+ item.classList.remove("no-match", "highlight")
119
+ )
120
+ this.display.style.display = "none"
121
+ window.scrollTo({
122
+ top: 0,
123
+ left: 0,
124
+ behavior: "smooth"
125
+ })
126
+ this.filter_field_clear.style.display = "none"
127
+ }
128
+ }
129
+
130
+ // Adds onkey up observer to search field
131
+ _observe() {
132
+ this.search_field.addEventListener("keyup", (evt) => {
133
+ const term = evt.target.value
134
+ this.filter(term.toLowerCase())
135
+ })
136
+ this.search_field.addEventListener("focus", () => key.setScope("search"))
137
+ this.filter_field_clear.addEventListener("click", () => {
138
+ this.search_field.value = ""
139
+ this.filter("")
140
+ return false
141
+ })
142
+ }
143
+
144
+ errorHandler(error) {
145
+ Alchemy.growl(error.message || error, "error")
146
+ console.error(error)
147
+ }
148
+ }
@@ -1,5 +1,5 @@
1
1
  import xhrMock from "xhr-mock"
2
- import ajax from "../ajax"
2
+ import { get, patch, post } from "../ajax"
3
3
 
4
4
  const token = "s3cr3t"
5
5
 
@@ -8,13 +8,13 @@ beforeEach(() => {
8
8
  xhrMock.setup()
9
9
  })
10
10
 
11
- describe("ajax('get')", () => {
11
+ describe("get", () => {
12
12
  it("sends X-CSRF-TOKEN header", async () => {
13
13
  xhrMock.get("/users", (req, res) => {
14
14
  expect(req.header("X-CSRF-TOKEN")).toEqual(token)
15
15
  return res.status(200).body('{"message":"Ok"}')
16
16
  })
17
- await ajax("get", "/users")
17
+ await get("/users")
18
18
  })
19
19
 
20
20
  it("sends Content-Type header", async () => {
@@ -24,7 +24,7 @@ describe("ajax('get')", () => {
24
24
  )
25
25
  return res.status(200).body('{"message":"Ok"}')
26
26
  })
27
- await ajax("get", "/users")
27
+ await get("/users")
28
28
  })
29
29
 
30
30
  it("sends Accept header", async () => {
@@ -32,14 +32,14 @@ describe("ajax('get')", () => {
32
32
  expect(req.header("Accept")).toEqual("application/json")
33
33
  return res.status(200).body('{"message":"Ok"}')
34
34
  })
35
- await ajax("get", "/users")
35
+ await get("/users")
36
36
  })
37
37
 
38
38
  it("returns JSON", async () => {
39
39
  xhrMock.get("/users", (_req, res) => {
40
40
  return res.status(200).body('{"email":"mail@example.com"}')
41
41
  })
42
- await ajax("get", "/users").then((res) => {
42
+ await get("/users").then((res) => {
43
43
  expect(res.data).toEqual({ email: "mail@example.com" })
44
44
  })
45
45
  })
@@ -49,7 +49,7 @@ describe("ajax('get')", () => {
49
49
  return res.status(200).body('email => "mail@example.com"')
50
50
  })
51
51
  expect.assertions(1)
52
- await ajax("get", "/users").catch((e) => {
52
+ await get("/users").catch((e) => {
53
53
  expect(e.message).toMatch("Unexpected token")
54
54
  })
55
55
  })
@@ -59,7 +59,7 @@ describe("ajax('get')", () => {
59
59
  return Promise.reject(new Error())
60
60
  })
61
61
  expect.assertions(1)
62
- await ajax("get", "/users").catch((e) => {
62
+ await get("/users").catch((e) => {
63
63
  expect(e.message).toEqual("An error occurred during the transaction")
64
64
  })
65
65
  })
@@ -69,7 +69,7 @@ describe("ajax('get')", () => {
69
69
  return res.status(401).body('{"error":"Unauthorized"}')
70
70
  })
71
71
  expect.assertions(1)
72
- await ajax("get", "/users").catch((e) => {
72
+ await get("/users").catch((e) => {
73
73
  expect(e.error).toEqual("Unauthorized")
74
74
  })
75
75
  })
@@ -79,19 +79,19 @@ describe("ajax('get')", () => {
79
79
  return res.status(401).body("Unauthorized")
80
80
  })
81
81
  expect.assertions(1)
82
- await ajax("get", "/users").catch((e) => {
82
+ await get("/users").catch((e) => {
83
83
  expect(e.message).toMatch("Unexpected token")
84
84
  })
85
85
  })
86
86
  })
87
87
 
88
- describe("ajax('post')", () => {
88
+ describe("patch", () => {
89
89
  it("sends X-CSRF-TOKEN header", async () => {
90
90
  xhrMock.post("/users", (req, res) => {
91
91
  expect(req.header("X-CSRF-TOKEN")).toEqual(token)
92
92
  return res.status(200).body('{"message":"Ok"}')
93
93
  })
94
- await ajax("post", "/users")
94
+ await patch("/users")
95
95
  })
96
96
 
97
97
  it("sends Content-Type header", async () => {
@@ -101,7 +101,7 @@ describe("ajax('post')", () => {
101
101
  )
102
102
  return res.status(200).body('{"message":"Ok"}')
103
103
  })
104
- await ajax("post", "/users")
104
+ await patch("/users")
105
105
  })
106
106
 
107
107
  it("sends Accept header", async () => {
@@ -109,7 +109,53 @@ describe("ajax('post')", () => {
109
109
  expect(req.header("Accept")).toEqual("application/json")
110
110
  return res.status(200).body('{"message":"Ok"}')
111
111
  })
112
- await ajax("post", "/users")
112
+ await patch("/users")
113
+ })
114
+
115
+ it("sends method override data", async () => {
116
+ xhrMock.post("/users", (req, res) => {
117
+ expect(req.body()).toEqual('{"_method":"patch"}')
118
+ return res.status(200).body('{"message":"Ok"}')
119
+ })
120
+ await patch("/users")
121
+ })
122
+
123
+ it("sends JSON data", async () => {
124
+ xhrMock.post("/users", (req, res) => {
125
+ expect(req.body()).toEqual(
126
+ '{"email":"mail@example.com","_method":"patch"}'
127
+ )
128
+ return res.status(200).body('{"message":"Ok"}')
129
+ })
130
+ await patch("/users", { email: "mail@example.com" })
131
+ })
132
+ })
133
+
134
+ describe("post", () => {
135
+ it("sends X-CSRF-TOKEN header", async () => {
136
+ xhrMock.post("/users", (req, res) => {
137
+ expect(req.header("X-CSRF-TOKEN")).toEqual(token)
138
+ return res.status(200).body('{"message":"Ok"}')
139
+ })
140
+ await post("/users")
141
+ })
142
+
143
+ it("sends Content-Type header", async () => {
144
+ xhrMock.post("/users", (req, res) => {
145
+ expect(req.header("Content-Type")).toEqual(
146
+ "application/json; charset=utf-8"
147
+ )
148
+ return res.status(200).body('{"message":"Ok"}')
149
+ })
150
+ await post("/users")
151
+ })
152
+
153
+ it("sends Accept header", async () => {
154
+ xhrMock.post("/users", (req, res) => {
155
+ expect(req.header("Accept")).toEqual("application/json")
156
+ return res.status(200).body('{"message":"Ok"}')
157
+ })
158
+ await post("/users")
113
159
  })
114
160
 
115
161
  it("sends JSON data", async () => {
@@ -117,7 +163,7 @@ describe("ajax('post')", () => {
117
163
  expect(req.body()).toEqual('{"email":"mail@example.com"}')
118
164
  return res.status(200).body('{"message":"Ok"}')
119
165
  })
120
- await ajax("post", "/users", { email: "mail@example.com" })
166
+ await post("/users", { email: "mail@example.com" })
121
167
  })
122
168
  })
123
169
 
@@ -29,6 +29,18 @@ function getToken() {
29
29
  return metaTag.attributes.content.textContent
30
30
  }
31
31
 
32
+ export function get(url, params) {
33
+ return ajax("GET", url, params)
34
+ }
35
+
36
+ export function patch(url, data = {}) {
37
+ return ajax("POST", url, { ...data, _method: "patch" })
38
+ }
39
+
40
+ export function post(url, data) {
41
+ return ajax("POST", url, data)
42
+ }
43
+
32
44
  export default function ajax(method, url, data) {
33
45
  const xhr = new XMLHttpRequest()
34
46
  const promise = buildPromise(xhr)
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alchemy_cms/admin",
3
- "version": "5.2.7",
3
+ "version": "5.3.2",
4
4
  "description": "AlchemyCMS",
5
5
  "browser": "package/admin.js",
6
6
  "files": [
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.2.7
4
+ version: 5.3.2
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-01 00:00:00.000000000 Z
16
+ date: 2022-03-24 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: active_model_serializers
@@ -270,7 +270,7 @@ dependencies:
270
270
  version: '1.8'
271
271
  - - "<"
272
272
  - !ruby/object:Gem::Version
273
- version: 2.4.2
273
+ version: '3.0'
274
274
  type: :runtime
275
275
  prerelease: false
276
276
  version_requirements: !ruby/object:Gem::Requirement
@@ -280,7 +280,7 @@ dependencies:
280
280
  version: '1.8'
281
281
  - - "<"
282
282
  - !ruby/object:Gem::Version
283
- version: 2.4.2
283
+ version: '3.0'
284
284
  - !ruby/object:Gem::Dependency
285
285
  name: request_store
286
286
  requirement: !ruby/object:Gem::Requirement
@@ -590,6 +590,7 @@ files:
590
590
  - ".hound.yml"
591
591
  - ".localeapp/config.rb"
592
592
  - ".prettierrc"
593
+ - ".rspec"
593
594
  - ".rubocop.yml"
594
595
  - ".yardopts"
595
596
  - CHANGELOG.md
@@ -632,10 +633,8 @@ files:
632
633
  - app/assets/javascripts/alchemy/alchemy.initializer.js.coffee
633
634
  - app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee
634
635
  - app/assets/javascripts/alchemy/alchemy.list_filter.js.coffee
635
- - app/assets/javascripts/alchemy/alchemy.page_sorter.js
636
636
  - app/assets/javascripts/alchemy/alchemy.preview.js.coffee
637
637
  - app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee
638
- - app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee
639
638
  - app/assets/javascripts/alchemy/alchemy.spinner.js
640
639
  - app/assets/javascripts/alchemy/alchemy.string_extension.js.coffee
641
640
  - app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee
@@ -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
@@ -1189,6 +1187,9 @@ files:
1189
1187
  - package/src/__tests__/i18n.spec.js
1190
1188
  - package/src/i18n.js
1191
1189
  - package/src/node_tree.js
1190
+ - package/src/page_publication_fields.js
1191
+ - package/src/page_sorter.js
1192
+ - package/src/sitemap.js
1192
1193
  - package/src/translations.js
1193
1194
  - package/src/utils/__tests__/ajax.spec.js
1194
1195
  - package/src/utils/__tests__/events.spec.js
@@ -1213,7 +1214,6 @@ files:
1213
1214
  - vendor/assets/javascripts/flatpickr/flatpickr.min.js
1214
1215
  - vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js
1215
1216
  - vendor/assets/javascripts/jquery_plugins/jquery.scrollTo.min.js
1216
- - vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js
1217
1217
  - vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js
1218
1218
  - vendor/assets/javascripts/jquery_plugins/select2.js
1219
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,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
@@ -1,2 +0,0 @@
1
- $('#fold_button_<%= @page.id %>').css('background', 'none');
2
- Alchemy.Sitemap.fetch(<%= @page.id %>);
@@ -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 %>