lesli 5.0.23 → 5.1.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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/lesli/application.css +1 -192
  3. data/app/controllers/lesli/abouts_controller.rb +1 -1
  4. data/app/controllers/lesli/{items → item}/activities_controller.rb +1 -1
  5. data/app/controllers/lesli/item/discussions_controller.rb +126 -0
  6. data/app/controllers/lesli/item/tasks_controller.rb +126 -0
  7. data/app/helpers/lesli/customization_helper.rb +1 -1
  8. data/app/helpers/lesli/html_helper.rb +1 -1
  9. data/app/models/concerns/lesli/item/activities.rb +106 -0
  10. data/app/models/concerns/lesli/item/discussions.rb +92 -0
  11. data/app/models/concerns/lesli/item/tasks.rb +95 -0
  12. data/app/models/lesli/account.rb +1 -0
  13. data/app/models/lesli/{items → item}/activity.rb +5 -13
  14. data/app/models/lesli/item/discussion.rb +10 -0
  15. data/{lib/lesli/r_spec.rb → app/models/lesli/item/task.rb} +9 -10
  16. data/app/views/lesli/partials/_application-lesli-header.html.erb +12 -0
  17. data/config/initializers/lesli_migration_helpers.rb +2 -2
  18. data/db/migrate/v1/0000000210_create_lesli_users.rb +1 -1
  19. data/lib/generators/lesli/base_generator.rb +172 -0
  20. data/lib/generators/lesli/controller/controller_generator.rb +40 -0
  21. data/lib/generators/lesli/controller/templates/controller.rb.tt +86 -0
  22. data/lib/generators/lesli/install/install_generator.rb +1 -1
  23. data/lib/generators/lesli/model/model_generator.rb +44 -0
  24. data/lib/generators/lesli/model/templates/model.rb.tt +16 -0
  25. data/lib/generators/lesli/scaffold/scaffold_generator.rb +47 -0
  26. data/lib/generators/lesli/service/service_generator.rb +40 -0
  27. data/lib/generators/lesli/service/templates/service.rb.tt +44 -0
  28. data/lib/generators/lesli/views/templates/_form.html.erb.tt +22 -0
  29. data/lib/generators/lesli/views/templates/index.html.erb.tt +17 -0
  30. data/lib/generators/lesli/views/templates/new.html.erb.tt +4 -0
  31. data/lib/generators/lesli/views/templates/show.html.erb.tt +22 -0
  32. data/lib/generators/lesli/views/views_generator.rb +106 -0
  33. data/lib/lesli/engine.rb +1 -23
  34. data/lib/lesli/router.rb +42 -43
  35. data/lib/lesli/version.rb +2 -2
  36. data/lib/migrate/common.rb +1 -1
  37. data/lib/migrate/items/activity_structure.rb +11 -5
  38. data/lib/migrate/items/discussion_structure.rb +9 -3
  39. data/lib/migrate/items/{action_structure.rb → task_structure.rb} +12 -6
  40. data/lib/migrate/shared/catalog_structure.rb +16 -0
  41. data/lib/tasks/lesli/db.rake +9 -0
  42. data/readme.md +1 -1
  43. metadata +58 -79
  44. data/app/assets/config/lesli_manifest.js +0 -42
  45. data/app/assets/images/lesli/brand/app-auth.svg +0 -9
  46. data/app/assets/images/lesli/brand/app-icon.svg +0 -48
  47. data/app/assets/images/lesli/brand/app-logo.png +0 -0
  48. data/app/assets/images/lesli/brand/app-logo.svg +0 -4
  49. data/app/assets/images/lesli/brand/favicon.png +0 -0
  50. data/app/assets/images/lesli/brand/favicon.svg +0 -61
  51. data/app/assets/images/lesli/brand/login-background.jpg +0 -0
  52. data/app/assets/images/lesli/brand/register-background.jpg +0 -0
  53. data/app/assets/javascripts/lesli/application.js +0 -1
  54. data/app/controllers/lesli/items/actions_controller.rb +0 -122
  55. data/app/controllers/lesli/items/discussions_controller.rb +0 -93
  56. data/app/models/lesli/items/action.rb +0 -15
  57. data/app/models/lesli/items/discussion.rb +0 -15
  58. data/config/importmap.rb +0 -1
  59. data/db/structure/00000000_locations.json +0 -32
  60. data/db/structure/00000020_catalogs.json +0 -0
  61. data/db/structure/00000201_workflows.json +0 -17
  62. data/db/structure/00000202_workflow_statuses.json +0 -24
  63. data/db/structure/00000203_workflow_associations.json +0 -14
  64. data/db/structure/00000204_workflow_actions.json +0 -39
  65. data/db/structure/00000205_workflow_checks.json +0 -27
  66. data/db/structure/00000300_custom_fields.json +0 -8
  67. data/db/structure/00000301_custom_fields.json +0 -38
  68. data/db/structure/00000401_custom_validations.json +0 -14
  69. data/db/structure/00000402_custom_validation_rules.json +0 -23
  70. data/db/structure/00000403_custom_validation_fields.json +0 -14
  71. data/lib/generators/application_lesli_generator_base.rb +0 -164
  72. data/lib/generators/lesli/spec/USAGE +0 -8
  73. data/lib/generators/lesli/spec/spec_generator.rb +0 -22
  74. data/lib/generators/lesli/spec/templates/spec-factory.template +0 -17
  75. data/lib/generators/lesli/spec/templates/spec-model.template +0 -70
  76. data/lib/generators/lesli/view/USAGE +0 -8
  77. data/lib/generators/lesli/view/templates/spec-factory.template +0 -17
  78. data/lib/generators/lesli/view/templates/spec-model.template +0 -70
  79. data/lib/generators/lesli/view/view_generator.rb +0 -22
  80. data/lib/scss/_apps.scss +0 -94
  81. data/lib/scss/application.scss +0 -34
  82. data/lib/tasks/lesli/docs.rake +0 -47
  83. data/lib/tasks/lesli/git.rake +0 -70
  84. data/lib/tasks/lesli/github.rake +0 -89
  85. data/lib/test/config.rb +0 -111
  86. data/lib/test/helpers/response_integration_helper.rb +0 -46
  87. data/lib/test/lesli.rb +0 -61
@@ -0,0 +1,92 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see http://www.gnu.org/licenses/.
19
+
20
+ Lesli · Ruby on Rails SaaS Development Framework.
21
+
22
+ Made with ♥ by LesliTech
23
+ Building a better future, one line of code at a time.
24
+
25
+ @contact hello@lesli.tech
26
+ @website https://www.lesli.tech
27
+ @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
28
+
29
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
+ // ·
31
+ =end
32
+
33
+ module Lesli
34
+ module Item
35
+ module Discussions
36
+ extend ActiveSupport::Concern
37
+
38
+ included do
39
+ class_attribute :lesli_discussions_class, instance_accessor: false
40
+ lesli_discussions_setup
41
+ end
42
+
43
+ class_methods do
44
+
45
+ # This acts as our allowlist flag
46
+ def is_lesli_commentable?
47
+ true
48
+ end
49
+
50
+ # Automatically sets the associations to the
51
+ # engine model that is implementing the task items
52
+ def lesli_discussions_setup(use: nil, as: :discussable, association_name: :discussions)
53
+ klass = if use
54
+ use.to_s.constantize
55
+ else
56
+ "#{name.deconstantize}::Item::Discussion".constantize
57
+ end
58
+
59
+ self.lesli_discussions_class = klass
60
+
61
+ # ✅ Auto-fix table name (works even when engine defines table_name_prefix)
62
+ expected_table = lesli_expected_discussions_table_name_for(klass)
63
+
64
+ if klass.table_name != expected_table
65
+ klass.table_name = expected_table
66
+ end
67
+
68
+ # Set associations
69
+ # Example:
70
+ # class LesliSupport::Ticket
71
+ # has_many :lesli_support_tasks
72
+ # end
73
+ has_many(association_name,
74
+ -> { where(deleted_at: nil).order(created_at: :desc) },
75
+ as: as,
76
+ class_name: klass.name,
77
+ dependent: :destroy)
78
+ end
79
+
80
+ private
81
+
82
+ # Build: "lesli_support_item_activities" from "LesliSupport::Item::Activity"
83
+ #
84
+ # We DO NOT rely on ActiveRecord's table_name_prefix, because that’s what breaks your case.
85
+ def lesli_expected_discussions_table_name_for(klass)
86
+ parts = klass.name.split("::").map(&:underscore) # ["lesli_support", "item", "discussion"]
87
+ "#{parts.join('_').pluralize}" # "lesli_support_item_discussions"
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,95 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see http://www.gnu.org/licenses/.
19
+
20
+ Lesli · Ruby on Rails SaaS Development Framework.
21
+
22
+ Made with ♥ by LesliTech
23
+ Building a better future, one line of code at a time.
24
+
25
+ @contact hello@lesli.tech
26
+ @website https://www.lesli.tech
27
+ @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
28
+
29
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
30
+ // ·
31
+ =end
32
+
33
+ module Lesli
34
+ module Item
35
+ module Tasks
36
+ extend ActiveSupport::Concern
37
+
38
+ included do
39
+ class_attribute :lesli_tasks_class, instance_accessor: false
40
+ lesli_tasks_setup
41
+ end
42
+
43
+ class_methods do
44
+
45
+ # This acts as our allowlist flag
46
+ def is_lesli_taskable?
47
+ true
48
+ end
49
+
50
+ # Automatically sets the associations to the
51
+ # engine model that is implementing the task items
52
+ def lesli_tasks_setup(use: nil, as: :taskable, association_name: :tasks)
53
+ klass = if use
54
+ use.to_s.constantize
55
+ else
56
+ "#{name.deconstantize}::Item::Task".constantize
57
+ end
58
+
59
+ self.lesli_tasks_class = klass
60
+
61
+ # ✅ Auto-fix table name (works even when engine defines table_name_prefix)
62
+ expected_table = lesli_expected_task_table_name_for(klass)
63
+
64
+ if klass.table_name != expected_table
65
+ klass.table_name = expected_table
66
+ end
67
+
68
+ # Set associations
69
+ # Example:
70
+ # class LesliSupport::Ticket
71
+ # has_many :lesli_support_tasks
72
+ # end
73
+ has_many(association_name,
74
+ -> { where(deleted_at: nil).order(created_at: :desc) },
75
+ as: as,
76
+ class_name: klass.name,
77
+ dependent: :destroy)
78
+ rescue NameError
79
+ raise NameError,
80
+ "Task class not found for #{name}. Expected #{name.deconstantize}::Task or pass `use:`"
81
+ end
82
+
83
+ private
84
+
85
+ # Build: "lesli_support_item_activities" from "LesliSupport::Item::Activity"
86
+ #
87
+ # We DO NOT rely on ActiveRecord's table_name_prefix, because that’s what breaks your case.
88
+ def lesli_expected_task_table_name_for(klass)
89
+ parts = klass.name.split("::").map(&:underscore) # ["lesli_support", "item", "task"]
90
+ "#{parts.join('_').pluralize}" # "lesli_support_item_tasks"
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -64,6 +64,7 @@ module Lesli
64
64
  has_one :dashboard, class_name: "LesliDashboard::Account"
65
65
 
66
66
 
67
+ validates :status, presence: true
67
68
 
68
69
  # account statuses
69
70
  enum :status, {
@@ -2,7 +2,7 @@
2
2
 
3
3
  Lesli
4
4
 
5
- Copyright (c) 2025, Lesli Technologies, S. A.
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
6
6
 
7
7
  This program is free software: you can redistribute it and/or modify
8
8
  it under the terms of the GNU General Public License as published by
@@ -31,20 +31,12 @@ Building a better future, one line of code at a time.
31
31
  =end
32
32
 
33
33
  module Lesli
34
- module Items
34
+ module Item
35
35
  class Activity < ApplicationRecord
36
36
  self.abstract_class = true
37
-
38
- # activity is for user
39
- # system is for jobs
40
- enum :activity_type, {
41
- activity: "activity",
42
- system: "system"
43
- }
44
-
45
- # if needed should be defined
46
- # by the user at resource level
47
- # enum activity_code: { }
37
+ belongs_to :user, class_name: "Lesli::User"
38
+ belongs_to :account, class_name: "Lesli::Account"
39
+ belongs_to :subject, polymorphic: true
48
40
  end
49
41
  end
50
42
  end
@@ -0,0 +1,10 @@
1
+ module Lesli
2
+ module Item
3
+ class Discussion < ApplicationRecord
4
+ self.abstract_class = true
5
+ belongs_to :user, class_name: "Lesli::User"
6
+ belongs_to :account, class_name: "Lesli::Account"
7
+ belongs_to :discussable, polymorphic: true
8
+ end
9
+ end
10
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  Lesli
4
4
 
5
- Copyright (c) 2024, Lesli Technologies, S. A.
5
+ Copyright (c) 2026, Lesli Technologies, S. A.
6
6
 
7
7
  This program is free software: you can redistribute it and/or modify
8
8
  it under the terms of the GNU General Public License as published by
@@ -30,14 +30,13 @@ Building a better future, one line of code at a time.
30
30
  // ·
31
31
  =end
32
32
 
33
- # ·
34
- module Lesli
35
- module RSpec
36
- def self.testers_request
37
- Lesli::Engine.root.join("lib/rspec/testers/request")
33
+ module Lesli
34
+ module Item
35
+ class Task < ApplicationRecord
36
+ self.abstract_class = true
37
+ belongs_to :user, class_name: "Lesli::User"
38
+ belongs_to :account, class_name: "Lesli::Account"
39
+ belongs_to :taskable, polymorphic: true
38
40
  end
39
- def self.testers_model
40
- Lesli::Engine.root.join("lib/rspec/testers/model")
41
- end
42
- end
41
+ end
43
42
  end
@@ -56,6 +56,18 @@ Building a better future, one line of code at a time.
56
56
  </button>
57
57
  </div>
58
58
  <div class="navbar-menu" :class="{ 'is-active': navActive }">
59
+ <div class="navbar-start is-flex is-flex-grow-1 is-justify-content-center">
60
+ <%# ["favorite","sentiment_excited","person_pin_circle","manage_accounts"].each do |icon| %>
61
+ <% [].each do |icon| %>
62
+ <div class="navbar-item">
63
+ <a data-turbo-frame="_top" href="/babel/labels" class="icon py-4 px-5">
64
+ <span class="material-symbols-outlined">
65
+ <%= icon %>
66
+ </span>
67
+ </a>
68
+ </div>
69
+ <% end %>
70
+ </div>
59
71
  <div class="navbar-end is-flex is-justify-content-center">
60
72
 
61
73
  <!-- notifications -->
@@ -32,7 +32,7 @@ Building a better future, one line of code at a time.
32
32
 
33
33
  require(Lesli::Engine.root.join("lib/migrate/common"))
34
34
 
35
- require(Lesli::Engine.root.join("lib/migrate/items/action_structure"))
35
+ require(Lesli::Engine.root.join("lib/migrate/items/task_structure"))
36
36
  require(Lesli::Engine.root.join("lib/migrate/items/activity_structure"))
37
37
  require(Lesli::Engine.root.join("lib/migrate/items/attachment_structure"))
38
38
  require(Lesli::Engine.root.join("lib/migrate/items/discussion_structure"))
@@ -45,7 +45,7 @@ require(Lesli::Engine.root.join("lib/migrate/shared/catalog_structure"))
45
45
 
46
46
  ActiveRecord::Migration.include(MigrationHelpers::Common)
47
47
 
48
- ActiveRecord::Migration.include(MigrationHelpers::Items::ActionStructure)
48
+ ActiveRecord::Migration.include(MigrationHelpers::Items::TaskStructure)
49
49
  ActiveRecord::Migration.include(MigrationHelpers::Items::ActivityStructure)
50
50
  ActiveRecord::Migration.include(MigrationHelpers::Items::AttachmentStructure)
51
51
  ActiveRecord::Migration.include(MigrationHelpers::Items::DiscussionStructure)
@@ -94,7 +94,7 @@ class CreateLesliUsers < ActiveRecord::Migration[7.2]
94
94
  add_reference(:lesli_users, :account, foreign_key: { to_table: :lesli_accounts })
95
95
  add_reference(:lesli_accounts, :user, foreign_key: { to_table: :lesli_users })
96
96
 
97
- add_index(:lesli_users, :uid, unique: true)
97
+ add_index(:lesli_users, :uid, unique: true)
98
98
  add_index(:lesli_users, :email, unique: true)
99
99
  add_index(:lesli_users, :unlock_token, unique: true)
100
100
  add_index(:lesli_users, :confirmation_token, unique: true)
@@ -0,0 +1,172 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module Lesli
6
+ module Generators
7
+ # Shared base generator for all Lesli generators.
8
+ #
9
+ # This class centralizes the logic used by all generators, such as:
10
+ #
11
+ # - engine name detection
12
+ # - engine namespace detection
13
+ # - domain name normalization
14
+ # - resource naming helpers
15
+ #
16
+ # This avoids duplicating the same helper methods in every generator.
17
+ class BaseGenerator < Rails::Generators::NamedBase
18
+
19
+ private
20
+
21
+ # Returns the current engine folder name in snake_case.
22
+ #
23
+ # Examples:
24
+ # "/code/lesli_support" -> "lesli_support"
25
+ # "/code/my_engine" -> "my_engine"
26
+ # "/code/store" -> "store"
27
+ def engine_name
28
+ File.basename(ENGINE_ROOT.to_s).underscore
29
+ end
30
+
31
+ # Returns the current engine Ruby namespace in CamelCase.
32
+ #
33
+ # Examples:
34
+ # "lesli_support" -> "LesliSupport"
35
+ # "my_engine" -> "MyEngine"
36
+ # "store" -> "Store"
37
+ def engine_namespace
38
+ engine_name.camelize
39
+ end
40
+
41
+ # Returns the domain name derived from the engine namespace.
42
+ #
43
+ # Rules:
44
+ # - If the engine starts with "Lesli", remove that prefix
45
+ # - Otherwise use the full engine namespace
46
+ # - Convert the result to snake_case
47
+ #
48
+ # Examples:
49
+ # "LesliSupport" -> "support"
50
+ # "LesliCalendar" -> "calendar"
51
+ # "MyEngine" -> "my_engine"
52
+ # "Store" -> "store"
53
+ def engine_domain_name
54
+ namespace = engine_namespace
55
+
56
+ if namespace.start_with?("Lesli") && namespace != "Lesli"
57
+ namespace.delete_prefix("Lesli").underscore
58
+ else
59
+ namespace.underscore
60
+ end
61
+ end
62
+
63
+ # Returns the singular normalized resource name.
64
+ #
65
+ # Examples:
66
+ # "tickets" -> "ticket"
67
+ # "products" -> "product"
68
+ # "store" -> "store"
69
+ #
70
+ # This is the main workaround for NamedBase, because by default
71
+ # a plural input like "products" may produce class_name = "Products".
72
+ def resource_name
73
+ name.to_s.singularize.underscore
74
+ end
75
+
76
+ # Returns the plural normalized resource name.
77
+ #
78
+ # Examples:
79
+ # "ticket" -> "tickets"
80
+ # "product" -> "products"
81
+ def resource_collection_name
82
+ resource_name.pluralize
83
+ end
84
+
85
+ # Returns the Ruby model class name.
86
+ #
87
+ # Examples:
88
+ # "ticket" -> "Ticket"
89
+ # "product" -> "Product"
90
+ def resource_class_name
91
+ resource_name.camelize
92
+ end
93
+
94
+ # Returns the plural controller class name.
95
+ #
96
+ # Examples:
97
+ # "tickets" -> "Tickets"
98
+ # "products" -> "Products"
99
+ def controller_class_name
100
+ resource_collection_name.camelize
101
+ end
102
+
103
+ # Returns the service class name.
104
+ #
105
+ # Examples:
106
+ # "Ticket" -> "TicketService"
107
+ # "Product" -> "ProductService"
108
+ def service_class_name
109
+ "#{resource_class_name}Service"
110
+ end
111
+
112
+ # Returns the resource instance variable name.
113
+ #
114
+ # Examples:
115
+ # "ticket" -> "@ticket"
116
+ # "product" -> "@product"
117
+ def resource_instance
118
+ "@#{resource_name}"
119
+ end
120
+
121
+ # Returns the resource collection instance variable name.
122
+ #
123
+ # Examples:
124
+ # "tickets" -> "@tickets"
125
+ # "products" -> "@products"
126
+ def resource_collection_instance
127
+ "@#{resource_collection_name}"
128
+ end
129
+
130
+ # Returns the before_action setter method name.
131
+ #
132
+ # Examples:
133
+ # "ticket" -> "set_ticket"
134
+ # "product" -> "set_product"
135
+ def set_resource_method_name
136
+ "set_#{resource_name}"
137
+ end
138
+
139
+ # Returns the params method name.
140
+ #
141
+ # Examples:
142
+ # "ticket" -> "ticket_params"
143
+ # "product" -> "product_params"
144
+ def params_method_name
145
+ "#{resource_name}_params"
146
+ end
147
+
148
+ # Returns the namespaced model class name.
149
+ #
150
+ # Examples:
151
+ # "LesliSupport::Ticket"
152
+ # "MyEngine::Product"
153
+ def namespaced_resource_class_name
154
+ "#{engine_namespace}::#{resource_class_name}"
155
+ end
156
+
157
+ # Returns only the attribute names passed to the generator.
158
+ #
159
+ # Example:
160
+ # ["subject:string", "owner_id:integer"] -> ["subject", "owner_id"]
161
+ def permitted_attributes
162
+ return [] unless respond_to?(:attributes)
163
+
164
+ attributes.map(&:name)
165
+ end
166
+
167
+ def namespaced_model_name
168
+ "#{engine_namespace}::#{resource_class_name}"
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require_relative "../base_generator"
5
+
6
+ module Lesli
7
+ module Generators
8
+ # Generates a Lesli-style controller inside the current engine.
9
+ class ControllerGenerator < BaseGenerator
10
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
11
+
12
+ source_root File.expand_path("templates", __dir__)
13
+
14
+ # Creates the controller file from the template.
15
+ def create_controller_file
16
+ template "controller.rb.tt", controller_file_path
17
+ end
18
+
19
+ private
20
+
21
+ # Returns the controller directory inside the engine namespace.
22
+ #
23
+ # Example:
24
+ # app/controllers/lesli_support
25
+ # app/controllers/my_engine
26
+ # app/controllers/store
27
+ def controller_directory
28
+ File.join(ENGINE_ROOT, "app/controllers", engine_name)
29
+ end
30
+
31
+ # Returns the final controller file path.
32
+ #
33
+ # Example:
34
+ # app/controllers/lesli_support/tickets_controller.rb
35
+ def controller_file_path
36
+ File.join(controller_directory, "#{resource_collection_name}_controller.rb")
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module <%= engine_namespace %>
4
+ class <%= controller_class_name %>Controller < ApplicationController
5
+ before_action :<%= set_resource_method_name %>, only: [:show, :edit, :update, :destroy]
6
+
7
+ def index
8
+ <%= resource_collection_instance %> = respond_with_pagination(
9
+ <%= service_class_name %>.new(current_user, query).index
10
+ )
11
+ end
12
+
13
+ def show
14
+ <%= resource_instance %> = <%= resource_instance %>.show
15
+ end
16
+
17
+ def new
18
+ <%= resource_instance %> = <%= resource_class_name %>.new
19
+ end
20
+
21
+ def edit
22
+ end
23
+
24
+ def create
25
+ <%= resource_name %> = <%= service_class_name %>.new(current_user, query).create(<%= params_method_name %>)
26
+
27
+ <%= resource_instance %> = <%= resource_name %>.result
28
+
29
+ if <%= resource_name %>.successful?
30
+ success("<%= resource_name %> creado de forma exitosa")
31
+
32
+ respond_with_lesli(
33
+ turbo: stream_redirection(<%= resource_name %>_path(<%= resource_instance %>.id))
34
+ )
35
+ else
36
+ respond_with_lesli(
37
+ turbo: <%= resource_name %>.errors_as_sentence
38
+ )
39
+ end
40
+ end
41
+
42
+ def update
43
+ if <%= resource_instance %>.update(<%= params_method_name %>)
44
+ respond_with_lesli(
45
+ turbo: stream_notification_success("<%= resource_class_name %> updated successfully")
46
+ )
47
+ else
48
+ respond_with_lesli(
49
+ turbo: stream_notification_danger(<%= resource_instance %>.errors)
50
+ )
51
+ end
52
+ end
53
+
54
+ def destroy
55
+ return respond_with_not_found unless <%= resource_instance %>
56
+ return respond_with_unauthorized unless <%= resource_instance %>.is_editable_by?(current_user)
57
+
58
+ <%= resource_name %>_destroy_response = <%= service_class_name %>.destroy(current_user, <%= resource_instance %>)
59
+
60
+ if <%= resource_name %>_destroy_response.successful?
61
+ respond_with_successful
62
+ else
63
+ respond_with_error(<%= resource_name %>_destroy_response.payload.errors.full_messages.to_sentence)
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def <%= set_resource_method_name %>
70
+ <%= resource_instance %> = <%= service_class_name %>.new(current_user, query).find(id: params[:id])
71
+ return respond_with_not_found unless <%= resource_instance %>.found?
72
+ end
73
+
74
+ def <%= params_method_name %>
75
+ params.require(:<%= resource_name %>).permit(
76
+ <% if permitted_attributes.any? -%>
77
+ <% permitted_attributes.each_with_index do |attribute, index| -%>
78
+ :<%= attribute %><%= "," unless index == permitted_attributes.length - 1 %>
79
+ <% end -%>
80
+ <% else -%>
81
+ # Add permitted attributes here
82
+ <% end -%>
83
+ )
84
+ end
85
+ end
86
+ end
@@ -38,7 +38,7 @@ module Lesli
38
38
  desc "Adds Lesli route and initializer"
39
39
 
40
40
  def add_route_to_routes_file
41
- route "Lesli::Routing.mount"
41
+ route "Lesli::Router.mount(self)"
42
42
  end
43
43
 
44
44
  def create_initializer_file
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require_relative "../base_generator"
5
+
6
+ module Lesli
7
+ module Generators
8
+ # Generates a Lesli-style model inside the current engine.
9
+ #
10
+ # Example:
11
+ # rails generate lesli:model tickets
12
+ #
13
+ # Result:
14
+ # app/models/lesli_support/ticket.rb
15
+ class ModelGenerator < BaseGenerator
16
+ argument :attributes, type: :array, default: [], banner: "field:type field:type"
17
+
18
+ source_root File.expand_path("templates", __dir__)
19
+
20
+ # Creates the model file from the template.
21
+ def create_model_file
22
+ template "model.rb.tt", model_file_path
23
+ end
24
+
25
+ private
26
+
27
+ # Returns the directory where the model file should be created.
28
+ #
29
+ # Example:
30
+ # app/models/lesli_support
31
+ def model_directory
32
+ File.join(ENGINE_ROOT, "app/models", engine_name)
33
+ end
34
+
35
+ # Returns the final path of the generated model file.
36
+ #
37
+ # Example:
38
+ # app/models/lesli_support/ticket.rb
39
+ def model_file_path
40
+ File.join(model_directory, "#{resource_name}.rb")
41
+ end
42
+ end
43
+ end
44
+ end