alchemy_cms 8.2.7 → 8.3.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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -1
  3. data/app/assets/builds/alchemy/admin.css +1 -1
  4. data/app/assets/builds/alchemy/alchemy_admin.min.js +1 -1
  5. data/app/assets/builds/alchemy/alchemy_admin.min.js.map +1 -1
  6. data/app/assets/builds/alchemy/dark-theme.css +1 -1
  7. data/app/assets/builds/alchemy/light-theme.css +1 -1
  8. data/app/assets/builds/alchemy/preview.min.js +1 -1
  9. data/app/assets/builds/alchemy/theme.css +1 -1
  10. data/app/assets/builds/alchemy/welcome.css +1 -1
  11. data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css +1 -1
  12. data/app/assets/builds/tinymce/skins/content/alchemy-dark/content.min.css +1 -1
  13. data/app/assets/builds/tinymce/skins/ui/alchemy/skin.min.css +1 -1
  14. data/app/assets/builds/tinymce/skins/ui/alchemy-dark/skin.min.css +1 -1
  15. data/app/assets/images/alchemy/admin/logo.svg +27 -0
  16. data/app/assets/images/alchemy/icons-sprite.svg +1 -1
  17. data/app/components/alchemy/admin/dashboard/widget.rb +40 -0
  18. data/app/components/alchemy/admin/dashboard/widgets/attachment_counts.rb +17 -0
  19. data/app/components/alchemy/admin/dashboard/widgets/element_usage.rb +37 -0
  20. data/app/components/alchemy/admin/dashboard/widgets/greeting.html.erb +13 -0
  21. data/app/components/alchemy/admin/dashboard/widgets/greeting.rb +21 -0
  22. data/app/components/alchemy/admin/dashboard/widgets/locked_pages.html.erb +54 -0
  23. data/app/components/alchemy/admin/dashboard/widgets/locked_pages.rb +20 -0
  24. data/app/components/alchemy/admin/dashboard/widgets/online_users.html.erb +22 -0
  25. data/app/components/alchemy/admin/dashboard/widgets/online_users.rb +19 -0
  26. data/app/components/alchemy/admin/dashboard/widgets/page_counts.rb +23 -0
  27. data/app/components/alchemy/admin/dashboard/widgets/page_usage.rb +46 -0
  28. data/app/components/alchemy/admin/dashboard/widgets/picture_counts.rb +17 -0
  29. data/app/components/alchemy/admin/dashboard/widgets/recent_pages.html.erb +41 -0
  30. data/app/components/alchemy/admin/dashboard/widgets/recent_pages.rb +16 -0
  31. data/app/components/alchemy/admin/dashboard/widgets/sites.html.erb +29 -0
  32. data/app/components/alchemy/admin/dashboard/widgets/sites.rb +15 -0
  33. data/app/components/alchemy/admin/dashboard/widgets/stat_widget.html.erb +23 -0
  34. data/app/components/alchemy/admin/dashboard/widgets/stat_widget.rb +19 -0
  35. data/app/components/alchemy/admin/dashboard/widgets/system_info.html.erb +32 -0
  36. data/app/components/alchemy/admin/dashboard/widgets/system_info.rb +37 -0
  37. data/app/components/alchemy/admin/dashboard/widgets/usage_widget.html.erb +42 -0
  38. data/app/components/alchemy/admin/dashboard/widgets/usage_widget.rb +66 -0
  39. data/app/components/alchemy/admin/dashboard/widgets/user_counts.rb +25 -0
  40. data/app/components/alchemy/admin/element_editor.html.erb +27 -20
  41. data/app/components/alchemy/admin/element_schedule_timestamps.rb +33 -0
  42. data/app/components/alchemy/admin/element_select.rb +4 -3
  43. data/app/components/alchemy/admin/page_node.html.erb +1 -20
  44. data/app/components/alchemy/admin/page_publication_fields.html.erb +30 -0
  45. data/app/components/alchemy/admin/page_publication_fields.rb +18 -0
  46. data/app/components/alchemy/admin/page_status_indicators.html.erb +29 -0
  47. data/app/components/alchemy/admin/page_status_indicators.rb +9 -0
  48. data/app/components/alchemy/admin/publish_element_button.html.erb +12 -4
  49. data/app/components/alchemy/ingredients/headline_editor.rb +1 -1
  50. data/app/controllers/alchemy/admin/dashboard/widgets_controller.rb +21 -0
  51. data/app/controllers/alchemy/admin/dashboard_controller.rb +3 -12
  52. data/app/controllers/alchemy/pages_controller.rb +5 -4
  53. data/app/helpers/alchemy/elements_block_helper.rb +1 -0
  54. data/app/javascript/alchemy_admin/components/auto_submit.js +15 -9
  55. data/app/javascript/alchemy_admin/components/char_counter.js +17 -7
  56. data/app/javascript/alchemy_admin/components/clipboard_button.js +2 -6
  57. data/app/javascript/alchemy_admin/components/color_select.js +13 -4
  58. data/app/javascript/alchemy_admin/components/datepicker.js +11 -14
  59. data/app/javascript/alchemy_admin/components/dialog_link.js +5 -2
  60. data/app/javascript/alchemy_admin/components/element_editor/delete_element_button.js +6 -3
  61. data/app/javascript/alchemy_admin/components/element_editor.js +45 -28
  62. data/app/javascript/alchemy_admin/components/element_select.js +7 -4
  63. data/app/javascript/alchemy_admin/components/elements_window.js +38 -31
  64. data/app/javascript/alchemy_admin/components/elements_window_handle.js +7 -3
  65. data/app/javascript/alchemy_admin/components/file_editor.js +5 -2
  66. data/app/javascript/alchemy_admin/components/ingredient_group.js +6 -4
  67. data/app/javascript/alchemy_admin/components/link_buttons/link_button.js +1 -2
  68. data/app/javascript/alchemy_admin/components/link_buttons/unlink_button.js +1 -2
  69. data/app/javascript/alchemy_admin/components/link_buttons.js +6 -2
  70. data/app/javascript/alchemy_admin/components/list_filter.js +44 -29
  71. data/app/javascript/alchemy_admin/components/message.js +22 -15
  72. data/app/javascript/alchemy_admin/components/overlay.js +5 -7
  73. data/app/javascript/alchemy_admin/components/page_publication_fields.js +38 -25
  74. data/app/javascript/alchemy_admin/components/picture_description_select.js +5 -2
  75. data/app/javascript/alchemy_admin/components/picture_editor.js +5 -10
  76. data/app/javascript/alchemy_admin/components/picture_thumbnail.js +4 -5
  77. data/app/javascript/alchemy_admin/components/preview_window.js +5 -10
  78. data/app/javascript/alchemy_admin/components/publish_page_button.js +2 -5
  79. data/app/javascript/alchemy_admin/components/remote_select.js +53 -23
  80. data/app/javascript/alchemy_admin/components/select.js +169 -26
  81. data/app/javascript/alchemy_admin/components/sortable_elements.js +1 -1
  82. data/app/javascript/alchemy_admin/components/spinner.js +11 -11
  83. data/app/javascript/alchemy_admin/components/tags_autocomplete.js +9 -1
  84. data/app/javascript/alchemy_admin/components/tinymce.js +16 -22
  85. data/app/javascript/alchemy_admin/components/uploader/file_upload.js +48 -45
  86. data/app/javascript/alchemy_admin/components/uploader/progress.js +70 -84
  87. data/app/javascript/alchemy_admin/components/uploader.js +71 -46
  88. data/app/javascript/alchemy_admin/dialog.js +3 -0
  89. data/app/javascript/alchemy_admin/hotkeys.js +0 -18
  90. data/app/javascript/alchemy_admin/image_cropper.js +7 -9
  91. data/app/javascript/alchemy_admin/initializer.js +21 -0
  92. data/app/javascript/alchemy_admin/utils/dispatch_page_dirty_event.js +7 -0
  93. data/app/javascript/tinymce/plugins/alchemy_link/index.js +9 -0
  94. data/app/jobs/alchemy/base_job.rb +2 -2
  95. data/app/jobs/alchemy/invalidate_elements_cache_job.rb +33 -0
  96. data/app/models/alchemy/page/page_naming.rb +28 -5
  97. data/app/models/alchemy/page/page_natures.rb +7 -2
  98. data/app/models/alchemy/page/page_scopes.rb +2 -2
  99. data/app/models/alchemy/page/url_path.rb +7 -2
  100. data/app/models/alchemy/page.rb +2 -2
  101. data/app/models/alchemy/page_definition.rb +1 -0
  102. data/app/models/alchemy/permissions.rb +1 -1
  103. data/app/models/concerns/alchemy/relatable_resource.rb +8 -0
  104. data/app/services/alchemy/page_finder.rb +88 -0
  105. data/app/stylesheets/alchemy/_custom-properties.scss +6 -4
  106. data/app/stylesheets/alchemy/_mixins.scss +1 -7
  107. data/app/stylesheets/alchemy/_themes.scss +13 -1
  108. data/app/stylesheets/alchemy/admin/_tom-select.scss +240 -0
  109. data/app/stylesheets/alchemy/admin/archive.scss +0 -1
  110. data/app/stylesheets/alchemy/admin/base.scss +0 -19
  111. data/app/stylesheets/alchemy/admin/dashboard.scss +395 -28
  112. data/app/stylesheets/alchemy/admin/elements.scss +14 -17
  113. data/app/stylesheets/alchemy/admin/form_fields.scss +3 -3
  114. data/app/stylesheets/alchemy/admin/forms.scss +107 -93
  115. data/app/stylesheets/alchemy/admin/icons.scss +28 -0
  116. data/app/stylesheets/alchemy/admin/image_library.scss +20 -10
  117. data/app/stylesheets/alchemy/admin/navigation.scss +4 -1
  118. data/app/stylesheets/alchemy/admin/popover.scss +3 -5
  119. data/app/stylesheets/alchemy/admin/resource_info.scss +11 -17
  120. data/app/stylesheets/alchemy/admin/shoelace.scss +8 -0
  121. data/app/stylesheets/alchemy/admin/sitemap.scss +5 -0
  122. data/app/stylesheets/alchemy/admin/tables.scss +32 -3
  123. data/app/stylesheets/alchemy/admin/toolbar.scss +0 -1
  124. data/app/stylesheets/alchemy/admin.scss +1 -0
  125. data/app/stylesheets/tinymce/skins/ui/alchemy/skin.scss +0 -4
  126. data/app/stylesheets/tinymce/skins/ui/alchemy-dark/skin.scss +0 -4
  127. data/app/types/alchemy/wildcard_url_type.rb +48 -0
  128. data/app/views/alchemy/_menubar.html.erb +1 -5
  129. data/app/views/alchemy/admin/attachments/edit.html.erb +6 -3
  130. data/app/views/alchemy/admin/dashboard/_dashboard.html.erb +3 -2
  131. data/app/views/alchemy/admin/dashboard/_footer.html.erb +22 -0
  132. data/app/views/alchemy/admin/dashboard/_stats.html.erb +7 -0
  133. data/app/views/alchemy/admin/dashboard/_top.html.erb +4 -12
  134. data/app/views/alchemy/admin/dashboard/_widgets.html.erb +7 -0
  135. data/app/views/alchemy/admin/dashboard/index.html.erb +0 -17
  136. data/app/views/alchemy/admin/dashboard/info.html.erb +1 -62
  137. data/app/views/alchemy/admin/dashboard/widgets/show.html.erb +3 -0
  138. data/app/views/alchemy/admin/elements/_form.html.erb +2 -1
  139. data/app/views/alchemy/admin/elements/_schedule.html.erb +2 -15
  140. data/app/views/alchemy/admin/elements/_schedule_fields.html.erb +2 -0
  141. data/app/views/alchemy/admin/layoutpages/edit.html.erb +6 -3
  142. data/app/views/alchemy/admin/nodes/_page_nodes.html.erb +10 -8
  143. data/app/views/alchemy/admin/pages/_form.html.erb +25 -19
  144. data/app/views/alchemy/admin/pages/_publication_fields.html.erb +2 -32
  145. data/app/views/alchemy/admin/pages/_table.html.erb +1 -18
  146. data/app/views/alchemy/admin/pages/configure.html.erb +2 -2
  147. data/app/views/alchemy/admin/pages/info.html.erb +6 -0
  148. data/app/views/alchemy/admin/resources/_form.html.erb +7 -4
  149. data/app/views/alchemy/admin/resources/edit.html.erb +3 -1
  150. data/app/views/alchemy/admin/resources/new.html.erb +3 -1
  151. data/app/views/alchemy/admin/styleguide/index.html.erb +52 -30
  152. data/app/views/alchemy/admin/translations/_en.js +4 -0
  153. data/app/views/layouts/alchemy/admin.html.erb +3 -3
  154. data/config/importmap.rb +2 -0
  155. data/config/locales/alchemy.en.yml +15 -0
  156. data/config/routes.rb +1 -0
  157. data/lib/alchemy/configuration/class_option.rb +46 -3
  158. data/lib/alchemy/configuration/collection_option.rb +4 -0
  159. data/lib/alchemy/configurations/dashboard.rb +79 -0
  160. data/lib/alchemy/configurations/main.rb +15 -0
  161. data/lib/alchemy/engine.rb +9 -3
  162. data/lib/alchemy/sprockets/skip_builds_compression.rb +33 -0
  163. data/lib/alchemy/test_support/capybara_helpers.rb +17 -0
  164. data/lib/alchemy/test_support/relatable_resource_examples.rb +20 -0
  165. data/lib/alchemy/test_support/rspec_matchers.rb +8 -0
  166. data/lib/alchemy/test_support/shared_publishable_examples.rb +38 -31
  167. data/lib/alchemy/tinymce.rb +1 -1
  168. data/lib/alchemy/version.rb +17 -3
  169. data/vendor/javascript/cropperjs.min.js +1 -1
  170. data/vendor/javascript/flatpickr.min.js +1 -1
  171. data/vendor/javascript/floating-ui.min.js +1 -0
  172. data/vendor/javascript/keymaster.min.js +1 -1
  173. data/vendor/javascript/rails-ujs.min.js +1 -1
  174. data/vendor/javascript/shoelace.min.js +93 -93
  175. data/vendor/javascript/sortable.min.js +1 -1
  176. data/vendor/javascript/tinymce.min.js +5 -1
  177. data/vendor/javascript/tom-select.min.js +1 -0
  178. metadata +57 -18
  179. data/app/javascript/alchemy_admin/components/alchemy_html_element.js +0 -129
  180. data/app/views/alchemy/admin/dashboard/_left_column.html.erb +0 -4
  181. data/app/views/alchemy/admin/dashboard/_right_column.html.erb +0 -9
  182. data/app/views/alchemy/admin/dashboard/widgets/_locked_pages.html.erb +0 -52
  183. data/app/views/alchemy/admin/dashboard/widgets/_recent_pages.html.erb +0 -34
  184. data/app/views/alchemy/admin/dashboard/widgets/_sites.html.erb +0 -25
  185. data/app/views/alchemy/admin/dashboard/widgets/_users.html.erb +0 -21
  186. data/app/views/alchemy/admin/languages/edit.html.erb +0 -1
  187. data/app/views/alchemy/admin/languages/new.html.erb +0 -1
  188. data/app/views/alchemy/admin/sites/edit.html.erb +0 -1
  189. data/app/views/alchemy/admin/sites/new.html.erb +0 -1
@@ -0,0 +1,240 @@
1
+ // Theme for the Tom Select powered `<select is="alchemy-select">`.
2
+ @use "../mixins";
3
+
4
+ .tomselected {
5
+ display: none;
6
+ }
7
+
8
+ .ts-wrapper.alchemy_selectbox {
9
+ position: relative;
10
+ width: 100%;
11
+ max-width: 100%;
12
+
13
+ &.medium {
14
+ width: var(--select-medium-width);
15
+ }
16
+
17
+ &.large {
18
+ width: var(--select-large-width);
19
+ }
20
+
21
+ &.x-large {
22
+ width: var(--select-x-large-width);
23
+ }
24
+
25
+ &.input-hidden .ts-control > input {
26
+ left: -10000px;
27
+ opacity: 0;
28
+ position: absolute;
29
+ }
30
+
31
+ &.single {
32
+ &.input-active {
33
+ .ts-control input {
34
+ position: absolute;
35
+ background-color: rgb(
36
+ from var(--form-field-background-color) r g b / 33%
37
+ );
38
+
39
+ transition: none;
40
+
41
+ &.has-value {
42
+ position: absolute;
43
+ background-color: var(--form-field-background-color);
44
+ }
45
+ }
46
+ }
47
+ }
48
+
49
+ .ts-control {
50
+ --input-max-width: calc(100% - var(--spacing-4));
51
+ align-items: center;
52
+ background: var(--select-background-color);
53
+ padding: var(--form-field-padding);
54
+ border: var(--form-field-border-width) var(--form-field-border-style)
55
+ var(--select-border-color);
56
+ color: var(--select-text-color);
57
+ margin: var(--form-field-margin);
58
+ line-height: var(--form-field-line-height);
59
+ min-height: var(--form-field-height);
60
+ font-size: var(--form-field-font-size);
61
+ border-radius: var(--border-radius_medium);
62
+ cursor: pointer;
63
+
64
+ > .item {
65
+ margin: 0;
66
+ line-height: 21px;
67
+ max-width: 90%;
68
+ }
69
+
70
+ > input {
71
+ color: var(--form-field-text-color);
72
+ font-size: var(--form-field-font-size);
73
+ height: auto;
74
+ max-width: var(--input-max-width);
75
+ margin: 0;
76
+ padding: 0;
77
+ border-radius: 0;
78
+ border: 0;
79
+
80
+ &:focus {
81
+ box-shadow: none;
82
+ border: none;
83
+ }
84
+ }
85
+
86
+ input::placeholder {
87
+ color: var(--text-color-muted);
88
+ }
89
+ }
90
+
91
+ &.single {
92
+ &.input-active {
93
+ .ts-control {
94
+ background: var(--select-background-color);
95
+ }
96
+ }
97
+
98
+ &.has-items:has(.clear-button) .ts-control::after {
99
+ margin-left: 0;
100
+ }
101
+
102
+ .ts-control {
103
+ display: flex;
104
+ align-items: center;
105
+
106
+ &::after {
107
+ content: "";
108
+ display: inline-flex;
109
+ flex: 0 0 1em;
110
+ width: 1em;
111
+ height: 1em;
112
+ margin-left: auto;
113
+ background: var(--select-background-image) no-repeat center / contain;
114
+ }
115
+ }
116
+ }
117
+
118
+ &.focus .ts-control {
119
+ @include mixins.default-focus-style(
120
+ $box-shadow: 0 0 0 1px var(--focus-color)
121
+ );
122
+ }
123
+
124
+ &.disabled .ts-control {
125
+ background-color: var(--select-disabled-background-color);
126
+ border-color: var(--select-disabled-border-color);
127
+ color: var(--text-color-muted);
128
+ cursor: not-allowed;
129
+ }
130
+
131
+ &.multi {
132
+ .ts-control {
133
+ --input-max-width: 100%;
134
+ height: auto;
135
+ padding: var(--spacing-0);
136
+
137
+ > input {
138
+ padding: 5px 6px;
139
+ margin: 0;
140
+ width: auto;
141
+ min-width: 7rem;
142
+ }
143
+
144
+ > .item {
145
+ display: inline-flex;
146
+ align-items: center;
147
+ gap: var(--spacing-0);
148
+ margin: var(--spacing-0);
149
+ padding: 0 var(--spacing-1);
150
+ color: var(--text-color);
151
+ background: var(--tag-background-color);
152
+ border: 0 none;
153
+ border-radius: var(--border-radius_medium);
154
+
155
+ .remove {
156
+ display: inline-flex;
157
+ align-items: center;
158
+ padding: 0 var(--spacing-0);
159
+ color: var(--icon-color);
160
+ text-decoration: none;
161
+
162
+ &:hover {
163
+ color: var(--text-color);
164
+ }
165
+ }
166
+ }
167
+
168
+ > .clear-button {
169
+ position: absolute;
170
+ top: 6.5px;
171
+ right: var(--spacing-1);
172
+ }
173
+
174
+ &:has(.clear-button) {
175
+ padding-right: var(--spacing-6);
176
+ }
177
+ }
178
+ }
179
+
180
+ &.has-items .clear-button {
181
+ display: inline-flex;
182
+ }
183
+
184
+ .clear-button {
185
+ --button-height: auto;
186
+ display: none;
187
+ background: none;
188
+ border: none;
189
+ box-shadow: none;
190
+ margin: 0 0 0 auto;
191
+ padding: var(--spacing-1);
192
+ }
193
+ }
194
+
195
+ .ts-dropdown-mask {
196
+ position: fixed;
197
+ top: 0;
198
+ left: 0;
199
+ width: 100vw;
200
+ height: 100vh;
201
+ z-index: 0;
202
+ }
203
+
204
+ .ts-dropdown {
205
+ position: absolute;
206
+ width: max-content;
207
+ top: 0;
208
+ left: 0;
209
+ z-index: 1;
210
+ background: var(--select-dropdown-background-color);
211
+ box-shadow: var(--select-dropdown-box-shadow);
212
+ color: var(--select-dropdown-text-color, var(--text-color));
213
+ border: 1px solid var(--select-dropdown-border-color);
214
+ border-radius: var(--border-radius_medium);
215
+
216
+ > .ts-dropdown-content {
217
+ border-radius: var(--border-radius_medium);
218
+ max-height: var(--select-dropdown-max-height, 80vh);
219
+ overflow-y: auto;
220
+ }
221
+
222
+ .option {
223
+ padding: var(--spacing-2);
224
+ cursor: pointer;
225
+
226
+ .highlight {
227
+ text-decoration: underline;
228
+ }
229
+
230
+ &.active {
231
+ background: var(--select-hover-bg-color, var(--color-blue_dark));
232
+ color: var(--select-hover-text-color, var(--color-white));
233
+ }
234
+ }
235
+
236
+ .no-results {
237
+ padding: var(--spacing-2);
238
+ color: var(--text-color-muted);
239
+ }
240
+ }
@@ -264,7 +264,6 @@ div#library_sidebar {
264
264
 
265
265
  padding: var(--spacing-2) var(--spacing-4) var(--spacing-2) var(--spacing-4);
266
266
  height: calc(100% - var(--top-menu-height) - var(--pagination-height));
267
- z-index: 3;
268
267
  background-color: var(--sidebar-background-color);
269
268
 
270
269
  h2 {
@@ -1,11 +1,5 @@
1
1
  @use "../mixins";
2
2
 
3
- @property --custom-elements-loaded {
4
- syntax: "<number>";
5
- inherits: true;
6
- initial-value: 0;
7
- }
8
-
9
3
  html {
10
4
  box-sizing: border-box;
11
5
  height: 100%;
@@ -53,9 +47,6 @@ body {
53
47
  background-color: var(--body-background-color);
54
48
  height: 100%;
55
49
  cursor: default;
56
- opacity: 1;
57
- transition: opacity var(--transition-duration);
58
- animation: custom-elements-loaded 0 linear 250ms forwards;
59
50
 
60
51
  // Fix for strange element window offset
61
52
  &.pages.edit {
@@ -65,16 +56,6 @@ body {
65
56
  &.prevent-scrolling {
66
57
  overflow: hidden;
67
58
  }
68
-
69
- &:has(alchemy-spinner:not(:defined)) {
70
- opacity: var(--custom-elements-loaded, 0);
71
- }
72
- }
73
-
74
- @keyframes custom-elements-loaded {
75
- to {
76
- --custom-elements-loaded: 1;
77
- }
78
59
  }
79
60
 
80
61
  a {