Skip to content

Commit

Permalink
Merge pull request #5068 from solidusio/nebulab/admin
Browse files Browse the repository at this point in the history
Add `SolidusAdmin`
  • Loading branch information
elia authored Sep 29, 2023
2 parents 803be9d + a5372d3 commit 105a8da
Show file tree
Hide file tree
Showing 205 changed files with 8,689 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ Style/FrozenStringLiteralComment:
- '*/lib/generators/**/*'
- '**/bin/**/*'
- '*/db/migrate/**/*'
- '*/config/importmap.rb'

# json.() is idiomatic in jbuilder files
Style/LambdaCall:
Expand All @@ -337,6 +338,7 @@ Lint/SuppressedException:

Lint/MissingSuper:
Exclude:
- '*/app/components/**/*' # components need pristine initializer methods
- 'core/lib/spree/deprecated_instance_variable_proxy.rb' # this is a known class that doesn't require super
- 'core/lib/spree/preferences/configuration.rb' # this class has no superclass defining `self.inherited`

Expand Down
6 changes: 6 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ group :backend do
gem 'webrick', require: false
end

group :admin do
gem 'solidus_admin', path: 'admin', require: false
gem 'axe-core-rspec', '~> 4.7', require: false
gem 'axe-core-capybara', '~> 4.7', require: false
end

group :utils do
gem 'pry'
gem 'launchy', require: false
Expand Down
2 changes: 2 additions & 0 deletions Procfile.dev
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
web: env RUBY_DEBUG_OPEN=true bin/rails server
admin_tailwind: bin/rails solidus_admin:tailwindcss:watch
6 changes: 4 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ task :clean do
end
end

SOLIDUS_GEM_NAMES = %w[core api backend sample]

namespace :gem do
def version
require_relative 'core/lib/spree/core/version'
Spree.solidus_version
end

def for_each_gem
%w(core api backend frontend sample).each do |gem_name|
SOLIDUS_GEM_NAMES.each do |gem_name|
print_title(gem_name)
yield "pkg/solidus_#{gem_name}-#{version}.gem"
end
Expand All @@ -72,7 +74,7 @@ namespace :gem do
pkgdir = File.expand_path('pkg', __dir__)
FileUtils.mkdir_p pkgdir

%w(core api backend frontend sample).each do |gem_name|
SOLIDUS_GEM_NAMES.each do |gem_name|
Dir.chdir(gem_name) do
sh "gem build solidus_#{gem_name}.gemspec"
mv "solidus_#{gem_name}-#{version}.gem", pkgdir
Expand Down
7 changes: 7 additions & 0 deletions admin/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Copyright © 2023 Solidus Team

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 changes: 31 additions & 0 deletions admin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# solidus_admin (WIP)

A Rails engine that provides an administrative interface to the Solidus ecommerce platform.

## Development

- [Customizing tailwind](docs/customizing_tailwind.md)
- [Customizing view components](docs/customizing_view_components.md)
- [Customizing the main navigation](docs/customizing_main_navigation.md)

### Adding components to Solidus Admin

When using the component generator from within the admin folder it will generate the component in the library
instead of the sandbox application.

```bash
# the `solidus_admin/` namespace is added by default
bin/rails admin g solidus_admin:component foo
create app/components/solidus_admin/foo/component.rb
create app/components/solidus_admin/foo/component.html.erb
create app/components/solidus_admin/foo/component.yml
create app/components/solidus_admin/foo/component.js
create spec/components/solidus_admin/foo/component_spec.rb
```

## Releasing

1. Update the version in `lib/solidus_admin/version.rb`
2. Commit the changes with the message `Release v1.2.3`
3. `cd admin; bundle exec rake release`
4. Manually release on GitHub
21 changes: 21 additions & 0 deletions admin/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

require 'rubygems'
require 'rake'
require 'rake/testtask'
require 'rspec/core/rake_task'
require 'spree/testing_support/dummy_app/rake_tasks'
require 'bundler/gem_tasks'

RSpec::Core::RakeTask.new
task default: :spec

DummyApp::RakeTasks.new(
gem_root: File.expand_path(__dir__),
lib_name: 'solidus_admin'
)

task test_app: 'db:reset'

# Namespace release tags, e.g. 'solidus_admin/v1.2.3'
Bundler::GemHelper.tag_prefix = 'solidus_admin/'
4 changes: 4 additions & 0 deletions admin/app/assets/config/solidus_admin_manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//= link_tree ../images
//= link_tree ../stylesheets .css
//= link_tree ../../javascript .js
//= link_tree ../../components .js
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions admin/app/assets/images/solidus_admin/arrow_right_up_line.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added admin/app/assets/images/solidus_admin/favicon.ico
Binary file not shown.
11 changes: 11 additions & 0 deletions admin/app/assets/images/solidus_admin/remixicon.symbol.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions admin/app/assets/stylesheets/solidus_admin/application.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/*
* = require solidus_admin/tailwind.css
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
.body-tiny {
@apply font-sans font-normal text-xs leading-5;
}

.body-tiny-bold {
@apply font-sans font-semibold text-xs leading-5;
}

.body-small {
@apply font-sans font-normal text-sm leading-6;
}

.body-small-bold {
@apply font-sans font-semibold text-sm leading-6;
}

.body-text {
@apply font-sans font-normal text-base leading-6;
}

.body-text-bold {
@apply font-sans font-semibold text-base leading-6;
}

.body-title {
@apply font-sans font-semibold text-xl leading-5;
}
}

<%= SolidusAdmin::Config.tailwind_stylesheets.map { File.read(_1) }.join("\n") %>
42 changes: 42 additions & 0 deletions admin/app/components/solidus_admin/base_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

module SolidusAdmin
# BaseComponent is the base class for all components in Solidus Admin.
class BaseComponent < ViewComponent::Base
include SolidusAdmin::ComponentsHelper
include Turbo::FramesHelper

def icon_tag(name, **attrs)
render component("ui/icon").new(name: name, **attrs)
end

def missing_translation(key, options)
keys = I18n.normalize_keys(options[:locale] || I18n.locale, key, options[:scope])

logger.debug " [#{self.class}] Missing translation: #{keys.join('.')}"

if options[:locale] != :en
t(key, **options, locale: :en)
else
"translation missing: #{keys.join('.')}"
end
end

def self.stimulus_id
@stimulus_id ||= name.underscore
.sub(/^solidus_admin\/(.*)\/component$/, '\1')
.gsub("/", "--")
.tr("_", "-")
end

delegate :stimulus_id, to: :class

def spree
@spree ||= Spree::Core::Engine.routes.url_helpers
end

def solidus_admin
@solidus_admin ||= SolidusAdmin::Engine.routes.url_helpers
end
end
end
11 changes: 11 additions & 0 deletions admin/app/components/solidus_admin/feedback/component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<span class="max-w-xs text-xs text-right text-gray-600 hidden lg:block">
<%= t(".feedback_description") %>
</span>
<%= render component("ui/button").new(
tag: :a,
text: t(".give_feedback"),
href: "https://solidus.io/feedback?category=solidus-admin",
icon: "feedback-line",
scheme: :secondary,
target: :_blank,
) %>
4 changes: 4 additions & 0 deletions admin/app/components/solidus_admin/feedback/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# frozen_string_literal: true

class SolidusAdmin::Feedback::Component < SolidusAdmin::BaseComponent
end
5 changes: 5 additions & 0 deletions admin/app/components/solidus_admin/feedback/component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Add your component translations here.
# Use the translation in the example in your template with `t(".hello")`.
en:
give_feedback: 'Give feedback'
feedback_description: 'We are constantly trying to improve. Please let us know what you think about this admin page.'
31 changes: 31 additions & 0 deletions admin/app/components/solidus_admin/orders/index/component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<div class="<%= stimulus_id %> px-4">
<header class="py-6 flex items-center">
<h1 class="body-title">
<%= title %>
</h1>

<div class="ml-auto flex gap-2 items-center">
<%= render component("feedback").new %>
<%= render component("ui/button").new(
tag: :a,
text: t('.create_order'),
href: spree.new_admin_order_path,
icon: "add-line",
) %>
</div>
</header>

<%= render component('ui/table').new(
id: 'orders-list',
model_class: Spree::Order,
rows: @page.records,
fade_row_proc: fade_row_proc,
search_key: SolidusAdmin::Config[:order_search_key],
search_url: solidus_admin.orders_path,
batch_actions: batch_actions,
filters: filters,
columns: columns,
prev_page_link: prev_page_link,
next_page_link: next_page_link,
) %>
</div>
118 changes: 118 additions & 0 deletions admin/app/components/solidus_admin/orders/index/component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# frozen_string_literal: true

class SolidusAdmin::Orders::Index::Component < SolidusAdmin::BaseComponent
def initialize(page:)
@page = page
end

class_attribute :fade_row_proc, default: ->(order) { order.paid? && order.shipped? }

def title
Spree::Order.model_name.human.pluralize
end

def prev_page_link
@page.first? ? nil : solidus_admin.url_for(host: request.host, port: request.port, **request.params, page: @page.number - 1)
end

def next_page_link
@page.last? ? nil : solidus_admin.url_for(host: request.host, port: request.port, **request.params, page: @page.next_param)
end

def batch_actions
[]
end

def filters
[
{
name: 'q[completed_at_not_null]',
value: 1,
label: t('.filters.only_show_complete_orders'),
},
]
end

def columns
[
number_column,
date_column,
customer_column,
total_column,
items_column,
payment_column,
shipment_column,
]
end

def number_column
{
header: :order,
data: ->(order) do
order_path = spree.edit_admin_order_path(order)

if !fade_row_proc.call(order)
link_to order.number, order_path, class: 'font-semibold'
else
link_to order.number, order_path
end
end
}
end

def date_column
{
header: :date,
data: ->(order) do
content_tag :div, l(order.created_at, format: :short)
end
}
end

def customer_column
{
class_name: "w-[400px]",
header: :customer,
data: ->(order) do
customer_email = order.user&.email
content_tag :div, String(customer_email)
end
}
end

def total_column
{
header: :total,
data: ->(order) do
content_tag :div, number_to_currency(order.total)
end
}
end

def items_column
{
header: :items,
data: ->(order) do
content_tag :div, t('.columns.items', count: order.line_items.sum(:quantity))
end
}
end

def payment_column
{
header: :payment,
data: ->(order) do
component('ui/badge').new(name: order.payment_state&.humanize, color: order.paid? ? :green : :yellow)
end
}
end

def shipment_column
{
header: :shipment,
data: ->(order) do
component('ui/badge').new(name: order.shipment_state&.humanize, color: order.shipped? ? :green : :yellow)
end
}
end
end
Loading

0 comments on commit 105a8da

Please sign in to comment.