lesli 5.0.16 → 5.0.18
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 +4 -4
- data/app/controllers/lesli/shared/dashboards_controller.rb +267 -259
- data/app/helpers/lesli/navigation_helper.rb +1 -1
- data/app/models/concerns/account_initializer.rb +2 -0
- data/app/models/lesli/role/action.rb +1 -1
- data/app/models/lesli/shared/dashboard.rb +12 -138
- data/app/services/lesli/role/action_service.rb +68 -50
- data/app/views/lesli/abouts/welcome.html.erb +1 -11
- data/app/views/lesli/apps/show.html.erb +1 -0
- data/app/views/lesli/shared/dashboards/_edit.html.erb +33 -0
- data/app/views/lesli/shared/dashboards/_show.html.erb +1 -33
- data/lib/lesli/engine.rb +0 -1
- data/lib/lesli/routing.rb +4 -1
- data/lib/lesli/version.rb +2 -2
- data/readme.md +22 -15
- metadata +3 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 51038011f00c8b51bb7b7911a9cfb0b38a383638c3a70d18dd8dd89cb47004eb
|
4
|
+
data.tar.gz: f71306386f4c825b39ae2067a7e04addcb487146630f261e4882ffd75901e4d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c299b8760b120a196e4ddd82b1af9069dfa2e7a478dab8f0efa3c27ec63ce2f54eb9e14d85ef16b0b74976f005b7f206c713aea04f57f9153115c0504c67f48
|
7
|
+
data.tar.gz: 2902ba64403c0b7e2769bd7aa214d6c5f4931003ab40f2113b620ef3e445ff4f0b97bd5ec5ab5f5dec573206505502004818dacab8df706a7530631179d9b6fd
|
@@ -32,277 +32,285 @@ Building a better future, one line of code at a time.
|
|
32
32
|
module Lesli
|
33
33
|
module Shared
|
34
34
|
class DashboardsController < ApplicationLesliController
|
35
|
-
before_action :set_dashboard, only: [:show, :update, :destroy, :options]
|
36
|
-
|
37
|
-
def index
|
38
|
-
respond_to do |format|
|
39
|
-
format.html {}
|
40
|
-
format.json do
|
41
|
-
dynamic_info = self.class.dynamic_info
|
42
|
-
model = dynamic_info[:model]
|
43
|
-
|
44
|
-
dashboards = model.list(current_user, @query)
|
45
|
-
respond_with_successful(dashboards)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def show
|
51
|
-
respond_to do |format|
|
52
|
-
format.html {}
|
53
|
-
format.json do
|
54
|
-
return respond_with_not_found unless @dashboard
|
55
|
-
respond_with_successful(@dashboard.show)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
35
|
+
#before_action :set_dashboard, only: [:show, :update, :destroy, :options]
|
59
36
|
|
60
|
-
def
|
37
|
+
def edit
|
61
38
|
end
|
62
39
|
|
63
|
-
def
|
40
|
+
def show
|
41
|
+
builder = LesliSystem::Klass.new(self)
|
42
|
+
@dashboard = builder.model.dashboard.first
|
64
43
|
end
|
65
44
|
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
|
89
|
-
#
|
90
|
-
#
|
91
|
-
|
92
|
-
#
|
93
|
-
#
|
94
|
-
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
#
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
|
140
|
-
# dashboard
|
141
|
-
#
|
142
|
-
#
|
143
|
-
|
45
|
+
# def index
|
46
|
+
# respond_to do |format|
|
47
|
+
# format.html {}
|
48
|
+
# format.json do
|
49
|
+
# dynamic_info = self.class.dynamic_info
|
50
|
+
# model = dynamic_info[:model]
|
51
|
+
|
52
|
+
# dashboards = model.list(current_user, @query)
|
53
|
+
# respond_with_successful(dashboards)
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
|
58
|
+
# def show
|
59
|
+
# respond_to do |format|
|
60
|
+
# format.html {}
|
61
|
+
# format.json do
|
62
|
+
# return respond_with_not_found unless @dashboard
|
63
|
+
# respond_with_successful(@dashboard.show)
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
|
68
|
+
# def new
|
69
|
+
# end
|
70
|
+
|
71
|
+
# def edit
|
72
|
+
# end
|
73
|
+
|
74
|
+
# # @controller_action_param :name [String] The name of the new dashboard
|
75
|
+
# # @controller_action_param :default [Boolean] A flag that marks this dashboard as default or not. The default dashboard is the dashboard all users will have access to on the root page
|
76
|
+
# # @controller_action_param :main [Boolean] A flag that marks this dashboard as main. Since a user can have multiple dashboards, this is the one they will see on the root page when loging in
|
77
|
+
# # @controller_action_param :roles_id [Integer] The id of the role that will have access to this dashboard
|
78
|
+
# # @controller_action_param :user_main_id [Integer] The id of the user
|
79
|
+
# # @controller_action_param :component_attributes [Array] Array of hashes that represent the attributes of the dashboard components
|
80
|
+
# # @controller_action_param :component_attributes.name [String] The name of this component given to the user
|
81
|
+
# # @controller_action_param :component_attributes.component_id [String] An enum value, that indicates which component is being loaded
|
82
|
+
# # @controller_action_param :component_attributes.layout [Integer] Number from 1 to 12, bigger numbers default to 12, smallest numbers default to 1. The column size that the UI component will use
|
83
|
+
# # @controller_action_param :component_attributes.index [Integer] The position of the component in the layout
|
84
|
+
# # @controller_action_param :component_attributes.configuration [Hash] Specific filtering and configuration of the components
|
85
|
+
# # @return [Json] Json that contains wheter the creation of the dashboard was successful or not.
|
86
|
+
# # If it is not successful, it returns an error message
|
87
|
+
# # @description Creates a new dashboard associated to the *current_user*'s *account*
|
88
|
+
# # @example
|
89
|
+
# # # Executing this controller's action from javascript's frontend
|
90
|
+
# # let data = {
|
91
|
+
# # dashboard: {
|
92
|
+
# # name: "Sales Dashboard",
|
93
|
+
# # default: false,
|
94
|
+
# # roles_id: 3,
|
95
|
+
# # components_attributes: [
|
96
|
+
# # {
|
97
|
+
# # name: 'Projects Count',
|
98
|
+
# # component_id: projects_component,
|
99
|
+
# # layout: 4,
|
100
|
+
# # index: 3,
|
101
|
+
# # configuration: {}
|
102
|
+
# # }, {
|
103
|
+
# # name: 'New Customers Count',
|
104
|
+
# # component_id: new_customers_component,
|
105
|
+
# # layout: 4,
|
106
|
+
# # index: 3,
|
107
|
+
# # configuration: {}
|
108
|
+
# # }
|
109
|
+
# # ]
|
110
|
+
# # }
|
111
|
+
# # };
|
112
|
+
# # this.http.post('127.0.0.1/help/dashboards', data);
|
113
|
+
# def create
|
114
|
+
# dynamic_info = self.class.dynamic_info
|
115
|
+
# module_name = dynamic_info[:module_name]
|
116
|
+
# model = dynamic_info[:model]
|
117
|
+
# full_module_name = dynamic_info[:full_module_name].underscore
|
118
|
+
|
119
|
+
# dashboard = model.new(dashboard_params)
|
120
|
+
# dashboard["#{full_module_name}_account_id".to_sym] = current_user.account.id
|
121
|
+
# dashboard.user_creator = current_user
|
122
|
+
|
123
|
+
# if dashboard.save
|
124
|
+
# respond_with_successful(dashboard)
|
125
|
+
# else
|
126
|
+
# respond_with_error(dashboard.errors.full_messages.to_sentence)
|
127
|
+
# end
|
128
|
+
# end
|
129
|
+
|
130
|
+
# # @controller_action_param :name [String] The name of the new dashboard
|
131
|
+
# # @controller_action_param :default [Boolean] A flag that marks this dashboard as default or not. The default dashboard is the dashboard all users will have access to on the root page
|
132
|
+
# # @controller_action_param :main [Boolean] A flag that marks this dashboard as main. Since a user can have multiple dashboards, this is the one they will see on the root page when loging in
|
133
|
+
# # @controller_action_param :roles_id [Integer] The id of the role that will have access to this dashboard
|
134
|
+
# # @controller_action_param :user_main_id [Integer] The id of the user
|
135
|
+
# # @controller_action_param :component_attributes [Array] Array of hashes that represent the attributes of the dashboard components
|
136
|
+
# # @controller_action_param :component_attributes.name [String] The name of this component given to the user
|
137
|
+
# # @controller_action_param :component_attributes.component_id [String] An enum value, that indicates which component is being loaded
|
138
|
+
# # @controller_action_param :component_attributes.layout [Integer] Number from 1 to 12, bigger numbers default to 12, smallest numbers default to 1. The column size that the UI component will use
|
139
|
+
# # @controller_action_param :component_attributes.index [Integer] The position of the component in the layout
|
140
|
+
# # @controller_action_param :component_attributes.configuration [Hash] Specific filtering and configuration of the components
|
141
|
+
# # @return [Json] Json that contains wheter the dashboard was successfully updated or not.
|
142
|
+
# # If it it not successful, it returns an error message
|
143
|
+
# # @description Updates an existing dashboard associated to the *current_user*'s *account*.
|
144
|
+
# # @example
|
145
|
+
# # # Executing this controller's action from javascript's frontend
|
146
|
+
# # let dashboard_id = 4;
|
147
|
+
# # let data = {
|
148
|
+
# # dashboard: {
|
149
|
+
# # name: "Sales Dashboard",
|
150
|
+
# # default: false,
|
151
|
+
# # roles_id: 3,
|
152
|
+
# # components_attributes: [
|
153
|
+
# # {
|
154
|
+
# # name: 'Projects Count',
|
155
|
+
# # component_id: projects_component,
|
156
|
+
# # layout: 4,
|
157
|
+
# # index: 3,
|
158
|
+
# # configuration: {}
|
159
|
+
# # }, {
|
160
|
+
# # name: 'New Customers Count',
|
161
|
+
# # component_id: new_customers_component,
|
162
|
+
# # layout: 4,
|
163
|
+
# # index: 3,
|
164
|
+
# # configuration: {}
|
165
|
+
# # }
|
166
|
+
# # ]
|
167
|
+
# # }
|
168
|
+
# # };
|
169
|
+
# # this.http.put(`127.0.0.1/help/dashboards/${dashboard_id}`, data);
|
170
|
+
# def update
|
171
|
+
# return respond_with_not_found unless @dashboard
|
172
|
+
|
173
|
+
# if @dashboard.update(dashboard_params)
|
174
|
+
# respond_with_successful(@dashboard.show)
|
175
|
+
# else
|
176
|
+
# respond_with_error(@dashboard.errors.full_messages.to_sentence)
|
177
|
+
# end
|
178
|
+
# end
|
179
|
+
|
180
|
+
# # @return [Json] Json that contains wheter the dashboard was successfully deleted or not.
|
181
|
+
# # If it it not successful, it returns an error message
|
182
|
+
# # @description Deletes an existing *dashboard* associated to the *current_user*'s *account*.
|
183
|
+
# # Since the dashboard has details, these are also deleted. However, if there
|
184
|
+
# # is an existing *cloud_object* associated to the *dashboard*, it cannot be deleted
|
185
|
+
# # @example
|
186
|
+
# # # Executing this controller's action from javascript's frontend
|
187
|
+
# # let dashboard_id = 4;
|
188
|
+
# # this.http.delete(`127.0.0.1/help/dashboards/${dashboard_id}`);
|
189
|
+
# def destroy
|
190
|
+
# return respond_with_not_found unless @dashboard
|
191
|
+
|
192
|
+
# if @dashboard.destroy
|
193
|
+
# respond_with_successful
|
194
|
+
# else
|
195
|
+
# respond_with_error(@dashboard.errors.full_messages.to_sentence)
|
196
|
+
# end
|
197
|
+
# end
|
198
|
+
|
199
|
+
# def options
|
200
|
+
# dynamic_info = self.class.dynamic_info
|
201
|
+
# model = dynamic_info[:module_model]
|
202
|
+
|
203
|
+
# respond_with_successful(model.options(current_user, @query))
|
204
|
+
# end
|
205
|
+
|
206
|
+
# def resource_component
|
207
|
+
# dynamic_info = self.class.dynamic_info
|
208
|
+
# component_model = dynamic_info[:component_model]
|
209
|
+
|
210
|
+
# component_id = sanitize(params[:component_id].to_sym)
|
211
|
+
|
212
|
+
# # We verify if the method exists, and if it is in the available component list
|
213
|
+
# if component_model.respond_to?(component_id) && component_model.component_ids[component_id]
|
214
|
+
# respond_with_successful(component_model.public_send(component_id, current_user, @query))
|
215
|
+
# else
|
216
|
+
# respond_with_not_found()
|
217
|
+
# end
|
218
|
+
# end
|
219
|
+
|
220
|
+
# private
|
221
|
+
|
222
|
+
# # @return [void]
|
223
|
+
# # @description Sets the variable @dashboard. The variable contains the *cloud_object* *dashboard*
|
224
|
+
# # to be handled by the controller action that called this method
|
225
|
+
# # @example
|
226
|
+
# # #suppose params[:id] = 1
|
227
|
+
# # puts @dashboard # will display nil
|
228
|
+
# # set_dashboard
|
229
|
+
# # puts @dashboard # will display an instance of CloudHelp:TicketDashboard
|
230
|
+
# def set_dashboard
|
231
|
+
# dynamic_info = self.class.dynamic_info
|
232
|
+
|
233
|
+
# model = dynamic_info[:module_model]
|
234
|
+
# module_name = dynamic_info[:module_name]
|
235
|
+
# module_name_full = dynamic_info[:module_name_full].underscore
|
236
|
+
|
237
|
+
# # When params[:id] is 'default' order of priority is:
|
238
|
+
# # Main dashboard for user goes first
|
239
|
+
# # Main dashboard for role goes second
|
240
|
+
# # Default dashboard goes third
|
241
|
+
# if params[:id] == "default"
|
242
|
+
# # Main dashboard for user
|
243
|
+
# @dashboard = model.find_by(
|
244
|
+
# #"#{full_module_name}_account_id".to_sym => current_user.account.id,
|
245
|
+
# account_id: current_user.account.id,
|
246
|
+
# main: true,
|
247
|
+
# #user_main_id: current_user.id
|
248
|
+
# )
|
249
|
+
|
250
|
+
# return if @dashboard
|
251
|
+
|
252
|
+
# # Main dashboard for role
|
253
|
+
# # @dashboard = model.find_by(
|
254
|
+
# # :account_id => current_user.account.id,
|
255
|
+
# # role_id: current_user.roles.first.id
|
256
|
+
# # )
|
257
|
+
# # return if @dashboard
|
258
|
+
|
259
|
+
# # Default dashboard
|
260
|
+
# @dashboard = model.find_by(
|
261
|
+
# account_id: current_user.account.id,
|
262
|
+
# default: true
|
263
|
+
# )
|
264
|
+
# else
|
265
|
+
# @dashboard = model.find_by(
|
266
|
+
# id: params[:id],
|
267
|
+
# :account_id => current_user.account.id,
|
268
|
+
# )
|
269
|
+
# end
|
270
|
+
# end
|
271
|
+
|
272
|
+
# def dashboard_params
|
273
|
+
# params.require(:dashboard).permit(
|
274
|
+
# :name,
|
275
|
+
# :default,
|
276
|
+
# :roles_id,
|
144
277
|
# components_attributes: [
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
#
|
151
|
-
# },
|
152
|
-
#
|
153
|
-
# component_id: new_customers_component,
|
154
|
-
# layout: 4,
|
155
|
-
# index: 3,
|
156
|
-
# configuration: {}
|
157
|
-
# }
|
278
|
+
# :id,
|
279
|
+
# :name,
|
280
|
+
# :component_id,
|
281
|
+
# :layout,
|
282
|
+
# :index,
|
283
|
+
# {query_configuration: {}},
|
284
|
+
# {custom_configuration: {}},
|
285
|
+
# :_destroy
|
158
286
|
# ]
|
159
|
-
#
|
160
|
-
#
|
161
|
-
# this.http.put(`127.0.0.1/help/dashboards/${dashboard_id}`, data);
|
162
|
-
def update
|
163
|
-
return respond_with_not_found unless @dashboard
|
164
|
-
|
165
|
-
if @dashboard.update(dashboard_params)
|
166
|
-
respond_with_successful(@dashboard.show)
|
167
|
-
else
|
168
|
-
respond_with_error(@dashboard.errors.full_messages.to_sentence)
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
# @return [Json] Json that contains wheter the dashboard was successfully deleted or not.
|
173
|
-
# If it it not successful, it returns an error message
|
174
|
-
# @description Deletes an existing *dashboard* associated to the *current_user*'s *account*.
|
175
|
-
# Since the dashboard has details, these are also deleted. However, if there
|
176
|
-
# is an existing *cloud_object* associated to the *dashboard*, it cannot be deleted
|
177
|
-
# @example
|
178
|
-
# # Executing this controller's action from javascript's frontend
|
179
|
-
# let dashboard_id = 4;
|
180
|
-
# this.http.delete(`127.0.0.1/help/dashboards/${dashboard_id}`);
|
181
|
-
def destroy
|
182
|
-
return respond_with_not_found unless @dashboard
|
183
|
-
|
184
|
-
if @dashboard.destroy
|
185
|
-
respond_with_successful
|
186
|
-
else
|
187
|
-
respond_with_error(@dashboard.errors.full_messages.to_sentence)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
def options
|
192
|
-
dynamic_info = self.class.dynamic_info
|
193
|
-
model = dynamic_info[:module_model]
|
194
|
-
|
195
|
-
respond_with_successful(model.options(current_user, @query))
|
196
|
-
end
|
197
|
-
|
198
|
-
def resource_component
|
199
|
-
dynamic_info = self.class.dynamic_info
|
200
|
-
component_model = dynamic_info[:component_model]
|
201
|
-
|
202
|
-
component_id = sanitize(params[:component_id].to_sym)
|
203
|
-
|
204
|
-
# We verify if the method exists, and if it is in the available component list
|
205
|
-
if component_model.respond_to?(component_id) && component_model.component_ids[component_id]
|
206
|
-
respond_with_successful(component_model.public_send(component_id, current_user, @query))
|
207
|
-
else
|
208
|
-
respond_with_not_found()
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
private
|
213
|
-
|
214
|
-
# @return [void]
|
215
|
-
# @description Sets the variable @dashboard. The variable contains the *cloud_object* *dashboard*
|
216
|
-
# to be handled by the controller action that called this method
|
217
|
-
# @example
|
218
|
-
# #suppose params[:id] = 1
|
219
|
-
# puts @dashboard # will display nil
|
220
|
-
# set_dashboard
|
221
|
-
# puts @dashboard # will display an instance of CloudHelp:TicketDashboard
|
222
|
-
def set_dashboard
|
223
|
-
dynamic_info = self.class.dynamic_info
|
224
|
-
|
225
|
-
model = dynamic_info[:module_model]
|
226
|
-
module_name = dynamic_info[:module_name]
|
227
|
-
module_name_full = dynamic_info[:module_name_full].underscore
|
228
|
-
|
229
|
-
# When params[:id] is 'default' order of priority is:
|
230
|
-
# Main dashboard for user goes first
|
231
|
-
# Main dashboard for role goes second
|
232
|
-
# Default dashboard goes third
|
233
|
-
if params[:id] == "default"
|
234
|
-
# Main dashboard for user
|
235
|
-
@dashboard = model.find_by(
|
236
|
-
#"#{full_module_name}_account_id".to_sym => current_user.account.id,
|
237
|
-
account_id: current_user.account.id,
|
238
|
-
main: true,
|
239
|
-
#user_main_id: current_user.id
|
240
|
-
)
|
241
|
-
|
242
|
-
return if @dashboard
|
243
|
-
|
244
|
-
# Main dashboard for role
|
245
|
-
# @dashboard = model.find_by(
|
246
|
-
# :account_id => current_user.account.id,
|
247
|
-
# role_id: current_user.roles.first.id
|
248
|
-
# )
|
249
|
-
# return if @dashboard
|
250
|
-
|
251
|
-
# Default dashboard
|
252
|
-
@dashboard = model.find_by(
|
253
|
-
account_id: current_user.account.id,
|
254
|
-
default: true
|
255
|
-
)
|
256
|
-
else
|
257
|
-
@dashboard = model.find_by(
|
258
|
-
id: params[:id],
|
259
|
-
:account_id => current_user.account.id,
|
260
|
-
)
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
def dashboard_params
|
265
|
-
params.require(:dashboard).permit(
|
266
|
-
:name,
|
267
|
-
:default,
|
268
|
-
:roles_id,
|
269
|
-
components_attributes: [
|
270
|
-
:id,
|
271
|
-
:name,
|
272
|
-
:component_id,
|
273
|
-
:layout,
|
274
|
-
:index,
|
275
|
-
{query_configuration: {}},
|
276
|
-
{custom_configuration: {}},
|
277
|
-
:_destroy
|
278
|
-
]
|
279
|
-
)
|
280
|
-
end
|
287
|
+
# )
|
288
|
+
# end
|
281
289
|
|
282
|
-
private
|
290
|
+
# private
|
283
291
|
|
284
|
-
# Build the Rails models and engine information for
|
285
|
-
# the current engine implementing the shared dashboards
|
286
|
-
# Example: For the LesliAudit engine
|
287
|
-
# {
|
288
|
-
# :module_name => "audit",
|
289
|
-
# :module_name_full => "LesliAudit",
|
290
|
-
# :module_model => "LesliAudit::Dashboard",
|
291
|
-
# :module_model_component => "LesliAudit::Dashboard::Component"
|
292
|
-
# }
|
293
|
-
def self.dynamic_info
|
292
|
+
# # Build the Rails models and engine information for
|
293
|
+
# # the current engine implementing the shared dashboards
|
294
|
+
# # Example: For the LesliAudit engine
|
295
|
+
# # {
|
296
|
+
# # :module_name => "audit",
|
297
|
+
# # :module_name_full => "LesliAudit",
|
298
|
+
# # :module_model => "LesliAudit::Dashboard",
|
299
|
+
# # :module_model_component => "LesliAudit::Dashboard::Component"
|
300
|
+
# # }
|
301
|
+
# def self.dynamic_info
|
294
302
|
|
295
|
-
|
303
|
+
# module_info = self.name.split("::")
|
296
304
|
|
297
|
-
|
305
|
+
# module_name = module_info[0].sub("Lesli", "").downcase
|
298
306
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
end
|
307
|
+
# {
|
308
|
+
# module_name: module_name,
|
309
|
+
# module_name_full: module_info[0],
|
310
|
+
# module_model: "#{ module_info[0] }::Dashboard".constantize,
|
311
|
+
# module_model_component: "#{ module_info[0] }::Dashboard::Component".constantize
|
312
|
+
# }
|
313
|
+
# end
|
306
314
|
end
|
307
315
|
end
|
308
316
|
end
|
@@ -140,7 +140,7 @@ module Lesli
|
|
140
140
|
end
|
141
141
|
|
142
142
|
# 03.06 Dashboard engine
|
143
|
-
def navigation_engine_dashboard(title: "Dashboard", subtitle: "
|
143
|
+
def navigation_engine_dashboard(title: "Dashboard", subtitle: "Dashboard Manager")
|
144
144
|
return unless defined? LesliDashboard
|
145
145
|
navigation_engine_item(title,subtitle,"dashboard",lesli_dashboard.root_path,controller_path.include?("lesli_dashboard"))
|
146
146
|
end
|
@@ -34,7 +34,7 @@ module Lesli
|
|
34
34
|
class Role::Action < ApplicationLesliRecord
|
35
35
|
belongs_to :role
|
36
36
|
|
37
|
-
|
37
|
+
after_save :synchronize_privileges
|
38
38
|
after_destroy :synchronize_privileges
|
39
39
|
|
40
40
|
belongs_to :action, class_name: "SystemController::Action"
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Lesli
|
4
4
|
|
5
|
-
Copyright (c)
|
5
|
+
Copyright (c) 2025, 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
|
@@ -17,157 +17,31 @@ GNU General Public License for more details.
|
|
17
17
|
You should have received a copy of the GNU General Public License
|
18
18
|
along with this program. If not, see http://www.gnu.org/licenses/.
|
19
19
|
|
20
|
-
Lesli ·
|
20
|
+
Lesli · Ruby on Rails SaaS Development Framework.
|
21
21
|
|
22
|
-
Made with ♥ by
|
22
|
+
Made with ♥ by LesliTech
|
23
23
|
Building a better future, one line of code at a time.
|
24
24
|
|
25
25
|
@contact hello@lesli.tech
|
26
|
-
@website https://lesli.tech
|
26
|
+
@website https://www.lesli.tech
|
27
27
|
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
28
28
|
|
29
|
-
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
30
|
-
// ·
|
31
|
-
|
29
|
+
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
30
|
+
// ·
|
32
31
|
=end
|
33
32
|
|
34
33
|
module Lesli
|
35
34
|
module Shared
|
36
|
-
class
|
35
|
+
class DashboardFallback < ::Lesli::ApplicationLesliRecord
|
37
36
|
self.abstract_class = true
|
38
|
-
|
39
|
-
belongs_to :user_creator, class_name: "User", foreign_key: "users_id", optional: true
|
40
|
-
|
41
|
-
after_update :verify_default_dashboard
|
42
|
-
after_create :verify_default_dashboard
|
43
|
-
|
44
|
-
#enum component_ids: {}
|
45
|
-
|
46
|
-
# @return [void]
|
47
|
-
# @param account [LesliEngine::Account]
|
48
|
-
# @description Initializes a default dummy dashboard for the account. This guarantees that the users
|
49
|
-
# will be able to access the dashboard page. Even if it's empty.
|
50
|
-
# @example
|
51
|
-
# # Imagine you are adding a new engine to your instance (CloudProposal)
|
52
|
-
# # To execute this function, you must only do
|
53
|
-
# my_account = Account.first
|
54
|
-
# my_account.proposal = CloudProposal::Account.new
|
55
|
-
def self.initialize_dashboard(modelo, account, components)
|
56
|
-
|
57
|
-
components.unshift({
|
58
|
-
name: "Engine version",
|
59
|
-
component_id: "engine-version",
|
60
|
-
layout: 2,
|
61
|
-
query_configuration: {},
|
62
|
-
custom_configuration: {}
|
63
|
-
})
|
64
|
-
|
65
|
-
modelo.create_with(
|
66
|
-
default: true,
|
67
|
-
main: false,
|
68
|
-
components_attributes: components
|
69
|
-
).find_or_create_by!(
|
70
|
-
account: account,
|
71
|
-
name: "Default Dashboard"
|
72
|
-
)
|
73
|
-
end
|
74
|
-
|
75
|
-
# @return [Hash] Hash of containing the information of the dashboard and its components.
|
76
|
-
# @description Returns a hash with information about the dashboard and all its *components*.
|
77
|
-
# Each component is returned in the configuration view, not the render view. This means that
|
78
|
-
# this method is ment to be used when updating the dashboard
|
79
|
-
# @example
|
80
|
-
# respond_with_successful(CloudHelp::Dashboard.first.show)
|
81
|
-
def show
|
82
|
-
attributes.merge({
|
83
|
-
components: components.order(index: :asc)
|
84
|
-
# components: [{
|
85
|
-
# name: "ticket",
|
86
|
-
# component_id: "ticket"
|
87
|
-
# },{
|
88
|
-
# name: "ticket",
|
89
|
-
# component_id: "ticket"
|
90
|
-
# }]
|
91
|
-
})
|
37
|
+
def self.initialize_dashboard(account)
|
92
38
|
end
|
39
|
+
end
|
93
40
|
|
94
|
-
|
95
|
-
# @param current_user [User] The user that made this request
|
96
|
-
# @param query [Hash] Query containing filters. Currently unused, but required
|
97
|
-
# @descriptions Returns a list of options needed to create and manage dashboard components. For now,
|
98
|
-
# the returned options are: A list of roles, the enoun containing the component_ids, generic configuration options
|
99
|
-
# for all dashboad components and a descriptions hash, that contains brief descriptions for each component to help
|
100
|
-
# the user understand what each component does. Any class that inherits from this one can send a block to add extra
|
101
|
-
# functionality. For example, the descriptions must be implemented directly from the engine.
|
102
|
-
# @example
|
103
|
-
# CloudHouse::Dashboard.options(User.find(2), nil)
|
104
|
-
def self.options(current_user, query)
|
105
|
-
dynamic_info = self.dynamic_info
|
106
|
-
component_model = dynamic_info[:module_model_component]
|
107
|
-
|
108
|
-
component_ids = component_model.component_ids.map do |comp|
|
109
|
-
{
|
110
|
-
value: comp,
|
111
|
-
text: comp
|
112
|
-
}
|
113
|
-
end
|
114
|
-
|
115
|
-
options = {
|
116
|
-
component_ids: component_ids,
|
117
|
-
#components_configuration_options: component_model.configuration_options,
|
118
|
-
descriptions: {}
|
119
|
-
}
|
120
|
-
|
121
|
-
if block_given?
|
122
|
-
yield(options)
|
123
|
-
else
|
124
|
-
return options
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
private
|
129
|
-
|
130
|
-
# @return [void]
|
131
|
-
# @descriptions This is an after_updated and after_create method that validates that at any moment in time, there is only
|
132
|
-
# one default dashboard in the engine. If there is another default dashboard, it's *default* field is set to false
|
133
|
-
# before committing the changes
|
134
|
-
# @example
|
135
|
-
# CloudFocus::Dasbhoard.where(default: false).first.update!(default: true)
|
136
|
-
# # This will automatically trigger this function and remove the *default* field from the old default dashboard
|
137
|
-
def verify_default_dashboard
|
138
|
-
if default
|
139
|
-
dashboards = self.class.where.not(id: id).where(account: account)
|
140
|
-
self.class.where.not(id: id).where(account: account).update_all(default: false)
|
141
|
-
end
|
142
|
-
|
143
|
-
unless self.class.where(account: account).find_by(default: true)
|
144
|
-
errors.add(:base, I18n.t("core.dashboards.messages_danger_default_dashboard_must_exist"))
|
145
|
-
raise ActiveRecord::Rollback
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
# Build the Rails models and engine information for
|
150
|
-
# the current engine implementing the shared dashboards
|
151
|
-
# Example: For the LesliAudit engine
|
152
|
-
# {
|
153
|
-
# :module_name => "audit",
|
154
|
-
# :module_name_full => "LesliAudit",
|
155
|
-
# :module_model => "LesliAudit::Dashboard",
|
156
|
-
# :module_model_component => "LesliAudit::Dashboard::Component"
|
157
|
-
# }
|
158
|
-
def self.dynamic_info
|
159
|
-
|
160
|
-
module_info = self.name.split("::")
|
41
|
+
base_class = "::LesliDashboard::Shared::Dashboard".safe_constantize || DashboardFallback
|
161
42
|
|
162
|
-
|
163
|
-
|
164
|
-
{
|
165
|
-
module_name: module_name,
|
166
|
-
module_name_full: module_info[0],
|
167
|
-
module_model: "#{ module_info[0] }::Dashboard".constantize,
|
168
|
-
module_model_component: "#{ module_info[0] }::Dashboard::Component".constantize
|
169
|
-
}
|
170
|
-
end
|
43
|
+
class Dashboard < DashboardFallback
|
44
|
+
self.abstract_class = true
|
171
45
|
end
|
172
46
|
end
|
173
47
|
end
|
@@ -1,58 +1,76 @@
|
|
1
1
|
module Lesli
|
2
2
|
class Role::ActionService < Lesli::ApplicationLesliService
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
:
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
4
|
+
def find id
|
5
|
+
#super(current_user.account.users.joins(:detail).find_by(id: id))
|
6
|
+
super(Lesli::Role::Action.with_deleted.find(id))
|
7
|
+
end
|
8
|
+
|
9
|
+
def index params
|
10
|
+
|
11
|
+
def clean action
|
12
|
+
{
|
13
|
+
:id => action.id,
|
14
|
+
:role_id => action.role_id,
|
15
|
+
:action_id => action.action_id,
|
16
|
+
:deleted_at => action.deleted_at,
|
17
|
+
:active => action.active
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
role_actions = {}
|
22
|
+
|
23
|
+
Lesli::Role::Action.with_deleted.joins(system_controller_action: :system_controller)
|
24
|
+
.select(
|
25
|
+
:id,
|
26
|
+
:role_id,
|
27
|
+
:action_id,
|
28
|
+
:deleted_at,
|
29
|
+
"lesli_system_controllers.id as controller_id",
|
30
|
+
"lesli_system_controllers.name as controller_name",
|
31
|
+
"lesli_system_controller_actions.name as controller_action_name",
|
32
|
+
"case when lesli_role_actions.deleted_at is null then TRUE else FALSE end active"
|
33
|
+
).each do |action|
|
34
|
+
|
35
|
+
unless role_actions.has_key?(action[:controller_name])
|
36
|
+
role_actions[action[:controller_name]] = {
|
37
|
+
list:nil,
|
38
|
+
index: nil,
|
39
|
+
show:nil,
|
40
|
+
create:nil,
|
41
|
+
update:nil,
|
42
|
+
destroy:nil
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
if action[:controller_action_name] == "list"
|
47
|
+
role_actions[action[:controller_name]][:list] = clean(action)
|
48
|
+
end
|
49
|
+
|
50
|
+
if action[:controller_action_name] == "index"
|
51
|
+
role_actions[action[:controller_name]][:index] = clean(action)
|
53
52
|
end
|
54
53
|
|
55
|
-
|
54
|
+
if action[:controller_action_name] == "show"
|
55
|
+
role_actions[action[:controller_name]][:show] = clean(action)
|
56
|
+
end
|
57
|
+
|
58
|
+
if action[:controller_action_name] == "create"
|
59
|
+
role_actions[action[:controller_name]][:create] = clean(action)
|
60
|
+
end
|
61
|
+
|
62
|
+
if action[:controller_action_name] == "update"
|
63
|
+
role_actions[action[:controller_name]][:update] = clean(action)
|
64
|
+
end
|
65
|
+
|
66
|
+
if action[:controller_action_name] == "destroy"
|
67
|
+
role_actions[action[:controller_name]][:destroy] = clean(action)
|
68
|
+
end
|
56
69
|
end
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
role_actions
|
57
74
|
end
|
75
|
+
end
|
58
76
|
end
|
@@ -125,20 +125,10 @@ html, body, * {
|
|
125
125
|
Getting started
|
126
126
|
</a>
|
127
127
|
</div>
|
128
|
+
<%= link_to("Apps", "/lesli/apps") unless defined?(LesliDashboard) %>
|
128
129
|
<% if defined?(LesliShield) %>
|
129
130
|
<%= link_to("Dashboard", "/dashboard") if user_signed_in? && defined?(LesliDashboard) %>
|
130
131
|
<%= link_to("Logout", "/logout") if user_signed_in? %>
|
131
132
|
<%= link_to("Login", "/login") unless user_signed_in? %>
|
132
133
|
<% end %>
|
133
134
|
</section>
|
134
|
-
|
135
|
-
<% if Rails.env.production? %>
|
136
|
-
<!-- Google tag (gtag.js) -->
|
137
|
-
<script async src="https://www.googletagmanager.com/gtag/js?id=G-LJRTGWVRCC"></script>
|
138
|
-
<script>
|
139
|
-
window.dataLayer = window.dataLayer || [];
|
140
|
-
function gtag(){dataLayer.push(arguments);}
|
141
|
-
gtag('js', new Date());
|
142
|
-
gtag('config', 'G-LJRTGWVRCC');
|
143
|
-
</script>
|
144
|
-
<% end %>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<%#
|
2
|
+
|
3
|
+
Lesli
|
4
|
+
|
5
|
+
Copyright (c) 2023, 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 https://www.lesli.tech
|
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
|
+
%>
|
32
|
+
|
33
|
+
<%= render("lesli_dashboard/dashboards/shared/edit") if defined?(LesliDashboard) %>
|
@@ -30,36 +30,4 @@ Building a better future, one line of code at a time.
|
|
30
30
|
// ·
|
31
31
|
%>
|
32
32
|
|
33
|
-
|
34
|
-
hour = Date2.new.date.get.hour # Returns the hour (0–23) based on the app's timezone
|
35
|
-
welcome_options = ["Good morning", "Good afternoon", "Good evening"]
|
36
|
-
welcome_text = ""
|
37
|
-
|
38
|
-
if hour < 12
|
39
|
-
welcome_text = welcome_options.first
|
40
|
-
elsif hour < 18
|
41
|
-
welcome_text = welcome_options.second
|
42
|
-
else
|
43
|
-
welcome_text = welcome_options.third
|
44
|
-
end
|
45
|
-
%>
|
46
|
-
|
47
|
-
<%= render(LesliView::Layout::Container.new("dashboards-show", :dashboard => true)) do %>
|
48
|
-
|
49
|
-
<section class="lesli-element-header is-flex mt-6 mb-6 pb-6 container">
|
50
|
-
<div class="lesli-element-header-title">
|
51
|
-
<h1 class="subtitle is-size-3 mb-0"><%= welcome_text %>, <%= current_user.full_name %>.</h1>
|
52
|
-
<p class=""><%= Date2.new.date_words_day %>.</p>
|
53
|
-
</div>
|
54
|
-
</section>
|
55
|
-
|
56
|
-
<%#= render(LesliView::Elements::Empty.new(text: "Empty dashboard")) if @dashboard[:components].blank? %>
|
57
|
-
|
58
|
-
<%= dd @dashboard %>
|
59
|
-
|
60
|
-
<div class="columns is-multiline is-variable is-4 dashboard-components">
|
61
|
-
<%# @dashboard[:components].each do |component| %>
|
62
|
-
<%#= render("#{controller.controller_path}/component-#{component}", { :component => component }) %>
|
63
|
-
<%# end %>
|
64
|
-
</div>
|
65
|
-
<% end %>
|
33
|
+
<%= render("lesli_dashboard/dashboards/shared/show") if defined?(LesliDashboard) %>
|
data/lib/lesli/engine.rb
CHANGED
data/lib/lesli/routing.rb
CHANGED
@@ -74,7 +74,10 @@ module Lesli
|
|
74
74
|
root to: "dashboards#show"
|
75
75
|
|
76
76
|
# Dashboard management
|
77
|
-
resource :dashboard, only: [:show]
|
77
|
+
resource :dashboard, only: [:show, :edit]
|
78
|
+
|
79
|
+
# uncomment this to enable multiple dashboards
|
80
|
+
#resources :dashboards, only: [:show, :edit]
|
78
81
|
# resources :dashboards do
|
79
82
|
# collection do
|
80
83
|
# post "list" => :index
|
data/lib/lesli/version.rb
CHANGED
data/readme.md
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
<
|
2
|
-
<img width="
|
3
|
-
<
|
4
|
-
</
|
1
|
+
<div align="center" class="documentation-header">
|
2
|
+
<img width="100" alt="Lesli logo" src="./app/assets/images/lesli/lesli-logo.svg" />
|
3
|
+
<h3 align="center">Ruby on Rails SaaS Development Framework.</h3>
|
4
|
+
</div>
|
5
|
+
|
5
6
|
|
7
|
+
<br />
|
6
8
|
<hr/>
|
7
9
|
|
8
|
-
<
|
10
|
+
<div align="center" class="documentation-statics">
|
9
11
|
<a target="blank" href="https://rubygems.org/gems/lesli">
|
10
12
|
<img height="22" alt="Gem Version" src="https://badge.fury.io/rb/lesli.svg"/>
|
11
13
|
</a>
|
@@ -15,7 +17,7 @@
|
|
15
17
|
<a href="https://codecov.io/github/LesliTech/LesliBabel">
|
16
18
|
<img height="22" src="https://sonarcloud.io/api/project_badges/measure?project=LesliTech_LesliBabel&metric=sqale_rating"/>
|
17
19
|
</a>
|
18
|
-
</
|
20
|
+
</div>
|
19
21
|
|
20
22
|
<hr/>
|
21
23
|
<br />
|
@@ -37,7 +39,7 @@ Lesli is completely open source and comes with features and tools that can save
|
|
37
39
|
|
38
40
|
<br />
|
39
41
|
<hr />
|
40
|
-
<p align="center">
|
42
|
+
<p align="center" class="has-text-centered">
|
41
43
|
Lesli is currently in alpha, but we're excited about the promising improvements coming soon!
|
42
44
|
</p>
|
43
45
|
<hr />
|
@@ -132,15 +134,16 @@ RAILS_SERVE_STATIC_FILES=true rails s --environment=production
|
|
132
134
|
<br />
|
133
135
|
|
134
136
|
|
137
|
+
### Lesli Documentation
|
138
|
+
* [website](https://www.lesli.dev/)
|
139
|
+
* [documentation](https://www.lesli.dev/lesli/)
|
140
|
+
|
135
141
|
|
136
142
|
### Get in touch with Lesli
|
137
143
|
|
138
|
-
* [
|
144
|
+
* [X: @LesliTech](https://x.com/LesliTech)
|
139
145
|
* [Email: hello@lesli.tech](hello@lesli.tech)
|
140
|
-
* [
|
141
|
-
|
142
|
-
<br />
|
143
|
-
|
146
|
+
* [Website: https://www.lesli.tech](https://www.lesli.tech)
|
144
147
|
|
145
148
|
|
146
149
|
### License
|
@@ -162,8 +165,12 @@ along with this program. If not, see http://www.gnu.org/licenses/.
|
|
162
165
|
|
163
166
|
<hr />
|
164
167
|
<br />
|
168
|
+
<br />
|
165
169
|
|
166
|
-
<
|
170
|
+
<div align="center" class="has-text-centered">
|
167
171
|
<img width="200" alt="Lesli logo" src="https://cdn.lesli.tech/lesli/brand/app-logo.svg" />
|
168
|
-
<h4 align="center">Ruby on Rails SaaS Development Framework.</h4>
|
169
|
-
</
|
172
|
+
<h4 align="center" class="mt-0">Ruby on Rails SaaS Development Framework.</h4>
|
173
|
+
</div>
|
174
|
+
|
175
|
+
<br />
|
176
|
+
<br />
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lesli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.
|
4
|
+
version: 5.0.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- The Lesli Development Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-07-
|
11
|
+
date: 2025-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n-js
|
@@ -80,20 +80,6 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 1.2.2
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: ancestry
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: 4.3.3
|
90
|
-
type: :runtime
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: 4.3.3
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: lesli_date
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -270,6 +256,7 @@ files:
|
|
270
256
|
- app/views/lesli/partials/_application-public-footer.html.erb
|
271
257
|
- app/views/lesli/partials/_application-public-javascript.html.erb
|
272
258
|
- app/views/lesli/partials/_application-public-scss.html.erb
|
259
|
+
- app/views/lesli/shared/dashboards/_edit.html.erb
|
273
260
|
- app/views/lesli/shared/dashboards/_show.html.erb
|
274
261
|
- app/views/lesli/wrappers/_application-devise-simple.erb
|
275
262
|
- app/views/lesli/wrappers/_application-devise.html.erb
|