alchemy_cms 8.0.0.a → 8.0.0.b
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/README.md +3 -0
- data/app/assets/builds/alchemy/admin/page-select.css +1 -1
- data/app/assets/builds/alchemy/admin.css +1 -1
- data/app/assets/builds/alchemy/dark-theme.css +1 -0
- data/app/assets/builds/alchemy/light-theme.css +1 -0
- data/app/assets/builds/alchemy/theme.css +1 -0
- data/app/assets/builds/alchemy/welcome.css +1 -1
- data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css +1 -1
- data/app/assets/builds/tinymce/skins/content/alchemy-dark/content.min.css +1 -0
- data/app/assets/builds/tinymce/skins/ui/alchemy/skin.min.css +1 -1
- data/app/assets/builds/tinymce/skins/ui/alchemy-dark/content.min.css +1 -0
- data/app/assets/builds/tinymce/skins/ui/alchemy-dark/skin.min.css +1 -0
- data/app/assets/images/alchemy/element_icons/default.svg +1 -0
- data/app/assets/images/alchemy/icons-sprite.svg +1 -1
- data/app/components/alchemy/admin/element_select.rb +39 -0
- data/app/components/alchemy/ingredients/datetime_view.rb +4 -2
- data/app/controllers/alchemy/admin/attachments_controller.rb +2 -0
- data/app/controllers/alchemy/admin/elements_controller.rb +2 -0
- data/app/controllers/alchemy/admin/pages_controller.rb +2 -0
- data/app/controllers/alchemy/admin/pictures_controller.rb +19 -33
- data/app/controllers/alchemy/pages_controller.rb +19 -2
- data/app/controllers/concerns/alchemy/admin/resource_filter.rb +1 -0
- data/app/helpers/alchemy/admin/attachments_helper.rb +5 -5
- data/app/helpers/alchemy/pages_helper.rb +1 -1
- data/app/javascript/alchemy_admin/components/auto_submit.js +20 -0
- data/app/javascript/alchemy_admin/components/datepicker.js +8 -5
- data/app/javascript/alchemy_admin/components/element_editor/delete_element_button.js +3 -2
- data/app/javascript/alchemy_admin/components/element_editor.js +25 -15
- data/app/javascript/alchemy_admin/components/element_select.js +43 -0
- data/app/javascript/alchemy_admin/components/index.js +5 -0
- data/app/javascript/alchemy_admin/components/link_buttons.js +6 -2
- data/app/javascript/alchemy_admin/components/remote_select.js +5 -1
- data/app/javascript/alchemy_admin/components/tinymce.js +93 -16
- data/app/javascript/alchemy_admin/dialog.js +1 -1
- data/app/javascript/alchemy_admin/file_editors.js +1 -1
- data/app/javascript/alchemy_admin/image_loader.js +4 -2
- data/app/javascript/alchemy_admin/picture_editors.js +7 -4
- data/app/javascript/alchemy_admin/picture_selector.js +4 -4
- data/app/jobs/alchemy/delete_picture_job.rb +12 -0
- data/app/models/alchemy/attachment.rb +2 -9
- data/app/models/alchemy/element.rb +1 -0
- data/app/models/alchemy/element_definition.rb +30 -0
- data/app/models/alchemy/ingredient.rb +1 -1
- data/app/models/alchemy/language.rb +2 -7
- data/app/models/alchemy/page/page_naming.rb +4 -11
- data/app/models/alchemy/page/page_natures.rb +16 -11
- data/app/models/alchemy/page.rb +1 -6
- data/app/models/alchemy/page_definition.rb +1 -1
- data/app/models/alchemy/picture.rb +6 -17
- data/app/models/alchemy/site/layout.rb +1 -0
- data/app/models/alchemy/site.rb +1 -6
- data/app/models/alchemy/storage_adapter/dragonfly/picture_url.rb +7 -2
- data/app/models/alchemy/storage_adapter/dragonfly.rb +24 -2
- data/app/models/concerns/alchemy/relatable_resource.rb +28 -0
- data/app/stylesheets/alchemy/_custom-properties.scss +162 -0
- data/app/stylesheets/alchemy/_mixins.scss +12 -24
- data/app/stylesheets/alchemy/_themes.scss +540 -0
- data/app/stylesheets/alchemy/admin/archive.scss +28 -8
- data/app/stylesheets/alchemy/admin/attachments.scss +10 -33
- data/app/stylesheets/alchemy/admin/base.scss +4 -1
- data/app/stylesheets/alchemy/admin/buttons.scss +7 -32
- data/app/stylesheets/alchemy/admin/dialogs.scss +17 -7
- data/app/stylesheets/alchemy/admin/element-select.scss +11 -0
- data/app/stylesheets/alchemy/admin/elements.scss +94 -33
- data/app/stylesheets/alchemy/admin/filters.scss +8 -9
- data/app/stylesheets/alchemy/admin/flatpickr.scss +12 -27
- data/app/stylesheets/alchemy/admin/form_fields.scss +0 -15
- data/app/stylesheets/alchemy/admin/forms.scss +3 -8
- data/app/stylesheets/alchemy/admin/frame.scss +5 -7
- data/app/stylesheets/alchemy/admin/icons.scss +0 -9
- data/app/stylesheets/alchemy/admin/image_library.scss +13 -55
- data/app/stylesheets/alchemy/admin/navigation.scss +1 -11
- data/app/stylesheets/alchemy/admin/node-select.scss +1 -10
- data/app/stylesheets/alchemy/admin/notices.scss +5 -4
- data/app/stylesheets/alchemy/admin/page-select.scss +16 -0
- data/app/stylesheets/alchemy/admin/pagination.scss +1 -8
- data/app/stylesheets/alchemy/admin/preview_window.scss +12 -1
- data/app/stylesheets/alchemy/admin/resource_info.scss +106 -3
- data/app/stylesheets/alchemy/admin/search.scss +1 -1
- data/app/stylesheets/alchemy/admin/selects.scss +58 -31
- data/app/stylesheets/alchemy/admin/shoelace.scss +32 -62
- data/app/stylesheets/alchemy/admin/sitemap.scss +1 -1
- data/app/stylesheets/alchemy/admin/tables.scss +3 -3
- data/app/stylesheets/alchemy/admin/tags.scss +18 -35
- data/app/stylesheets/alchemy/admin/toolbar.scss +0 -6
- data/app/stylesheets/alchemy/admin/typography.scss +2 -5
- data/app/stylesheets/alchemy/admin.scss +1 -1
- data/app/stylesheets/alchemy/dark-theme.scss +5 -0
- data/app/stylesheets/alchemy/light-theme.scss +6 -0
- data/app/stylesheets/alchemy/theme.scss +13 -0
- data/app/stylesheets/tinymce/skins/content/alchemy/content.scss +8 -8
- data/app/stylesheets/tinymce/skins/content/alchemy-dark/content.scss +70 -0
- data/app/stylesheets/tinymce/skins/ui/alchemy/skin.scss +28 -43
- data/app/stylesheets/tinymce/skins/ui/alchemy-dark/content.scss +1 -0
- data/app/stylesheets/tinymce/skins/ui/alchemy-dark/skin.scss +3784 -0
- data/app/views/alchemy/admin/attachments/_files_list.html.erb +20 -10
- data/app/views/alchemy/admin/attachments/assign.js.erb +4 -3
- data/app/views/alchemy/admin/attachments/show.html.erb +55 -43
- data/app/views/alchemy/admin/crop.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_form.html.erb +9 -9
- data/app/views/alchemy/admin/elements/_header.html.erb +4 -1
- data/app/views/alchemy/admin/ingredients/_picture_fields.html.erb +1 -1
- data/app/views/alchemy/admin/pages/info.html.erb +1 -1
- data/app/views/alchemy/admin/partials/_search_form.html.erb +1 -0
- data/app/views/alchemy/admin/pictures/_archive.html.erb +12 -22
- data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +1 -6
- data/app/views/alchemy/admin/pictures/_form.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/_infos.html.erb +21 -52
- data/app/views/alchemy/admin/pictures/_library_sidebar.html.erb +7 -0
- data/app/views/alchemy/admin/pictures/_picture.html.erb +14 -20
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +20 -16
- data/app/views/alchemy/admin/pictures/_sorting_select.html.erb +13 -0
- data/app/views/alchemy/admin/pictures/_tag_list.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/edit_multiple.html.erb +1 -6
- data/app/views/alchemy/admin/pictures/index.html.erb +3 -12
- data/app/views/alchemy/admin/pictures/show.html.erb +10 -5
- data/app/views/alchemy/admin/resources/_filter_bar.html.erb +5 -15
- data/app/views/alchemy/admin/resources/_resource_usage_info.html.erb +36 -0
- data/app/views/alchemy/admin/styleguide/index.html.erb +118 -66
- data/app/views/alchemy/base/error_notice.html.erb +1 -1
- data/app/views/alchemy/ingredients/_page_editor.html.erb +0 -1
- data/app/views/alchemy/ingredients/_richtext_editor.html.erb +0 -1
- data/app/views/alchemy/ingredients/_select_editor.html.erb +1 -2
- data/app/views/layouts/alchemy/admin.html.erb +22 -17
- data/config/locales/alchemy.en.yml +26 -8
- data/db/migrate/20250905140323_add_created_at_index_to_pictures_and_attachments.rb +14 -0
- data/lib/alchemy/configurations/format_matchers.rb +1 -1
- data/lib/alchemy/configurations/main.rb +7 -0
- data/lib/alchemy/configurations/page_cache.rb +19 -0
- data/lib/alchemy/engine.rb +16 -7
- data/lib/alchemy/install/tasks.rb +0 -12
- data/lib/alchemy/name_conversions.rb +6 -0
- data/lib/alchemy/tasks/tidy.rb +18 -0
- data/lib/alchemy/test_support/factories/picture_factory.rb +1 -0
- data/lib/alchemy/test_support/relatable_resource_examples.rb +58 -0
- data/lib/alchemy/tinymce.rb +0 -1
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy.rb +2 -11
- data/lib/generators/alchemy/install/install_generator.rb +21 -10
- data/lib/generators/alchemy/install/templates/alchemy.rb.tt +10 -6
- data/lib/tasks/alchemy/tidy.rake +6 -0
- data/lib/tasks/alchemy/usage.rake +2 -0
- data/vendor/assets/stylesheets/tinymce/skins/content/dark/content.min.css +1 -0
- data/vendor/assets/stylesheets/tinymce/skins/content/default/content.min.css +1 -0
- data/vendor/assets/stylesheets/tinymce/skins/ui/oxide/skin.min.css +1 -0
- data/vendor/assets/stylesheets/tinymce/skins/ui/oxide-dark/content.min.css +1 -0
- data/vendor/assets/stylesheets/tinymce/skins/ui/oxide-dark/skin.min.css +1 -0
- data/vendor/javascript/clipboard.min.js +1 -1
- data/vendor/javascript/cropperjs.min.js +1 -1
- data/vendor/javascript/handlebars.min.js +3 -3
- data/vendor/javascript/jquery.min.js +1 -1
- data/vendor/javascript/select2.min.js +3 -3
- data/vendor/javascript/shoelace.min.js +92 -76
- data/vendor/javascript/sortable.min.js +2 -2
- data/vendor/javascript/tinymce.min.js +1 -1
- data/vendor/javascript/ungap-custom-elements.min.js +2 -2
- metadata +46 -32
- data/CHANGELOG.md +0 -2100
- data/CODE_OF_CONDUCT.md +0 -13
- data/CONTRIBUTING.md +0 -73
- data/Gemfile +0 -78
- data/Rakefile +0 -102
- data/SECURITY.md +0 -13
- data/alchemy_cms.gemspec +0 -97
- data/app/assets/builds/alchemy/custom-properties.css +0 -1
- data/app/helpers/alchemy/admin/elements_helper.rb +0 -25
- data/app/stylesheets/alchemy/custom-properties.css +0 -244
- data/bin/importmap +0 -4
- data/bin/rails +0 -9
- data/bin/rspec +0 -3
- data/bin/setup +0 -30
- data/bin/start +0 -17
- data/bun.lockb +0 -0
- data/bundles/remixicon.mjs +0 -153
- data/bundles/shoelace.js +0 -12
- data/bundles/tinymce.js +0 -22
- data/eslint.config.js +0 -18
- data/lib/alchemy/upgrader/.keep +0 -0
- data/lib/alchemy/upgrader/tasks/.keep +0 -0
- data/rollup.config.mjs +0 -108
- data/vitest.config.js +0 -21
@@ -0,0 +1,36 @@
|
|
1
|
+
<div class="resource-usage-info">
|
2
|
+
<% if assignments.any? %>
|
3
|
+
<alchemy-message type="info">
|
4
|
+
<%= Alchemy.t(resource_name, scope: :used_on_these_pages) %>
|
5
|
+
</alchemy-message>
|
6
|
+
<ul class="resource_page_list">
|
7
|
+
<% assignments.group_by(&:page).each do |page, related_ingredients| %>
|
8
|
+
<% if page %>
|
9
|
+
<li>
|
10
|
+
<h3>
|
11
|
+
<%= render_icon 'file' %>
|
12
|
+
<p><%= link_to page.name, edit_admin_page_path(page) %></p>
|
13
|
+
</h3>
|
14
|
+
<ul class="list">
|
15
|
+
<% related_ingredients.group_by(&:element).each do |element, related_ingredients| %>
|
16
|
+
<li class="<%= cycle('even', 'odd') %>">
|
17
|
+
<% page_link = link_to element.display_name_with_preview_text,
|
18
|
+
edit_admin_page_path(page, anchor: "element_#{element.id}") %>
|
19
|
+
<% ingredients = related_ingredients.map { |p| Alchemy::IngredientEditor.new(p).translated_role }.to_sentence %>
|
20
|
+
<%= render_icon(:draggable, style: false) %>
|
21
|
+
<p>
|
22
|
+
<%== Alchemy.t(:pictures_in_page, page: page_link, pictures: ingredients) %>
|
23
|
+
</p>
|
24
|
+
</li>
|
25
|
+
<% end %>
|
26
|
+
</ul>
|
27
|
+
</li>
|
28
|
+
<% end %>
|
29
|
+
<% end %>
|
30
|
+
</ul>
|
31
|
+
<% else %>
|
32
|
+
<%= render_message do %>
|
33
|
+
<%= Alchemy.t(resource_name, scope: :not_in_use_yet) %>
|
34
|
+
<% end %>
|
35
|
+
<% end %>
|
36
|
+
</div>
|
@@ -19,71 +19,6 @@
|
|
19
19
|
|
20
20
|
<h1>AlchemyCMS Styleguide</h1>
|
21
21
|
|
22
|
-
<h2>Typography</h2>
|
23
|
-
|
24
|
-
<h1>Heading 1</h1>
|
25
|
-
<h2>Heading 2</h2>
|
26
|
-
<h3>Heading 3</h3>
|
27
|
-
<h4>Heading 4</h4>
|
28
|
-
<h5>Heading 5</h5>
|
29
|
-
|
30
|
-
<p>This is a paragraph, with <a href="#">a link</a>, a <kbd>keyboard shortcut</kbd> and an <code>inline code snippet</code>.</p>
|
31
|
-
|
32
|
-
<h2>Messages</h2>
|
33
|
-
|
34
|
-
<h3>Info Message</h3>
|
35
|
-
|
36
|
-
<%= render_message do %>
|
37
|
-
<p>Lorem ipsum <strong>dolor</strong> sit amet, consectetur adipiscing elit.</p>
|
38
|
-
<% end %>
|
39
|
-
|
40
|
-
<h3>Warning Message</h3>
|
41
|
-
|
42
|
-
<%= render_message :warning do %>
|
43
|
-
<p>Lorem ipsum dolor sit amet, <a href="">consectetur</a> adipiscing elit.</p>
|
44
|
-
<% end %>
|
45
|
-
|
46
|
-
<h3>Error Message</h3>
|
47
|
-
|
48
|
-
<%= render_message :error do %>
|
49
|
-
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
|
50
|
-
<% end %>
|
51
|
-
|
52
|
-
<h3>Tags Autocomplete</h3>
|
53
|
-
|
54
|
-
<div>
|
55
|
-
<alchemy-tags-autocomplete>
|
56
|
-
<input type="text" class="full_width" />
|
57
|
-
</alchemy-tags-autocomplete>
|
58
|
-
</div>
|
59
|
-
|
60
|
-
<h3>Growl Messages</h3>
|
61
|
-
|
62
|
-
<%= link_to render_icon(:check), 'javascript:Alchemy.growl("Success message")', class: "icon_button" %>
|
63
|
-
<%= link_to render_icon(:info), 'javascript:Alchemy.growl("Info message", "info")', class: "icon_button" %>
|
64
|
-
<%= link_to render_icon(:alert), 'javascript:Alchemy.growl("Warning message", "warn")', class: "icon_button" %>
|
65
|
-
<%= link_to render_icon(:bug), 'javascript:Alchemy.growl("Error message", "error")', class: "icon_button" %>
|
66
|
-
|
67
|
-
<h2>Dialog Links</h2>
|
68
|
-
|
69
|
-
<sl-tooltip content="Open in Dialog">
|
70
|
-
<a
|
71
|
-
href="/admin/styleguide"
|
72
|
-
is="alchemy-dialog-link"
|
73
|
-
class="icon_button"
|
74
|
-
data-dialog-options="{"size":"800x600","title":"Styleguide in Dialog"}"
|
75
|
-
>
|
76
|
-
<%= render_icon "window" %>
|
77
|
-
</a>
|
78
|
-
</sl-tooltip>
|
79
|
-
<a
|
80
|
-
href="#"
|
81
|
-
is="alchemy-dialog-link"
|
82
|
-
class="icon_button disabled"
|
83
|
-
>
|
84
|
-
<%= render_icon "window" %>
|
85
|
-
</a>
|
86
|
-
|
87
22
|
<h2>Forms</h2>
|
88
23
|
|
89
24
|
<div class="panel">
|
@@ -102,6 +37,13 @@
|
|
102
37
|
</select>
|
103
38
|
</div>
|
104
39
|
|
40
|
+
<div class="input select">
|
41
|
+
<label class="select control-label" for="select">Disabled Select</label>
|
42
|
+
<select class="select" id="disabled-select" is="alchemy-select" disabled>
|
43
|
+
<option value="">Cannot choose</option>
|
44
|
+
</select>
|
45
|
+
</div>
|
46
|
+
|
105
47
|
<div class="input">
|
106
48
|
<label class="control-label" for="datetime_picker">Date Time Picker</label>
|
107
49
|
<alchemy-datepicker input-type="datetime">
|
@@ -171,7 +113,7 @@
|
|
171
113
|
<div class="input text">
|
172
114
|
<label class="text control-label" for="textarea">Textarea</label>
|
173
115
|
<textarea class="text" id="textarea"></textarea>
|
174
|
-
<small class="hint">With hint</small>
|
116
|
+
<small class="hint">With hint and a <a href="/admin/styleguide">link</a> inside.</small>
|
175
117
|
</div>
|
176
118
|
|
177
119
|
<div class="input text tinymce_container">
|
@@ -188,6 +130,116 @@
|
|
188
130
|
</form>
|
189
131
|
</div>
|
190
132
|
|
133
|
+
<h2>Buttons</h2>
|
134
|
+
|
135
|
+
<p>
|
136
|
+
<button class="secondary" disabled>Disabled Secondary</button>
|
137
|
+
<button type="submit" is="alchemy-button" disabled>Disabled Primary</button>
|
138
|
+
</p>
|
139
|
+
|
140
|
+
<h2>Selects</h2>
|
141
|
+
|
142
|
+
<div style="display: flex; gap: 1em;">
|
143
|
+
<div style="width: 25%">
|
144
|
+
<h3>Select with Search</h3>
|
145
|
+
<select is="alchemy-select" class="full_width">
|
146
|
+
<option value="1">Option 1</option>
|
147
|
+
<option value="2">Option 2</option>
|
148
|
+
<option value="3">Option 3</option>
|
149
|
+
<option value="4">Option 4</option>
|
150
|
+
<option value="5">Option 5</option>
|
151
|
+
<option value="6">Option 6</option>
|
152
|
+
<option value="7">Option 7</option>
|
153
|
+
</select>
|
154
|
+
</div>
|
155
|
+
|
156
|
+
<div style="width: 25%">
|
157
|
+
<h3>Page Select</h3>
|
158
|
+
<%= render Alchemy::Admin::PageSelect.new do %>
|
159
|
+
<input name="page" class="full_width" />
|
160
|
+
<% end %>
|
161
|
+
</div>
|
162
|
+
|
163
|
+
<div style="width: 25%">
|
164
|
+
<h3>Node Select</h3>
|
165
|
+
<%= render Alchemy::Admin::NodeSelect.new do %>
|
166
|
+
<input name="node" class="full_width" />
|
167
|
+
<% end %>
|
168
|
+
</div>
|
169
|
+
|
170
|
+
<div style="width: 25%">
|
171
|
+
<h3>Attachment Select</h3>
|
172
|
+
<%= render Alchemy::Admin::AttachmentSelect.new do %>
|
173
|
+
<input name="attachment" class="full_width" />
|
174
|
+
<% end %>
|
175
|
+
</div>
|
176
|
+
</div>
|
177
|
+
|
178
|
+
<h3>Tags Autocomplete</h3>
|
179
|
+
|
180
|
+
<div style="width: 25%">
|
181
|
+
<alchemy-tags-autocomplete>
|
182
|
+
<input type="text" class="full_width" />
|
183
|
+
</alchemy-tags-autocomplete>
|
184
|
+
</div>
|
185
|
+
|
186
|
+
<h2>Typography</h2>
|
187
|
+
|
188
|
+
<h1>Heading 1</h1>
|
189
|
+
<h2>Heading 2</h2>
|
190
|
+
<h3>Heading 3</h3>
|
191
|
+
<h4>Heading 4</h4>
|
192
|
+
<h5>Heading 5</h5>
|
193
|
+
|
194
|
+
<p>This is a paragraph, with <a href="#">a link</a>, a <kbd>keyboard shortcut</kbd> and an <code>inline code snippet</code>.</p>
|
195
|
+
|
196
|
+
<h2>Messages</h2>
|
197
|
+
|
198
|
+
<h3>Info Message</h3>
|
199
|
+
|
200
|
+
<%= render_message do %>
|
201
|
+
<p>Lorem ipsum <strong>dolor</strong> sit amet, <a href="">consectetur</a> adipiscing elit.</p>
|
202
|
+
<% end %>
|
203
|
+
|
204
|
+
<h3>Warning Message</h3>
|
205
|
+
|
206
|
+
<%= render_message :warning do %>
|
207
|
+
<p>Lorem ipsum dolor sit amet, <a href="">consectetur</a> adipiscing elit.</p>
|
208
|
+
<% end %>
|
209
|
+
|
210
|
+
<h3>Error Message</h3>
|
211
|
+
|
212
|
+
<%= render_message :error do %>
|
213
|
+
<p>Lorem ipsum dolor sit amet, <a href="">consectetur</a> adipiscing elit.</p>
|
214
|
+
<% end %>
|
215
|
+
|
216
|
+
<h3>Growl Messages</h3>
|
217
|
+
|
218
|
+
<%= link_to render_icon(:check), 'javascript:Alchemy.growl("Success message")', class: "icon_button" %>
|
219
|
+
<%= link_to render_icon(:info), 'javascript:Alchemy.growl("Info message", "info")', class: "icon_button" %>
|
220
|
+
<%= link_to render_icon(:alert), 'javascript:Alchemy.growl("Warning message", "warn")', class: "icon_button" %>
|
221
|
+
<%= link_to render_icon(:bug), 'javascript:Alchemy.growl("Error message", "error")', class: "icon_button" %>
|
222
|
+
|
223
|
+
<h2>Dialog Links</h2>
|
224
|
+
|
225
|
+
<sl-tooltip content="Open in Dialog">
|
226
|
+
<a
|
227
|
+
href="/admin/styleguide"
|
228
|
+
is="alchemy-dialog-link"
|
229
|
+
class="icon_button"
|
230
|
+
data-dialog-options="{"size":"800x600","title":"Styleguide in Dialog"}"
|
231
|
+
>
|
232
|
+
<%= render_icon "window" %>
|
233
|
+
</a>
|
234
|
+
</sl-tooltip>
|
235
|
+
<a
|
236
|
+
href="#"
|
237
|
+
is="alchemy-dialog-link"
|
238
|
+
class="icon_button disabled"
|
239
|
+
>
|
240
|
+
<%= render_icon "window" %>
|
241
|
+
</a>
|
242
|
+
|
191
243
|
<h2>Tables</h2>
|
192
244
|
|
193
245
|
<h3>Normal Table</h3>
|
@@ -9,7 +9,6 @@
|
|
9
9
|
<%= f.text_area :value,
|
10
10
|
minlength: richtext_editor.length_validation&.fetch(:minimum, nil),
|
11
11
|
maxlength: richtext_editor.length_validation&.fetch(:maximum, nil),
|
12
|
-
required: richtext_editor.presence_validation?,
|
13
12
|
id: richtext_editor.form_field_id(:value) %>
|
14
13
|
<% end %>
|
15
14
|
<% end %>
|
@@ -1,8 +1,9 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
|
-
<html lang="<%= ::I18n.locale %>" class="no-js loading-custom-elements
|
2
|
+
<html lang="<%= ::I18n.locale %>" class="no-js loading-custom-elements">
|
3
3
|
<head>
|
4
4
|
<meta charset="utf-8">
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
6
|
+
<meta name="color-scheme" content="light dark">
|
6
7
|
<title><%= render_alchemy_title %></title>
|
7
8
|
<link rel="shortcut icon" href="<%= asset_path('alchemy/favicon.ico') %>">
|
8
9
|
<link rel="preload" href="<%= asset_path("alchemy/icons-sprite.svg") %>" as="image" type="<%= Mime::Type.lookup_by_extension(:svg) %>" crossorigin>
|
@@ -10,6 +11,7 @@
|
|
10
11
|
<meta name="robots" content="noindex">
|
11
12
|
<meta name="turbo-prefetch" content="false">
|
12
13
|
<meta name="turbo-cache-control" content="no-cache">
|
14
|
+
<%= stylesheet_link_tag('alchemy/theme', media: 'screen', 'data-turbo-track' => true) %>
|
13
15
|
<%= stylesheet_link_tag('alchemy/admin', media: 'screen', 'data-turbo-track' => true) %>
|
14
16
|
<%= stylesheet_link_tag('alchemy/admin/print', media: 'print', 'data-turbo-track' => true) %>
|
15
17
|
<% Alchemy.admin_stylesheets.each do |stylesheet| %>
|
@@ -49,23 +51,26 @@
|
|
49
51
|
<% end %>
|
50
52
|
<%= yield(:alchemy_main_navigation) %>
|
51
53
|
</div>
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
54
|
+
|
55
|
+
<div id="logout">
|
56
|
+
<div class="main_navi_entry">
|
57
|
+
<% if current_alchemy_user %>
|
58
|
+
<%= link_to_dialog(
|
59
|
+
%(
|
60
|
+
#{render_icon('logout-box-r', class: 'module')}
|
61
|
+
<label>#{Alchemy.t(:leave)}</label>
|
62
|
+
).html_safe,
|
63
|
+
alchemy.leave_admin_path, {
|
64
|
+
size: "300x155",
|
65
|
+
title: Alchemy.t("Leave Alchemy")
|
66
|
+
}, {'data-alchemy-hotkey' => 'alt+q'}) %>
|
67
|
+
<% else %>
|
68
|
+
<%= link_to(alchemy.root_path) do %>
|
69
|
+
<%= render_icon "logout-box-r", size: "lg" %>
|
70
|
+
<label><%= Alchemy.t(:leave) %></label>
|
71
|
+
<% end %>
|
67
72
|
<% end %>
|
68
|
-
|
73
|
+
</div>
|
69
74
|
</div>
|
70
75
|
</div>
|
71
76
|
<% if current_alchemy_user %>
|
@@ -143,7 +143,7 @@ en:
|
|
143
143
|
without_tag:
|
144
144
|
name: Without tag
|
145
145
|
deletable:
|
146
|
-
name: Not
|
146
|
+
name: Not used
|
147
147
|
attachment:
|
148
148
|
by_file_type:
|
149
149
|
name: File Type
|
@@ -156,6 +156,8 @@ en:
|
|
156
156
|
name: Recently uploaded only
|
157
157
|
without_tag:
|
158
158
|
name: Without tag
|
159
|
+
deletable:
|
160
|
+
name: Not used
|
159
161
|
|
160
162
|
default_ingredient_texts:
|
161
163
|
lorem: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
@@ -224,6 +226,11 @@ en:
|
|
224
226
|
elements:
|
225
227
|
toolbar:
|
226
228
|
hide: Hide
|
229
|
+
pictures:
|
230
|
+
sorting_select:
|
231
|
+
label: "Sorting"
|
232
|
+
by_latest: "Latest"
|
233
|
+
alphabetical: "A-Z"
|
227
234
|
add_nested_element: "Add %{name}"
|
228
235
|
anchor: "Anchor"
|
229
236
|
anchor_link_headline: You can link to an anchor from the current page.
|
@@ -333,7 +340,6 @@ en:
|
|
333
340
|
"Size": "Size"
|
334
341
|
"Successfully deleted element": "Successfully deleted %{element}"
|
335
342
|
"Tags": "Tags"
|
336
|
-
"These pictures could not be deleted, because they were in use": "These pictures could not be deleted, because they were in use: %{names}"
|
337
343
|
"This page is locked": "This page is currently locked by %{name}"
|
338
344
|
"Title": "Title"
|
339
345
|
"Trash": "Trash"
|
@@ -561,6 +567,7 @@ en:
|
|
561
567
|
password: "Password"
|
562
568
|
paste: "paste"
|
563
569
|
pictures_in_page: "%{page} in %{pictures}"
|
570
|
+
pictures_will_be_deleted_now: Pictures will be deleted now
|
564
571
|
place_link: "Add link"
|
565
572
|
player_version: "Flash Player version"
|
566
573
|
"please enter subject and mail address": "Please enter recipient and subject."
|
@@ -621,6 +628,12 @@ en:
|
|
621
628
|
tag_list: Tags
|
622
629
|
tags_get_created_if_used_the_first_time: "Tags get created if used the first time."
|
623
630
|
this_picture_is_used_on_these_pages: "This picture is used on following pages"
|
631
|
+
used_on_these_pages:
|
632
|
+
attachment: "This file is used on following pages"
|
633
|
+
picture: "This picture is used on following pages"
|
634
|
+
not_in_use_yet:
|
635
|
+
attachment: "This file is not in use yet."
|
636
|
+
picture: "This picture is not in use yet."
|
624
637
|
title: "Title"
|
625
638
|
to_alchemy: "To Alchemy"
|
626
639
|
unknown: "unknown"
|
@@ -773,16 +786,19 @@ en:
|
|
773
786
|
node_ingredients_present: "This menu item is in use inside an Alchemy element on the following pages: %{page_names}."
|
774
787
|
alchemy/site:
|
775
788
|
attributes:
|
776
|
-
|
777
|
-
|
789
|
+
base:
|
790
|
+
restrict_dependent_destroy:
|
791
|
+
has_many: "There are still %{record} attached to this site. Please remove them first."
|
778
792
|
alchemy/language:
|
779
793
|
attributes:
|
780
|
-
|
781
|
-
|
794
|
+
base:
|
795
|
+
restrict_dependent_destroy:
|
796
|
+
has_many: "There are still %{record} attached to this language. Please remove them first."
|
782
797
|
alchemy/page:
|
783
798
|
attributes:
|
784
|
-
|
785
|
-
|
799
|
+
base:
|
800
|
+
restrict_dependent_destroy:
|
801
|
+
has_many: "There are still %{record} attached to this page. Please remove them first."
|
786
802
|
models:
|
787
803
|
gutentag/tag:
|
788
804
|
one: Tag
|
@@ -869,6 +885,7 @@ en:
|
|
869
885
|
public: "Public"
|
870
886
|
locale: Localization
|
871
887
|
code: ISO Code
|
888
|
+
nodes: Menu nodes
|
872
889
|
alchemy/legacy_page_url:
|
873
890
|
urlname: "URL-Path"
|
874
891
|
alchemy/node:
|
@@ -887,6 +904,7 @@ en:
|
|
887
904
|
meta_description: "Description"
|
888
905
|
meta_keywords: "Keywords"
|
889
906
|
name: "Name"
|
907
|
+
nodes: "Menu nodes"
|
890
908
|
page_layout: "Page type"
|
891
909
|
public: "public"
|
892
910
|
restricted: "restricted"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class AddCreatedAtIndexToPicturesAndAttachments < ActiveRecord::Migration[7.1]
|
2
|
+
disable_ddl_transaction! if connection.adapter_name.match?(/postgres/i)
|
3
|
+
|
4
|
+
def change
|
5
|
+
add_index :alchemy_pictures, :created_at, if_not_exists: true, algorithm: algorithm
|
6
|
+
add_index :alchemy_attachments, :created_at, if_not_exists: true, algorithm: algorithm
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def algorithm
|
12
|
+
connection.adapter_name.match?(/postgres/i) ? :concurrently : nil
|
13
|
+
end
|
14
|
+
end
|
@@ -4,7 +4,7 @@ module Alchemy
|
|
4
4
|
module Configurations
|
5
5
|
class FormatMatchers < Alchemy::Configuration
|
6
6
|
option :email, :regexp, default: /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/
|
7
|
-
option :url, :regexp, default: /\A[a-z0-9]+([
|
7
|
+
option :url, :regexp, default: /\A[a-z0-9]+([-.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?\z/ix
|
8
8
|
option :link_url, :regexp, default: /^(tel:|mailto:|\/|[a-z]+:\/\/)/
|
9
9
|
end
|
10
10
|
end
|
@@ -5,6 +5,7 @@ require "alchemy/configurations/default_language"
|
|
5
5
|
require "alchemy/configurations/default_site"
|
6
6
|
require "alchemy/configurations/format_matchers"
|
7
7
|
require "alchemy/configurations/mailer"
|
8
|
+
require "alchemy/configurations/page_cache"
|
8
9
|
require "alchemy/configurations/preview"
|
9
10
|
require "alchemy/configurations/sitemap"
|
10
11
|
require "alchemy/configurations/uploader"
|
@@ -31,6 +32,12 @@ module Alchemy
|
|
31
32
|
#
|
32
33
|
option :cache_pages, :boolean, default: true
|
33
34
|
|
35
|
+
# === Page caching max age
|
36
|
+
#
|
37
|
+
# max-age [Integer] # The duration in seconds for which the page is cached before revalidation.
|
38
|
+
# stale-while-revalidate [Boolean] # If true, enables the stale-while-revalidate caching strategy.
|
39
|
+
configuration :page_cache, PageCache
|
40
|
+
|
34
41
|
# === Sitemap
|
35
42
|
#
|
36
43
|
# Alchemy creates a XML, Google compatible, sitemap for you.
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
module Configurations
|
5
|
+
class PageCache < Alchemy::Configuration
|
6
|
+
# === Page caching max age
|
7
|
+
#
|
8
|
+
# Control the max-age duration in seconds in the cache-control header.
|
9
|
+
#
|
10
|
+
option :max_age, :integer, default: 600
|
11
|
+
|
12
|
+
# === Page caching stale-while-revalidate
|
13
|
+
#
|
14
|
+
# Set stale-while-revalidate cache-control header.
|
15
|
+
#
|
16
|
+
option :stale_while_revalidate, :integer
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/alchemy/engine.rb
CHANGED
@@ -62,13 +62,15 @@ module Alchemy
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
# All the initialization that needs to be re-triggered during reloads
|
65
66
|
config.to_prepare do
|
67
|
+
# Definition files
|
66
68
|
elements_reloader = Rails.application.config.file_watcher.new([ElementDefinition.definitions_file_path]) do
|
67
|
-
Rails.logger.info "[
|
69
|
+
Rails.logger.info "[alchemy] Reloading Element Definitions."
|
68
70
|
ElementDefinition.reset!
|
69
71
|
end
|
70
72
|
page_layouts_reloader = Rails.application.config.file_watcher.new([PageDefinition.layouts_file_path]) do
|
71
|
-
Rails.logger.info "[
|
73
|
+
Rails.logger.info "[alchemy] Reloading Page Layouts."
|
72
74
|
PageDefinition.reset!
|
73
75
|
end
|
74
76
|
[elements_reloader, page_layouts_reloader].each do |reloader|
|
@@ -77,12 +79,19 @@ module Alchemy
|
|
77
79
|
reloader.execute_if_updated
|
78
80
|
end
|
79
81
|
end
|
80
|
-
end
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
# The storage adapter for Pictures and Attachments
|
84
|
+
#
|
85
|
+
# Chose between 'active_storage' (default) or 'dragonfly' (legacy)
|
86
|
+
#
|
87
|
+
# Can be set via 'ALCHEMY_STORAGE_ADAPTER' env var.
|
88
|
+
Alchemy.storage_adapter = Alchemy::StorageAdapter.new(
|
89
|
+
ENV.fetch("ALCHEMY_STORAGE_ADAPTER", Alchemy.config.storage_adapter)
|
90
|
+
)
|
91
|
+
|
92
|
+
# Gutentag downcases all tags before save
|
93
|
+
# and Gutentag validations are not case sensitive.
|
94
|
+
# But we support having tags with uppercase characters.
|
86
95
|
Gutentag.normaliser = ->(value) { value.to_s }
|
87
96
|
Gutentag.tag_validations = Alchemy::TagValidations
|
88
97
|
end
|
@@ -22,18 +22,6 @@ module Alchemy
|
|
22
22
|
{after: SENTINEL, verbose: true}
|
23
23
|
end
|
24
24
|
|
25
|
-
def set_primary_language(code: "en", name: "English", auto_accept: false)
|
26
|
-
unless auto_accept
|
27
|
-
code = ask("- What is the language code of your site's primary language?", default: code)
|
28
|
-
end
|
29
|
-
unless auto_accept
|
30
|
-
name = ask("- What is the name of your site's primary language?", default: name)
|
31
|
-
end
|
32
|
-
gsub_file "./config/alchemy/config.yml", /default_language:\n\s\scode:\sen\n\s\sname:\sEnglish/m do
|
33
|
-
"default_language:\n code: #{code}\n name: #{name}"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
25
|
def inject_seeder
|
38
26
|
seed_file = Rails.root.join("db", "seeds.rb")
|
39
27
|
args = [seed_file, "Alchemy::Seeder.seed!\n"]
|
@@ -22,5 +22,11 @@ module Alchemy
|
|
22
22
|
def convert_to_humanized_name(name, suffix)
|
23
23
|
name.gsub(/\.#{::Regexp.quote(suffix)}$/i, "").tr("_", " ").strip
|
24
24
|
end
|
25
|
+
|
26
|
+
# Sanitizes a given filename by removing directory traversal attempts and HTML entities.
|
27
|
+
def sanitized_filename(file_name)
|
28
|
+
file_name = File.basename(file_name)
|
29
|
+
CGI.escapeHTML(file_name)
|
30
|
+
end
|
25
31
|
end
|
26
32
|
end
|
data/lib/alchemy/tasks/tidy.rb
CHANGED
@@ -73,6 +73,24 @@ module Alchemy
|
|
73
73
|
log "Deleted #{count} duplicate legacy URLs"
|
74
74
|
end
|
75
75
|
|
76
|
+
def remove_legacy_essence_tables
|
77
|
+
puts "\n## Removing legacy essence tables"
|
78
|
+
matching_tables = ActiveRecord::Base.connection.tables.select do |table|
|
79
|
+
table.start_with?("alchemy_essence_")
|
80
|
+
end
|
81
|
+
if matching_tables.length.zero?
|
82
|
+
log "No legacy essence tables found", :skip
|
83
|
+
nil
|
84
|
+
else
|
85
|
+
matching_tables.each do |table|
|
86
|
+
ActiveRecord::Base.connection.drop_table(table, if_exists: true)
|
87
|
+
print "."
|
88
|
+
end
|
89
|
+
puts "\n"
|
90
|
+
log "Deleted #{matching_tables.length} legacy essence tables"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
76
94
|
private
|
77
95
|
|
78
96
|
def destroy_orphaned_records(records, class_name)
|