motor-admin 0.1.47 → 0.1.48

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bb7c564e999344d1cd2b2939b095e1e5c0b27d441b176365192275f623a1a887
4
- data.tar.gz: 748ecbf8188b5375efb7b957503f1d0986144e0fd394956edf81677623a73a59
3
+ metadata.gz: 55c1bf8c2fc221d84cbb142204893b6625d980d9c9966fe08cab12b1b8b9e9f6
4
+ data.tar.gz: 25c3c29dac2b0abd4414cf5c90ada44e4af357efb43ddd63fad4a632321bf89f
5
5
  SHA512:
6
- metadata.gz: 8faab90b6e21873a78e2eab889d2a328550c4533b922040662011930d89e6d9e515ba1eb860ed2978033ab339b0cd686250994cf8ee8a70b89223fb66337ecb5
7
- data.tar.gz: f51c89fdcd5f453793b89a37b4868f282ed2bb5d457cd4cb50b0a786592ccbceb8d0d458a98fa19a3b176698a1787b1845e7321a18ad5d3d11bbd94dd4684ca2
6
+ metadata.gz: 6faa1ebe8212cf8855b064f4c80df93b6f8a4ef93b09ba98d5565a24a86d6e4274f746511c28ffc5fca2da67710572ee53b2aaa384199ef3fa6de908cf774330
7
+ data.tar.gz: 737e7e1768be0721d825029176e3397007feb21794eb1eeec2ebe777c0a5c3880b3942f23be50476bdf7f12f564fd03fa3aadb8a69a31d8b06ba2dfb1111e845
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2021 Pete Matsyburka
1
+ Copyright (c) 2021 Pete Matsyburka <pete.matsy@gmail.com>
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  Low-code Admin panel and Business intelligence Rails engine **(no DSL - configurable from the UI)**.
4
4
 
5
- 🤓 [Demo App](https://motor-admin-demo.herokuapp.com)
5
+ 🤓 [Demo App](https://motor-admin.herokuapp.com/demo) | [Features overview](https://www.youtube.com/watch?v=ngVoci8Hll4&list=PLu7llEMh0KcOkR3Uy_RJT0cXPZQKAYVsq&index=1)
6
6
 
7
- [![Admin Panel](https://user-images.githubusercontent.com/5418788/119258612-2351f780-bbd3-11eb-8264-2e044cde868d.png)](https://motor-admin-demo.herokuapp.com)
7
+ [![Admin Panel](https://user-images.githubusercontent.com/5418788/119318538-1f30e300-bc82-11eb-94a4-107c31c93b13.png)](https://motor-admin.herokuapp.com/demo)
8
8
 
9
9
  ## Installation
10
10
  Add this line to your application's Gemfile:
@@ -20,7 +20,7 @@ $ bundle install
20
20
 
21
21
  Create and run migration:
22
22
  ```bash
23
- $ rails generate motor:install && rake db:migrate
23
+ $ rails motor:install && rake db:migrate
24
24
  ```
25
25
 
26
26
  ## Features
@@ -38,11 +38,11 @@ $ rails generate motor:install && rake db:migrate
38
38
 
39
39
  ### Customizable CRUD
40
40
 
41
- ![Resource settings](https://user-images.githubusercontent.com/5418788/119262945-b136de00-bbe5-11eb-846a-6e01c8c42904.png)
41
+ ![Resource settings](https://user-images.githubusercontent.com/5418788/119318569-2a840e80-bc82-11eb-9ba3-f3964eb6f997.png)
42
42
 
43
43
  ![Settings UI](https://user-images.githubusercontent.com/5418788/119263883-90708780-bbe9-11eb-9f9f-f76fed0b7f27.png)
44
44
 
45
- Everything in the admin panel can be configured using the intuitive settings that can be opened via the icon in the top right corner.
45
+ Everything in the admin panel can be configured using intuitive settings UI, which can be opened via the icon in the top right corner.
46
46
 
47
47
  Data displayed on the resource page can be completely custimized via [SQL queries](#sql-queries) and [dashboards](#dashboards) attached to the resource as a tab. Usually, queries used to display resource data should contain `{{resource_name_id}}` [variable](#sql-queries).
48
48
 
@@ -50,13 +50,13 @@ Data displayed on the resource page can be completely custimized via [SQL querie
50
50
 
51
51
  ![Custom actions](https://user-images.githubusercontent.com/5418788/119266132-3c1dd580-bbf2-11eb-9666-09e1640eaf7b.png)
52
52
 
53
- Custom resource actions can be added via Active Record method call, API endpoint, or [custom forms](#forms-builder). Also, it's possible to override default Create/Update/Delete actions.
53
+ Custom resource actions can be added via Active Record method call, API endpoint, or [custom forms](#forms-builder). Also, it's possible to override default create/update/delete actions.
54
54
 
55
55
  ### Forms Builder
56
56
 
57
57
  ![Custom form](https://user-images.githubusercontent.com/5418788/119264008-1391dd80-bbea-11eb-9f14-cb405e77fb60.png)
58
58
 
59
- Values from the form fields can be used in API path via `{field_name}` syntax: `/api/some-endpoint/{field_name}/apply`
59
+ Values from the form fields can be used in API path via `{field_name}` syntax: `/api/some-endpoint/{resource_id}/apply`
60
60
 
61
61
  ### SQL Queries
62
62
 
@@ -68,7 +68,7 @@ Queries can include embeded variables via `{{variable}}` syntax ([mustache](http
68
68
 
69
69
  ![motor-visualization](https://user-images.githubusercontent.com/5418788/119264625-a2075e80-bbec-11eb-986c-6106dd6e47ce.png)
70
70
 
71
- Data from the SQL query can be represented as: [table](https://motor-admin-demo.herokuapp.com/queries/12), [number](https://motor-admin-demo.herokuapp.com/queries/6), [line chart](https://motor-admin-demo.herokuapp.com/queries/3), [bar chart](https://motor-admin-demo.herokuapp.com/queries/1), [pie chart](https://motor-admin-demo.herokuapp.com/queries/9), [funnel](https://motor-admin-demo.herokuapp.com/queries/7), [markdown](https://motor-admin-demo.herokuapp.com/queries/8)
71
+ Data from the SQL query can be represented as: [table](https://motor-admin.herokuapp.com/demo/queries/12), [number](https://motor-admin.herokuapp.com/demo/queries/6), [line chart](https://motor-admin.herokuapp.com/demo/queries/3), [bar chart](https://motor-admin.herokuapp.com/demo/queries/1), [pie chart](https://motor-admin.herokuapp.com/demo/queries/9), [funnel](https://motor-admin.herokuapp.com/demo/queries/7), [markdown](https://motor-admin.herokuapp.com/demo/queries/8)
72
72
 
73
73
  ### Dashboards
74
74
 
@@ -80,20 +80,20 @@ SQL queries can be organized into dashboards to create a convenient representati
80
80
 
81
81
  ![Email alert](https://user-images.githubusercontent.com/5418788/119265049-feb74900-bbed-11eb-8070-bcc8d6113b9b.png)
82
82
 
83
- Query data can be sent via email periodically using the alerts feature. Interval of the alert email can be specified using natural language, e.g. `every day at midnight`, `every Monday at 8 PM`, `every weekday at 6AM and 6PM`, `every minute`.
83
+ Query data can be sent via email periodically using the alerts feature. Interval of the alert email can be specified using natural language, e.g., `every day at midnight`, `every Monday at 8 PM`, `every weekday at 6AM and 6PM`, `every minute`.
84
84
 
85
- The sender address can be specified using `MOTOR_ADMIN_FROM_ADDRESS` environment variable.
85
+ The sender address can be specified using `MOTOR_ALERTS_FROM_ADDRESS` environment variable.
86
86
 
87
87
  ### Intelligence Search
88
88
 
89
89
  ![Intelligence search](https://user-images.githubusercontent.com/5418788/119266559-eea26800-bbf3-11eb-8cb3-d0538aa386a9.png)
90
90
 
91
- Intelligence search can be opened from the top right corner or using <kbd>Cmd</kbd> + <kbd>P</kbd> shortcut.
91
+ Intelligence search can be opened via the top right corner button or using <kbd>Cmd</kbd> + <kbd>P</kbd> shortcut.
92
92
 
93
93
 
94
94
  ### Optimized for Mobile
95
95
 
96
- ![motor-mobile](https://user-images.githubusercontent.com/5418788/119265905-38d61a00-bbf1-11eb-95c8-a4c95a2d77f7.png)
96
+ ![motor-mobile](https://user-images.githubusercontent.com/5418788/119269566-03392d00-bc01-11eb-9e9d-1f6a58fe0749.png)
97
97
 
98
98
 
99
99
  ### Configurations Sync
@@ -127,6 +127,12 @@ Start webpack dev server:
127
127
  yarn install && yarn serve
128
128
  ```
129
129
 
130
+ Setup development database:
131
+
132
+ ```bash
133
+ rake app:db:create && rake app:db:setup
134
+ ```
135
+
130
136
  Start example application in development mode:
131
137
 
132
138
  ```bash
@@ -143,4 +149,4 @@ MOTOR_DEVELOPMENT=true rails s
143
149
 
144
150
  ## License
145
151
 
146
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
152
+ The gem is available as open source under the terms of the [MIT License](https://github.com/omohokcoj/motor-admin/blob/master/LICENSE).
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Motor
4
+ module CurrentUserMethod
5
+ def current_user
6
+ if defined?(current_admin)
7
+ current_admin
8
+ elsif defined?(current_admin_user)
9
+ current_admin_user
10
+ elsif defined?(super)
11
+ super
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,30 +2,24 @@
2
2
 
3
3
  module Motor
4
4
  class ApiBaseController < ActionController::API
5
+ include Motor::CurrentUserMethod
6
+
7
+ class CanCanAbilityManageAll
8
+ include CanCan::Ability
9
+
10
+ def initialize(_)
11
+ can :manage, :all
12
+ end
13
+ end
14
+
5
15
  rescue_from StandardError do |e|
6
16
  Rails.logger.error(e)
7
17
 
8
18
  render json: { errors: [e.message] }, status: :internal_server_error
9
19
  end
10
20
 
11
- def current_user
12
- if defined?(current_admin)
13
- current_admin
14
- elsif defined?(current_admin_user)
15
- current_admin_user
16
- elsif defined?(super)
17
- super
18
- end
19
- end
20
-
21
21
  def current_ability
22
- klass = Class.new
23
- klass.include(CanCan::Ability)
24
- klass.define_method(:initialize) do |_user|
25
- can :manage, :all
26
- end
27
-
28
- klass.new(current_user)
22
+ CanCanAbilityManageAll.new(current_user)
29
23
  end
30
24
  end
31
25
  end
@@ -2,5 +2,6 @@
2
2
 
3
3
  module Motor
4
4
  class ApplicationController < ActionController::Base
5
+ include Motor::CurrentUserMethod
5
6
  end
6
7
  end
@@ -20,7 +20,7 @@ module Motor
20
20
  def show
21
21
  filename = params[:filename]
22
22
 
23
- return [404, {}, ''] unless Motor::Assets.manifest.values.include?(filename)
23
+ return [404, {}, ''] unless Motor::Assets.manifest.value?(filename)
24
24
 
25
25
  assign_headers(filename)
26
26
 
@@ -4,6 +4,8 @@ module Motor
4
4
  class UiController < ApplicationController
5
5
  layout 'motor/application'
6
6
 
7
+ helper_method :current_user
8
+
7
9
  def index
8
10
  Motor.reload! if Motor.development?
9
11
 
@@ -26,11 +26,11 @@ module Motor
26
26
  end
27
27
 
28
28
  def from_address
29
- from = ENV['MOTOR_ADMIN_FROM_ADDRESS'].presence
29
+ from = ENV['MOTOR_ALERTS_FROM_ADDRESS'].presence
30
30
 
31
31
  from ||= application_mailer_default_from
32
32
  from ||= mailer_config_from_address
33
- from ||= "reports@#{ENV['HOST'].sub(/\Awww\./, '')}" if ENV['HOST'].present?
33
+ from ||= "reports@#{ENV['HOST'].delete_prefix('www.')}" if ENV['HOST'].present?
34
34
 
35
35
  from || 'reports@example.com'
36
36
  end
@@ -44,7 +44,7 @@ module Motor
44
44
  def mailer_config_from_address
45
45
  return if Rails.application.config.action_mailer.default_url_options&.dig(:host).blank?
46
46
 
47
- "reports@#{Rails.application.config.action_mailer.default_url_options[:host].sub(/\Awww\./, '')}"
47
+ "reports@#{Rails.application.config.action_mailer.default_url_options[:host].delete_prefix('www.')}"
48
48
  end
49
49
  end
50
50
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Motor
4
4
  class Tag < ::Motor::ApplicationRecord
5
- has_many :taggable_tags
5
+ has_many :taggable_tags, dependent: :destroy
6
6
  end
7
7
  end
@@ -1 +1 @@
1
- <%= raw(Motor::Configs::BuildUiAppTag.call) %>
1
+ <%= raw(Motor::Configs::BuildUiAppTag.call(current_user)) %>
@@ -18,7 +18,7 @@ module Motor
18
18
  end
19
19
 
20
20
  def apply_filter_scope(rel, scope)
21
- configs = Motor::Resource.find_by_name(rel.klass.name.underscore)
21
+ configs = Motor::Resource.find_by(name: rel.klass.name.underscore)
22
22
 
23
23
  return rel unless configs
24
24
 
@@ -96,8 +96,8 @@ module Motor
96
96
  def normalize_include_params(params)
97
97
  case params
98
98
  when Array
99
- params.each_with_object({}) do |name, hash|
100
- hash[name] = { 'include' => {} }
99
+ params.index_with do |_|
100
+ { 'include' => {} }
101
101
  end
102
102
  when String
103
103
  { params => { 'include' => {} } }
@@ -57,13 +57,7 @@ module Motor
57
57
  def find_searchable_columns(model)
58
58
  model.columns.map do |column|
59
59
  next unless column.type.in?(COLUMN_TYPES)
60
-
61
- has_inclusion_validator =
62
- model.validators_on(column.name).any? do |e|
63
- e.is_a?(ActiveModel::Validations::InclusionValidator)
64
- end
65
-
66
- next if has_inclusion_validator
60
+ next if model.validators_on(column.name).any?(ActiveModel::Validations::InclusionValidator)
67
61
 
68
62
  column.name
69
63
  end.compact
data/lib/motor/assets.rb CHANGED
@@ -16,7 +16,7 @@ module Motor
16
16
 
17
17
  def icons
18
18
  manifest.select do |k, v|
19
- !k.ends_with?('.gz') && v.starts_with?('icons/') && !v.include?('DS_Store')
19
+ !k.ends_with?('.gz') && v.starts_with?('icons/') && v.exclude?('DS_Store')
20
20
  end.keys
21
21
  end
22
22
 
@@ -13,6 +13,7 @@ module Motor
13
13
  'location' => 'gps',
14
14
  'photo' => 'photo',
15
15
  'image' => 'photo',
16
+ 'screenshot' => 'photo',
16
17
  'picture' => 'photo',
17
18
  'video' => 'video',
18
19
  'file' => 'file',
@@ -12,21 +12,21 @@ module Motor
12
12
 
13
13
  module_function
14
14
 
15
- def call
15
+ def call(current_user = nil)
16
16
  cache_keys = LoadFromCache.load_cache_keys
17
17
 
18
- CACHE_STORE.fetch(cache_keys.hash) do
18
+ CACHE_STORE.fetch("#{cache_keys.hash}#{current_user&.id}") do
19
19
  CACHE_STORE.clear
20
20
 
21
- Motor::ApplicationController.helpers.content_tag(
22
- :div, '', id: 'app', data: build_data(cache_keys)
23
- )
21
+ Motor::ApplicationController.helpers.tag.div('', id: 'app', data: build_data(cache_keys, current_user))
24
22
  end
25
23
  end
26
24
 
27
25
  # @return [Hash]
28
- def build_data(cache_keys = {})
26
+ def build_data(cache_keys = {}, current_user = nil)
29
27
  {
28
+ current_user: current_user&.as_json(only: %i[id email]),
29
+ audits_count: Motor::Audit.count,
30
30
  base_path: Motor::Admin.routes.url_helpers.motor_path,
31
31
  schema: Motor::BuildSchema.call(cache_keys),
32
32
  header_links: header_links_data_hash(cache_keys[:configs]),
@@ -57,7 +57,7 @@ module Motor
57
57
  end
58
58
 
59
59
  def maybe_fetch_from_cache(type, cache_key, &block)
60
- return block.call unless cache_key
60
+ return yield unless cache_key
61
61
 
62
62
  CACHE_STORE.fetch(type + cache_key.to_s, &block)
63
63
  end
@@ -9,7 +9,7 @@ module Motor
9
9
  module_function
10
10
 
11
11
  def call(remote_url, api_key)
12
- url = remote_url.sub(%r{/\z}, '') + Motor::Configs::SYNC_API_PATH
12
+ url = remote_url.delete_suffix('/') + Motor::Configs::SYNC_API_PATH
13
13
 
14
14
  sync_from_remote!(url, api_key)
15
15
  sync_to_remote!(url, api_key)
@@ -73,7 +73,7 @@ module Motor
73
73
 
74
74
  attributes = build_statement_attributes(query_variables)
75
75
 
76
- [format(WITH_STATEMENT_TEMPLATE, sql_body: sql.strip.gsub(/;\z/, ''), limit: limit), 'SQL', attributes]
76
+ [format(WITH_STATEMENT_TEMPLATE, sql_body: sql.strip.delete_suffix(';'), limit: limit), 'SQL', attributes]
77
77
  end
78
78
 
79
79
  # @param variables [Array<(String, Object)>]
data/lib/motor/tags.rb CHANGED
@@ -8,7 +8,7 @@ module Motor
8
8
  return taggable unless tags
9
9
 
10
10
  tags.each do |tag_name|
11
- next if taggable.taggable_tags.find { |tt| tt.tag.name.downcase == tag_name.downcase }
11
+ next if taggable.taggable_tags.find { |tt| tt.tag.name.casecmp(tag_name).zero? }
12
12
 
13
13
  tag = Tag.where('lower(name) = ?', tag_name.downcase).take || Tag.new(name: tag_name)
14
14
 
@@ -3,6 +3,10 @@
3
3
  namespace :motor do
4
4
  desc 'Update configs/motor.yml file'
5
5
 
6
+ task install: :environment do
7
+ Rails::Generators.invoke('motor:install')
8
+ end
9
+
6
10
  task dump: :environment do
7
11
  Motor::Configs::WriteToFile.write_with_lock
8
12
 
data/lib/motor/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Motor
4
- VERSION = '0.1.47'
4
+ VERSION = '0.1.48'
5
5
  end
@@ -2068,11 +2068,11 @@
2068
2068
  "mail-opened.svg": "icons/mail-opened.svg",
2069
2069
  "mail.svg": "icons/mail.svg",
2070
2070
  "mailbox.svg": "icons/mailbox.svg",
2071
- "main-5cac10cadc5aa16e9b69.css.gz": "main-5cac10cadc5aa16e9b69.css.gz",
2072
- "main-5cac10cadc5aa16e9b69.js.LICENSE.txt": "main-5cac10cadc5aa16e9b69.js.LICENSE.txt",
2073
- "main-5cac10cadc5aa16e9b69.js.gz": "main-5cac10cadc5aa16e9b69.js.gz",
2074
- "main.css": "main-5cac10cadc5aa16e9b69.css",
2075
- "main.js": "main-5cac10cadc5aa16e9b69.js",
2071
+ "main-af386d0c907b80c29f22.css.gz": "main-af386d0c907b80c29f22.css.gz",
2072
+ "main-af386d0c907b80c29f22.js.LICENSE.txt": "main-af386d0c907b80c29f22.js.LICENSE.txt",
2073
+ "main-af386d0c907b80c29f22.js.gz": "main-af386d0c907b80c29f22.js.gz",
2074
+ "main.css": "main-af386d0c907b80c29f22.css",
2075
+ "main.js": "main-af386d0c907b80c29f22.js",
2076
2076
  "man.svg": "icons/man.svg",
2077
2077
  "manual-gearbox.svg": "icons/manual-gearbox.svg",
2078
2078
  "map-2.svg": "icons/map-2.svg",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motor-admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.47
4
+ version: 0.1.48
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pete Matsyburka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-23 00:00:00.000000000 Z
11
+ date: 2021-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord-filter
@@ -118,6 +118,7 @@ files:
118
118
  - LICENSE
119
119
  - README.md
120
120
  - Rakefile
121
+ - app/controllers/concerns/motor/current_user_method.rb
121
122
  - app/controllers/concerns/motor/load_and_authorize_dynamic_resource.rb
122
123
  - app/controllers/concerns/motor/wrap_io_params.rb
123
124
  - app/controllers/motor/active_storage_attachments_controller.rb
@@ -1480,8 +1481,8 @@ files:
1480
1481
  - ui/dist/icons/zoom-money.svg.gz
1481
1482
  - ui/dist/icons/zoom-out.svg.gz
1482
1483
  - ui/dist/icons/zoom-question.svg.gz
1483
- - ui/dist/main-5cac10cadc5aa16e9b69.css.gz
1484
- - ui/dist/main-5cac10cadc5aa16e9b69.js.gz
1484
+ - ui/dist/main-af386d0c907b80c29f22.css.gz
1485
+ - ui/dist/main-af386d0c907b80c29f22.js.gz
1485
1486
  - ui/dist/manifest.json
1486
1487
  homepage:
1487
1488
  licenses: