solidus_admin 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|