alchemy_cms 4.3.2 → 4.4.0

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.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +92 -0
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +59 -2
  5. data/Gemfile +6 -5
  6. data/README.md +7 -6
  7. data/alchemy_cms.gemspec +4 -2
  8. data/app/assets/config/alchemy_manifest.js +15 -0
  9. data/app/assets/javascripts/alchemy/admin.js +1 -0
  10. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +1 -13
  11. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +1 -1
  12. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +84 -87
  13. data/app/assets/javascripts/alchemy/alchemy.preview.js.coffee +0 -4
  14. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +1 -1
  15. data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee +2 -2
  16. data/app/assets/javascripts/alchemy/page_select.js +41 -0
  17. data/app/assets/javascripts/alchemy/templates/index.js +1 -0
  18. data/app/assets/javascripts/alchemy/templates/page.hbs +9 -0
  19. data/app/assets/stylesheets/alchemy/_mixins.scss +11 -1
  20. data/app/assets/stylesheets/alchemy/admin.scss +3 -0
  21. data/app/assets/stylesheets/alchemy/elements.scss +1 -0
  22. data/app/assets/stylesheets/alchemy/forms.scss +6 -5
  23. data/app/assets/stylesheets/alchemy/labels.scss +6 -0
  24. data/app/assets/stylesheets/alchemy/nodes.scss +154 -0
  25. data/app/assets/stylesheets/alchemy/page-select.scss +30 -0
  26. data/app/assets/stylesheets/alchemy/selects.scss +39 -22
  27. data/app/assets/stylesheets/alchemy/sitemap.scss +0 -33
  28. data/app/assets/stylesheets/alchemy/tags.scss +0 -3
  29. data/app/controllers/alchemy/admin/base_controller.rb +1 -0
  30. data/app/controllers/alchemy/admin/elements_controller.rb +24 -11
  31. data/app/controllers/alchemy/admin/languages_controller.rb +5 -0
  32. data/app/controllers/alchemy/admin/nodes_controller.rb +43 -0
  33. data/app/controllers/alchemy/admin/pages_controller.rb +1 -21
  34. data/app/controllers/alchemy/admin/resources_controller.rb +1 -1
  35. data/app/controllers/alchemy/admin/tags_controller.rb +1 -2
  36. data/app/controllers/alchemy/api/contents_controller.rb +17 -2
  37. data/app/controllers/alchemy/api/elements_controller.rb +26 -1
  38. data/app/controllers/alchemy/api/pages_controller.rb +78 -7
  39. data/app/controllers/alchemy/messages_controller.rb +23 -8
  40. data/app/helpers/alchemy/admin/contents_helper.rb +1 -1
  41. data/app/helpers/alchemy/admin/elements_helper.rb +6 -0
  42. data/app/helpers/alchemy/admin/essences_helper.rb +23 -4
  43. data/app/helpers/alchemy/elements_block_helper.rb +11 -3
  44. data/app/helpers/alchemy/elements_helper.rb +3 -3
  45. data/app/helpers/alchemy/essences_helper.rb +36 -9
  46. data/app/helpers/alchemy/pages_helper.rb +29 -0
  47. data/app/models/alchemy/content.rb +1 -1
  48. data/app/models/alchemy/element.rb +20 -8
  49. data/app/models/alchemy/element/element_contents.rb +6 -4
  50. data/app/models/alchemy/element/presenters.rb +2 -2
  51. data/app/models/alchemy/essence_page.rb +29 -0
  52. data/app/models/alchemy/essence_picture.rb +8 -3
  53. data/app/models/alchemy/language.rb +10 -2
  54. data/app/models/alchemy/node.rb +48 -0
  55. data/app/models/alchemy/page.rb +74 -3
  56. data/app/models/alchemy/page/page_elements.rb +12 -4
  57. data/app/models/alchemy/page/page_natures.rb +6 -0
  58. data/app/models/alchemy/page/page_scopes.rb +1 -1
  59. data/app/models/alchemy/picture.rb +5 -1
  60. data/app/models/concerns/alchemy/content_touching.rb +1 -1
  61. data/app/serializers/alchemy/element_serializer.rb +7 -1
  62. data/app/serializers/alchemy/page_serializer.rb +0 -4
  63. data/app/views/alchemy/_menubar.html.erb +1 -1
  64. data/app/views/alchemy/admin/elements/_element.html.erb +18 -2
  65. data/app/views/alchemy/admin/leave.html.erb +1 -1
  66. data/app/views/alchemy/admin/nodes/_form.html.erb +39 -0
  67. data/app/views/alchemy/admin/nodes/_node.html.erb +87 -0
  68. data/app/views/alchemy/admin/nodes/edit.html.erb +1 -0
  69. data/app/views/alchemy/admin/nodes/index.html.erb +58 -0
  70. data/app/views/alchemy/admin/nodes/new.html.erb +1 -0
  71. data/app/views/alchemy/admin/pages/_anchor_link.html.erb +22 -0
  72. data/app/views/alchemy/admin/pages/_form.html.erb +1 -1
  73. data/app/views/alchemy/admin/pages/_internal_link.html.erb +7 -11
  74. data/app/views/alchemy/admin/pages/_menu_fields.html.erb +33 -0
  75. data/app/views/alchemy/admin/pages/_sitemap.html.erb +0 -7
  76. data/app/views/alchemy/admin/pages/link.html.erb +4 -0
  77. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +7 -3
  78. data/app/views/alchemy/admin/partials/_routes.html.erb +3 -3
  79. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +1 -0
  80. data/app/views/alchemy/essences/_essence_date_view.html.erb +1 -0
  81. data/app/views/alchemy/essences/_essence_file_view.html.erb +1 -0
  82. data/app/views/alchemy/essences/_essence_html_view.html.erb +1 -0
  83. data/app/views/alchemy/essences/_essence_link_view.html.erb +1 -0
  84. data/app/views/alchemy/essences/_essence_page_editor.html.erb +23 -0
  85. data/app/views/alchemy/essences/_essence_page_view.html.erb +5 -0
  86. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +2 -0
  87. data/app/views/alchemy/essences/_essence_picture_view.html.erb +1 -0
  88. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +1 -0
  89. data/app/views/alchemy/essences/_essence_select_editor.html.erb +1 -0
  90. data/app/views/alchemy/essences/_essence_select_view.html.erb +1 -0
  91. data/app/views/alchemy/essences/_essence_text_editor.html.erb +3 -0
  92. data/app/views/alchemy/essences/_essence_text_view.html.erb +1 -0
  93. data/config/alchemy/modules.yml +13 -4
  94. data/config/initializers/assets.rb +1 -13
  95. data/config/locales/alchemy.en.yml +27 -9
  96. data/config/routes.rb +11 -3
  97. data/db/migrate/20191016073858_create_alchemy_essence_pages.rb +8 -0
  98. data/db/migrate/20191029212236_create_alchemy_nodes.rb +24 -0
  99. data/lib/alchemy/admin/locale.rb +1 -1
  100. data/lib/alchemy/auth_accessors.rb +8 -2
  101. data/lib/alchemy/cache_digests/template_tracker.rb +8 -5
  102. data/lib/alchemy/elements_finder.rb +17 -14
  103. data/lib/alchemy/engine.rb +4 -0
  104. data/lib/alchemy/essence.rb +40 -2
  105. data/lib/alchemy/permissions.rb +2 -0
  106. data/lib/alchemy/tasks/tidy.rb +1 -1
  107. data/lib/alchemy/test_support/essence_shared_examples.rb +25 -8
  108. data/lib/alchemy/test_support/factories/essence_page_factory.rb +10 -0
  109. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +5 -0
  110. data/lib/alchemy/test_support/factories/node_factory.rb +21 -0
  111. data/lib/alchemy/version.rb +1 -1
  112. data/lib/rails/generators/alchemy/elements/elements_generator.rb +0 -1
  113. data/lib/rails/generators/alchemy/elements/templates/view.html.erb +3 -3
  114. data/lib/rails/generators/alchemy/elements/templates/view.html.haml +3 -3
  115. data/lib/rails/generators/alchemy/elements/templates/view.html.slim +3 -3
  116. data/lib/rails/generators/alchemy/install/files/{_article_view.html.erb → _article.html.erb} +2 -2
  117. data/lib/rails/generators/alchemy/install/files/application.html.erb +13 -10
  118. data/lib/rails/generators/alchemy/install/install_generator.rb +2 -11
  119. data/lib/rails/generators/alchemy/menus/menus_generator.rb +24 -0
  120. data/lib/rails/generators/alchemy/menus/templates/node.html.erb +19 -0
  121. data/lib/rails/generators/alchemy/menus/templates/node.html.haml +16 -0
  122. data/lib/rails/generators/alchemy/menus/templates/node.html.slim +16 -0
  123. data/lib/rails/generators/alchemy/menus/templates/wrapper.html.erb +8 -0
  124. data/lib/rails/generators/alchemy/menus/templates/wrapper.html.haml +6 -0
  125. data/lib/rails/generators/alchemy/menus/templates/wrapper.html.slim +6 -0
  126. data/lib/rails/generators/alchemy/views/views_generator.rb +1 -1
  127. data/lib/tasks/alchemy/convert.rake +60 -0
  128. metadata +79 -20
  129. data/.rspec +0 -1
  130. data/.travis.yml +0 -28
  131. data/app/models/alchemy/page/page_users.rb +0 -60
  132. data/app/views/alchemy/admin/elements/list.html.erb +0 -16
  133. data/app/views/alchemy/admin/pages/_page_for_links.html.erb +0 -53
  134. data/lib/rails/generators/alchemy/elements/templates/editor.html.erb +0 -9
  135. data/lib/rails/generators/alchemy/elements/templates/editor.html.haml +0 -8
  136. data/lib/rails/generators/alchemy/elements/templates/editor.html.slim +0 -8
  137. data/lib/rails/generators/alchemy/install/files/_article_editor.html.erb +0 -5
  138. data/lib/rails/generators/alchemy/install/files/alchemy.de.yml +0 -31
  139. data/lib/rails/generators/alchemy/install/files/alchemy.es.yml +0 -31
@@ -1,5 +1,3 @@
1
- #= require alchemy/alchemy.i18n
2
-
3
1
  window.Alchemy = Alchemy || {}
4
2
 
5
3
  Alchemy.initAlchemyPreviewMode = ->
@@ -30,12 +28,10 @@ Alchemy.initAlchemyPreviewMode = ->
30
28
  @elements = document.querySelectorAll("[data-alchemy-element]")
31
29
  @elements.forEach (element) =>
32
30
  element.addEventListener 'mouseover', =>
33
- element.setAttribute('title', Alchemy.t('click_to_edit'))
34
31
  unless element.classList.contains('selected')
35
32
  Object.assign element.style, @getStyle('hover')
36
33
  return
37
34
  element.addEventListener 'mouseout', =>
38
- element.removeAttribute('title')
39
35
  unless element.classList.contains('selected')
40
36
  Object.assign element.style, @getStyle('reset')
41
37
  return
@@ -55,7 +55,7 @@ Alchemy.Sitemap =
55
55
  self.options.ready()
56
56
 
57
57
  request.fail (jqXHR, status) ->
58
- Alchemy.debug("Request failed: " + status)
58
+ console.warn("Request failed: " + status)
59
59
 
60
60
  # Filters the sitemap
61
61
  filter: (term) ->
@@ -51,7 +51,7 @@ $.extend Alchemy.Tinymce,
51
51
  # remove editor instance, if already initialized
52
52
  editor.remove() if editor
53
53
  if textarea.length == 0
54
- Alchemy.log_error "Could not initialize TinyMCE for textarea#tinymce_#{id}!"
54
+ console.warn "Could not initialize TinyMCE for textarea#tinymce_#{id}!"
55
55
  return
56
56
  config = @getConfig(id, textarea[0].classList[1])
57
57
  if config
@@ -59,7 +59,7 @@ $.extend Alchemy.Tinymce,
59
59
  textarea.closest('.tinymce_container').prepend spinner.spin().el
60
60
  tinymce.init(config)
61
61
  else
62
- Alchemy.debug('No tinymce configuration found for', id)
62
+ console.warn('No tinymce configuration found for', id)
63
63
 
64
64
  # Gets called after an editor instance gets intialized
65
65
  #
@@ -0,0 +1,41 @@
1
+ $.fn.alchemyPageSelect = function(options) {
2
+ var pageTemplate = HandlebarsTemplates.page
3
+
4
+ return this.select2({
5
+ placeholder: options.placeholder,
6
+ allowClear: true,
7
+ minimumInputLength: 3,
8
+ initSelection: function (_$el, callback) {
9
+ if (options.initialSelection) {
10
+ callback(options.initialSelection)
11
+ }
12
+ },
13
+ ajax: {
14
+ url: options.url,
15
+ datatype: 'json',
16
+ quietMillis: 300,
17
+ data: function (term, page) {
18
+ return {
19
+ q: $.extend({
20
+ name_cont: term
21
+ }, options.query_params),
22
+ page: page
23
+ }
24
+ },
25
+ results: function (data) {
26
+ var meta = data.meta
27
+
28
+ return {
29
+ results: data.pages,
30
+ more: meta.page * meta.per_page < meta.total_count
31
+ }
32
+ }
33
+ },
34
+ formatSelection: function (page) {
35
+ return page.text || page.name
36
+ },
37
+ formatResult: function(page) {
38
+ return pageTemplate({page: page})
39
+ }
40
+ })
41
+ }
@@ -1 +1,2 @@
1
1
  //= require alchemy/templates/spinner
2
+ //= require alchemy/templates/page
@@ -0,0 +1,9 @@
1
+ <div class="page-select--page">
2
+ <i class="icon far fa-file fa-lg"></i>
3
+ <span class="page-select--page-name">
4
+ {{ page.name }}
5
+ </span>
6
+ <span class="page-select--page-urlname">
7
+ /{{ page.urlname }}
8
+ </span>
9
+ </div>
@@ -136,13 +136,23 @@
136
136
  box-shadow: $shadow;
137
137
  }
138
138
 
139
- @mixin tag-base($margin: 2*$default-margin 0, $padding: $default-padding 3*$default-padding) {
139
+ @mixin label-base($margin: 2*$default-margin 0, $padding: $default-padding 3*$default-padding) {
140
+ display: inline-block;
141
+ vertical-align: middle;
140
142
  padding: $padding;
141
143
  margin: $margin;
142
144
  background-color: $medium-gray;
143
145
  overflow: hidden;
144
146
  position: relative;
145
147
  border-radius: $default-border-radius;
148
+ color: $text-color;
149
+ }
150
+
151
+ @mixin tag-base($margin: 2*$default-margin 0, $padding: $default-padding 3*$default-padding) {
152
+ @include label-base(
153
+ $margin: $margin,
154
+ $padding: $padding
155
+ );
146
156
 
147
157
  &:before {
148
158
  content: fa-content($fa-var-tag);
@@ -29,7 +29,10 @@
29
29
  @import "alchemy/hints";
30
30
  @import "alchemy/icons";
31
31
  @import "alchemy/image_library";
32
+ @import "alchemy/labels";
33
+ @import "alchemy/nodes";
32
34
  @import "alchemy/notices";
35
+ @import "alchemy/page-select";
33
36
  @import "alchemy/pagination";
34
37
  @import "alchemy/preview_window";
35
38
  @import "alchemy/resource_info";
@@ -266,6 +266,7 @@
266
266
  }
267
267
 
268
268
  .message {
269
+ width: 100%;
269
270
  margin: 2*$default-margin 0;
270
271
  }
271
272
 
@@ -38,6 +38,10 @@ form {
38
38
  float: right;
39
39
  }
40
40
 
41
+ .input > .select2-container {
42
+ width: 100%;
43
+ }
44
+
41
45
  > .autocomplete_tag_list {
42
46
 
43
47
  .select2-container, .select2-choices {
@@ -49,11 +53,8 @@ form {
49
53
  line-height: 16px;
50
54
  }
51
55
 
52
- &.select, &.grouped_select {
53
-
54
- .select2-container {
55
- margin: 4px 0;
56
- }
56
+ .select2-container {
57
+ margin: 4px 0;
57
58
  }
58
59
 
59
60
  &.boolean {
@@ -0,0 +1,6 @@
1
+ .label {
2
+ @include label-base(
3
+ $margin: $default-margin/2 0,
4
+ $padding: $default-padding 2*$default-padding $default-padding
5
+ );
6
+ }
@@ -0,0 +1,154 @@
1
+ .nodes_tree.list {
2
+ margin: 2em 0;
3
+
4
+ &.sorting {
5
+ padding-top: 100px;
6
+
7
+ .page_icon {
8
+ cursor: move
9
+ }
10
+ }
11
+
12
+ .sitemap_node-level_0 {
13
+
14
+ > .node_name {
15
+ font-weight: bold;
16
+ }
17
+ }
18
+
19
+ .node_page,
20
+ .node_url {
21
+ width: 200px;
22
+ max-width: 45%;
23
+ white-space: nowrap;
24
+ text-overflow: ellipsis;
25
+ overflow: hidden;
26
+
27
+ > a {
28
+ overflow: hidden;
29
+ text-overflow: ellipsis;
30
+ max-width: 100%;
31
+
32
+ .external & {
33
+ max-width: 90%;
34
+ }
35
+ }
36
+ }
37
+
38
+ .node_page {
39
+ padding: 0 8px;
40
+ margin-left: auto;
41
+ }
42
+
43
+ .node_url {
44
+ display: flex;
45
+ align-items: center;
46
+ padding: 0 2*$default-padding;
47
+ white-space: nowrap;
48
+ background-color: $sitemap-info-background-color;
49
+ line-height: $sitemap-line-height;
50
+ font-size: $small-font-size;
51
+ @include border-right-radius($default-border-radius);
52
+
53
+ > i {
54
+ margin-left: auto;
55
+ padding-left: $default-padding;
56
+ }
57
+ }
58
+
59
+ .node_folder {
60
+ cursor: pointer;
61
+ }
62
+
63
+ ul {
64
+ margin: 0;
65
+ padding: 0;
66
+ }
67
+
68
+ li {
69
+ line-height: $sitemap-line-height;
70
+ padding-left: $default-padding;
71
+
72
+ li {
73
+ padding-left: $sitemap-line-height;
74
+ }
75
+ }
76
+ }
77
+
78
+ #node_filter_result {
79
+ display: none;
80
+ margin-left: 2*$default-margin;
81
+ }
82
+
83
+ .sitemap_node {
84
+ margin: 3*$default-margin 0;
85
+ transition: background-color $transition-duration;
86
+
87
+ &.highlight {
88
+ background-color: $sitemap-highlight-color;
89
+ }
90
+
91
+ &.no-match .sitemap_pagename_link {
92
+ color: $medium-gray;
93
+ }
94
+
95
+ &:hover {
96
+ background-color: $sitemap-page-hover-color;
97
+ border-radius: $default-border-radius;
98
+ }
99
+
100
+ .node_name {
101
+ display: flex;
102
+ justify-content: space-between;
103
+ @include border-left-radius($default-border-radius);
104
+ padding: 0 0 0 10px;
105
+ margin: 2px;
106
+ text-decoration: none;
107
+ overflow: hidden;
108
+ background-color: $sitemap-page-background-color;
109
+
110
+ &.without-status {
111
+ @include border-right-radius($default-border-radius);
112
+ }
113
+
114
+ &.inactive {
115
+ color: #656565;
116
+ }
117
+ }
118
+ }
119
+
120
+ .nodes_tree-left_images {
121
+ position: relative;
122
+ width: 32px;
123
+ line-height: $sitemap-line-height;
124
+ float: left;
125
+ padding: 0 2*$default-padding;
126
+ text-align: center;
127
+ }
128
+
129
+ .nodes_tree-right_tools {
130
+ height: $sitemap-line-height;
131
+ padding: 0 2*$default-padding;
132
+ float: right;
133
+
134
+ > a {
135
+ float: left;
136
+ width: $sitemap-line-height;
137
+ height: $sitemap-line-height;
138
+ line-height: $sitemap-line-height;
139
+ text-align: center;
140
+ margin: 0;
141
+
142
+ &.disabled .icon {
143
+ opacity: 0.25;
144
+ filter: grayscale(100%);
145
+ }
146
+ }
147
+
148
+ .icon.blank {
149
+ margin-left: 2px;
150
+ float: left;
151
+ margin-top: 3px;
152
+ margin-right: 3px;
153
+ }
154
+ }
@@ -0,0 +1,30 @@
1
+ .page-select--page,
2
+ .page-select--page-urlname {
3
+ text-overflow: ellipsis;
4
+ overflow: hidden;
5
+ white-space: nowrap;
6
+ }
7
+
8
+ .page-select--page {
9
+ display: flex;
10
+ align-items: center;
11
+
12
+ .icon {
13
+ margin: 0 8px 0 4px;
14
+
15
+ .select2-highlighted & {
16
+ color: $white
17
+ }
18
+ }
19
+ }
20
+
21
+ .page-select--page-urlname {
22
+ margin-left: auto;
23
+ padding: $default-padding 2*$default-padding;
24
+ color: $dark-gray;
25
+ font-size: $small-font-size;
26
+
27
+ .select2-highlighted & {
28
+ color: $white
29
+ }
30
+ }
@@ -40,6 +40,10 @@ select {
40
40
  font-weight: normal;
41
41
  text-align: left;
42
42
 
43
+ .select2-chosen {
44
+ overflow: visible;
45
+ }
46
+
43
47
  .select2-arrow {
44
48
  top: 0;
45
49
  width: $form-field-height;
@@ -61,6 +65,11 @@ select {
61
65
  }
62
66
  }
63
67
  }
68
+
69
+ .select2-search-choice-close {
70
+ top: 9px;
71
+ right: 28px;
72
+ }
64
73
  }
65
74
 
66
75
  &.medium {
@@ -103,6 +112,30 @@ select {
103
112
  }
104
113
  }
105
114
 
115
+ &.select2-container-multi,
116
+ &.select2-allowclear {
117
+ .select2-search-choice-close {
118
+ @extend .fas;
119
+ @extend .fa-fw;
120
+ left: auto;
121
+ right: 5px;
122
+ top: 5px;
123
+ background: none;
124
+ font-size: $small-font-size;
125
+ text-decoration: none;
126
+
127
+ &:before {
128
+ @extend .fa-xs;
129
+ content: fa-content($fa-var-times);
130
+ opacity: $addon-icon-opacity;
131
+ }
132
+
133
+ &:hover {
134
+ color: $text-color;
135
+ }
136
+ }
137
+ }
138
+
106
139
  &.select2-container-multi {
107
140
  margin-top: 0 !important;
108
141
 
@@ -127,27 +160,6 @@ select {
127
160
  color: $text-color;
128
161
  }
129
162
 
130
- .select2-search-choice-close {
131
- @extend .fas;
132
- @extend .fa-fw;
133
- left: auto;
134
- right: 5px;
135
- top: 5px;
136
- background: none;
137
- font-size: $small-font-size;
138
- text-decoration: none;
139
-
140
- &:before {
141
- @extend .fa-xs;
142
- content: fa-content($fa-var-times);
143
- opacity: $addon-icon-opacity;
144
- }
145
-
146
- &:hover {
147
- color: $text-color;
148
- }
149
- }
150
-
151
163
  .select2-search-field {
152
164
  height: 29px;
153
165
 
@@ -162,7 +174,6 @@ select {
162
174
  }
163
175
 
164
176
  .select2-drop {
165
-
166
177
  .select2-search {
167
178
  margin: $default-margin 0;
168
179
 
@@ -219,6 +230,12 @@ select {
219
230
  border-radius: $default-border-radius;
220
231
  border: $default-border;
221
232
  }
233
+
234
+ .select2-more-results,
235
+ .select2-ajax-error {
236
+ padding: 2*$default-padding;
237
+ margin-bottom: 0;
238
+ }
222
239
  }
223
240
 
224
241
  .window_form, #filter_bar {