meta_workflows 0.7.1 → 0.8.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd9461e41652231e6ddcbd6aff71c4ced97fdb79a1a349a2cd789a0803379d67
4
- data.tar.gz: 778d893c99b094d987021a41b6a80966044abae432a5a3644ec629339756daee
3
+ metadata.gz: 431a4051a349e98758ed8b86e331191c4cab06e76fb6baeb873e35993b8d7ac3
4
+ data.tar.gz: ced2c7a5b62d0f6c12b9a369dd750e9027bb93fd68f702ae6fb7191eaf0e9fc0
5
5
  SHA512:
6
- metadata.gz: 6473b7dbcaab6cbb688846dbba1bc403081f6b63d0833da4033a57fb45b8b316d104ab4273a260d2b23f06750b8770d914dd3f89749a1822f11a0b82d3b7ea7c
7
- data.tar.gz: 05e7e92d737f5d2dc6a3f8b39e4be6aa0e456d07738f4d91e9e9f1f2bb0f2f990d74e9dd307d40fb3b44ea5ee4f1909933a18e8c19c7d57217a234f9dbb3fd2d
6
+ metadata.gz: c309e7acdaab0f25f4451a688cda47c19fa2367d394e1e0392ef596c7ab78d3a44fc08259ae2c6871fa51d95ab35a1c853f442824a8290a0afabe7963fde5738
7
+ data.tar.gz: 6270d2f04ebfc06e624cb5881578b46490550256558e22e3c8599af384e5de4fe5b0616317acf585a094e9ce34df02197cf9fd58811b5f62ba8324f34006582d
data/README.md CHANGED
@@ -524,3 +524,72 @@ For detailed information about the MetaWorkflows system:
524
524
  ## License
525
525
 
526
526
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
527
+
528
+ ## Tray System (Sidebar, Bottom, and Main Content Trays)
529
+
530
+ MetaWorkflows provides a flexible tray system for building modern, multi-pane layouts. The tray system supports left (Beta), right (Gamma), and bottom (Delta) trays, as well as a main content area (Alpha). Each tray can be shown, hidden, or made collapsible on a per-controller or per-page basis.
531
+
532
+ ### Tray Placement Overview
533
+
534
+ | Tray | Placement | Description |
535
+ |:-----:|:--------------|:--------------------------------------------|
536
+ | Beta | Left sidebar | Optional collapsible sidebar on the left |
537
+ | Alpha | Center/main | Main content area (always visible) |
538
+ | Gamma | Right sidebar | Optional collapsible sidebar on the right |
539
+ | Delta | Bottom tray | Optional collapsible tray at the bottom |
540
+
541
+ ### How It Works
542
+ - The tray system is controlled by a `TrayConfigurable` concern included in your controllers.
543
+ - By default, all trays are hidden. You must explicitly set `visible: true` for any tray you want to show.
544
+ - The engine's layout will automatically respect your tray configuration.
545
+
546
+ ### Enabling and Configuring Trays
547
+
548
+ 1. **Include the Concern in Your ApplicationController:**
549
+
550
+ ```ruby
551
+ class ApplicationController < ActionController::Base
552
+ include TrayConfigurable
553
+ before_action :configure_trays
554
+ end
555
+ ```
556
+
557
+ 2. **Override Tray Settings in Any Controller:**
558
+
559
+ ```ruby
560
+ class PostsController < ApplicationController
561
+ def configure_trays
562
+ super
563
+ tray_config[:beta][:visible] = true # Show Beta (left) tray
564
+ tray_config[:gamma][:visible] = false # Hide Gamma (right) tray
565
+ tray_config[:delta][:collapsible] = false # Make Delta (bottom) tray not collapsible
566
+ end
567
+ end
568
+ ```
569
+
570
+ 3. **Default Behavior:**
571
+ - All trays are hidden unless set to `visible: true`.
572
+ - Trays are collapsible by default; set `collapsible: false` to disable collapsing.
573
+
574
+ 4. **Layout:**
575
+ - The engine's layout (`app/views/layouts/meta_workflows/application.html.erb`) will automatically render trays based on your configuration.
576
+
577
+ ### Example: Show Only the Left Tray
578
+
579
+ ```ruby
580
+ class DashboardController < ApplicationController
581
+ def configure_trays
582
+ super
583
+ tray_config[:beta][:visible] = true
584
+ tray_config[:gamma][:visible] = false
585
+ tray_config[:delta][:visible] = false
586
+ end
587
+ end
588
+ ```
589
+
590
+ ### Notes
591
+ - The tray system is available in both the engine and the dummy app for development/testing.
592
+ - You can override tray configuration per controller or per action as needed.
593
+ - The main content area (Alpha tray) is always visible and holds your page content.
594
+
595
+ For more advanced usage or to contribute improvements, see the tray logic in `TrayConfigurable` and the engine layout file.
@@ -0,0 +1,109 @@
1
+ import { Controller } from "@hotwired/stimulus"
2
+
3
+ function getCookie(name) {
4
+ const value = `; ${document.cookie}`;
5
+ const parts = value.split(`; ${name}=`);
6
+ if (parts.length !== 2) return null;
7
+ return parts.pop().split(';').shift();
8
+ }
9
+
10
+ function setCookie(name, value) {
11
+ document.cookie = `${name}=${value}; path=/; max-age=31536000`;
12
+ }
13
+
14
+ function chevronDirection(tray, expanded) {
15
+ if (tray === "beta") return expanded ? "fa-chevron-left" : "fa-chevron-right";
16
+ if (tray === "gamma") return expanded ? "fa-chevron-right" : "fa-chevron-left";
17
+ if (tray === "delta") return expanded ? "fa-chevron-down" : "fa-chevron-up";
18
+ return "";
19
+ }
20
+
21
+ export default class extends Controller {
22
+ static values = { name: String }
23
+ static targets = ["content", "chevron"]
24
+
25
+ connect() {
26
+ // Load state from cookies
27
+ const savedState = getCookie(`tray_${this.nameValue}`);
28
+ if (savedState === "collapsed") {
29
+ this.expanded = false;
30
+ } else {
31
+ this.expanded = true;
32
+ }
33
+ this.updateTray();
34
+ // Set chevron direction from cookie if present
35
+ const chevron = this.hasChevronTarget ? this.chevronTarget : null;
36
+ if (chevron) {
37
+ const chevronCookie = getCookie(`chevron_${this.nameValue}`);
38
+ if (chevronCookie) {
39
+ chevron.classList.remove("fa-chevron-left", "fa-chevron-right", "fa-chevron-up", "fa-chevron-down");
40
+ chevron.classList.add(chevronCookie);
41
+ }
42
+ }
43
+ }
44
+
45
+ toggle() {
46
+ this.expanded = !this.expanded;
47
+ // Save state to cookies
48
+ setCookie(`tray_${this.nameValue}`, this.expanded ? "expanded" : "collapsed");
49
+ // Save chevron direction to cookies
50
+ setCookie(`chevron_${this.nameValue}`, chevronDirection(this.nameValue, this.expanded));
51
+ this.updateTray();
52
+ }
53
+
54
+ updateTray() {
55
+ // Only update chevron if it exists (tray is collapsible)
56
+ const hasChevron = this.hasChevronTarget;
57
+ if (this.nameValue === "delta") {
58
+ if (this.expanded) {
59
+ this.element.classList.remove("collapsed");
60
+ this.element.classList.add("h-[200px]");
61
+ if (hasChevron) {
62
+ this.chevronTarget.classList.remove("fa-chevron-up");
63
+ this.chevronTarget.classList.add("fa-chevron-down");
64
+ }
65
+ } else {
66
+ this.element.classList.remove("h-[200px]");
67
+ this.element.classList.add("collapsed");
68
+ if (hasChevron) {
69
+ this.chevronTarget.classList.remove("fa-chevron-down");
70
+ this.chevronTarget.classList.add("fa-chevron-up");
71
+ }
72
+ }
73
+ } else if (this.nameValue === "beta") {
74
+ // Beta: open=left, collapsed=right
75
+ if (this.expanded) {
76
+ this.element.classList.remove("collapsed");
77
+ this.element.classList.add("w-[300px]");
78
+ if (hasChevron) {
79
+ this.chevronTarget.classList.remove("fa-chevron-right");
80
+ this.chevronTarget.classList.add("fa-chevron-left");
81
+ }
82
+ } else {
83
+ this.element.classList.remove("w-[300px]");
84
+ this.element.classList.add("collapsed");
85
+ if (hasChevron) {
86
+ this.chevronTarget.classList.remove("fa-chevron-left");
87
+ this.chevronTarget.classList.add("fa-chevron-right");
88
+ }
89
+ }
90
+ } else if (this.nameValue === "gamma") {
91
+ // Gamma: open=right, collapsed=left
92
+ if (this.expanded) {
93
+ this.element.classList.remove("collapsed");
94
+ this.element.classList.add("w-[300px]");
95
+ if (hasChevron) {
96
+ this.chevronTarget.classList.remove("fa-chevron-left");
97
+ this.chevronTarget.classList.add("fa-chevron-right");
98
+ }
99
+ } else {
100
+ this.element.classList.remove("w-[300px]");
101
+ this.element.classList.add("collapsed");
102
+ if (hasChevron) {
103
+ this.chevronTarget.classList.remove("fa-chevron-right");
104
+ this.chevronTarget.classList.add("fa-chevron-left");
105
+ }
106
+ }
107
+ }
108
+ }
109
+ }
@@ -158,4 +158,61 @@
158
158
  em {
159
159
  font-style: italic;
160
160
  }
161
- }
161
+ }
162
+
163
+ /* Tray Animations */
164
+ .tray-container {
165
+ transition: all 500ms ease-in-out;
166
+ }
167
+
168
+ /* Beta Tray (Left) */
169
+ .beta-tray {
170
+ transition: width 500ms ease-in-out;
171
+ }
172
+
173
+ .beta-tray.collapsed {
174
+ width: 70px;
175
+ }
176
+
177
+ .beta-tray.collapsed .tray-content {
178
+ opacity: 0;
179
+ transform: translateX(1rem);
180
+ pointer-events: none;
181
+ }
182
+
183
+ /* Gamma Tray (Right) */
184
+ .gamma-tray {
185
+ transition: width 500ms ease-in-out;
186
+ }
187
+
188
+ .gamma-tray.collapsed {
189
+ width: 70px;
190
+ }
191
+
192
+ .gamma-tray.collapsed .tray-content {
193
+ opacity: 0;
194
+ transform: translateX(-1rem);
195
+ pointer-events: none;
196
+ }
197
+
198
+ /* Delta Tray (Bottom) */
199
+ .delta-tray {
200
+ transition: height 500ms ease-in-out;
201
+ }
202
+
203
+ .delta-tray.collapsed {
204
+ height: 50px;
205
+ }
206
+
207
+ .delta-tray.collapsed .tray-content {
208
+ opacity: 0;
209
+ transform: translateY(1rem);
210
+ pointer-events: none;
211
+ }
212
+
213
+ /* Common content transitions */
214
+ .tray-content {
215
+ transition: opacity 500ms ease-in-out, transform 500ms ease-in-out;
216
+ opacity: 1;
217
+ transform: translate(0);
218
+ }
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TrayConfigurable
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ helper_method :tray_config
8
+ end
9
+
10
+ def tray_config
11
+ @tray_config ||= {
12
+ beta: {
13
+ visible: false,
14
+ collapsible: true
15
+ },
16
+ gamma: {
17
+ visible: false,
18
+ collapsible: true
19
+ },
20
+ delta: {
21
+ visible: false,
22
+ collapsible: true
23
+ }
24
+ }
25
+ end
26
+
27
+ # Override in controllers to customize tray configuration
28
+ def configure_trays
29
+ # Example:
30
+ # tray_config[:beta][:visible] = true
31
+ # tray_config[:gamma][:collapsible] = false
32
+ end
33
+ end
@@ -4,6 +4,15 @@ module MetaWorkflows
4
4
  class ApplicationController < ActionController::Base
5
5
  protect_from_forgery with: :exception
6
6
 
7
+ include TrayConfigurable
8
+ before_action :configure_trays
9
+
10
+ def configure_trays
11
+ super
12
+ tray_config[:beta][:visible] = false
13
+ tray_config[:gamma][:visible] = false
14
+ tray_config[:delta][:visible] = false
15
+ end
7
16
  # Add any MetaWorkflows-specific controller functionality here
8
17
  # This ensures proper engine isolation
9
18
  end
@@ -37,5 +37,23 @@ module MetaWorkflows
37
37
  'Happy with this, or want changes?'
38
38
  ].sample
39
39
  end
40
+
41
+ def tray_state(tray)
42
+ (cookies['tray_'] && cookies['tray_'][tray.to_s]) || cookies["tray_#{tray}"] || 'expanded'
43
+ end
44
+
45
+ def chevron_direction(tray)
46
+ state = tray_state(tray)
47
+ case tray.to_s
48
+ when 'beta'
49
+ state == 'collapsed' ? 'fa-chevron-right' : 'fa-chevron-left'
50
+ when 'gamma'
51
+ state == 'collapsed' ? 'fa-chevron-left' : 'fa-chevron-right'
52
+ when 'delta'
53
+ state == 'collapsed' ? 'fa-chevron-up' : 'fa-chevron-down'
54
+ else
55
+ ''
56
+ end
57
+ end
40
58
  end
41
59
  end
@@ -14,8 +14,8 @@ module MetaWorkflows
14
14
  private
15
15
 
16
16
  def broadcast_redirect(params)
17
- record_id = params['record_id']
18
- record_class = params['record_class']
17
+ record_id = params['redirect_id']
18
+ record_class = params['redirect_class']
19
19
  redirect_method = params['redirect_method']
20
20
 
21
21
  record_class_constant = record_class.to_s.safe_constantize
@@ -8,12 +8,10 @@ module MetaWorkflows
8
8
 
9
9
  # Default values for fields
10
10
  attribute :current_step, :integer, default: 0
11
- attribute :repetition, :integer, default: 0
12
11
  attribute :completed, :boolean, default: false
13
12
  attribute :workflow_params, :json, default: -> { {} }
14
13
 
15
14
  validates :current_step, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
16
- validates :repetition, presence: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
17
15
  validates :completed, inclusion: { in: [true, false] }
18
16
 
19
17
  def increment_step
@@ -1,17 +1,16 @@
1
1
  <!DOCTYPE html>
2
2
  <html>
3
- <head>
4
- <title>Meta workflows</title>
5
- <%= csrf_meta_tags %>
6
- <%= csp_meta_tag %>
3
+ <head>
4
+ <title>Meta Workflows</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
7
 
8
- <%= yield :head %>
8
+ <%= stylesheet_link_tag "meta_workflows/application", media: "all" %>
9
+ <%= javascript_include_tag "meta_workflows/application" %>
10
+ </head>
9
11
 
10
- <%= stylesheet_link_tag "meta_workflows/application", media: "all" %>
11
- </head>
12
- <body>
13
-
14
- <%= yield %>
15
-
16
- </body>
12
+ <body>
13
+ <%= render 'layouts/meta_workflows/flash' %>
14
+ <%= yield %>
15
+ </body>
17
16
  </html>
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RemoveRepetitionFromMetaWorkflowsWorkflowExecutions < ActiveRecord::Migration[7.2]
4
+ def change
5
+ remove_column :meta_workflows_workflow_executions, :repetition, :integer
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddCallIdAndStatusToMetaWorkflowsToolCalls < ActiveRecord::Migration[7.2]
4
+ def change
5
+ add_column :meta_workflows_tool_calls, :call_id, :string
6
+ add_column :meta_workflows_tool_calls, :status, :string
7
+ end
8
+ end
@@ -9,7 +9,6 @@ module MetaWorkflows
9
9
  #{root}/app/controllers/concerns
10
10
  #{root}/app/models/concerns
11
11
  #{root}/app/services
12
- #{root}/app/components
13
12
  #{root}/app/jobs
14
13
  #{root}/app/sidekiq
15
14
  #{root}/lib
@@ -29,14 +28,6 @@ module MetaWorkflows
29
28
  # Configure Sidekiq for MetaWorkflows jobs
30
29
  app.config.active_job.queue_adapter = :sidekiq
31
30
  end
32
-
33
- # Configure ViewComponent if available
34
- if defined?(ViewComponent)
35
- existing_paths = [*ViewComponent::Base.view_component_path]
36
- engine_component_path = root.join('app', 'components').to_s
37
-
38
- app.config.view_component.view_component_path = (existing_paths + [engine_component_path]).uniq
39
- end
40
31
  end
41
32
 
42
33
  # Configure routes
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MetaWorkflows
4
- VERSION = '0.7.1'
4
+ VERSION = '0.8.2'
5
5
  end
@@ -169,10 +169,8 @@ module Services
169
169
 
170
170
  raise ArgumentError, "Invalid collection creator class: #{service_class_name}" unless service_class
171
171
 
172
- parent_record = find_parent_record(workflow_execution)
173
-
174
172
  service_class.new(
175
- parent_record: parent_record,
173
+ workflow_execution: workflow_execution,
176
174
  collection: inputs[:collection]
177
175
  )
178
176
  end
@@ -189,6 +187,8 @@ module Services
189
187
  service_class.new(target_record, attributes_to_update, workflow_execution.workflow_params)
190
188
  end
191
189
 
190
+ # TODO: We should refactor this along with the build_record_update_service method
191
+ # to only use workflow_params and use better naming (instead of record_id and record_class)
192
192
  def find_parent_record(workflow_execution)
193
193
  record_class = workflow_execution.record.class.name.constantize
194
194
  record_class.find(workflow_execution.workflow_params['record_id'])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meta_workflows
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Leonid Medovyy
@@ -9,28 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-06-17 00:00:00.000000000 Z
12
+ date: 2025-06-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ">="
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
20
  version: 7.2.0
21
- - - "<"
22
- - !ruby/object:Gem::Version
23
- version: '8.1'
24
21
  type: :runtime
25
22
  prerelease: false
26
23
  version_requirements: !ruby/object:Gem::Requirement
27
24
  requirements:
28
- - - ">="
25
+ - - "~>"
29
26
  - !ruby/object:Gem::Version
30
27
  version: 7.2.0
31
- - - "<"
32
- - !ruby/object:Gem::Version
33
- version: '8.1'
34
28
  - !ruby/object:Gem::Dependency
35
29
  name: sidekiq
36
30
  requirement: !ruby/object:Gem::Requirement
@@ -73,20 +67,6 @@ dependencies:
73
67
  - - ">="
74
68
  - !ruby/object:Gem::Version
75
69
  version: '0'
76
- - !ruby/object:Gem::Dependency
77
- name: view_component
78
- requirement: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '3.0'
83
- type: :runtime
84
- prerelease: false
85
- version_requirements: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '3.0'
90
70
  - !ruby/object:Gem::Dependency
91
71
  name: stimulus-rails
92
72
  requirement: !ruby/object:Gem::Requirement
@@ -131,8 +111,10 @@ files:
131
111
  - app/assets/javascripts/meta_workflows/controllers/loading_phrases_controller.js
132
112
  - app/assets/javascripts/meta_workflows/controllers/redirect_controller.js
133
113
  - app/assets/javascripts/meta_workflows/controllers/response_scroll_controller.js
114
+ - app/assets/javascripts/meta_workflows/controllers/tray_controller.js
134
115
  - app/assets/javascripts/meta_workflows_manifest.js
135
116
  - app/assets/stylesheets/meta_workflows/application.css
117
+ - app/controllers/concerns/tray_configurable.rb
136
118
  - app/controllers/meta_workflows/application_controller.rb
137
119
  - app/controllers/meta_workflows/debug_controller.rb
138
120
  - app/controllers/meta_workflows/humans_controller.rb
@@ -177,6 +159,8 @@ files:
177
159
  - db/migrate/20250530220737_create_meta_workflows_tool_calls.rb
178
160
  - db/migrate/20250530220750_create_meta_workflows_workflow_steps.rb
179
161
  - db/migrate/20250613213159_add_error_fields_to_workflow_steps.rb
162
+ - db/migrate/20250617192849_remove_repetition_from_meta_workflows_workflow_executions.rb
163
+ - db/migrate/20250618175439_add_call_id_and_status_to_meta_workflows_tool_calls.rb
180
164
  - lib/meta_workflows.rb
181
165
  - lib/meta_workflows/asset_installer.rb
182
166
  - lib/meta_workflows/configuration.rb
@@ -188,15 +172,15 @@ files:
188
172
  - lib/services/meta_workflows/updaters/meta_service.rb
189
173
  - lib/tasks/git_hooks.rake
190
174
  - lib/tasks/meta_workflows_tasks.rake
191
- homepage: https://github.com/strongmind/meta_workflows
175
+ homepage: https://github.com/strongmind/meta-workflows
192
176
  licenses:
193
177
  - None
194
178
  metadata:
195
179
  allowed_push_host: https://rubygems.org
196
- homepage_uri: https://github.com/strongmind/meta_workflows
197
- source_code_uri: https://github.com/strongmind/meta_workflows
198
- changelog_uri: https://github.com/strongmind/meta_workflows/blob/main/CHANGELOG.md
199
- documentation_uri: https://github.com/strongmind/meta_workflows/blob/main/README.md
180
+ homepage_uri: https://github.com/strongmind/meta-workflows
181
+ source_code_uri: https://github.com/strongmind/meta-workflows
182
+ changelog_uri: https://github.com/strongmind/meta-workflows/blob/main/CHANGELOG.md
183
+ documentation_uri: https://github.com/strongmind/meta-workflows/blob/main/README.md
200
184
  rubygems_mfa_required: 'true'
201
185
  post_install_message:
202
186
  rdoc_options: []