maquina 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.overmind.env +1 -0
- data/Gemfile +20 -0
- data/Gemfile.lock +346 -0
- data/Procfile.dev +3 -0
- data/app/assets/images/maquina/.keep +0 -0
- data/app/assets/javascripts/maquina/controllers/file_controller.js +1 -1
- data/app/assets/stylesheets/maquina/application.tailwind.css +96 -97
- data/app/controllers/concerns/.keep +0 -0
- data/app/controllers/concerns/maquina/authenticate.rb +5 -1
- data/app/controllers/concerns/maquina/resourceful.rb +9 -9
- data/app/models/concerns/.keep +0 -0
- data/app/models/concerns/maquina/blockeable.rb +13 -3
- data/app/models/maquina/current.rb +2 -1
- data/app/models/maquina/membership.rb +10 -0
- data/app/models/maquina/organization.rb +7 -0
- data/app/models/maquina/plan.rb +2 -0
- data/app/models/maquina/user.rb +8 -0
- data/app/policies/maquina/application_policy.rb +3 -6
- data/app/policies/maquina/navigation_policy.rb +2 -2
- data/app/policies/maquina/user_policy.rb +7 -3
- data/app/views/layouts/maquina/application.html.erb +1 -2
- data/app/views/layouts/maquina/sessions.html.erb +1 -2
- data/app/views/maquina/application/components/file_component.rb +38 -5
- data/app/views/maquina/application/form.rb +3 -2
- data/config/importmap.rb +12 -0
- data/db/migrate/20230829183530_create_maquina_organizations.rb +11 -0
- data/db/migrate/20230829192656_create_maquina_memberships.rb +15 -0
- data/lib/generators/maquina/tailwind_config/USAGE +14 -0
- data/lib/generators/maquina/tailwind_config/tailwind_config_generator.rb +17 -3
- data/lib/generators/maquina/tailwind_config/templates/app/assets/stylesheets/maquina.css +96 -0
- data/lib/generators/maquina/tailwind_config/templates/lib/generators/tailwind_config/tailwind_config_generator.rb.tt +11 -0
- data/lib/generators/maquina/tailwind_config/templates/{app/assets/config/maquina → lib/generators/tailwind_config/templates/config}/tailwind.config.js.tt +4 -0
- data/lib/generators/maquina/tailwind_config/templates/lib/tasks/tailwind.rake.tt +11 -0
- data/lib/maquina/engine.rb +0 -4
- data/lib/maquina/version.rb +1 -1
- data/lib/maquina.rb +7 -4
- metadata +22 -9
- data/config/definitions.rb +0 -1
- data/config/initializers/importmap.rb +0 -17
- data/lib/tasks/tailwind.rake +0 -25
@@ -4,7 +4,16 @@ module Maquina
|
|
4
4
|
module Blockeable
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
included do
|
7
|
+
included do |base|
|
8
|
+
if base.eql?(Maquina::User)
|
9
|
+
define_method(:memberships_blocked?) do
|
10
|
+
return false if management?
|
11
|
+
|
12
|
+
return @memberships_blocked if !@memberships_blocked.nil?
|
13
|
+
@memberships_blocked = !memberships.includes(:organization).where(blocked_at: nil).where(maquina_organizations: {active: true}).exists?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
8
17
|
if has_attribute?(:blocked_at) && has_attribute?(:temporary_blocked_at)
|
9
18
|
define_method(:blocked?) do
|
10
19
|
temporary_blocked_until = nil
|
@@ -12,13 +21,14 @@ module Maquina
|
|
12
21
|
temporary_blocked_until = temporary_blocked_at.since(Maquina.configuration.temporary_block)
|
13
22
|
end
|
14
23
|
|
15
|
-
blocked_at.present? || (temporary_blocked_until.present? && temporary_blocked_until > Time.zone.now)
|
24
|
+
blocked_at.present? || (temporary_blocked_until.present? && temporary_blocked_until > Time.zone.now) ||
|
25
|
+
(respond_to?(:memberships_blocked?) && memberships_blocked?)
|
16
26
|
end
|
17
27
|
|
18
28
|
scope :unblocked, -> { where(blocked_at: nil).where("(coalesce(temporary_blocked_at + interval '? minutes', now())) <= now()", Maquina.configuration.temporary_block&.in_minutes&.to_i || 0) }
|
19
29
|
elsif has_attribute(:blocked_at)
|
20
30
|
define_method(:blocked?) do
|
21
|
-
blocked_at.present?
|
31
|
+
blocked_at.present? || (respond_to?(:memberships_blocked?) && memberships_blocked?)
|
22
32
|
end
|
23
33
|
|
24
34
|
scope :unblocked, -> { where(blocked_at: nil) }
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Maquina
|
4
4
|
class Current < ActiveSupport::CurrentAttributes
|
5
|
-
attribute :active_session, :user
|
5
|
+
attribute :active_session, :user, :membership
|
6
6
|
|
7
7
|
def signed_in?
|
8
8
|
return false if active_session.blank?
|
@@ -12,6 +12,7 @@ module Maquina
|
|
12
12
|
def active_session=(value)
|
13
13
|
super
|
14
14
|
self.user = value&.user
|
15
|
+
self.membership = user.default_membership
|
15
16
|
end
|
16
17
|
|
17
18
|
def management?
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Maquina
|
4
|
+
class Membership < ApplicationRecord
|
5
|
+
belongs_to :organization, class_name: "Maquina::Organization", foreign_key: :maquina_organization_id
|
6
|
+
belongs_to :user, class_name: "Maquina::User", foreign_key: :maquina_user_id
|
7
|
+
|
8
|
+
enum role: Maquina.configuration.membership_roles
|
9
|
+
end
|
10
|
+
end
|
data/app/models/maquina/plan.rb
CHANGED
@@ -27,6 +27,8 @@ module Maquina
|
|
27
27
|
class Plan < ApplicationRecord
|
28
28
|
include Searchable
|
29
29
|
|
30
|
+
has_many :organizations, class_name: "Maquina::Organization", foreign_key: :maquina_plan_id, dependent: :nullify
|
31
|
+
|
30
32
|
monetize :price_cents
|
31
33
|
|
32
34
|
validates :price, numericality: {greater_than_or_equal_to: 0}, if: ->(plan) { plan.free? }
|
data/app/models/maquina/user.rb
CHANGED
@@ -11,6 +11,8 @@ module Maquina
|
|
11
11
|
PASSWORD_COMPLEXITY_REGEX = /\A(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&#-=+])[A-Za-z\d@$!%*?&#-=+]{8,}\z/
|
12
12
|
has_secure_password
|
13
13
|
|
14
|
+
has_many :memberships, class_name: "Maquina::Membership", foreign_key: :maquina_user_id, inverse_of: :user
|
15
|
+
|
14
16
|
validates :email, presence: true, uniqueness: true, format: {with: URI::MailTo::EMAIL_REGEXP}
|
15
17
|
validates :password, format: {with: PASSWORD_COMPLEXITY_REGEX}, unless: ->(user) { user.password.blank? }
|
16
18
|
|
@@ -24,6 +26,12 @@ module Maquina
|
|
24
26
|
password_expires_at < Time.zone.now
|
25
27
|
end
|
26
28
|
|
29
|
+
def default_membership
|
30
|
+
return nil if management?
|
31
|
+
|
32
|
+
memberships.detect { |membership| membership.blocked_at.blank? && membership.organization.present? && membership.organization.active? }
|
33
|
+
end
|
34
|
+
|
27
35
|
private
|
28
36
|
|
29
37
|
def downcase_email
|
@@ -40,11 +40,8 @@ module Maquina
|
|
40
40
|
user.management?
|
41
41
|
end
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
# def owner?
|
47
|
-
# record.user_id == user.id
|
48
|
-
# end
|
43
|
+
def admin?
|
44
|
+
(Maquina::Current.membership.present? && Maquina::Current.membership.admin?)
|
45
|
+
end
|
49
46
|
end
|
50
47
|
end
|
@@ -3,11 +3,11 @@
|
|
3
3
|
module Maquina
|
4
4
|
class UserPolicy < ApplicationPolicy
|
5
5
|
def index?
|
6
|
-
management?
|
6
|
+
management? || admin?
|
7
7
|
end
|
8
8
|
|
9
9
|
def new?
|
10
|
-
management?
|
10
|
+
management? || admin?
|
11
11
|
end
|
12
12
|
|
13
13
|
def create?
|
@@ -21,7 +21,11 @@ module Maquina
|
|
21
21
|
private
|
22
22
|
|
23
23
|
relation_scope do |scope|
|
24
|
-
|
24
|
+
if management?
|
25
|
+
scope.where(management: management?)
|
26
|
+
else
|
27
|
+
scope.joins(memberships: :organization).where(maquina_organizations: {id: Maquina::Current.membership.organization.id})
|
28
|
+
end
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|
@@ -6,8 +6,7 @@
|
|
6
6
|
<%= csrf_meta_tags %>
|
7
7
|
<%= csp_meta_tag %>
|
8
8
|
|
9
|
-
<%= stylesheet_link_tag "
|
10
|
-
<%= stylesheet_link_tag "maquina/application", "data-turbo-track": "reload", media: "all" %>
|
9
|
+
<%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
|
11
10
|
|
12
11
|
<%= maquina_importmap_tags %>
|
13
12
|
</head>
|
@@ -6,8 +6,7 @@
|
|
6
6
|
<%= csrf_meta_tags %>
|
7
7
|
<%= csp_meta_tag %>
|
8
8
|
|
9
|
-
<%= stylesheet_link_tag "
|
10
|
-
<%= stylesheet_link_tag "maquina/application", "data-turbo-track": "reload" %>
|
9
|
+
<%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
|
11
10
|
|
12
11
|
<%= maquina_importmap_tags %>
|
13
12
|
</head>
|
@@ -5,17 +5,21 @@ module Maquina
|
|
5
5
|
module Components
|
6
6
|
class FileComponent < ComponentBase
|
7
7
|
include Phlex::Rails::Helpers::NumberToHumanSize
|
8
|
+
include Phlex::Rails::Helpers::TokenList
|
9
|
+
|
10
|
+
delegate :main_app, to: :helpers
|
8
11
|
|
9
12
|
def template
|
10
|
-
div(**extend_control_options(
|
13
|
+
div(**extend_control_options(control_html)) do
|
11
14
|
@form.label attribute_name, class: "label #{label_css_class}"
|
12
15
|
div(class: "mt-1") do
|
13
16
|
div(data_file_target: "container") do
|
14
17
|
@form.file_field attribute_name, **extend_input_options(input_html(no_helpers: true))
|
15
|
-
img(class: "
|
16
|
-
svg(viewbox: "0 0 24 24", fill: "currentColor", aria_hidden: "true", data_action: "click->file#select", data_file_target: "placeholder") do |s|
|
18
|
+
img(class: token_list("", hidden: !attached_file?), data_file_target: "preview", src: attached_url)
|
19
|
+
svg(viewbox: "0 0 24 24", fill: "currentColor", class: token_list("", hidden: attached_file?), aria_hidden: "true", data_action: "click->file#select", data_file_target: "placeholder") do |s|
|
17
20
|
s.path(fill_rule: "evenodd", d: "M1.5 6a2.25 2.25 0 012.25-2.25h16.5A2.25 2.25 0 0122.5 6v12a2.25 2.25 0 01-2.25 2.25H3.75A2.25 2.25 0 011.5 18V6zM3 16.06V18c0 .414.336.75.75.75h16.5A.75.75 0 0021 18v-1.94l-2.69-2.689a1.5 1.5 0 00-2.12 0l-.88.879.97.97a.75.75 0 11-1.06 1.06l-5.16-5.159a1.5 1.5 0 00-2.12 0L3 16.061zm10.125-7.81a1.125 1.125 0 112.25 0 1.125 1.125 0 01-2.25 0z", clip_rule: "evenodd")
|
18
21
|
end
|
22
|
+
p(class: "text-skin-muted pb-4 pt-2 italic text-sm") { attached_info } if attached_file?
|
19
23
|
help_template
|
20
24
|
error_template
|
21
25
|
end
|
@@ -41,18 +45,47 @@ module Maquina
|
|
41
45
|
}.deep_merge(input_html)
|
42
46
|
end
|
43
47
|
|
44
|
-
def extend_control_options(
|
48
|
+
def extend_control_options(control_html)
|
45
49
|
max_size = control_html.dig(:data, :file_max_size_value) || 4_194_304
|
46
50
|
human_max_size = number_to_human_size(max_size)
|
51
|
+
file_url = attached_url
|
47
52
|
|
48
53
|
{
|
49
54
|
data: {
|
50
55
|
controller: "file",
|
51
56
|
file_max_size_value: max_size,
|
52
|
-
file_validation_message_value: t("activerecord.errors.attributes.#{@form.object.model_name.i18n_key}.#{attribute_name}.oversize", size: human_max_size, default: t("activerecord.errors.attributes.file.oversize", size: human_max_size))
|
57
|
+
file_validation_message_value: t("activerecord.errors.attributes.#{@form.object.model_name.i18n_key}.#{attribute_name}.oversize", size: human_max_size, default: t("activerecord.errors.attributes.file.oversize", size: human_max_size)),
|
58
|
+
file_url_value: file_url
|
53
59
|
}
|
54
60
|
}.deep_merge(control_html)
|
55
61
|
end
|
62
|
+
|
63
|
+
# Todo: Work on not representable files
|
64
|
+
def attached_url
|
65
|
+
return "" if !attached_file?
|
66
|
+
|
67
|
+
if attached_file.blob.representable?
|
68
|
+
puts "Representable"
|
69
|
+
main_app.url_for(attached_file.blob.variant(resize_to_limit: [1200, 768]))
|
70
|
+
else
|
71
|
+
puts "No representable"
|
72
|
+
main_app.url_for(attached_file.blob)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def attached_info
|
77
|
+
return "" if !attached_file?
|
78
|
+
|
79
|
+
"#{attached_file.blob.filename} (#{number_to_human_size(attached_file.blob.byte_size)})"
|
80
|
+
end
|
81
|
+
|
82
|
+
def attached_file
|
83
|
+
@attached_file ||= @resource.send(attribute_name)
|
84
|
+
end
|
85
|
+
|
86
|
+
def attached_file?
|
87
|
+
attached_file&.attached?
|
88
|
+
end
|
56
89
|
end
|
57
90
|
end
|
58
91
|
end
|
@@ -49,8 +49,9 @@ module Maquina
|
|
49
49
|
|
50
50
|
def form_header_template
|
51
51
|
div do
|
52
|
-
|
53
|
-
|
52
|
+
prefix = @resource.persisted? ? :edit : :new
|
53
|
+
h3(class: "text-lg font-medium leading-6 text-skin-base") { t("#{prefix}.#{resource_class.model_name.i18n_key}.title", model: model_human_name.downcase, default: t("#{prefix}.title", default: model_human_name.downcase)) }
|
54
|
+
p(class: "mt-1 text-sm text-skin-dimmed") { t("#{prefix}.#{resource_class.model_name.i18n_key}.description", model: model_human_name.downcase, default: t("#{prefix}.description", model: model_human_name.downcase)) }
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
data/config/importmap.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Stimulus & Turbo
|
4
|
+
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
|
5
|
+
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
|
6
|
+
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
|
7
|
+
pin "stimulus-use", to: "https://ga.jspm.io/npm:stimulus-use@0.52.0/dist/index.js"
|
8
|
+
|
9
|
+
# Maquina entrypoint
|
10
|
+
pin "application", to: "maquina/application.js", preload: true
|
11
|
+
|
12
|
+
pin_all_from Maquina::Engine.root.join("app/assets/javascripts/maquina/controllers"), under: "controllers", to: "maquina/controllers"
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class CreateMaquinaOrganizations < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
create_table :maquina_organizations do |t|
|
4
|
+
t.string :name
|
5
|
+
t.boolean :active, default: true
|
6
|
+
t.references :maquina_plan, null: true, foreign_key: true
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateMaquinaMemberships < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
create_enum :maquina_role, %w[admin member]
|
4
|
+
|
5
|
+
create_table :maquina_memberships do |t|
|
6
|
+
t.references :maquina_organization, null: false, foreign_key: true
|
7
|
+
t.references :maquina_user, null: false, foreign_key: true
|
8
|
+
t.boolean :owner, default: false
|
9
|
+
t.enum :role, enum_type: :maquina_role, default: "member", null: false
|
10
|
+
t.timestamp :blocked_at
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Description:
|
2
|
+
It will create a custom TailwindCSS configuration file for Rails applications. The custom configuration file is
|
3
|
+
auto-generated that allows to include Engines files.
|
4
|
+
|
5
|
+
Add the file config/tailwind.config.js to the .gitignore file, and if you need to modify it, modify the template
|
6
|
+
file included in the generator.
|
7
|
+
|
8
|
+
Example:
|
9
|
+
bin/rails generate maquina:tailwind_config
|
10
|
+
|
11
|
+
This will create:
|
12
|
+
lib/tailwind.rake
|
13
|
+
lib/generators/tailwind_config/tailwind_config_generator.rb
|
14
|
+
lib/generators/tailwind_config/templates/tailwind.config.js.tt
|
@@ -2,10 +2,24 @@
|
|
2
2
|
|
3
3
|
module Maquina
|
4
4
|
class TailwindConfigGenerator < Rails::Generators::Base
|
5
|
-
source_root File.expand_path("
|
5
|
+
source_root File.expand_path("templates", __dir__)
|
6
6
|
|
7
|
-
def
|
8
|
-
|
7
|
+
def create_generator
|
8
|
+
tailwind_config_file = "lib/generators/tailwind_config/templates/config/tailwind.config.js.tt"
|
9
|
+
|
10
|
+
template "lib/tasks/tailwind.rake"
|
11
|
+
template "lib/generators/tailwind_config/tailwind_config_generator.rb"
|
12
|
+
|
13
|
+
# Seems that template can't handle .tt.tt extensions correctly
|
14
|
+
copy_file tailwind_config_file, tailwind_config_file
|
15
|
+
end
|
16
|
+
|
17
|
+
def configure_css
|
18
|
+
copy_file "app/assets/stylesheets/maquina.css"
|
19
|
+
|
20
|
+
inject_into_file "app/assets/stylesheets/application.tailwind.css", after: /base"?;/ do
|
21
|
+
%(\n@import "./maquina.css";)
|
22
|
+
end
|
9
23
|
end
|
10
24
|
end
|
11
25
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
:root {
|
2
|
+
--color-base: 31 27 54;
|
3
|
+
--color-accented: 37 99 235;
|
4
|
+
--color-inverted: 255 255 255;
|
5
|
+
--color-accented-hover: 59 130 246;
|
6
|
+
--color-muted: 55 65 81;
|
7
|
+
--color-dimmed: 75 85 99;
|
8
|
+
--color-error: 220 38 38;
|
9
|
+
|
10
|
+
--color-border-base: 209 213 219;
|
11
|
+
--color-border-accented: 37 99 235;
|
12
|
+
}
|
13
|
+
|
14
|
+
.label {
|
15
|
+
@apply text-sm font-medium text-skin-muted;
|
16
|
+
}
|
17
|
+
|
18
|
+
.input {
|
19
|
+
@apply appearance-none rounded-md border border-skin-base px-3 py-2 placeholder-gray-400 shadow-sm focus:border-skin-accented focus:outline-none focus:ring-skin-accented sm:text-sm;
|
20
|
+
}
|
21
|
+
|
22
|
+
.link {
|
23
|
+
@apply font-medium text-skin-accented hover:text-skin-accented-hover;
|
24
|
+
}
|
25
|
+
|
26
|
+
.check {
|
27
|
+
@apply border-skin-base h-4 w-4 text-skin-accented focus:ring-skin-accented rounded;
|
28
|
+
}
|
29
|
+
|
30
|
+
.button {
|
31
|
+
@apply inline-flex justify-center py-2 px-4 border border-skin-base rounded-md shadow-sm text-sm font-medium text-skin-muted bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-skin-accented;
|
32
|
+
}
|
33
|
+
|
34
|
+
.control-error .label {
|
35
|
+
@apply text-skin-error;
|
36
|
+
}
|
37
|
+
|
38
|
+
.control-error .input {
|
39
|
+
@apply border-skin-error focus:border-skin-error focus:ring-skin-error;
|
40
|
+
}
|
41
|
+
|
42
|
+
.help {
|
43
|
+
@apply mt-2 text-sm text-skin-dimmed;
|
44
|
+
}
|
45
|
+
|
46
|
+
.help-error {
|
47
|
+
@apply text-skin-error;
|
48
|
+
}
|
49
|
+
|
50
|
+
.button[disabled] {
|
51
|
+
@apply bg-gray-50 text-skin-dimmed cursor-default;
|
52
|
+
}
|
53
|
+
|
54
|
+
.button-accented {
|
55
|
+
@apply rounded-md border border-transparent bg-skin-accented py-2 px-4 text-sm font-medium text-skin-inverted shadow-sm hover:bg-skin-accented-hover focus:outline-none focus:ring-2 focus:ring-skin-accented focus:ring-offset-2;
|
56
|
+
}
|
57
|
+
|
58
|
+
input[type="search"] {
|
59
|
+
@apply block w-full rounded-md border border-skin-base pl-10 leading-5 placeholder-gray-400 focus:placeholder-gray-300 focus:outline-none focus:ring-1 focus:ring-skin-accented focus:border-skin-accented sm:text-sm;
|
60
|
+
}
|
61
|
+
|
62
|
+
.desktop-menu {
|
63
|
+
@apply hidden lg:ml-6 lg:flex lg:space-x-8;
|
64
|
+
}
|
65
|
+
|
66
|
+
.desktop-menu-item {
|
67
|
+
@apply font-sans uppercase border-transparent text-skin-dimmed underline-offset-4 decoration-2 hover:underline hover:decoration-skin-accented hover:text-skin-muted inline-flex items-center px-1 pt-1 text-sm font-medium;
|
68
|
+
}
|
69
|
+
|
70
|
+
.desktop-menu-item__active {
|
71
|
+
@apply decoration-skin-accented underline text-skin-base;
|
72
|
+
}
|
73
|
+
|
74
|
+
.mobile-menu {
|
75
|
+
@apply pt-2 pb-3 space-y-1;
|
76
|
+
}
|
77
|
+
|
78
|
+
.mobile-menu-item {
|
79
|
+
@apply font-sans border-transparent text-skin-dimmed hover:bg-gray-200 hover:border-gray-300 hover:text-skin-muted block pl-3 pr-4 py-2 border-l-4 text-base font-medium;
|
80
|
+
}
|
81
|
+
|
82
|
+
.mobile-menu-item__active {
|
83
|
+
@apply bg-skin-accented-hover border-skin-accented text-skin-accented hover:text-skin-accented hover:bg-skin-accented-hover hover:border-skin-accented;
|
84
|
+
}
|
85
|
+
|
86
|
+
.desktop-profile-menu-item {
|
87
|
+
@apply block w-full text-left font-sans px-4 py-2 text-sm text-skin-dimmed hover:bg-gray-200 hover:text-skin-muted;
|
88
|
+
}
|
89
|
+
|
90
|
+
.mobile-profile-menu-item {
|
91
|
+
@apply block font-sans px-4 py-2 text-base font-medium text-skin-dimmed hover:text-skin-muted hover:bg-gray-200;
|
92
|
+
}
|
93
|
+
|
94
|
+
.mobile-button {
|
95
|
+
@apply inline-flex items-center justify-center p-2 rounded-md text-skin-dimmed hover:text-skin-muted hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-skin-accented;
|
96
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class TailwindConfigGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path("templates", __dir__)
|
5
|
+
|
6
|
+
def create_tailwind_config_file
|
7
|
+
@engines_paths = Maquina.configuration.tailwind_content
|
8
|
+
|
9
|
+
template "config/tailwind.config.js"
|
10
|
+
end
|
11
|
+
end
|
@@ -2,6 +2,10 @@ const defaultTheme = require('tailwindcss/defaultTheme')
|
|
2
2
|
|
3
3
|
module.exports = {
|
4
4
|
content: [
|
5
|
+
'public/*.html',
|
6
|
+
'app/helpers/**/*.rb',
|
7
|
+
'app/javascript/**/*.js',
|
8
|
+
'app/views/**/*.{erb,haml,html,slim}',
|
5
9
|
<%= Maquina.configuration.tailwind_content.map{|path| "'#{path}'"}.join(",\n") %>
|
6
10
|
],
|
7
11
|
theme: {
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :tailwindcss do
|
4
|
+
desc "Generates your tailwind config file"
|
5
|
+
task :config do
|
6
|
+
Rails::Generators.invoke("tailwind_config", ["--force"])
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
Rake::Task["tailwindcss:build"].enhance(["tailwindcss:config"])
|
11
|
+
Rake::Task["tailwindcss:watch"].enhance(["tailwindcss:config"])
|
data/lib/maquina/engine.rb
CHANGED
@@ -9,9 +9,5 @@ module Maquina
|
|
9
9
|
class Engine < ::Rails::Engine
|
10
10
|
config.autoload_paths += %W[#{Engine.root}/app/views]
|
11
11
|
isolate_namespace Maquina
|
12
|
-
|
13
|
-
initializer "maquina.importmap", before: "importmap" do |app|
|
14
|
-
app.config.importmap.paths << Engine.root.join("config/initializers/importmap.rb")
|
15
|
-
end
|
16
12
|
end
|
17
13
|
end
|
data/lib/maquina/version.rb
CHANGED
data/lib/maquina.rb
CHANGED
@@ -15,22 +15,25 @@ module Maquina
|
|
15
15
|
|
16
16
|
class Configuration
|
17
17
|
attr_accessor :password_retain_count, :temporary_block, :session_expiration, :signin_attempts, :tailwind_content,
|
18
|
-
:importmap, :root_app_path
|
18
|
+
:importmap, :root_app_path, :membership_roles
|
19
19
|
|
20
20
|
def initialize
|
21
21
|
@password_retain_count = 3
|
22
22
|
@temporary_block = 5.minutes
|
23
23
|
@session_expiration = 2.days
|
24
24
|
@signin_attempts = 5
|
25
|
-
@importmap = Importmap::Map.new
|
26
25
|
@root_app_path = nil
|
27
26
|
|
27
|
+
@membership_roles = {admin: "admin", member: "member"}
|
28
|
+
|
29
|
+
@importmap = Importmap::Map.new
|
30
|
+
@importmap.draw(Engine.root.join("config/importmap.rb"))
|
31
|
+
|
28
32
|
@tailwind_content = [
|
29
33
|
"#{Maquina::Engine.root}/app/views/**/*.{rb,erb}",
|
30
34
|
"#{Maquina::Engine.root}/app/helpers/**/*.rb",
|
31
35
|
"#{Maquina::Engine.root}/app/controllers/**/*.rb",
|
32
|
-
"#{Maquina::Engine.root}/app/javascript/**/*.js"
|
33
|
-
"#{Maquina::Engine.root}/app/assets/**/application.tailwind.css"
|
36
|
+
"#{Maquina::Engine.root}/app/javascript/**/*.js"
|
34
37
|
]
|
35
38
|
end
|
36
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maquina
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mario Alberto Chávez
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-08-
|
11
|
+
date: 2023-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 1.
|
89
|
+
version: 1.2.0
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 1.
|
96
|
+
version: 1.2.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: tailwindcss-rails
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -295,9 +295,14 @@ executables: []
|
|
295
295
|
extensions: []
|
296
296
|
extra_rdoc_files: []
|
297
297
|
files:
|
298
|
+
- ".overmind.env"
|
299
|
+
- Gemfile
|
300
|
+
- Gemfile.lock
|
298
301
|
- MIT-LICENSE
|
302
|
+
- Procfile.dev
|
299
303
|
- README.md
|
300
304
|
- Rakefile
|
305
|
+
- app/assets/images/maquina/.keep
|
301
306
|
- app/assets/images/maquina/maquina.svg
|
302
307
|
- app/assets/javascripts/maquina/application.js
|
303
308
|
- app/assets/javascripts/maquina/controllers/alert_controller.js
|
@@ -311,6 +316,7 @@ files:
|
|
311
316
|
- app/assets/javascripts/maquina/controllers/submit_form_controller.js
|
312
317
|
- app/assets/stylesheets/maquina/application.css
|
313
318
|
- app/assets/stylesheets/maquina/application.tailwind.css
|
319
|
+
- app/controllers/concerns/.keep
|
314
320
|
- app/controllers/concerns/maquina/authenticate.rb
|
315
321
|
- app/controllers/concerns/maquina/create.rb
|
316
322
|
- app/controllers/concerns/maquina/destroy.rb
|
@@ -334,6 +340,7 @@ files:
|
|
334
340
|
- app/jobs/maquina/application_job.rb
|
335
341
|
- app/mailers/maquina/application_mailer.rb
|
336
342
|
- app/mailers/maquina/user_notifications_mailer.rb
|
343
|
+
- app/models/concerns/.keep
|
337
344
|
- app/models/concerns/maquina/authenticate_by.rb
|
338
345
|
- app/models/concerns/maquina/blockeable.rb
|
339
346
|
- app/models/concerns/maquina/multifactor.rb
|
@@ -343,6 +350,8 @@ files:
|
|
343
350
|
- app/models/maquina/application_record.rb
|
344
351
|
- app/models/maquina/current.rb
|
345
352
|
- app/models/maquina/invitation.rb
|
353
|
+
- app/models/maquina/membership.rb
|
354
|
+
- app/models/maquina/organization.rb
|
346
355
|
- app/models/maquina/plan.rb
|
347
356
|
- app/models/maquina/used_password.rb
|
348
357
|
- app/models/maquina/user.rb
|
@@ -399,8 +408,7 @@ files:
|
|
399
408
|
- app/views/maquina/unauthorized/401.html.erb
|
400
409
|
- app/views/maquina/user_notifications_mailer/invitation_email.html.erb
|
401
410
|
- app/views/maquina/user_notifications_mailer/invitation_email.text.erb
|
402
|
-
- config/
|
403
|
-
- config/initializers/importmap.rb
|
411
|
+
- config/importmap.rb
|
404
412
|
- config/initializers/money.rb
|
405
413
|
- config/initializers/pagy.rb
|
406
414
|
- config/locales/flash.en.yml
|
@@ -415,18 +423,23 @@ files:
|
|
415
423
|
- db/migrate/20221113020108_create_maquina_used_passwords.rb
|
416
424
|
- db/migrate/20221115223414_create_maquina_active_sessions.rb
|
417
425
|
- db/migrate/20230201203922_create_maquina_invitations.rb
|
426
|
+
- db/migrate/20230829183530_create_maquina_organizations.rb
|
427
|
+
- db/migrate/20230829192656_create_maquina_memberships.rb
|
418
428
|
- db/schema.rb
|
419
429
|
- lib/generators/maquina/install_generator.rb
|
420
430
|
- lib/generators/maquina/install_templates/install_templates_generator.rb
|
431
|
+
- lib/generators/maquina/tailwind_config/USAGE
|
421
432
|
- lib/generators/maquina/tailwind_config/tailwind_config_generator.rb
|
422
|
-
- lib/generators/maquina/tailwind_config/templates/app/assets/
|
433
|
+
- lib/generators/maquina/tailwind_config/templates/app/assets/stylesheets/maquina.css
|
434
|
+
- lib/generators/maquina/tailwind_config/templates/lib/generators/tailwind_config/tailwind_config_generator.rb.tt
|
435
|
+
- lib/generators/maquina/tailwind_config/templates/lib/generators/tailwind_config/templates/config/tailwind.config.js.tt
|
436
|
+
- lib/generators/maquina/tailwind_config/templates/lib/tasks/tailwind.rake.tt
|
423
437
|
- lib/generators/maquina/templates/config/initializers/maquina.rb
|
424
438
|
- lib/maquina.rb
|
425
439
|
- lib/maquina/engine.rb
|
426
440
|
- lib/maquina/version.rb
|
427
441
|
- lib/tasks/install.rake
|
428
442
|
- lib/tasks/maquina_tasks.rake
|
429
|
-
- lib/tasks/tailwind.rake
|
430
443
|
homepage: https://mariochavez.io
|
431
444
|
licenses:
|
432
445
|
- MIT
|
@@ -449,7 +462,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
449
462
|
- !ruby/object:Gem::Version
|
450
463
|
version: '0'
|
451
464
|
requirements: []
|
452
|
-
rubygems_version: 3.4.
|
465
|
+
rubygems_version: 3.4.19
|
453
466
|
signing_key:
|
454
467
|
specification_version: 4
|
455
468
|
summary: Rails engine for building Rails applications.
|