rivet_cms 0.1.2.pre → 0.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 (127) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +53 -0
  3. data/COPYING +674 -0
  4. data/COPYING.LESSER +165 -0
  5. data/README.md +173 -10
  6. data/app/assets/builds/rivet_cms.css +2 -2
  7. data/app/assets/builds/rivet_cms.js +395 -9505
  8. data/app/assets/stylesheets/rivet_cms/application.tailwind.css +145 -22
  9. data/app/controllers/concerns/rivet_cms/inertia_props.rb +239 -0
  10. data/app/controllers/rivet_cms/api_docs_controller.rb +47 -0
  11. data/app/controllers/rivet_cms/api_tokens_controller.rb +43 -0
  12. data/app/controllers/rivet_cms/application_controller.rb +220 -2
  13. data/app/controllers/rivet_cms/auth_controller.rb +28 -0
  14. data/app/controllers/rivet_cms/components_controller.rb +93 -2
  15. data/app/controllers/rivet_cms/content_controller.rb +105 -0
  16. data/app/controllers/rivet_cms/content_manager_controller.rb +32 -0
  17. data/app/controllers/rivet_cms/content_types_controller.rb +118 -26
  18. data/app/controllers/rivet_cms/dashboard_controller.rb +55 -5
  19. data/app/controllers/rivet_cms/documents_controller.rb +204 -0
  20. data/app/controllers/rivet_cms/fields_controller.rb +77 -74
  21. data/app/controllers/rivet_cms/invitations_controller.rb +36 -0
  22. data/app/controllers/rivet_cms/media_assets_controller.rb +76 -0
  23. data/app/controllers/rivet_cms/sessions_controller.rb +122 -0
  24. data/app/controllers/rivet_cms/setup_controller.rb +60 -0
  25. data/app/controllers/rivet_cms/trash_controller.rb +68 -0
  26. data/app/controllers/rivet_cms/users_controller.rb +117 -0
  27. data/app/helpers/rivet_cms/application_helper.rb +13 -3
  28. data/app/helpers/rivet_cms/components_helper.rb +4 -0
  29. data/app/helpers/rivet_cms/content_types_helper.rb +4 -0
  30. data/app/helpers/rivet_cms/dashboard_helper.rb +4 -0
  31. data/app/jobs/rivet_cms/webhook_delivery_job.rb +35 -0
  32. data/app/models/concerns/rivet_cms/has_fields.rb +31 -0
  33. data/app/models/concerns/rivet_cms/organization_scoped.rb +17 -0
  34. data/app/models/concerns/rivet_cms/revision_owned.rb +36 -0
  35. data/app/models/concerns/rivet_cms/sluggable.rb +38 -0
  36. data/app/models/concerns/rivet_cms/soft_deletable.rb +42 -0
  37. data/app/models/concerns/rivet_cms/typed_value.rb +51 -0
  38. data/app/models/rivet_cms/api_token.rb +64 -0
  39. data/app/models/rivet_cms/category.rb +20 -0
  40. data/app/models/rivet_cms/component.rb +10 -0
  41. data/app/models/rivet_cms/component_instance.rb +27 -0
  42. data/app/models/rivet_cms/content_type.rb +36 -23
  43. data/app/models/rivet_cms/content_value.rb +19 -0
  44. data/app/models/rivet_cms/current.rb +6 -0
  45. data/app/models/rivet_cms/document.rb +71 -0
  46. data/app/models/rivet_cms/document_revision.rb +128 -0
  47. data/app/models/rivet_cms/entry.rb +73 -0
  48. data/app/models/rivet_cms/entry_collection.rb +41 -0
  49. data/app/models/rivet_cms/field.rb +203 -61
  50. data/app/models/rivet_cms/media_asset.rb +109 -0
  51. data/app/models/rivet_cms/organization.rb +46 -0
  52. data/app/models/rivet_cms/relation.rb +23 -0
  53. data/app/models/rivet_cms/user.rb +61 -0
  54. data/app/serializers/rivet_cms/revision_preloader.rb +146 -0
  55. data/app/serializers/rivet_cms/revision_serializer.rb +123 -0
  56. data/app/services/rivet_cms/content_query.rb +158 -0
  57. data/app/services/rivet_cms/content_validator.rb +150 -0
  58. data/app/services/rivet_cms/draft_writer.rb +74 -0
  59. data/app/services/rivet_cms/open_api_generator.rb +173 -221
  60. data/app/services/rivet_cms/revision_pruner.rb +64 -0
  61. data/app/services/rivet_cms/webhooks.rb +61 -0
  62. data/app/views/layouts/rivet_cms/application.html.erb +35 -42
  63. data/config/routes.rb +68 -45
  64. data/db/migrate/20251119193607_create_rivet_cms_organizations.rb +17 -0
  65. data/db/migrate/20251120050818_create_rivet_cms_content_types.rb +14 -0
  66. data/db/migrate/20251121020625_create_rivet_cms_components.rb +14 -0
  67. data/db/migrate/20251121040115_create_rivet_cms_categories.rb +14 -0
  68. data/db/migrate/20260119185946_create_content_system_tables.rb +95 -0
  69. data/db/migrate/20260722000001_create_rivet_cms_media_assets.rb +15 -0
  70. data/db/migrate/20260722000002_create_rivet_cms_api_tokens.rb +16 -0
  71. data/db/migrate/20260806000001_add_title_and_alt_to_rivet_cms_media_assets.rb +7 -0
  72. data/db/migrate/20260806000002_add_deleted_at_to_rivet_cms_content_types.rb +6 -0
  73. data/db/migrate/20260807000001_add_deleted_at_to_rivet_cms_documents.rb +6 -0
  74. data/db/migrate/20260808000001_create_rivet_cms_users.rb +15 -0
  75. data/db/seeds/README.md +70 -0
  76. data/db/seeds/templates/blog.rb +39 -0
  77. data/db/seeds/templates/events.rb +12 -0
  78. data/db/seeds/templates/faq.rb +9 -0
  79. data/db/seeds/templates/pages.rb +35 -0
  80. data/db/seeds/templates/site_settings.rb +22 -0
  81. data/db/seeds/templates/team.rb +11 -0
  82. data/db/seeds/templates/testimonials.rb +11 -0
  83. data/lib/generators/rivet_cms/install/install_generator.rb +13 -0
  84. data/lib/generators/rivet_cms/install/templates/initializer.rb +77 -0
  85. data/lib/rivet_cms/access_check.rb +12 -0
  86. data/lib/rivet_cms/audit.rb +43 -0
  87. data/lib/rivet_cms/engine.rb +28 -22
  88. data/lib/rivet_cms/hooks.rb +106 -0
  89. data/lib/rivet_cms/navigation.rb +111 -0
  90. data/lib/rivet_cms/safe_pattern.rb +40 -0
  91. data/lib/rivet_cms/seeds.rb +264 -0
  92. data/lib/rivet_cms/version.rb +1 -1
  93. data/lib/rivet_cms.rb +289 -32
  94. data/lib/tasks/rivet_cms_tasks.rake +18 -4
  95. metadata +138 -98
  96. data/MIT-LICENSE +0 -20
  97. data/app/assets/builds/rivet_cms.js.map +0 -7
  98. data/app/assets/stylesheets/rivet_cms/brand_colors.css +0 -168
  99. data/app/controllers/rivet_cms/api/docs_controller.rb +0 -38
  100. data/app/helpers/rivet_cms/brand_color_helper.rb +0 -71
  101. data/app/helpers/rivet_cms/flash_helper.rb +0 -37
  102. data/app/helpers/rivet_cms/sign_out_helper.rb +0 -11
  103. data/app/javascript/controllers/content_type_form_controller.js +0 -53
  104. data/app/javascript/controllers/field_layout_controller.js +0 -709
  105. data/app/javascript/rivet_cms.js +0 -29
  106. data/app/models/rivet_cms/content.rb +0 -4
  107. data/app/models/rivet_cms/field_values/base.rb +0 -11
  108. data/app/models/rivet_cms/field_values/boolean.rb +0 -4
  109. data/app/models/rivet_cms/field_values/integer.rb +0 -4
  110. data/app/models/rivet_cms/field_values/string.rb +0 -4
  111. data/app/models/rivet_cms/field_values/text.rb +0 -4
  112. data/app/views/rivet_cms/api/docs/show.html.erb +0 -47
  113. data/app/views/rivet_cms/content_types/_form.html.erb +0 -98
  114. data/app/views/rivet_cms/content_types/edit.html.erb +0 -27
  115. data/app/views/rivet_cms/content_types/index.html.erb +0 -151
  116. data/app/views/rivet_cms/content_types/new.html.erb +0 -19
  117. data/app/views/rivet_cms/content_types/show.html.erb +0 -147
  118. data/app/views/rivet_cms/dashboard/index.html.erb +0 -263
  119. data/app/views/rivet_cms/fields/_form.html.erb +0 -111
  120. data/app/views/rivet_cms/fields/edit.html.erb +0 -25
  121. data/app/views/rivet_cms/fields/index.html.erb +0 -126
  122. data/app/views/rivet_cms/fields/new.html.erb +0 -25
  123. data/app/views/rivet_cms/shared/_navigation.html.erb +0 -153
  124. data/config/i18n-tasks.yml +0 -178
  125. data/config/locales/en.yml +0 -14
  126. data/db/migrate/20250317194359_create_core_tables.rb +0 -90
  127. data/lib/rivet_cms/routes.rb +0 -49
@@ -1,168 +0,0 @@
1
- /*
2
- This file contains overrides for brand colors.
3
- It should be loaded after the main Tailwind CSS.
4
- */
5
-
6
- /* Brand color backgrounds */
7
- .bg-brand-50 { background-color: var(--color-brand-50) !important; }
8
- .bg-brand-100 { background-color: var(--color-brand-100) !important; }
9
- .bg-brand-200 { background-color: var(--color-brand-200) !important; }
10
- .bg-brand-300 { background-color: var(--color-brand-300) !important; }
11
- .bg-brand-400 { background-color: var(--color-brand-400) !important; }
12
- .bg-brand-500 { background-color: var(--color-brand-500) !important; }
13
- .bg-brand-600 { background-color: var(--color-brand-600) !important; }
14
- .bg-brand-700 { background-color: var(--color-brand-700) !important; }
15
- .bg-brand-800 { background-color: var(--color-brand-800) !important; }
16
- .bg-brand-900 { background-color: var(--color-brand-900) !important; }
17
- .bg-brand-950 { background-color: var(--color-brand-950) !important; }
18
-
19
- /* Brand color text */
20
- .text-brand-50 { color: var(--color-brand-50) !important; }
21
- .text-brand-100 { color: var(--color-brand-100) !important; }
22
- .text-brand-200 { color: var(--color-brand-200) !important; }
23
- .text-brand-300 { color: var(--color-brand-300) !important; }
24
- .text-brand-400 { color: var(--color-brand-400) !important; }
25
- .text-brand-500 { color: var(--color-brand-500) !important; }
26
- .text-brand-600 { color: var(--color-brand-600) !important; }
27
- .text-brand-700 { color: var(--color-brand-700) !important; }
28
- .text-brand-800 { color: var(--color-brand-800) !important; }
29
- .text-brand-900 { color: var(--color-brand-900) !important; }
30
- .text-brand-950 { color: var(--color-brand-950) !important; }
31
-
32
- /* Brand color borders */
33
- .border-brand-50 { border-color: var(--color-brand-50) !important; }
34
- .border-brand-100 { border-color: var(--color-brand-100) !important; }
35
- .border-brand-200 { border-color: var(--color-brand-200) !important; }
36
- .border-brand-300 { border-color: var(--color-brand-300) !important; }
37
- .border-brand-400 { border-color: var(--color-brand-400) !important; }
38
- .border-brand-500 { border-color: var(--color-brand-500) !important; }
39
- .border-brand-600 { border-color: var(--color-brand-600) !important; }
40
- .border-brand-700 { border-color: var(--color-brand-700) !important; }
41
- .border-brand-800 { border-color: var(--color-brand-800) !important; }
42
- .border-brand-900 { border-color: var(--color-brand-900) !important; }
43
- .border-brand-950 { border-color: var(--color-brand-950) !important; }
44
-
45
- /* Hover states */
46
- .hover\:bg-brand-50:hover { background-color: var(--color-brand-50) !important; }
47
- .hover\:bg-brand-100:hover { background-color: var(--color-brand-100) !important; }
48
- .hover\:bg-brand-200:hover { background-color: var(--color-brand-200) !important; }
49
- .hover\:bg-brand-300:hover { background-color: var(--color-brand-300) !important; }
50
- .hover\:bg-brand-400:hover { background-color: var(--color-brand-400) !important; }
51
- .hover\:bg-brand-500:hover { background-color: var(--color-brand-500) !important; }
52
- .hover\:bg-brand-600:hover { background-color: var(--color-brand-600) !important; }
53
- .hover\:bg-brand-700:hover { background-color: var(--color-brand-700) !important; }
54
- .hover\:bg-brand-800:hover { background-color: var(--color-brand-800) !important; }
55
- .hover\:bg-brand-900:hover { background-color: var(--color-brand-900) !important; }
56
- .hover\:bg-brand-950:hover { background-color: var(--color-brand-950) !important; }
57
-
58
- .hover\:text-brand-50:hover { color: var(--color-brand-50) !important; }
59
- .hover\:text-brand-100:hover { color: var(--color-brand-100) !important; }
60
- .hover\:text-brand-200:hover { color: var(--color-brand-200) !important; }
61
- .hover\:text-brand-300:hover { color: var(--color-brand-300) !important; }
62
- .hover\:text-brand-400:hover { color: var(--color-brand-400) !important; }
63
- .hover\:text-brand-500:hover { color: var(--color-brand-500) !important; }
64
- .hover\:text-brand-600:hover { color: var(--color-brand-600) !important; }
65
- .hover\:text-brand-700:hover { color: var(--color-brand-700) !important; }
66
- .hover\:text-brand-800:hover { color: var(--color-brand-800) !important; }
67
- .hover\:text-brand-900:hover { color: var(--color-brand-900) !important; }
68
- .hover\:text-brand-950:hover { color: var(--color-brand-950) !important; }
69
-
70
- .hover\:border-brand-50:hover { border-color: var(--color-brand-50) !important; }
71
- .hover\:border-brand-100:hover { border-color: var(--color-brand-100) !important; }
72
- .hover\:border-brand-200:hover { border-color: var(--color-brand-200) !important; }
73
- .hover\:border-brand-300:hover { border-color: var(--color-brand-300) !important; }
74
- .hover\:border-brand-400:hover { border-color: var(--color-brand-400) !important; }
75
- .hover\:border-brand-500:hover { border-color: var(--color-brand-500) !important; }
76
- .hover\:border-brand-600:hover { border-color: var(--color-brand-600) !important; }
77
- .hover\:border-brand-700:hover { border-color: var(--color-brand-700) !important; }
78
- .hover\:border-brand-800:hover { border-color: var(--color-brand-800) !important; }
79
- .hover\:border-brand-900:hover { border-color: var(--color-brand-900) !important; }
80
- .hover\:border-brand-950:hover { border-color: var(--color-brand-950) !important; }
81
-
82
- /* Focus states */
83
- .focus\:ring-brand-50:focus { --tw-ring-color: var(--color-brand-50) !important; }
84
- .focus\:ring-brand-100:focus { --tw-ring-color: var(--color-brand-100) !important; }
85
- .focus\:ring-brand-200:focus { --tw-ring-color: var(--color-brand-200) !important; }
86
- .focus\:ring-brand-300:focus { --tw-ring-color: var(--color-brand-300) !important; }
87
- .focus\:ring-brand-400:focus { --tw-ring-color: var(--color-brand-400) !important; }
88
- .focus\:ring-brand-500:focus { --tw-ring-color: var(--color-brand-500) !important; }
89
- .focus\:ring-brand-600:focus { --tw-ring-color: var(--color-brand-600) !important; }
90
- .focus\:ring-brand-700:focus { --tw-ring-color: var(--color-brand-700) !important; }
91
- .focus\:ring-brand-800:focus { --tw-ring-color: var(--color-brand-800) !important; }
92
- .focus\:ring-brand-900:focus { --tw-ring-color: var(--color-brand-900) !important; }
93
- .focus\:ring-brand-950:focus { --tw-ring-color: var(--color-brand-950) !important; }
94
-
95
- .focus\:border-brand-50:focus { border-color: var(--color-brand-50) !important; }
96
- .focus\:border-brand-100:focus { border-color: var(--color-brand-100) !important; }
97
- .focus\:border-brand-200:focus { border-color: var(--color-brand-200) !important; }
98
- .focus\:border-brand-300:focus { border-color: var(--color-brand-300) !important; }
99
- .focus\:border-brand-400:focus { border-color: var(--color-brand-400) !important; }
100
- .focus\:border-brand-500:focus { border-color: var(--color-brand-500) !important; }
101
- .focus\:border-brand-600:focus { border-color: var(--color-brand-600) !important; }
102
- .focus\:border-brand-700:focus { border-color: var(--color-brand-700) !important; }
103
- .focus\:border-brand-800:focus { border-color: var(--color-brand-800) !important; }
104
- .focus\:border-brand-900:focus { border-color: var(--color-brand-900) !important; }
105
- .focus\:border-brand-950:focus { border-color: var(--color-brand-950) !important; }
106
-
107
-
108
- [type='text']:focus,
109
- [type='email']:focus,
110
- [type='url']:focus,
111
- [type='password']:focus,
112
- [type='number']:focus,
113
- [type='date']:focus,
114
- [type='datetime-local']:focus,
115
- [type='month']:focus,
116
- [type='search']:focus,
117
- [type='tel']:focus,
118
- [type='time']:focus,
119
- [type='week']:focus,
120
- [multiple]:focus,
121
- textarea:focus,
122
- select:focus {
123
- --tw-ring-color: var(--color-brand-500) !important;
124
- --tw-ring-opacity: 0.5 !important;
125
- border-color: var(--color-brand-500) !important;
126
- outline: 2px solid transparent;
127
- outline-offset: 2px;
128
- }
129
-
130
- /* Override focus styles for checkboxes and radio buttons */
131
- [type='checkbox']:focus,
132
- [type='radio']:focus {
133
- --tw-ring-color: var(--color-brand-500) !important;
134
- --tw-ring-opacity: 0.5 !important;
135
- outline: 2px solid transparent;
136
- outline-offset: 2px;
137
- }
138
-
139
- /* Override checked styles for checkboxes and radio buttons */
140
- [type='checkbox']:checked,
141
- [type='radio']:checked {
142
- background-color: var(--color-brand-600) !important;
143
- border-color: var(--color-brand-600) !important;
144
- }
145
-
146
- /* Override focus-visible styles for all form elements */
147
- [type='text']:focus-visible,
148
- [type='email']:focus-visible,
149
- [type='url']:focus-visible,
150
- [type='password']:focus-visible,
151
- [type='number']:focus-visible,
152
- [type='date']:focus-visible,
153
- [type='datetime-local']:focus-visible,
154
- [type='month']:focus-visible,
155
- [type='search']:focus-visible,
156
- [type='tel']:focus-visible,
157
- [type='time']:focus-visible,
158
- [type='week']:focus-visible,
159
- [multiple]:focus-visible,
160
- textarea:focus-visible,
161
- select:focus-visible,
162
- [type='checkbox']:focus-visible,
163
- [type='radio']:focus-visible {
164
- --tw-ring-color: var(--color-brand-500) !important;
165
- --tw-ring-opacity: 0.5 !important;
166
- outline: 2px solid transparent;
167
- outline-offset: 2px;
168
- }
@@ -1,38 +0,0 @@
1
- module RivetCms
2
- module Api
3
- class DocsController < RivetCms::ApplicationController
4
- layout false
5
-
6
- def show
7
- @schema = RivetCms::OpenApiGenerator.generate
8
-
9
- respond_to do |format|
10
- format.html
11
- format.json { render json: @schema }
12
- format.yaml { render plain: @schema.to_yaml, content_type: 'application/x-yaml' }
13
- rescue StandardError => e
14
- Rails.logger.error "Error generating API documentation: #{e.message}"
15
- render_error_response(format)
16
- end
17
- end
18
-
19
- private
20
-
21
- def render_error_response(format)
22
- error_schema = {
23
- openapi: "3.0.1",
24
- info: {
25
- title: "API Documentation Temporarily Unavailable",
26
- version: "1.0.0",
27
- description: "There was an error generating the API documentation. Please try again later."
28
- },
29
- paths: {}
30
- }
31
-
32
- format.html { render :error, status: :internal_server_error }
33
- format.json { render json: error_schema, status: :internal_server_error }
34
- format.yaml { render plain: error_schema.to_yaml, status: :internal_server_error }
35
- end
36
- end
37
- end
38
- end
@@ -1,71 +0,0 @@
1
- module RivetCms
2
- module BrandColorHelper
3
- # Generate CSS for brand colors based on the primary color
4
- def brand_color_css
5
- base_color = "#ff7043"
6
-
7
- # Generate CSS variables for all the shades
8
- <<~CSS
9
- <style id="brand-colors">
10
- :root {
11
- --color-brand-50: #{lighten_color(base_color, 0.85)};
12
- --color-brand-100: #{lighten_color(base_color, 0.7)};
13
- --color-brand-200: #{lighten_color(base_color, 0.55)};
14
- --color-brand-300: #{lighten_color(base_color, 0.4)};
15
- --color-brand-400: #{lighten_color(base_color, 0.2)};
16
- --color-brand-500: #{lighten_color(base_color, 0.1)};
17
- --color-brand-600: #{base_color};
18
- --color-brand-700: #{darken_color(base_color, 0.1)};
19
- --color-brand-800: #{darken_color(base_color, 0.2)};
20
- --color-brand-900: #{darken_color(base_color, 0.3)};
21
- --color-brand-950: #{darken_color(base_color, 0.4)};
22
- }
23
- </style>
24
- CSS
25
- end
26
-
27
- private
28
-
29
- # Simple color manipulation helpers
30
- def lighten_color(hex_color, amount)
31
- manipulate_color(hex_color) do |r, g, b|
32
- [
33
- [(r + (255 - r) * amount).round, 255].min,
34
- [(g + (255 - g) * amount).round, 255].min,
35
- [(b + (255 - b) * amount).round, 255].min
36
- ]
37
- end
38
- end
39
-
40
- def darken_color(hex_color, amount)
41
- manipulate_color(hex_color) do |r, g, b|
42
- [
43
- [(r * (1 - amount)).round, 0].max,
44
- [(g * (1 - amount)).round, 0].max,
45
- [(b * (1 - amount)).round, 0].max
46
- ]
47
- end
48
- end
49
-
50
- def manipulate_color(hex_color)
51
- hex_color = hex_color.gsub('#', '')
52
-
53
- # Convert to RGB
54
- if hex_color.length == 3
55
- r = hex_color[0].to_i(16) * 17
56
- g = hex_color[1].to_i(16) * 17
57
- b = hex_color[2].to_i(16) * 17
58
- else
59
- r = hex_color[0..1].to_i(16)
60
- g = hex_color[2..3].to_i(16)
61
- b = hex_color[4..5].to_i(16)
62
- end
63
-
64
- # Apply transformation
65
- new_r, new_g, new_b = yield(r, g, b)
66
-
67
- # Convert back to hex
68
- "#%02x%02x%02x" % [new_r, new_g, new_b]
69
- end
70
- end
71
- end
@@ -1,37 +0,0 @@
1
- module RivetCms
2
- module FlashHelper
3
- def flash_class_for(type)
4
- case type.to_sym
5
- when :notice, :success
6
- "bg-green-50"
7
- when :error, :alert
8
- "bg-red-50"
9
- when :warning
10
- "bg-yellow-50"
11
- else
12
- "bg-gray-50"
13
- end
14
- end
15
-
16
- def flash_icon_for(type)
17
- case type.to_sym
18
- when :notice, :success
19
- content_tag(:svg, class: "h-5 w-5 text-green-400", viewBox: "0 0 20 20", fill: "currentColor") do
20
- content_tag(:path, nil, fill_rule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z", clip_rule: "evenodd")
21
- end
22
- when :error, :alert
23
- content_tag(:svg, class: "h-5 w-5 text-red-400", viewBox: "0 0 20 20", fill: "currentColor") do
24
- content_tag(:path, nil, fill_rule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z", clip_rule: "evenodd")
25
- end
26
- when :warning
27
- content_tag(:svg, class: "h-5 w-5 text-yellow-400", viewBox: "0 0 20 20", fill: "currentColor") do
28
- content_tag(:path, nil, fill_rule: "evenodd", d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z", clip_rule: "evenodd")
29
- end
30
- else
31
- content_tag(:svg, class: "h-5 w-5 text-gray-400", viewBox: "0 0 20 20", fill: "currentColor") do
32
- content_tag(:path, nil, fill_rule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clip_rule: "evenodd")
33
- end
34
- end
35
- end
36
- end
37
- end
@@ -1,11 +0,0 @@
1
- module RivetCms
2
- module SignOutHelper
3
- # Returns the sign-out path for the application.
4
- # Uses RivetCmsAuth’s auth_sign_out_path if available, otherwise falls back to the configured path or root.
5
- def rivet_sign_out_path
6
- config = RivetCms.configuration
7
- return config.sign_out_path.call if config.sign_out_path.respond_to?(:call)
8
- config.sign_out_path || "/"
9
- end
10
- end
11
- end
@@ -1,53 +0,0 @@
1
- import { Controller } from "@hotwired/stimulus"
2
- import pluralize from "pluralize"
3
-
4
- export default class extends Controller {
5
- static targets = ["name", "slug", "isSingle"]
6
-
7
- connect() {
8
- this.nameTarget.addEventListener("input", this.updateSlug.bind(this))
9
- this.isSingleTarget.addEventListener("change", this.updateSlug.bind(this))
10
- this.lastGeneratedSlug = this.slugTarget.value
11
- }
12
-
13
- updateSlug() {
14
- const name = this.nameTarget.value.trim()
15
- if (!name) {
16
- this.slugTarget.value = ""
17
- return
18
- }
19
-
20
- let slug = this.generateSlug(name)
21
- if (!slug) {
22
- this.slugTarget.value = ""
23
- return
24
- }
25
-
26
- const isSingle = this.isSingleTarget.checked
27
- if (isSingle && pluralize.isPlural(slug)) {
28
- slug = pluralize.singular(slug)
29
- } else if (!isSingle && !pluralize.isPlural(slug)) {
30
- slug = pluralize(slug)
31
- }
32
-
33
- if (slug !== this.lastGeneratedSlug) {
34
- this.slugTarget.value = slug
35
- this.lastGeneratedSlug = slug
36
- }
37
- }
38
-
39
- generateSlug(text) {
40
- return text
41
- .toLowerCase()
42
- .replace(/[\s_]+/g, "-") // Spaces or underscores to hyphen
43
- .replace(/[^a-z0-9-]/g, "") // Keep letters, numbers, hyphens
44
- .replace(/-+/g, "-") // Collapse hyphens
45
- .replace(/^-|-$/g, "") // Trim leading/trailing hyphens
46
- .trim()
47
- }
48
-
49
- disconnect() {
50
- this.nameTarget.removeEventListener("input", this.updateSlug.bind(this))
51
- this.isSingleTarget.removeEventListener("change", this.updateSlug.bind(this))
52
- }
53
- }