active_canvas 0.0.1

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 (80) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +318 -0
  4. data/Rakefile +6 -0
  5. data/app/assets/javascripts/active_canvas/editor/ai_panel.js +1607 -0
  6. data/app/assets/javascripts/active_canvas/editor/asset_manager.js +498 -0
  7. data/app/assets/javascripts/active_canvas/editor/blocks.js +1083 -0
  8. data/app/assets/javascripts/active_canvas/editor/code_panel.js +572 -0
  9. data/app/assets/javascripts/active_canvas/editor/component_toolbar.js +394 -0
  10. data/app/assets/javascripts/active_canvas/editor/panels.js +460 -0
  11. data/app/assets/javascripts/active_canvas/editor/utils.js +56 -0
  12. data/app/assets/javascripts/active_canvas/editor.js +295 -0
  13. data/app/assets/stylesheets/active_canvas/application.css +15 -0
  14. data/app/assets/stylesheets/active_canvas/editor.css +2929 -0
  15. data/app/controllers/active_canvas/admin/ai_controller.rb +181 -0
  16. data/app/controllers/active_canvas/admin/application_controller.rb +56 -0
  17. data/app/controllers/active_canvas/admin/media_controller.rb +61 -0
  18. data/app/controllers/active_canvas/admin/page_types_controller.rb +57 -0
  19. data/app/controllers/active_canvas/admin/page_versions_controller.rb +23 -0
  20. data/app/controllers/active_canvas/admin/pages_controller.rb +133 -0
  21. data/app/controllers/active_canvas/admin/partials_controller.rb +88 -0
  22. data/app/controllers/active_canvas/admin/settings_controller.rb +256 -0
  23. data/app/controllers/active_canvas/application_controller.rb +20 -0
  24. data/app/controllers/active_canvas/pages_controller.rb +18 -0
  25. data/app/controllers/concerns/active_canvas/current_user.rb +12 -0
  26. data/app/controllers/concerns/active_canvas/rate_limitable.rb +75 -0
  27. data/app/controllers/concerns/active_canvas/tailwind_compilation.rb +39 -0
  28. data/app/helpers/active_canvas/application_helper.rb +4 -0
  29. data/app/jobs/active_canvas/application_job.rb +4 -0
  30. data/app/jobs/active_canvas/compile_tailwind_job.rb +64 -0
  31. data/app/mailers/active_canvas/application_mailer.rb +6 -0
  32. data/app/models/active_canvas/ai_model.rb +136 -0
  33. data/app/models/active_canvas/application_record.rb +5 -0
  34. data/app/models/active_canvas/media.rb +141 -0
  35. data/app/models/active_canvas/page.rb +85 -0
  36. data/app/models/active_canvas/page_type.rb +22 -0
  37. data/app/models/active_canvas/page_version.rb +80 -0
  38. data/app/models/active_canvas/partial.rb +73 -0
  39. data/app/models/active_canvas/setting.rb +292 -0
  40. data/app/services/active_canvas/ai_configuration.rb +40 -0
  41. data/app/services/active_canvas/ai_models.rb +128 -0
  42. data/app/services/active_canvas/ai_service.rb +289 -0
  43. data/app/services/active_canvas/content_sanitizer.rb +112 -0
  44. data/app/services/active_canvas/tailwind_compiler.rb +156 -0
  45. data/app/views/active_canvas/admin/media/index.html.erb +401 -0
  46. data/app/views/active_canvas/admin/media/show.html.erb +297 -0
  47. data/app/views/active_canvas/admin/page_types/_form.html.erb +25 -0
  48. data/app/views/active_canvas/admin/page_types/edit.html.erb +13 -0
  49. data/app/views/active_canvas/admin/page_types/index.html.erb +29 -0
  50. data/app/views/active_canvas/admin/page_types/new.html.erb +9 -0
  51. data/app/views/active_canvas/admin/page_types/show.html.erb +18 -0
  52. data/app/views/active_canvas/admin/page_versions/show.html.erb +469 -0
  53. data/app/views/active_canvas/admin/pages/_form.html.erb +62 -0
  54. data/app/views/active_canvas/admin/pages/content.html.erb +139 -0
  55. data/app/views/active_canvas/admin/pages/edit.html.erb +335 -0
  56. data/app/views/active_canvas/admin/pages/editor.html.erb +710 -0
  57. data/app/views/active_canvas/admin/pages/index.html.erb +149 -0
  58. data/app/views/active_canvas/admin/pages/new.html.erb +19 -0
  59. data/app/views/active_canvas/admin/pages/show.html.erb +258 -0
  60. data/app/views/active_canvas/admin/pages/versions.html.erb +333 -0
  61. data/app/views/active_canvas/admin/partials/edit.html.erb +182 -0
  62. data/app/views/active_canvas/admin/partials/editor.html.erb +703 -0
  63. data/app/views/active_canvas/admin/partials/index.html.erb +131 -0
  64. data/app/views/active_canvas/admin/settings/show.html.erb +1864 -0
  65. data/app/views/active_canvas/pages/no_homepage.html.erb +45 -0
  66. data/app/views/active_canvas/pages/show.html.erb +113 -0
  67. data/app/views/layouts/active_canvas/admin/application.html.erb +960 -0
  68. data/app/views/layouts/active_canvas/admin/editor.html.erb +826 -0
  69. data/app/views/layouts/active_canvas/application.html.erb +55 -0
  70. data/config/routes.rb +48 -0
  71. data/db/migrate/20260202000001_create_active_canvas_tables.rb +113 -0
  72. data/db/migrate/20260202000002_create_active_canvas_ai_models.rb +26 -0
  73. data/lib/active_canvas/configuration.rb +232 -0
  74. data/lib/active_canvas/engine.rb +44 -0
  75. data/lib/active_canvas/version.rb +3 -0
  76. data/lib/active_canvas.rb +26 -0
  77. data/lib/generators/active_canvas/install/install_generator.rb +263 -0
  78. data/lib/generators/active_canvas/install/templates/initializer.rb.tt +163 -0
  79. data/lib/tasks/active_canvas_tasks.rake +69 -0
  80. metadata +150 -0
@@ -0,0 +1,295 @@
1
+ /**
2
+ * ActiveCanvas Visual Editor
3
+ *
4
+ * Main entry point that orchestrates all editor modules.
5
+ * Configuration is passed via window.ActiveCanvasEditor.config
6
+ *
7
+ * Module dependencies (loaded in order):
8
+ * - editor/utils.js - Utility functions
9
+ * - editor/blocks.js - Custom block definitions
10
+ * - editor/asset_manager.js - Asset manager modal
11
+ * - editor/code_panel.js - Monaco code editor
12
+ * - editor/component_toolbar.js - Component toolbar/menu
13
+ * - editor/panels.js - Panel controls, save, devices
14
+ * - editor.js - This file (main orchestrator)
15
+ */
16
+
17
+ (function() {
18
+ 'use strict';
19
+
20
+ // Initialize namespace
21
+ window.ActiveCanvasEditor = window.ActiveCanvasEditor || {};
22
+
23
+ // Wait for DOM and config to be ready
24
+ document.addEventListener('DOMContentLoaded', function() {
25
+ if (!window.ActiveCanvasEditor || !window.ActiveCanvasEditor.config) {
26
+ console.error('ActiveCanvasEditor config not found');
27
+ return;
28
+ }
29
+
30
+ const config = window.ActiveCanvasEditor.config;
31
+ initEditor(config);
32
+ });
33
+
34
+ /**
35
+ * Initialize the GrapeJS editor and all modules
36
+ * @param {Object} config - Editor configuration from Rails
37
+ */
38
+ function initEditor(config) {
39
+ const csrfToken = window.ActiveCanvasEditor.getCsrfToken();
40
+
41
+ // Parse components JSON if available, otherwise use HTML content
42
+ let componentsToLoad = config.content || '';
43
+ if (config.contentComponents) {
44
+ try {
45
+ componentsToLoad = JSON.parse(config.contentComponents);
46
+ } catch (e) {
47
+ console.warn('Could not parse components JSON, falling back to HTML content');
48
+ componentsToLoad = config.content || '';
49
+ }
50
+ }
51
+
52
+ // Determine canvas configuration based on framework
53
+ const canvasConfig = buildCanvasConfig(config);
54
+
55
+ // Initialize GrapeJS
56
+ const editor = grapesjs.init({
57
+ container: '#gjs',
58
+ height: '100%',
59
+ width: 'auto',
60
+ fromElement: false,
61
+
62
+ // Load existing content
63
+ components: componentsToLoad,
64
+ style: config.contentCss || '',
65
+
66
+ // Storage - we'll handle saving manually
67
+ storageManager: false,
68
+
69
+ // Device Manager
70
+ deviceManager: {
71
+ devices: [
72
+ { name: 'Desktop', width: '' },
73
+ { name: 'Tablet', width: '768px', widthMedia: '992px' },
74
+ { name: 'Mobile', width: '320px', widthMedia: '480px' }
75
+ ]
76
+ },
77
+
78
+ // Panels - we'll use custom panels
79
+ panels: { defaults: [] },
80
+
81
+ // Block Manager
82
+ blockManager: {
83
+ appendTo: '#blocks-container'
84
+ },
85
+
86
+ // Layer Manager
87
+ layerManager: {
88
+ appendTo: '#layers-container'
89
+ },
90
+
91
+ // Style Manager
92
+ styleManager: {
93
+ appendTo: '#styles-container',
94
+ sectors: [
95
+ {
96
+ name: 'Dimension',
97
+ open: true,
98
+ buildProps: ['width', 'min-width', 'max-width', 'height', 'min-height', 'max-height', 'padding', 'margin']
99
+ },
100
+ {
101
+ name: 'Typography',
102
+ open: false,
103
+ buildProps: ['font-family', 'font-size', 'font-weight', 'letter-spacing', 'color', 'line-height', 'text-align', 'text-decoration', 'text-shadow']
104
+ },
105
+ {
106
+ name: 'Decorations',
107
+ open: false,
108
+ buildProps: ['background-color', 'border-radius', 'border', 'box-shadow']
109
+ },
110
+ {
111
+ name: 'Extra',
112
+ open: false,
113
+ buildProps: ['opacity', 'transition', 'transform']
114
+ }
115
+ ]
116
+ },
117
+
118
+ // Trait Manager
119
+ traitManager: {
120
+ appendTo: '#traits-container'
121
+ },
122
+
123
+ // Selector Manager
124
+ selectorManager: {
125
+ appendTo: '#styles-container',
126
+ componentFirst: true
127
+ },
128
+
129
+ // Asset Manager (basic config, custom modal handles most functionality)
130
+ assetManager: {
131
+ uploadName: 'media[file]',
132
+ uploadFile: createUploadHandler(config, csrfToken),
133
+ assets: []
134
+ },
135
+
136
+ // Canvas
137
+ canvas: canvasConfig,
138
+
139
+ // Plugins
140
+ plugins: [
141
+ 'gjs-blocks-basic',
142
+ 'grapesjs-plugin-forms',
143
+ 'grapesjs-preset-webpage',
144
+ 'grapesjs-style-bg',
145
+ 'grapesjs-tabs',
146
+ 'grapesjs-custom-code',
147
+ 'grapesjs-touch',
148
+ 'grapesjs-parser-postcss',
149
+ 'grapesjs-tooltip',
150
+ 'grapesjs-typed'
151
+ ],
152
+
153
+ pluginsOpts: {
154
+ 'gjs-blocks-basic': {
155
+ flexGrid: true,
156
+ stylePrefix: 'gjs-'
157
+ },
158
+ 'grapesjs-plugin-forms': {},
159
+ 'grapesjs-preset-webpage': {
160
+ modalImportTitle: 'Import Template',
161
+ modalImportLabel: '<div style="margin-bottom: 10px; font-size: 13px;">Paste your HTML/CSS here</div>',
162
+ modalImportContent: function(editor) {
163
+ return editor.getHtml() + '<style>' + editor.getCss() + '</style>';
164
+ }
165
+ },
166
+ 'grapesjs-tabs': {
167
+ tabsBlock: { category: 'Extra' }
168
+ },
169
+ 'grapesjs-typed': {
170
+ block: {
171
+ category: 'Extra',
172
+ content: {
173
+ type: 'typed',
174
+ 'type-speed': 40,
175
+ strings: ['Text row one', 'Text row two', 'Text row three']
176
+ }
177
+ }
178
+ }
179
+ }
180
+ });
181
+
182
+ // Setup all modules
183
+ setupModules(editor, config, csrfToken);
184
+
185
+ // Expose editor instance for debugging
186
+ window.ActiveCanvasEditor.instance = editor;
187
+ }
188
+
189
+ /**
190
+ * Build canvas configuration based on CSS framework
191
+ */
192
+ function buildCanvasConfig(config) {
193
+ const canvasStyles = [];
194
+ const canvasScripts = [];
195
+
196
+ if (config.cssFrameworkUrl) {
197
+ if (config.cssFrameworkType === 'script') {
198
+ canvasScripts.push(config.cssFrameworkUrl);
199
+ } else if (config.cssFrameworkType === 'stylesheet') {
200
+ canvasStyles.push(config.cssFrameworkUrl);
201
+ }
202
+ }
203
+
204
+ return {
205
+ styles: canvasStyles,
206
+ scripts: canvasScripts
207
+ };
208
+ }
209
+
210
+ /**
211
+ * Create the upload handler for the asset manager
212
+ */
213
+ function createUploadHandler(config, csrfToken) {
214
+ const { showToast } = window.ActiveCanvasEditor;
215
+
216
+ return function(e) {
217
+ const files = e.dataTransfer ? e.dataTransfer.files : e.target.files;
218
+ const formData = new FormData();
219
+ const editor = window.ActiveCanvasEditor.instance;
220
+
221
+ for (let i = 0; i < files.length; i++) {
222
+ formData.append('media[file]', files[i]);
223
+ formData.append('media[filename]', files[i].name);
224
+ }
225
+
226
+ fetch(config.uploadUrl, {
227
+ method: 'POST',
228
+ headers: {
229
+ 'X-CSRF-Token': csrfToken
230
+ },
231
+ body: formData
232
+ })
233
+ .then(response => response.json())
234
+ .then(result => {
235
+ if (result.src) {
236
+ editor.AssetManager.add(result);
237
+ showToast('Image uploaded successfully', 'success');
238
+ } else if (result.errors) {
239
+ showToast(result.errors.join(', '), 'error');
240
+ }
241
+ })
242
+ .catch(error => {
243
+ showToast('Upload failed', 'error');
244
+ console.error('Upload error:', error);
245
+ });
246
+ };
247
+ }
248
+
249
+ /**
250
+ * Setup all editor modules
251
+ */
252
+ function setupModules(editor, config, csrfToken) {
253
+ const AC = window.ActiveCanvasEditor;
254
+
255
+ // Add custom blocks (framework-specific based on config.cssFramework)
256
+ AC.addCustomBlocks(editor, config);
257
+
258
+ // Load existing assets
259
+ AC.loadAssets(editor, config.mediaUrl);
260
+
261
+ // Setup component toolbar and context menu
262
+ AC.setupComponentToolbar(editor);
263
+
264
+ // Inject global and page-specific CSS/JS into canvas
265
+ AC.setupCanvasInjection(editor, config);
266
+
267
+ // Setup panel controls
268
+ AC.setupPanelControls(editor);
269
+
270
+ // Setup device switching
271
+ AC.setupDeviceSwitching(editor);
272
+
273
+ // Setup undo/redo
274
+ AC.setupUndoRedo(editor);
275
+
276
+ // Setup code panel
277
+ AC.setupCodePanel(editor, config);
278
+
279
+ // Setup save functionality
280
+ AC.setupSave(editor, config, csrfToken);
281
+
282
+ // Setup add section button
283
+ AC.setupAddSection(editor);
284
+
285
+ // Setup RTE toolbar visibility
286
+ AC.setupRteToolbar(editor);
287
+
288
+ // Setup assets panel
289
+ AC.setupAssetsPanel(editor, config, csrfToken);
290
+
291
+ // Setup custom asset manager modal
292
+ AC.setupCustomAssetManager(editor, config, csrfToken);
293
+ }
294
+
295
+ })();
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */