shimmer 0.0.10 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bd35afc832326e3510edad8c3bd0e4953ad4e34e6bd1b2c75f280df15efb4e6
4
- data.tar.gz: bb11df2bdc2de3e2b94f9f3ebccf0732d903d1d045b1c159a138f5aa0dc9214d
3
+ metadata.gz: aa623a504a48b7e6f3a1c0d4ccf748b2068b8934288094524a8039c52588c384
4
+ data.tar.gz: 67ccb1224024c812aad171ddca3437c3d130fb1bbf71dc5c9326da143061be1c
5
5
  SHA512:
6
- metadata.gz: 53c455d63d7683234d565bac406c3deb95c2d6926b6bde7c71299fd0357842576cec99a10ae38b3a69656dd4594b15a93eca9d96351eea2110c26b0623ef7f09
7
- data.tar.gz: 311c7cd5b3bf082fdeefec75b87cd50245459446490f35abd488429d2b3e13e508504a94dbc2976b4c8809366d041d4d003a7e781528bef80350b9ad61093c8a
6
+ metadata.gz: 9de1f128d5baafb0c5effb645c59ccecec08b7c7319761802cfb8ed7bbeb55cc01abb9f365f85e0397ceff692e835dc5131683bac01f514619bf1623be831c37
7
+ data.tar.gz: 856718e8800d539c1c31c9b867768c9db4939fe979019f44e6eebf6203cb1d60f8daca6ce42d3b21cab1027d00106345a531cb28bd912bcdea31028885042803
data/.rubocop.yml ADDED
@@ -0,0 +1,9 @@
1
+ inherit_from: config/rubocop_base.yml
2
+
3
+ # Allow controllers created in this library to inherit directly from ActionController::Base.
4
+ Rails/ApplicationController:
5
+ Enabled: false
6
+
7
+ # Allow jobs created in this library to inherit directly from ActiveJob::Base.
8
+ Rails/ApplicationJob:
9
+ Enabled: false
data/.solargraph.yml CHANGED
@@ -1,4 +1,4 @@
1
- plugins:
2
- - solargraph-standardrb
3
1
  reporters:
4
- - standardrb
2
+ - rubocop
3
+ formatter:
4
+ - rubocop
@@ -1,3 +1,8 @@
1
1
  {
2
- "solargraph.useBundler": true
2
+ "solargraph.useBundler": false,
3
+ "solargraph.formatting": true,
4
+ "[ruby]": {
5
+ "editor.formatOnSave": false,
6
+ "editor.defaultFormatter": "castwide.solargraph"
7
+ },
3
8
  }
data/Gemfile CHANGED
@@ -4,7 +4,3 @@ source "https://rubygems.org"
4
4
 
5
5
  # Specify your gem's dependencies in shimmer.gemspec
6
6
  gemspec
7
-
8
- gem "rake", "~> 13.0"
9
- gem "standard"
10
- gem "solargraph-standardrb"
data/Gemfile.lock CHANGED
@@ -6,29 +6,23 @@ PATH
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ activesupport (7.0.2.3)
10
+ concurrent-ruby (~> 1.0, >= 1.0.2)
11
+ i18n (>= 1.6, < 2)
12
+ minitest (>= 5.1)
13
+ tzinfo (~> 2.0)
9
14
  ast (2.4.2)
10
- backport (1.2.0)
11
- benchmark (0.2.0)
12
- diff-lcs (1.4.4)
13
- e2mmap (0.1.0)
14
- jaro_winkler (1.5.4)
15
- kramdown (2.3.1)
16
- rexml
17
- kramdown-parser-gfm (1.1.0)
18
- kramdown (~> 2.0)
19
- nokogiri (1.12.5-x86_64-darwin)
20
- racc (~> 1.4)
21
- nokogiri (1.12.5-x86_64-linux)
22
- racc (~> 1.4)
15
+ concurrent-ruby (1.1.10)
16
+ i18n (1.10.0)
17
+ concurrent-ruby (~> 1.0)
18
+ minitest (5.15.0)
23
19
  parallel (1.21.0)
24
20
  parser (3.0.3.2)
25
21
  ast (~> 2.4.1)
26
- racc (1.6.0)
22
+ rack (2.2.3)
27
23
  rainbow (3.0.0)
28
24
  rake (13.0.6)
29
25
  regexp_parser (2.2.0)
30
- reverse_markdown (2.1.1)
31
- nokogiri
32
26
  rexml (3.2.5)
33
27
  rubocop (1.23.0)
34
28
  parallel (~> 1.10)
@@ -44,34 +38,23 @@ GEM
44
38
  rubocop-performance (1.12.0)
45
39
  rubocop (>= 1.7.0, < 2.0)
46
40
  rubocop-ast (>= 0.4.0)
41
+ rubocop-rails (2.14.2)
42
+ activesupport (>= 4.2.0)
43
+ rack (>= 1.1)
44
+ rubocop (>= 1.7.0, < 2.0)
45
+ rubocop-rake (0.6.0)
46
+ rubocop (~> 1.0)
47
+ rubocop-rspec (2.9.0)
48
+ rubocop (~> 1.19)
47
49
  ruby-progressbar (1.11.0)
48
- solargraph (0.44.2)
49
- backport (~> 1.2)
50
- benchmark
51
- bundler (>= 1.17.2)
52
- diff-lcs (~> 1.4)
53
- e2mmap
54
- jaro_winkler (~> 1.5)
55
- kramdown (~> 2.3)
56
- kramdown-parser-gfm (~> 1.1)
57
- parser (~> 3.0)
58
- reverse_markdown (>= 1.0.5, < 3)
59
- rubocop (>= 0.52)
60
- thor (~> 1.0)
61
- tilt (~> 2.0)
62
- yard (~> 0.9, >= 0.9.24)
63
- solargraph-standardrb (0.0.4)
64
- solargraph (>= 0.39.1)
65
- standard (>= 0.4.1)
66
50
  standard (1.5.0)
67
51
  rubocop (= 1.23.0)
68
52
  rubocop-performance (= 1.12.0)
69
- thor (1.1.0)
70
- tilt (2.0.10)
53
+ standardrb (1.0.1)
54
+ standard
55
+ tzinfo (2.0.4)
56
+ concurrent-ruby (~> 1.0)
71
57
  unicode-display_width (2.1.0)
72
- webrick (1.7.0)
73
- yard (0.9.27)
74
- webrick (~> 1.7.0)
75
58
 
76
59
  PLATFORMS
77
60
  x86_64-darwin-21
@@ -79,9 +62,13 @@ PLATFORMS
79
62
 
80
63
  DEPENDENCIES
81
64
  rake (~> 13.0)
65
+ rubocop
66
+ rubocop-performance
67
+ rubocop-rails
68
+ rubocop-rake
69
+ rubocop-rspec
82
70
  shimmer!
83
- solargraph-standardrb
84
- standard
71
+ standardrb
85
72
 
86
73
  BUNDLED WITH
87
74
  2.2.32
data/README.md CHANGED
@@ -4,6 +4,21 @@ Shimmer is a collection of Rails extensions that bring advanced UI features into
4
4
 
5
5
  ## Features
6
6
 
7
+ ### Rubocop Base Configuration
8
+
9
+ *Shimmer* offers an opiniated *Rubocop* base configuration. This configuration inherits itself from *StandardRB* and aim at remaining as close to it as possible. Why not only use *StandardRB*, since it is so fast and prevent bikeshedding? Well, sadly, it does not solve all problems and using *Rubocop* still integrates a lot easier in most toolsets. However, the idea is to still prevent bikeshedding our *Rubocop* configuration by making sure that every exception to what's configured in *StandardRB* is justified (with a comment over its configuration block in `./config/rubocop_base.yml`), reviewed, debated, and agreed upon before being merged.
10
+
11
+ #### Use Shared Configuration In Projects
12
+
13
+ Typically, a `.rubocop.yml` file in projects using *Shimmer* looks like this.
14
+
15
+ ```yml
16
+ inherit_gem:
17
+ shimmer: config/rubocop_base.yml
18
+ ```
19
+
20
+ Then, if there are specific cops you want to use in the specific project you are working on, you still can easily add them. But at least, the base configuration is shared between projects and is itself as close to *StandardRB* as possible.
21
+
7
22
  ### Static File Serving
8
23
 
9
24
  `ActiveStorage` is great, but serving of files, especially behind a CDN, can be complicated to get right. This can be fixed easily:
data/bin/rubocop ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rubocop' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rubocop", "rubocop")
data/bin/solargraph ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'solargraph' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("solargraph", "solargraph")
@@ -0,0 +1,32 @@
1
+ AllCops:
2
+ NewCops: disable
3
+ Exclude:
4
+ - '**/vendor/bundle/**/*'
5
+ - '**/bin/**/*'
6
+ - '**/db/schema.rb'
7
+ - '**/node_modules/**/*'
8
+
9
+ require:
10
+ - standard
11
+ - rubocop-rails
12
+ - rubocop-rake
13
+
14
+ inherit_gem:
15
+ standard: config/base.yml
16
+
17
+ # String literals should never be mutable.
18
+ Style/FrozenStringLiteralComment:
19
+ Enabled: true
20
+
21
+ # Constants should never be mutable.
22
+ Style/MutableConstant:
23
+ Enabled: true
24
+ EnforcedStyle: strict
25
+
26
+ # Allow `.update_all`.
27
+ Rails/SkipsModelValidations:
28
+ Enabled: false
29
+
30
+ # Allow Rake tasks to not require the full Rails app to be loaded.
31
+ Rails/RakeEnvironment:
32
+ Enabled: false
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shimmer
4
+ module Auth
5
+ class AppleProvider < Provider
6
+ self.token_column = :apple_id
7
+
8
+ private
9
+
10
+ def request_details(params)
11
+ name = params[:user] ? JSON.parse(params[:user])["name"] : {}
12
+ headers = {
13
+ 'Content-Type': "application/x-www-form-urlencoded"
14
+ }
15
+ form = {
16
+ grant_type: "authorization_code",
17
+ code: params[:code],
18
+ client_id: ENV.fetch("APPLE_BUNDLE_ID"),
19
+ client_secret: ENV.fetch("APPLE_CLIENT_SECRET"),
20
+ scope: "name email"
21
+ }
22
+ response = HTTParty.post("https://appleid.apple.com/auth/token", body: URI.encode_www_form(form), headers: headers)
23
+ raise InvalidTokenError, "Login check failed: #{response.body}" unless response.ok?
24
+
25
+ token = JWT.decode(response["id_token"], nil, false).first
26
+ UserDetails.new token: token["sub"], email: token["email"], first_name: name["firstName"], last_name: name["lastName"]
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shimmer
4
+ module Auth
5
+ module Authenticating
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ before_action :authenticate
10
+ helper_method :current_user
11
+
12
+ def require_login
13
+ redirect_to login_path unless current_user
14
+ end
15
+
16
+ def current_user
17
+ ::Current.user
18
+ end
19
+
20
+ def login(device:)
21
+ ::Current.device = device
22
+ cookies.encrypted[:device_token] = {value: device.token, expires: 2.years.from_now}
23
+ end
24
+
25
+ def logout
26
+ cookies.delete :device_token
27
+ end
28
+
29
+ private
30
+
31
+ def authenticate
32
+ ::Current.device = cookies.encrypted[:device_token].presence&.then { |e| ::Device.find_by token: e }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shimmer
4
+ module Auth
5
+ module Current
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ attribute :device
10
+
11
+ delegate :user, to: :device, allow_nil: true
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shimmer
4
+ module Auth
5
+ class DevProvider < Provider
6
+ def login(email:, user_agent: nil, ip: nil)
7
+ user = model.find_or_create_by!(email: email)
8
+ device = user.devices.create! user_agent: user_agent
9
+ log_login(user, device_id: device.id, user_agent: user_agent, ip: ip)
10
+ device
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shimmer
4
+ module Auth
5
+ module Device
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ has_secure_token
10
+
11
+ def name
12
+ [browser.platform.name, browser.name].join(" ")
13
+ end
14
+
15
+ private
16
+
17
+ def browser
18
+ @browser ||= Browser.new user_agent
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shimmer
4
+ module Auth
5
+ class GoogleProvider < Provider
6
+ self.token_column = :google_id
7
+
8
+ private
9
+
10
+ def request_details(params)
11
+ payload = GoogleIDToken::Validator.new.check(params[:credential], ENV.fetch("GOOGLE_CLIENT_ID"))
12
+ UserDetails.new token: payload["sub"], email: payload["email"], first_name: payload["given_name"].presence, last_name: payload["family_name"].presence
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shimmer
4
+ module Auth
5
+ module User
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ def authenticate!(user_agent: nil, ip: nil)
10
+ Provider.new(self.class).create_device(user: self, user_agent: user_agent, ip: ip)
11
+ end
12
+ end
13
+
14
+ class_methods do
15
+ def login!(provider:, **attributes)
16
+ "Shimmer::Auth::#{provider.to_s.classify}Provider".constantize
17
+ .new(self).login(**attributes)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shimmer
4
+ module Auth
5
+ class Provider
6
+ class InvalidTokenError < StandardError; end
7
+ UserDetails = Struct.new(:token, :email, :first_name, :last_name, keyword_init: true)
8
+ attr_reader :model
9
+ cattr_accessor :token_column
10
+
11
+ def initialize(model)
12
+ @model = model
13
+ end
14
+
15
+ def login(params:, user_agent: nil, ip: nil)
16
+ user = fetch_user request_details(params)
17
+ create_device user: user, user_agent: user_agent, ip: ip
18
+ end
19
+
20
+ def create_device(user:, user_agent: nil, ip: nil)
21
+ user.devices.create!(user_agent: user_agent).tap do |device|
22
+ log_login(user, device_id: device.id, user_agent: user_agent, ip: ip)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def log_login(user, device_id:, user_agent: nil, ip: nil)
29
+ return unless user.respond_to? :publish
30
+
31
+ user.publish :login, provider: self.class.name.demodulize.underscore, device_id: device_id, user_agent: user_agent, ip: ip
32
+ end
33
+
34
+ def fetch_user(details)
35
+ user = model.find_by(token_column => details.token) || model.find_by(email: details.email) || model.new
36
+ user[token_column] ||= details.token
37
+ user.email ||= details.email
38
+ user.first_name ||= details.first_name
39
+ user.last_name ||= details.last_name
40
+ user.save! if user.changed?
41
+ user
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ Dir["#{File.expand_path("./auth", __dir__)}/*"].sort.each { |e| require e }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Shimmer
2
4
  class Railtie < Rails::Railtie
3
5
  rake_tasks do
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :auth do
4
+ desc "Generates a Sign in with Apple Token"
5
+ task :apple_token do
6
+ ecdsa_key = OpenSSL::PKey::EC.new IO.read ".apple-key.p8"
7
+ headers = {
8
+ "kid" => Shimmer::Config.instance.apple_key_id!
9
+ }
10
+ claims = {
11
+ "iss" => Shimmer::Config.instance.apple_team_id!,
12
+ "iat" => Time.now.to_i,
13
+ "exp" => 180.days.from_now.to_i,
14
+ "aud" => "https://appleid.apple.com",
15
+ "sub" => Shimmer::Config.instance.apple_bundle_id!
16
+ }
17
+ puts JWT.encode claims, ecdsa_key, "ES256", headers
18
+ end
19
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  namespace :db do
4
- desc "Downloads the app database from heroku to local db"
4
+ desc "Downloads the app database from Heroku and imports it to the local database"
5
5
  task pull_data: :environment do
6
6
  config = if Rails.version.to_f >= 7
7
7
  ActiveRecord::Base.connection_db_config.configuration_hash.with_indifferent_access
@@ -18,6 +18,7 @@ namespace :db do
18
18
  sh "RAILS_ENV=test rails db:create"
19
19
  end
20
20
 
21
+ desc "Downloads the app assets from Heroku to directory `storage`."
21
22
  task pull_assets: :environment do
22
23
  config = JSON.parse(`heroku config --json`)
23
24
  ENV["AWS_DEFAULT_REGION"] = config.fetch("AWS_REGION")
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shimmer
4
+ class Config
5
+ include Singleton
6
+ class MissingConfigError < StandardError; end
7
+
8
+ def method_missing(method_name)
9
+ method_name = method_name.to_s
10
+ type = :string
11
+ key = method_name.delete_suffix("!").delete_suffix("?")
12
+ required = method_name.end_with?("!")
13
+ type = :bool if method_name.end_with?("?")
14
+ value = ENV[key.upcase].presence
15
+ value ||= Rails.application.credentials.send(key)
16
+ raise MissingConfigError, "#{key.upcase} environment value is missing" if required && value.blank?
17
+
18
+ coerce value, type
19
+ end
20
+
21
+ def respond_to_missing?(method_name)
22
+ true
23
+ end
24
+
25
+ private
26
+
27
+ def coerce(value, type)
28
+ return !value.in?(["n", "0", "no", "false"]) if type == :bool && value.is_a?(String)
29
+
30
+ value
31
+ end
32
+ end
33
+ end
@@ -45,7 +45,7 @@ module Shimmer
45
45
  end
46
46
 
47
47
  def resizeable
48
- resize.present? && !blob.content_type.include?("svg")
48
+ resize.present? && blob.content_type.exclude?("svg")
49
49
  end
50
50
 
51
51
  def variant
@@ -45,7 +45,6 @@ module Shimmer
45
45
  option_names = options.except(:count, :default, :raise, :scope).map { |k, v| "#{k}=#{v}" }.join(", ")
46
46
  return "#{key_name} #{option_names}" if I18n.debug && !untranslated
47
47
 
48
- options.reverse_merge!(default: old_translate(key, **options.merge(locale: :de))) if untranslated
49
48
  old_translate(key, **options)
50
49
  end
51
50
  alias_method :t, :translate
@@ -81,15 +81,19 @@ module Shimmer
81
81
  queued_updates.push turbo_stream.remove(id)
82
82
  end
83
83
 
84
- def open_modal(path, id: nil, size: nil, close: true)
84
+ def open_modal(url, id: nil, size: nil, close: true)
85
85
  run_javascript "ui.modal.open(#{{url: url, id: id, size: size, close: close}.to_json})"
86
86
  end
87
87
 
88
- def close_modal
89
- run_javascript "ui.modal.close()"
88
+ def close_modal(id = nil)
89
+ if id.present?
90
+ run_javascript "ui.modal.close('#{id}')"
91
+ else
92
+ run_javascript "ui.modal.close()"
93
+ end
90
94
  end
91
95
 
92
- def open_popover(path, selector:, placement: nil)
96
+ def open_popover(url, selector:, placement: nil)
93
97
  run_javascript "ui.popover.open(#{{url: url, selector: selector, placement: placement}.to_json})"
94
98
  end
95
99
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Shimmer
4
- VERSION = "0.0.10"
4
+ VERSION = "0.0.13"
5
5
  end
data/lib/shimmer.rb CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  require_relative "shimmer/version"
4
4
  require_relative "shimmer/railtie" if defined?(Rails::Railtie)
5
- Dir["#{File.expand_path("../lib/shimmer/middlewares", __dir__)}/*"].each { |e| require e }
6
- Dir["#{File.expand_path("../lib/shimmer/controllers", __dir__)}/*"].each { |e| require e }
7
- Dir["#{File.expand_path("../lib/shimmer/jobs", __dir__)}/*"].each { |e| require e }
8
- Dir["#{File.expand_path("../lib/shimmer/utils", __dir__)}/*"].each { |e| require e }
5
+ Dir["#{File.expand_path("../lib/shimmer/middlewares", __dir__)}/*"].sort.each { |e| require e }
6
+ Dir["#{File.expand_path("../lib/shimmer/controllers", __dir__)}/*"].sort.each { |e| require e }
7
+ Dir["#{File.expand_path("../lib/shimmer/jobs", __dir__)}/*"].sort.each { |e| require e }
8
+ Dir["#{File.expand_path("../lib/shimmer/utils", __dir__)}/*"].sort.each { |e| require e }
9
+ require_relative "shimmer/auth"
9
10
 
10
11
  module Shimmer
11
12
  class Error < StandardError; end
data/src/modal.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { createElement, nextFrame, getHTML } from "./util";
1
+ import { createElement, nextFrame, getHTML, guid, wait } from "./util";
2
2
 
3
3
  export interface ModalOptions {
4
4
  id?: string;
@@ -15,7 +15,7 @@ export class ModalPresenter {
15
15
  }
16
16
 
17
17
  async open(options: ModalOptions): Promise<void> {
18
- const id = (options.id = options.id ?? "default-modal");
18
+ const id = (options.id = options.id ?? guid());
19
19
  (this.modals[id] = new Modal({ presenter: this, id })).open(options);
20
20
  this.updateBlindStatus();
21
21
  }
@@ -44,30 +44,41 @@ export class ModalPresenter {
44
44
  }
45
45
 
46
46
  export class Modal {
47
- private readonly root: HTMLDivElement;
48
- private readonly frame: HTMLDivElement;
49
- private readonly closeButton: HTMLDivElement;
47
+ id: string;
48
+ private presenter: ModalPresenter;
49
+ private root?: HTMLDivElement;
50
50
 
51
51
  constructor({ presenter, id }: { presenter: ModalPresenter; id: string }) {
52
- this.root = createElement(document.body, "modal");
53
- const content = createElement(this.root, "modal__content");
54
- this.closeButton = createElement(content, "modal__close");
55
- this.closeButton.addEventListener("click", () => {
56
- presenter.close({ id });
57
- });
58
- this.frame = createElement(content, "modal__frame");
52
+ this.presenter = presenter;
53
+ this.id = id;
59
54
  }
60
55
 
61
56
  async open({ size, url, close }: ModalOptions): Promise<void> {
57
+ const root = createElement(document.body, "modal");
58
+ this.root = root;
59
+ const content = createElement(root, "modal__content");
60
+ const closeButton = createElement(content, "modal__close");
61
+ closeButton.addEventListener("click", () => {
62
+ this.presenter.close({ id: this.id });
63
+ });
64
+ const frame = createElement(content, "modal__frame");
62
65
  await nextFrame();
63
- this.closeButton.style.display = close ?? true ? "block" : "none";
64
- this.root.classList.add("modal--open");
65
- this.root.classList.add("modal--loading");
66
- this.root.classList.toggle("modal--small", size === "small");
67
- this.frame.innerHTML = await getHTML(url);
66
+ closeButton.style.display = close ?? true ? "block" : "none";
67
+ root.classList.add("modal--open");
68
+ root.classList.add("modal--loading");
69
+ root.classList.toggle("modal--small", size === "small");
70
+ frame.innerHTML = await getHTML(url);
71
+ root.classList.remove("modal--loading");
68
72
  }
69
73
 
70
74
  async close(): Promise<void> {
71
- this.root.classList.remove("modal--open");
75
+ const root = this.root;
76
+ if (!root) {
77
+ return;
78
+ }
79
+ root.classList.remove("modal--open");
80
+ await wait(1);
81
+ root.remove();
82
+ this.root = undefined;
72
83
  }
73
84
  }
data/src/util.ts CHANGED
@@ -29,3 +29,18 @@ export function createElement(
29
29
  parent.append(element);
30
30
  return element;
31
31
  }
32
+
33
+ export function guid(): string {
34
+ function s4(): string {
35
+ return Math.floor((1 + Math.random()) * 0x10000)
36
+ .toString(16)
37
+ .substring(1);
38
+ }
39
+ return [s4() + s4(), s4(), s4(), s4(), s4() + s4() + s4()].join("-");
40
+ }
41
+
42
+ export function wait(seconds: number): Promise<void> {
43
+ return new Promise((res) => {
44
+ setTimeout(res, seconds * 1000);
45
+ });
46
+ }
metadata CHANGED
@@ -1,15 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shimmer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jens Ravens
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-20 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2022-06-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '13.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '13.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: standardrb
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-performance
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
13
111
  description:
14
112
  email:
15
113
  - jens@nerdgeschoss.de
@@ -20,6 +118,7 @@ files:
20
118
  - ".editorconfig"
21
119
  - ".eslintrc.js"
22
120
  - ".prettierrc"
121
+ - ".rubocop.yml"
23
122
  - ".ruby-version"
24
123
  - ".solargraph.yml"
25
124
  - ".vscode/settings.json"
@@ -31,15 +130,28 @@ files:
31
130
  - README.md
32
131
  - Rakefile
33
132
  - bin/console
133
+ - bin/rubocop
34
134
  - bin/setup
135
+ - bin/solargraph
136
+ - config/rubocop_base.yml
35
137
  - lib/shimmer.rb
138
+ - lib/shimmer/auth.rb
139
+ - lib/shimmer/auth/apple_provider.rb
140
+ - lib/shimmer/auth/authenticating.rb
141
+ - lib/shimmer/auth/current.rb
142
+ - lib/shimmer/auth/dev_provider.rb
143
+ - lib/shimmer/auth/device.rb
144
+ - lib/shimmer/auth/google_provider.rb
145
+ - lib/shimmer/auth/user.rb
36
146
  - lib/shimmer/controllers/files_controller.rb
37
147
  - lib/shimmer/controllers/sitemaps_controller.rb
38
148
  - lib/shimmer/jobs/sitemap_job.rb
39
149
  - lib/shimmer/middlewares/cloudflare.rb
40
150
  - lib/shimmer/railtie.rb
151
+ - lib/shimmer/tasks/auth.rake
41
152
  - lib/shimmer/tasks/db.rake
42
153
  - lib/shimmer/tasks/lint.rake
154
+ - lib/shimmer/utils/config.rb
43
155
  - lib/shimmer/utils/file_helper.rb
44
156
  - lib/shimmer/utils/file_proxy.rb
45
157
  - lib/shimmer/utils/localizable.rb