solidus_admin 0.0.0 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/LICENSE +7 -0
- data/README.md +31 -0
- data/Rakefile +21 -0
- data/app/assets/config/solidus_admin_manifest.js +4 -0
- data/app/assets/images/solidus_admin/.keep +0 -0
- data/app/assets/images/solidus_admin/arrow_down_s_fill_gray_700.svg +3 -0
- data/app/assets/images/solidus_admin/arrow_down_s_fill_red_400.svg +3 -0
- data/app/assets/images/solidus_admin/arrow_right_up_line.svg +5 -0
- data/app/assets/images/solidus_admin/favicon.ico +0 -0
- data/app/assets/images/solidus_admin/remixicon.symbol.svg +11 -0
- data/app/assets/stylesheets/solidus_admin/application.css +3 -0
- data/app/assets/stylesheets/solidus_admin/application.tailwind.css.erb +35 -0
- data/app/components/solidus_admin/base_component.rb +42 -0
- data/app/components/solidus_admin/feedback/component.html.erb +11 -0
- data/app/components/solidus_admin/feedback/component.rb +4 -0
- data/app/components/solidus_admin/feedback/component.yml +5 -0
- data/app/components/solidus_admin/orders/index/component.html.erb +31 -0
- data/app/components/solidus_admin/orders/index/component.rb +118 -0
- data/app/components/solidus_admin/orders/index/component.yml +13 -0
- data/app/components/solidus_admin/products/index/component.html.erb +30 -0
- data/app/components/solidus_admin/products/index/component.rb +126 -0
- data/app/components/solidus_admin/products/index/component.yml +13 -0
- data/app/components/solidus_admin/products/show/component.html.erb +149 -0
- data/app/components/solidus_admin/products/show/component.js +9 -0
- data/app/components/solidus_admin/products/show/component.rb +26 -0
- data/app/components/solidus_admin/products/show/component.yml +17 -0
- data/app/components/solidus_admin/products/status/component.rb +31 -0
- data/app/components/solidus_admin/products/status/component.yml +3 -0
- data/app/components/solidus_admin/sidebar/account_nav/component.html.erb +67 -0
- data/app/components/solidus_admin/sidebar/account_nav/component.rb +15 -0
- data/app/components/solidus_admin/sidebar/account_nav/component.yml +3 -0
- data/app/components/solidus_admin/sidebar/component.html.erb +39 -0
- data/app/components/solidus_admin/sidebar/component.js +14 -0
- data/app/components/solidus_admin/sidebar/component.rb +21 -0
- data/app/components/solidus_admin/sidebar/component.yml +2 -0
- data/app/components/solidus_admin/sidebar/item/component.html.erb +26 -0
- data/app/components/solidus_admin/sidebar/item/component.rb +27 -0
- data/app/components/solidus_admin/skip_link/component.rb +24 -0
- data/app/components/solidus_admin/skip_link/component.yml +2 -0
- data/app/components/solidus_admin/ui/badge/component.rb +34 -0
- data/app/components/solidus_admin/ui/button/component.rb +101 -0
- data/app/components/solidus_admin/ui/forms/checkbox/component.rb +42 -0
- data/app/components/solidus_admin/ui/forms/field/component.html.erb +28 -0
- data/app/components/solidus_admin/ui/forms/field/component.rb +72 -0
- data/app/components/solidus_admin/ui/forms/input/component.js +16 -0
- data/app/components/solidus_admin/ui/forms/input/component.rb +99 -0
- data/app/components/solidus_admin/ui/forms/switch/component.rb +47 -0
- data/app/components/solidus_admin/ui/icon/component.rb +25 -0
- data/app/components/solidus_admin/ui/icon/names.txt +2494 -0
- data/app/components/solidus_admin/ui/panel/component.html.erb +36 -0
- data/app/components/solidus_admin/ui/panel/component.js +14 -0
- data/app/components/solidus_admin/ui/panel/component.rb +19 -0
- data/app/components/solidus_admin/ui/panel/component.yml +4 -0
- data/app/components/solidus_admin/ui/tab/component.rb +43 -0
- data/app/components/solidus_admin/ui/table/component.html.erb +170 -0
- data/app/components/solidus_admin/ui/table/component.js +118 -0
- data/app/components/solidus_admin/ui/table/component.rb +150 -0
- data/app/components/solidus_admin/ui/table/component.yml +11 -0
- data/app/components/solidus_admin/ui/table/pagination/component.html.erb +28 -0
- data/app/components/solidus_admin/ui/table/pagination/component.rb +14 -0
- data/app/components/solidus_admin/ui/table/pagination/component.yml +3 -0
- data/app/components/solidus_admin/ui/toast/component.html.erb +26 -0
- data/app/components/solidus_admin/ui/toast/component.js +17 -0
- data/app/components/solidus_admin/ui/toast/component.rb +18 -0
- data/app/components/solidus_admin/ui/toast/component.yml +4 -0
- data/app/components/solidus_admin/ui/toggletip/component.html.erb +53 -0
- data/app/components/solidus_admin/ui/toggletip/component.js +26 -0
- data/app/components/solidus_admin/ui/toggletip/component.rb +98 -0
- data/app/components/solidus_admin/ui/toggletip/component.yml +2 -0
- data/app/controllers/solidus_admin/accounts_controller.rb +11 -0
- data/app/controllers/solidus_admin/authentication_adapters/backend.rb +26 -0
- data/app/controllers/solidus_admin/base_controller.rb +21 -0
- data/app/controllers/solidus_admin/controller_helpers/authentication.rb +31 -0
- data/app/controllers/solidus_admin/controller_helpers/authorization.rb +29 -0
- data/app/controllers/solidus_admin/controller_helpers/locale.rb +32 -0
- data/app/controllers/solidus_admin/orders_controller.rb +21 -0
- data/app/controllers/solidus_admin/products_controller.rb +93 -0
- data/app/helpers/solidus_admin/components_helper.rb +9 -0
- data/app/helpers/solidus_admin/layout_helper.rb +18 -0
- data/app/javascript/solidus_admin/application.js +2 -0
- data/app/javascript/solidus_admin/controllers/application.js +9 -0
- data/app/javascript/solidus_admin/controllers/components.js +35 -0
- data/app/javascript/solidus_admin/controllers/hello_controller.js +7 -0
- data/app/javascript/solidus_admin/controllers/index.js +14 -0
- data/app/javascript/solidus_admin/utils.js +8 -0
- data/app/views/layouts/solidus_admin/application.html.erb +30 -0
- data/app/views/layouts/solidus_admin/preview.html.erb +10 -0
- data/app/views/solidus_admin/.keep +0 -0
- data/bin/rails +13 -0
- data/config/importmap.rb +13 -0
- data/config/locales/main_nav.en.yml +13 -0
- data/config/locales/orders.en.yml +4 -0
- data/config/locales/products.en.yml +10 -0
- data/config/routes.rb +13 -0
- data/config/solidus_admin/tailwind.config.js.erb +95 -0
- data/docs/customizing_main_navigation.md +42 -0
- data/docs/customizing_tailwind.md +78 -0
- data/docs/customizing_view_components.md +153 -0
- data/lib/generators/solidus_admin/component/USAGE +13 -0
- data/lib/generators/solidus_admin/component/component_generator.rb +130 -0
- data/lib/generators/solidus_admin/component/templates/component.html.erb.tt +3 -0
- data/lib/generators/solidus_admin/component/templates/component.js.tt +14 -0
- data/lib/generators/solidus_admin/component/templates/component.rb.tt +14 -0
- data/lib/generators/solidus_admin/component/templates/component.yml.tt +4 -0
- data/lib/generators/solidus_admin/component/templates/component_preview.rb.tt +15 -0
- data/lib/generators/solidus_admin/component/templates/component_preview_overview.html.erb +7 -0
- data/lib/generators/solidus_admin/component/templates/component_spec.rb.tt +16 -0
- data/lib/generators/solidus_admin/install/install_generator.rb +44 -0
- data/lib/generators/solidus_admin/install/templates/config/initializers/solidus_admin.rb +44 -0
- data/lib/solidus_admin/configuration.rb +217 -0
- data/lib/solidus_admin/engine.rb +67 -0
- data/lib/solidus_admin/importmap.rb +26 -0
- data/lib/solidus_admin/main_nav_item.rb +97 -0
- data/lib/solidus_admin/preview.rb +81 -0
- data/lib/solidus_admin/tailwindcss.rb +58 -0
- data/lib/solidus_admin/version.rb +5 -0
- data/lib/solidus_admin.rb +15 -0
- data/lib/tasks/importmap.rake +10 -0
- data/lib/tasks/tailwindcss.rake +55 -0
- data/solidus_admin.gemspec +35 -0
- metadata +255 -18
data/config/routes.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
SolidusAdmin::Engine.routes.draw do
|
|
4
|
+
resource :account, only: :show
|
|
5
|
+
resources :products, only: [:index, :show, :edit, :update] do
|
|
6
|
+
collection do
|
|
7
|
+
delete :destroy
|
|
8
|
+
put :discontinue
|
|
9
|
+
put :activate
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
resources :orders, only: :index
|
|
13
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const defaultTheme = require('tailwindcss/defaultTheme')
|
|
2
|
+
const plugin = require('tailwindcss/plugin')
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
content: [
|
|
6
|
+
<%= SolidusAdmin::Config.tailwind_content.map { "'#{_1}'" }.join(",\n ") %>
|
|
7
|
+
],
|
|
8
|
+
theme: {
|
|
9
|
+
extend: {
|
|
10
|
+
aria: {
|
|
11
|
+
'current': 'current="true"',
|
|
12
|
+
},
|
|
13
|
+
fontFamily: {
|
|
14
|
+
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
|
|
15
|
+
},
|
|
16
|
+
colors: {
|
|
17
|
+
transparent: "transparent",
|
|
18
|
+
current: "currentColor",
|
|
19
|
+
|
|
20
|
+
// Primary palette
|
|
21
|
+
solidusRed: "#ef3023",
|
|
22
|
+
black: "#222222",
|
|
23
|
+
graphite: "#c7ccc7",
|
|
24
|
+
graphiteLight: "#d8dad8",
|
|
25
|
+
sand: "#f5f3f0",
|
|
26
|
+
white: "#ffffff",
|
|
27
|
+
|
|
28
|
+
// Secondary palette
|
|
29
|
+
yellow: "#fdc071",
|
|
30
|
+
orange: "#f68050",
|
|
31
|
+
blue: "#2554b1",
|
|
32
|
+
moss: "#2d3925",
|
|
33
|
+
forest: "#096756",
|
|
34
|
+
midnight: "#163449",
|
|
35
|
+
pink: "#f6d7e2",
|
|
36
|
+
plum: "#3a0e31",
|
|
37
|
+
sky: "#cbdff1",
|
|
38
|
+
seafoam: "#c1e0de",
|
|
39
|
+
dune: "#e6bf9b",
|
|
40
|
+
|
|
41
|
+
// Extra colors (not part of the original palette)
|
|
42
|
+
papayaWhip: "#f9e3d9",
|
|
43
|
+
|
|
44
|
+
// UI Red
|
|
45
|
+
red: {
|
|
46
|
+
100: "#f8d6d3",
|
|
47
|
+
200: "#f1ada7",
|
|
48
|
+
300: "#ea8980",
|
|
49
|
+
400: "#e36054",
|
|
50
|
+
500: "#dc3728",
|
|
51
|
+
600: "#b12c20",
|
|
52
|
+
700: "#862219",
|
|
53
|
+
800: "#561610",
|
|
54
|
+
900: "#2b0b08",
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
// Grayscale
|
|
58
|
+
gray: {
|
|
59
|
+
15: "#fafafa",
|
|
60
|
+
25: "#f5f5f5",
|
|
61
|
+
50: "#f0f0f0",
|
|
62
|
+
100: "#dedede",
|
|
63
|
+
200: "#cfcfcf",
|
|
64
|
+
300: "#bababa",
|
|
65
|
+
400: "#a3a3a3",
|
|
66
|
+
500: "#737373",
|
|
67
|
+
600: "#616161",
|
|
68
|
+
700: "#4a4a4a",
|
|
69
|
+
800: "#333333",
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
borderRadius: {
|
|
73
|
+
sm: '4px',
|
|
74
|
+
},
|
|
75
|
+
backgroundImage: {
|
|
76
|
+
'arrow-right-up-line': "url('solidus_admin/arrow_right_up_line.svg')",
|
|
77
|
+
'arrow-down-s-fill-gray-700': "url('solidus_admin/arrow_down_s_fill_gray_700.svg')",
|
|
78
|
+
'arrow-down-s-fill-red-400': "url('solidus_admin/arrow_down_s_fill_red_400.svg')",
|
|
79
|
+
},
|
|
80
|
+
boxShadow: {
|
|
81
|
+
sm: '0px 1px 2px 0px rgba(0, 0, 0, 0.04)',
|
|
82
|
+
base: '0px 4px 8px 0px rgba(0, 0, 0, 0.08), 0px 2px 4px -1px rgba(0, 0, 0, 0.04)'
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
plugins: [
|
|
87
|
+
require('@tailwindcss/forms')({ strategy: 'class' }),
|
|
88
|
+
require('@tailwindcss/aspect-ratio'),
|
|
89
|
+
require('@tailwindcss/typography'),
|
|
90
|
+
require('@tailwindcss/container-queries'),
|
|
91
|
+
plugin(({ addVariant }) => addVariant('hidden', '&([hidden])')),
|
|
92
|
+
plugin(({ addVariant }) => addVariant('visible', '&:not([hidden])')),
|
|
93
|
+
plugin(({ addVariant }) => addVariant('search-cancel', '&::-webkit-search-cancel-button')),
|
|
94
|
+
]
|
|
95
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Customizing the main navigation
|
|
2
|
+
|
|
3
|
+
You are allowed to add your custom links to the main navigation. To do so, you can access `SolidusAdmin::Config.main_nav` in an initializer:
|
|
4
|
+
|
|
5
|
+
```ruby
|
|
6
|
+
# config/initializers/solidus_admin.rb
|
|
7
|
+
SolidusAdmin::Config.menu_items << {
|
|
8
|
+
key: :my_custom_link,
|
|
9
|
+
route: :my_custom_link_path,
|
|
10
|
+
icon: "24-hours-fill",
|
|
11
|
+
position: 80
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- The key you provide will be used to translate the link's label under the
|
|
16
|
+
`solidus_admin.main_nav.#{key}` key.
|
|
17
|
+
- Icon needs to be an icon name from [Remixicon](https://remixicon.com/).
|
|
18
|
+
- Position tells Solidus where to place the link in the main navigation. The
|
|
19
|
+
default items are placed with 10 points of difference between them.
|
|
20
|
+
|
|
21
|
+
For nested links, you can provide a `children:` option with an array of hashes:
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
# config/initializers/solidus_admin.rb
|
|
25
|
+
SolidusAdmin::Config.configure do |config|
|
|
26
|
+
config.menu_items << {
|
|
27
|
+
key: :my_custom_link,
|
|
28
|
+
route: :my_custom_link_path,
|
|
29
|
+
icon: "24-hours-fill",
|
|
30
|
+
position: 80,
|
|
31
|
+
children: [
|
|
32
|
+
{
|
|
33
|
+
key: :my_custom_nested_link,
|
|
34
|
+
route: :my_custom_nested_link_path,
|
|
35
|
+
position: 80
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Your custom link will be rendered in the active state when its base path (i.e, the path without the query string) matches the one for the current url.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Customizing tailwind
|
|
2
|
+
|
|
3
|
+
Solidus Admin uses [Tailwind CSS](https://tailwindcss.com/) for styling. The
|
|
4
|
+
benefit of using Tailwind is that it allows you to customize the look and feel
|
|
5
|
+
of the admin without having to write any CSS. By leveraging utility classes,
|
|
6
|
+
you can easily change the colors, fonts, and spacing in use.
|
|
7
|
+
|
|
8
|
+
Solidus Admin sets up Tailwind in a way that allows customization. When you
|
|
9
|
+
install `solidus_admin`, its compiled CSS file is generated at
|
|
10
|
+
`app/assets/builds/solidus_admin/tailwind.css`. As we'll see below, there are
|
|
11
|
+
different ways in which you can add your styles to it. There are a couple of
|
|
12
|
+
tasks you can run to recompile the CSS file:
|
|
13
|
+
|
|
14
|
+
- `bin/rails solidus_admin:tailwindcss:build` - compiles the CSS file once.
|
|
15
|
+
- `bin/rails solidus_admin:tailwindcss:watch` - compiles the CSS file and
|
|
16
|
+
watches for changes.
|
|
17
|
+
|
|
18
|
+
When deploying to production, the build task is automatically added as part of
|
|
19
|
+
the assets precompilation process.
|
|
20
|
+
|
|
21
|
+
### Adding new paths to Tailwind
|
|
22
|
+
|
|
23
|
+
Tailwind generates its CSS by scanning a configured set of paths for CSS
|
|
24
|
+
classes. By default, Solidus Admin will add to this list the following globs
|
|
25
|
+
from your host application:
|
|
26
|
+
|
|
27
|
+
- `app/components/solidus_admin/**/*.rb`
|
|
28
|
+
- `app/views/solidus_admin/**/*.{erb,haml,html,slim}`
|
|
29
|
+
- `app/helpers/solidus_admin/**/*.rb`
|
|
30
|
+
- `app/assets/javascripts/solidus_admin/**/*.js`
|
|
31
|
+
- `public/solidus_admin/*.html`
|
|
32
|
+
|
|
33
|
+
If that flexibility is not enough, you can add your own paths by appending the
|
|
34
|
+
`SolidusAdmin::Config.tailwind_content` setting:
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
# config/initializers/solidus_admin.rb
|
|
38
|
+
SolidusAdmin::Config.tailwind_content << Rails.root.join("app/my/custom/path/**/*.rb")
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
> ⚠ Remember to re-run the `build` or `watch` tasks after changing this setting.
|
|
42
|
+
|
|
43
|
+
### Adding custom CSS
|
|
44
|
+
|
|
45
|
+
If you need advanced Tailwind customization, you can also create your own CSS
|
|
46
|
+
file and append it to the Solidus Admin's default one. Be aware that's
|
|
47
|
+
[considered a last-resort option](https://tailwindcss.com/docs/reusing-styles)
|
|
48
|
+
according to Tailwind's philosophy, and most of the time you should be ok by
|
|
49
|
+
making use of the available Tailwind classes.
|
|
50
|
+
|
|
51
|
+
In case you need to do it, you can append your CSS file by pushing it to the
|
|
52
|
+
`SolidusAdmin.tailwind_stylesheets` array:
|
|
53
|
+
|
|
54
|
+
```ruby
|
|
55
|
+
# config/initializers/solidus_admin.rb
|
|
56
|
+
SolidusAdmin.tailwind_stylesheets << Rails.root.join("app/my/custom/path/my_styles.css")
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
> ⚠ Remember to re-run the `build` or `watch` tasks after changing this setting.
|
|
60
|
+
|
|
61
|
+
## Acquiring full control over Tailwind configuration
|
|
62
|
+
|
|
63
|
+
For very advanced use cases, it's possible to bail out of the Solidus Admin's
|
|
64
|
+
managed Tailwind configuration and get a grip on it yourself. This is not
|
|
65
|
+
recommended, as it will make your app more brittle to future changes in Solidus
|
|
66
|
+
Admin, so do it at your own risk!
|
|
67
|
+
|
|
68
|
+
There are a couple of tasks you can run for that:
|
|
69
|
+
|
|
70
|
+
- `bin/rails solidus_admin:tailwindcss:override_config` - copies the default
|
|
71
|
+
Tailwind configuration file to `config/solidus_admin/tailwind.config.js.erb`.
|
|
72
|
+
- `bin/rails solidus_admin:tailwindcss:override_stylesheet` - copies the
|
|
73
|
+
default Tailwind stylesheet file to
|
|
74
|
+
`app/assets/stylesheets/solidus_admin/application.tailwind.css.erb`.
|
|
75
|
+
|
|
76
|
+
Notice that, unlike in a regular Tailwind setup, the config and stylesheet
|
|
77
|
+
files are ERB templates. This is because they need to be able to access the
|
|
78
|
+
Solidus Admin and application paths.
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Customizing view components
|
|
2
|
+
|
|
3
|
+
Solidus Admin uses [view components](https://viewcomponent.org/) to render the views. Components are
|
|
4
|
+
a pattern for breaking up the view layer into small, reusable pieces, easy to
|
|
5
|
+
reason about and test.
|
|
6
|
+
|
|
7
|
+
All the components Solidus Admin uses are located in the [`app/components`](../app/components) folder of the
|
|
8
|
+
`solidus_admin` gem. As you can see, they are organized in a particular folder structure:
|
|
9
|
+
|
|
10
|
+
- All of them are under the `SolidusAdmin` namespace.
|
|
11
|
+
- They are grouped in sidecar directories, where the main component file and
|
|
12
|
+
all its related files (assets, i18n files, etc.) live together.
|
|
13
|
+
|
|
14
|
+
For instance, the component for the main navigation is located in
|
|
15
|
+
[`app/components/solidus_admin/main_nav/component.rb`](../app/components/solidus_admin/main_nav/component.rb).
|
|
16
|
+
|
|
17
|
+
Solidus Admin components are designed to be easily customizable by the host
|
|
18
|
+
application. Because of that, if you look at how they are designed, you'll find
|
|
19
|
+
a series of patterns are followed consistently:
|
|
20
|
+
|
|
21
|
+
- Components are always resolved from a global registry in
|
|
22
|
+
`SolidusAdmin::Config.components` instead of being referenced by their constant. For
|
|
23
|
+
example, we call `component('main_nav')` instead of referencing
|
|
24
|
+
`SolidusAdmin::MainNav::Component` directly. As you'll see later, this makes
|
|
25
|
+
it easy to replace or tweak a component.
|
|
26
|
+
- It's possible to override the registry locally inside a component by redefining
|
|
27
|
+
the `#component` method. This is useful when you need to use a component that
|
|
28
|
+
is not registered in the global registry or need to address some edge case.
|
|
29
|
+
- In any case, Solidus Admin components initializers only take keyword
|
|
30
|
+
arguments.
|
|
31
|
+
|
|
32
|
+
A picture is worth a thousand words, so let's depict how this works with an
|
|
33
|
+
example:
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
# app/components/solidus_admin/foo/component.rb
|
|
37
|
+
class SolidusAdmin::Foo::Component < SolidusAdmin::BaseComponent
|
|
38
|
+
def component(key)
|
|
39
|
+
return MyApplication::Bar::Component if key == 'bar'
|
|
40
|
+
|
|
41
|
+
super
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
erb_template <<~ERB
|
|
45
|
+
<div>
|
|
46
|
+
<%= render component('bar').new %>
|
|
47
|
+
</div>
|
|
48
|
+
ERB
|
|
49
|
+
end
|
|
50
|
+
# render component('foo').new
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Customizing components
|
|
54
|
+
|
|
55
|
+
Some of the customizations detailed below require you to match Solidus Admin's
|
|
56
|
+
component paths in your application. For instance, if we talk about the
|
|
57
|
+
component in `solidus_admin` gem's
|
|
58
|
+
`app/components/solidus_admin/main_nav/component.rb`, the matching path in your
|
|
59
|
+
application would be
|
|
60
|
+
`app/components/my_application/solidus_admin/main_nav/component.rb`, where
|
|
61
|
+
`my_application` is the underscored name of your application (you can get it by
|
|
62
|
+
running `Rails.application.class.module_parent_name`).
|
|
63
|
+
|
|
64
|
+
### Replacing a component's template
|
|
65
|
+
|
|
66
|
+
In the most typical case, you'll only need to replace the template used by a
|
|
67
|
+
component. You can do that by creating a new component with a maching path in
|
|
68
|
+
your application, inheriting from the default one. Then, you can create a new
|
|
69
|
+
template for it. For example, to replace the main nav template:
|
|
70
|
+
|
|
71
|
+
```erb
|
|
72
|
+
# app/components/my_application/solidus_admin/main_nav/component.rb %>
|
|
73
|
+
class MyApplication::SolidusAdmin::MainNav::Component < ::SolidusAdmin::MainNav::Component
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
<%# app/components/my_application/solidus_admin/main_nav/component.html.erb %>
|
|
77
|
+
<nav class="my_own_classes">
|
|
78
|
+
<%=
|
|
79
|
+
render main_nav_item_component.with_collection(
|
|
80
|
+
sorted_items
|
|
81
|
+
)
|
|
82
|
+
%>
|
|
83
|
+
</nav>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Prepending or appending to a component's template
|
|
87
|
+
|
|
88
|
+
In some situations, you might only need to add some markup before or after a
|
|
89
|
+
component. You can easily do that by rendering the Solidus Admin component and
|
|
90
|
+
adding your markup before or after it.
|
|
91
|
+
|
|
92
|
+
```erb
|
|
93
|
+
<%# app/components/my_application/solidus_admin/main_nav/component.html.erb %>
|
|
94
|
+
<h1>MY STORE ADMINISTRATION</h1>
|
|
95
|
+
<%= render SolidusAdmin::MainNav::Component.new %>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Replacing a component
|
|
99
|
+
|
|
100
|
+
You can replace a component by creating a new one with a matching path in your
|
|
101
|
+
application.
|
|
102
|
+
|
|
103
|
+
There are two considerations to keep in mind:
|
|
104
|
+
|
|
105
|
+
- Be aware that other components might be using the component you're replacing.
|
|
106
|
+
They should only be using its `#initialize` method, so make sure to keep
|
|
107
|
+
compatibility with it when they're called.
|
|
108
|
+
- Solidus Admin's components always inherit from
|
|
109
|
+
[SolidusAdmin::BaseComponent](../app/components/solidus_admin/base_component.rb).
|
|
110
|
+
You can consider doing the same if you need to use one of its helpers.
|
|
111
|
+
|
|
112
|
+
For example, the following replaces the main nav component:
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
# app/components/my_application/solidus_admin/main_nav/component.rb
|
|
116
|
+
class MyApplication::SolidusAdmin::MainNav::Component < SolidusAdmin::BaseComponent
|
|
117
|
+
# do your thing
|
|
118
|
+
end
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
If you need more control, you can explicitly register your component in the
|
|
122
|
+
Solidus Admin container instead of using an implicit path:
|
|
123
|
+
|
|
124
|
+
> ⓘ Right now, that will raise an error when the application is reloaded. We
|
|
125
|
+
> need to fix it.
|
|
126
|
+
|
|
127
|
+
```ruby
|
|
128
|
+
# config/initalizers/solidus_admin.rb
|
|
129
|
+
Rails.application.config.to_prepare do
|
|
130
|
+
SolidusAdmin::Config.components['ui/button'] = MyApplication::Button::Component
|
|
131
|
+
end
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Tweaking a component
|
|
135
|
+
|
|
136
|
+
If you only need to tweak a component, you can always inherit from it in a
|
|
137
|
+
matching path from within your application (or manually add it to the
|
|
138
|
+
registry) and override the methods you need to change:
|
|
139
|
+
|
|
140
|
+
```ruby
|
|
141
|
+
# app/components/my_application/solidus_admin/main_nav/component.rb
|
|
142
|
+
class MyApplication::SolidusAdmin::MainNav::Component < ::SolidusAdmin::MainNav::Component
|
|
143
|
+
def sorted_items
|
|
144
|
+
super.reverse
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Be aware that this approach comes with an important trade-off: You'll need to
|
|
150
|
+
keep your component in sync with the original one as it changes on future updates.
|
|
151
|
+
For instance, in the example above, the component is overriding a private
|
|
152
|
+
method, so there's no guarantee that it will continue to exist in the future
|
|
153
|
+
without being deprecated, as we only guarantee public API stability.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
|
|
3
|
+
Creates a SolidusAdmin component.
|
|
4
|
+
|
|
5
|
+
Example:
|
|
6
|
+
|
|
7
|
+
$ bin/rails generate solidus_admin:component my_namespace/my_module_name my_attribute
|
|
8
|
+
|
|
9
|
+
create app/components/my_namespace/my_module_name/component.rb
|
|
10
|
+
create app/components/my_namespace/my_module_name/component.html.erb
|
|
11
|
+
create app/components/my_namespace/my_module_name/component.yml
|
|
12
|
+
create app/components/my_namespace/my_module_name/component.js
|
|
13
|
+
create spec/components/my_namespace/my_module_name/component_spec.rb
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidusAdmin
|
|
4
|
+
class ComponentGenerator < Rails::Generators::NamedBase
|
|
5
|
+
source_root File.expand_path('templates', __dir__)
|
|
6
|
+
|
|
7
|
+
argument :attributes, type: :array, default: [], banner: "attribute"
|
|
8
|
+
|
|
9
|
+
class_option :html, type: :boolean, default: true
|
|
10
|
+
class_option :i18n, type: :boolean, default: true
|
|
11
|
+
class_option :js, type: :boolean, default: true
|
|
12
|
+
class_option :spec, type: :boolean, default: true
|
|
13
|
+
class_option :preview, type: :boolean, default: true
|
|
14
|
+
|
|
15
|
+
def setup_inflections
|
|
16
|
+
# This is needed because the generator won't run the initialization process,
|
|
17
|
+
# in order to ensure that UI is not rendered as Ui we need to setup inflections
|
|
18
|
+
# manually.
|
|
19
|
+
SolidusAdmin::Engine.initializers.find { _1.name =~ /inflections/ }.run
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def create_component_files
|
|
23
|
+
template "component.html.erb", destination(".html.erb")
|
|
24
|
+
unless options["html"]
|
|
25
|
+
say_status :inline, destination(".html.erb"), :blue
|
|
26
|
+
@inline_html = File.read(destination(".html.erb"))
|
|
27
|
+
shell.mute { remove_file(destination(".html.erb")) }
|
|
28
|
+
end
|
|
29
|
+
template "component.rb", destination(".rb")
|
|
30
|
+
template "component.yml", destination(".yml") if options["i18n"]
|
|
31
|
+
template "component.js", destination(".js") if options["js"]
|
|
32
|
+
template "component_spec.rb", destination("_spec.rb", root: "spec/components") if options["spec"]
|
|
33
|
+
|
|
34
|
+
if options["preview"]
|
|
35
|
+
preview_destination_path = destination("_preview.rb", root: "spec/components/previews")
|
|
36
|
+
template "component_preview.rb", preview_destination_path
|
|
37
|
+
template "component_preview_overview.html.erb", preview_destination_path.sub(/\.rb/, '/overview.html.erb')
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def component_registry_id
|
|
44
|
+
[class_path.presence, file_name].compact.join("/")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def destination(suffix, root: "app/components")
|
|
48
|
+
File.join(root, class_path, file_name, "component#{suffix}")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def file_name
|
|
52
|
+
@_file_name ||= super.sub(/_component\z/i, "")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def dom_class
|
|
56
|
+
[class_path.presence, file_name].compact.join("/").tr("_", "-").gsub("/", "--")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def stimulus_controller_name
|
|
60
|
+
dom_class
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def stimulus_attributes
|
|
64
|
+
' data-controller="<%= stimulus_id %>"'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def initialize_signature
|
|
68
|
+
return if attributes.blank?
|
|
69
|
+
|
|
70
|
+
attributes.map { |attr| "#{attr.name}:" }.join(", ")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def initialize_body
|
|
74
|
+
attributes.map { |attr| "@#{attr.name} = #{attr.name}" }.join("\n ")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def preview_signature
|
|
78
|
+
return if attributes.blank?
|
|
79
|
+
|
|
80
|
+
signature = attributes.map { |attr| "#{attr.name}: #{attr.name.to_s.inspect}" }.join(", ")
|
|
81
|
+
"(#{signature})"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def preview_playground_yard_tags
|
|
85
|
+
return if attributes.blank?
|
|
86
|
+
|
|
87
|
+
# See https://lookbook.build/guide/previews/params#input-types
|
|
88
|
+
attributes.map { |attr| "# @param #{attr.name} text" }.join("\n ")
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def preview_playground_body
|
|
92
|
+
render_signature = attributes.map { |attr| "#{attr.name}: #{attr.name}" }.join(", ")
|
|
93
|
+
render_signature = "(#{render_signature})" if render_signature.present?
|
|
94
|
+
|
|
95
|
+
"render component(#{component_registry_id.inspect}).new#{render_signature}"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def preview_overview_body
|
|
99
|
+
component_registry_id = [class_path.presence, file_name].compact.join("/")
|
|
100
|
+
|
|
101
|
+
"render component(#{component_registry_id.inspect}).new#{preview_signature}"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def attributes_html
|
|
105
|
+
attributes.map { |attr| "<p> <%= @#{attr.name} %> </p>" }.join("\n ")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def stimulus_html
|
|
109
|
+
%{\n <label>Your name: <input data-action="input->#{stimulus_controller_name}#typed"/></label>} +
|
|
110
|
+
%{\n <p>Hello <span data-#{stimulus_controller_name}-target="output"></span></p>}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def i18n_html
|
|
114
|
+
"<%= t '.hello' %>"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def initialize_html
|
|
118
|
+
[
|
|
119
|
+
"<p>Add #{class_name} HTML here</p>",
|
|
120
|
+
(attributes_html if attributes.present?),
|
|
121
|
+
(stimulus_html if options["js"]),
|
|
122
|
+
(i18n_html if options["i18n"]),
|
|
123
|
+
].compact.join("\n ")
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def inline_html(indent: '')
|
|
127
|
+
@inline_html.gsub!(/^/, indent).strip
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Controller } from '@hotwired/stimulus'
|
|
2
|
+
|
|
3
|
+
export default class extends Controller {
|
|
4
|
+
static targets = ['output']
|
|
5
|
+
|
|
6
|
+
typed(event) {
|
|
7
|
+
this.text = event.currentTarget.value
|
|
8
|
+
this.render()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
render() {
|
|
12
|
+
this.outputTarget.innerText = this.text
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class <%= File.join(*[namespaced_path, file_path].compact).classify %>::Component < SolidusAdmin::BaseComponent
|
|
4
|
+
<%- if initialize_signature -%>
|
|
5
|
+
def initialize(<%= initialize_signature %>)
|
|
6
|
+
<%= initialize_body %>
|
|
7
|
+
end
|
|
8
|
+
<%- end -%>
|
|
9
|
+
<% unless options['html'] %>
|
|
10
|
+
erb_template <<~ERB
|
|
11
|
+
<%= inline_html indent: ' ' %>
|
|
12
|
+
ERB
|
|
13
|
+
<%- end -%>
|
|
14
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# @component <%= component_registry_id.inspect %>
|
|
4
|
+
class <%= File.join(*[namespaced_path, file_path].compact).classify %>::ComponentPreview < ViewComponent::Preview
|
|
5
|
+
include SolidusAdmin::Preview
|
|
6
|
+
|
|
7
|
+
def overview
|
|
8
|
+
render_with_template
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
<%= preview_playground_yard_tags %>
|
|
12
|
+
def playground<%= preview_signature %>
|
|
13
|
+
<%= preview_playground_body %>
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
RSpec.describe <%= File.join(*[namespaced_path, file_path].compact).classify %>::Component, type: :component do
|
|
6
|
+
it "renders the overview preview" do
|
|
7
|
+
render_preview(:overview)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# it "renders something useful" do
|
|
11
|
+
# render_inline(described_class.new(<%= attributes.map { |attr| "#{attr.name}: #{attr.name.to_s.inspect}" }.join(", ") %>))
|
|
12
|
+
#
|
|
13
|
+
# expect(page).to have_text "Hello, components!"
|
|
14
|
+
# expect(page).to have_css '.value'
|
|
15
|
+
# end
|
|
16
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidusAdmin
|
|
4
|
+
module Generators
|
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
|
6
|
+
class_option :lookbook, type: :boolean, default: !!ENV['SOLIDUS_ADMIN_LOOKBOOK'], desc: 'Install Lookbook for component previews'
|
|
7
|
+
|
|
8
|
+
source_root "#{__dir__}/templates"
|
|
9
|
+
|
|
10
|
+
def install_solidus_core_support
|
|
11
|
+
route <<~RUBY
|
|
12
|
+
mount SolidusAdmin::Engine, at: '/admin', constraints: ->(req) {
|
|
13
|
+
req.cookies['solidus_admin'] != 'false' &&
|
|
14
|
+
req.params['solidus_admin'] != 'false'
|
|
15
|
+
}
|
|
16
|
+
RUBY
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def copy_initializer
|
|
20
|
+
copy_file "config/initializers/solidus_admin.rb"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def ignore_tailwind_build_files
|
|
24
|
+
append_file(".gitignore", "app/assets/builds/solidus_admin/") if File.exist?(Rails.root.join(".gitignore"))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def build_tailwind
|
|
28
|
+
rake "solidus_admin:tailwindcss:build"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def install_lookbook
|
|
32
|
+
return unless options[:lookbook]
|
|
33
|
+
|
|
34
|
+
gem_group :development, :test do
|
|
35
|
+
gem "lookbook"
|
|
36
|
+
gem "listen"
|
|
37
|
+
gem "actioncable"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
route "mount Lookbook::Engine, at: '/lookbook' if Rails.env.development?"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|