Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
8b3d53b263
|
@ -0,0 +1,54 @@
|
|||
name: Bug Report
|
||||
description: If something isn't working as expected
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before opening an issue, please make sure to check if the [issue tracker](https://github.com/Retrospring/retrospring/issues?q=is%3Aissue+label%3Abug) in case it has been previously reported or fixed.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce the problem
|
||||
description: What were you trying to do?
|
||||
value: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected behaviour
|
||||
description: What should have happened?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Actual behaviour
|
||||
description: What happened?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Detailed description
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Specifications
|
||||
description: |
|
||||
If you host Retrospring, what version/commit hash of Retrospring did this issue occur in?
|
||||
|
||||
If a front-end issue, what browser and operating systems were you using?
|
||||
placeholder: |
|
||||
Retrospring 1970.0101.0
|
||||
Ruby 3.1.3
|
||||
Node.js 18.13.0
|
||||
|
||||
Google Chrome 112
|
||||
Firefox 109.0
|
||||
|
||||
etc...
|
||||
validations:
|
||||
required: true
|
|
@ -0,0 +1,20 @@
|
|||
name: Feature Request
|
||||
description: If you have a suggestion
|
||||
labels: [suggestion]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Please use a concise and distinct title for the issue.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Pitch
|
||||
description: Describe your idea for a feature. Please check our [issue tracker](https://github.com/Retrospring/retrospring/issues?q=is%3Aissue+label%3Asuggestion) to make sure it has not already been suggested/implemented/turned down before.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: Why do you think this feature is needed? Who would benefit from it?
|
||||
validations:
|
||||
required: true
|
|
@ -0,0 +1,5 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: GitHub Discussions
|
||||
url: https://github.com/retrospring/retrospring/discussions
|
||||
about: Please ask and answer questions here.
|
6
Gemfile
6
Gemfile
|
@ -50,9 +50,9 @@ gem "sentry-rails"
|
|||
gem "sentry-ruby"
|
||||
gem "sentry-sidekiq"
|
||||
|
||||
gem "sidekiq", "< 6" # remove version constraint once we have redis 5
|
||||
gem "sidekiq", "< 7" # remove version constraint once are ready to upgrade https://github.com/mperham/sidekiq/blob/main/docs/7.0-Upgrade.md
|
||||
|
||||
gem "questiongenerator", "~> 1.0"
|
||||
gem "questiongenerator", "~> 1.1"
|
||||
|
||||
gem "httparty"
|
||||
gem "redcarpet"
|
||||
|
@ -97,7 +97,7 @@ group :development, :test do
|
|||
gem "rspec-mocks"
|
||||
gem "rspec-rails", "~> 6.0"
|
||||
gem "rspec-sidekiq", "~> 3.0", require: false
|
||||
gem "rubocop", "~> 1.43"
|
||||
gem "rubocop", "~> 1.44"
|
||||
gem "rubocop-rails", "~> 2.17"
|
||||
gem "shoulda-matchers", "~> 5.3"
|
||||
gem "simplecov", require: false
|
||||
|
|
151
Gemfile.lock
151
Gemfile.lock
|
@ -9,40 +9,40 @@ GIT
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (6.1.7.1)
|
||||
actionpack (= 6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
actioncable (6.1.7.2)
|
||||
actionpack (= 6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (6.1.7.1)
|
||||
actionpack (= 6.1.7.1)
|
||||
activejob (= 6.1.7.1)
|
||||
activerecord (= 6.1.7.1)
|
||||
activestorage (= 6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
actionmailbox (6.1.7.2)
|
||||
actionpack (= 6.1.7.2)
|
||||
activejob (= 6.1.7.2)
|
||||
activerecord (= 6.1.7.2)
|
||||
activestorage (= 6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
mail (>= 2.7.1)
|
||||
actionmailer (6.1.7.1)
|
||||
actionpack (= 6.1.7.1)
|
||||
actionview (= 6.1.7.1)
|
||||
activejob (= 6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
actionmailer (6.1.7.2)
|
||||
actionpack (= 6.1.7.2)
|
||||
actionview (= 6.1.7.2)
|
||||
activejob (= 6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (6.1.7.1)
|
||||
actionview (= 6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
actionpack (6.1.7.2)
|
||||
actionview (= 6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
rack (~> 2.0, >= 2.0.9)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actiontext (6.1.7.1)
|
||||
actionpack (= 6.1.7.1)
|
||||
activerecord (= 6.1.7.1)
|
||||
activestorage (= 6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
actiontext (6.1.7.2)
|
||||
actionpack (= 6.1.7.2)
|
||||
activerecord (= 6.1.7.2)
|
||||
activestorage (= 6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
actionview (6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
|
@ -50,26 +50,26 @@ GEM
|
|||
active_model_otp (2.3.1)
|
||||
activemodel
|
||||
rotp (~> 6.2.0)
|
||||
activejob (6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
activejob (6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
activemodel (6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
activemodel-serializers-xml (1.0.2)
|
||||
activemodel (> 5.x)
|
||||
activesupport (> 5.x)
|
||||
builder (~> 3.1)
|
||||
activerecord (6.1.7.1)
|
||||
activemodel (= 6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
activestorage (6.1.7.1)
|
||||
actionpack (= 6.1.7.1)
|
||||
activejob (= 6.1.7.1)
|
||||
activerecord (= 6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
activerecord (6.1.7.2)
|
||||
activemodel (= 6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
activestorage (6.1.7.2)
|
||||
actionpack (= 6.1.7.2)
|
||||
activejob (= 6.1.7.2)
|
||||
activerecord (= 6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
marcel (~> 1.0)
|
||||
mini_mime (>= 1.1.0)
|
||||
activesupport (6.1.7.1)
|
||||
activesupport (6.1.7.2)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
|
@ -85,7 +85,7 @@ GEM
|
|||
rack (>= 0.9.0)
|
||||
binding_of_caller (1.0.0)
|
||||
debug_inspector (>= 0.0.1)
|
||||
bootsnap (1.15.0)
|
||||
bootsnap (1.16.0)
|
||||
msgpack (~> 1.2)
|
||||
bootstrap_form (5.1.0)
|
||||
actionpack (>= 5.2)
|
||||
|
@ -105,8 +105,8 @@ GEM
|
|||
chunky_png (1.4.0)
|
||||
coderay (1.1.3)
|
||||
colorize (0.8.1)
|
||||
concurrent-ruby (1.1.10)
|
||||
connection_pool (2.2.5)
|
||||
concurrent-ruby (1.2.0)
|
||||
connection_pool (2.3.0)
|
||||
crass (1.0.6)
|
||||
cssbundling-rails (1.1.2)
|
||||
railties (>= 6.0.0)
|
||||
|
@ -150,7 +150,7 @@ GEM
|
|||
zeitwerk (~> 2.6)
|
||||
equalizer (0.0.11)
|
||||
erubi (1.12.0)
|
||||
excon (0.93.1)
|
||||
excon (0.98.0)
|
||||
factory_bot (6.2.0)
|
||||
activesupport (>= 5.0.0)
|
||||
factory_bot_rails (6.2.0)
|
||||
|
@ -165,7 +165,7 @@ GEM
|
|||
ffi-compiler (1.0.1)
|
||||
ffi (>= 1.0.0)
|
||||
rake
|
||||
fog-aws (3.15.0)
|
||||
fog-aws (3.16.0)
|
||||
fog-core (~> 2.1)
|
||||
fog-json (~> 1.1)
|
||||
fog-xml (~> 0.1)
|
||||
|
@ -184,13 +184,13 @@ GEM
|
|||
nokogiri (>= 1.5.11, < 2.0.0)
|
||||
formatador (1.1.0)
|
||||
glob (0.3.1)
|
||||
globalid (1.0.1)
|
||||
globalid (1.1.0)
|
||||
activesupport (>= 5.0)
|
||||
haml (6.1.1)
|
||||
temple (>= 0.8.2)
|
||||
thor
|
||||
tilt
|
||||
haml_lint (0.43.0)
|
||||
haml_lint (0.45.0)
|
||||
haml (>= 4.0, < 6.2)
|
||||
parallel (~> 1.10)
|
||||
rainbow
|
||||
|
@ -321,27 +321,27 @@ GEM
|
|||
nio4r (~> 2.0)
|
||||
pundit (2.3.0)
|
||||
activesupport (>= 3.0.0)
|
||||
questiongenerator (1.0.0)
|
||||
questiongenerator (1.1.0)
|
||||
racc (1.6.2)
|
||||
rack (2.2.6.2)
|
||||
rack-protection (2.2.2)
|
||||
rack-protection (3.0.5)
|
||||
rack
|
||||
rack-test (2.0.2)
|
||||
rack (>= 1.3)
|
||||
rails (6.1.7.1)
|
||||
actioncable (= 6.1.7.1)
|
||||
actionmailbox (= 6.1.7.1)
|
||||
actionmailer (= 6.1.7.1)
|
||||
actionpack (= 6.1.7.1)
|
||||
actiontext (= 6.1.7.1)
|
||||
actionview (= 6.1.7.1)
|
||||
activejob (= 6.1.7.1)
|
||||
activemodel (= 6.1.7.1)
|
||||
activerecord (= 6.1.7.1)
|
||||
activestorage (= 6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
rails (6.1.7.2)
|
||||
actioncable (= 6.1.7.2)
|
||||
actionmailbox (= 6.1.7.2)
|
||||
actionmailer (= 6.1.7.2)
|
||||
actionpack (= 6.1.7.2)
|
||||
actiontext (= 6.1.7.2)
|
||||
actionview (= 6.1.7.2)
|
||||
activejob (= 6.1.7.2)
|
||||
activemodel (= 6.1.7.2)
|
||||
activerecord (= 6.1.7.2)
|
||||
activestorage (= 6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 6.1.7.1)
|
||||
railties (= 6.1.7.2)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-controller-testing (1.0.5)
|
||||
actionpack (>= 5.0.1.rc1)
|
||||
|
@ -361,17 +361,17 @@ GEM
|
|||
nested_form (~> 0.3)
|
||||
rails (>= 6.0, < 8)
|
||||
turbo-rails (~> 1.0)
|
||||
railties (6.1.7.1)
|
||||
actionpack (= 6.1.7.1)
|
||||
activesupport (= 6.1.7.1)
|
||||
railties (6.1.7.2)
|
||||
actionpack (= 6.1.7.2)
|
||||
activesupport (= 6.1.7.2)
|
||||
method_source
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0)
|
||||
rainbow (3.1.1)
|
||||
rake (13.0.6)
|
||||
redcarpet (3.5.1)
|
||||
redis (4.5.1)
|
||||
regexp_parser (2.6.1)
|
||||
redcarpet (3.6.0)
|
||||
redis (4.8.0)
|
||||
regexp_parser (2.6.2)
|
||||
request_store (1.5.1)
|
||||
rack (>= 1.4)
|
||||
responders (3.0.1)
|
||||
|
@ -417,7 +417,7 @@ GEM
|
|||
rspec-core (~> 3.0, >= 3.0.0)
|
||||
sidekiq (>= 2.4.0)
|
||||
rspec-support (3.12.0)
|
||||
rubocop (1.43.0)
|
||||
rubocop (1.44.1)
|
||||
json (~> 2.3)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.2.0.0)
|
||||
|
@ -437,7 +437,7 @@ GEM
|
|||
ruby-vips (2.1.4)
|
||||
ffi (~> 1.12)
|
||||
rubyzip (2.3.2)
|
||||
sanitize (6.0.0)
|
||||
sanitize (6.0.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.12.0)
|
||||
sassc (2.4.0)
|
||||
|
@ -458,11 +458,10 @@ GEM
|
|||
sidekiq (>= 3.0)
|
||||
shoulda-matchers (5.3.0)
|
||||
activesupport (>= 5.2.0)
|
||||
sidekiq (5.2.10)
|
||||
connection_pool (~> 2.2, >= 2.2.2)
|
||||
sidekiq (6.5.8)
|
||||
connection_pool (>= 2.2.5, < 3)
|
||||
rack (~> 2.0)
|
||||
rack-protection (>= 1.5.0)
|
||||
redis (~> 4.5, < 4.6.0)
|
||||
redis (>= 4.5.0, < 5)
|
||||
simple_oauth (0.3.1)
|
||||
simplecov (0.22.0)
|
||||
docile (~> 1.1)
|
||||
|
@ -485,7 +484,7 @@ GEM
|
|||
activesupport (>= 5.2)
|
||||
sprockets (>= 3.0.0)
|
||||
sysexits (1.2.0)
|
||||
temple (0.9.1)
|
||||
temple (0.10.0)
|
||||
thor (1.2.1)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.11)
|
||||
|
@ -511,7 +510,7 @@ GEM
|
|||
twitter-text (3.1.0)
|
||||
idn-ruby
|
||||
unf (~> 0.1.0)
|
||||
tzinfo (2.0.5)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
|
@ -579,7 +578,7 @@ DEPENDENCIES
|
|||
pghero
|
||||
puma
|
||||
pundit (~> 2.3)
|
||||
questiongenerator (~> 1.0)
|
||||
questiongenerator (~> 1.1)
|
||||
rails (~> 6.1)
|
||||
rails-controller-testing
|
||||
rails-i18n (~> 7.0)
|
||||
|
@ -594,7 +593,7 @@ DEPENDENCIES
|
|||
rspec-mocks
|
||||
rspec-rails (~> 6.0)
|
||||
rspec-sidekiq (~> 3.0)
|
||||
rubocop (~> 1.43)
|
||||
rubocop (~> 1.44)
|
||||
rubocop-rails (~> 2.17)
|
||||
ruby-progressbar
|
||||
rubyzip (~> 2.3)
|
||||
|
@ -604,7 +603,7 @@ DEPENDENCIES
|
|||
sentry-ruby
|
||||
sentry-sidekiq
|
||||
shoulda-matchers (~> 5.3)
|
||||
sidekiq (< 6)
|
||||
sidekiq (< 7)
|
||||
simplecov
|
||||
simplecov-cobertura
|
||||
simplecov-json
|
||||
|
|
9
Rakefile
9
Rakefile
|
@ -51,6 +51,15 @@ namespace :justask do # rubocop:disable Metrics/BlockLength
|
|||
user.remove_role :moderator
|
||||
puts "#{user.screen_name} is no longer a moderator."
|
||||
end
|
||||
|
||||
desc "Removes users whose accounts haven't been verified for over 3 months."
|
||||
task remove_stale: :environment do
|
||||
puts "Removing stale users…"
|
||||
removed = User.where(confirmed_at: nil)
|
||||
.where("confirmation_sent_at < ?", DateTime.now.utc - 3.months)
|
||||
.destroy_all.count
|
||||
puts "Removed #{removed} users"
|
||||
end
|
||||
end
|
||||
|
||||
namespace :db do
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# Security Policy
|
||||
|
||||
If you believe you've found a security vulnerability in Retrospring (a bug that allows something to happen that shouldn't be possible), you can reach us at <security@retrospring.net>.
|
||||
|
||||
You should *not* report such issues on GitHub or in other public spaces to give us time to publish a fix for the issue without exposing Retrospring's users to increased risk.
|
||||
|
||||
## Scope
|
||||
|
||||
A "vulnerability in Retrospring" is a vulnerability in the code distributed through our main source code repository on GitHub. Vulnerabilities that are specific to a given installation (e.g. misconfiguration) should be reported to the owner of that installation and not us.
|
||||
|
||||
## Supported Versions
|
||||
|
||||
As long as Retrospring is in rapid development pace the currently supported version for security issues is always the [latest tagged release](https://github.com/Retrospring/retrospring/releases/latest).
|
|
@ -125,6 +125,8 @@ $spacers: map-merge($rs-spacers, $spacers);
|
|||
--muted-text: 108, 117, 125;
|
||||
--input-text: 0, 0, 0;
|
||||
--input-placeholder: 108, 117, 125;
|
||||
--raised-text: 0, 0, 0;
|
||||
--raised-accent-text: 0, 0, 0;
|
||||
|
||||
--turbolinks-progress-color: #a58adc; // --primary lightened by 25%
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
& .dropdown-item:hover,
|
||||
& .dropdown-item:active {
|
||||
background: transparent;
|
||||
color: RGB(var(--body-text));
|
||||
color: RGB(var(--raised-text));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
margin-bottom: map.get($spacers, 3);
|
||||
box-shadow: $box-shadow-sm;
|
||||
background-color: var(--raised-bg);
|
||||
color: RGB(var(--raised-text));
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
|
@ -17,4 +18,5 @@
|
|||
.card-header,
|
||||
.card-footer {
|
||||
background-color: var(--raised-accent);
|
||||
color: RGB(var(--raised-accent-text));
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
.dropdown-menu {
|
||||
color: RGB(var(--body-text));
|
||||
color: RGB(var(--raised-text));
|
||||
background-color: var(--raised-bg);
|
||||
box-shadow: $box-shadow-lg;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
color: RGB(var(--body-text));
|
||||
color: RGB(var(--raised-text));
|
||||
|
||||
&.active,
|
||||
&.active,
|
||||
&:active,
|
||||
&:active:hover {
|
||||
color: RGB(var(--primary-text));
|
||||
|
@ -16,6 +16,7 @@
|
|||
}
|
||||
|
||||
&:hover {
|
||||
color: RGB(var(--raised-accent-text));
|
||||
background-color: var(--raised-accent);
|
||||
}
|
||||
}
|
||||
|
@ -32,4 +33,4 @@
|
|||
.dropdown-menu--lists {
|
||||
max-width: 275px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,10 @@
|
|||
}
|
||||
|
||||
.list-group-item-action {
|
||||
color: RGB(var(--body-text));
|
||||
color: RGB(var(--raised-text));
|
||||
|
||||
&:hover, &:focus {
|
||||
color: RGB(var(--raised-accent-text));
|
||||
background-color: var(--raised-accent);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AjaxController < ApplicationController
|
||||
skip_before_action :find_active_announcements
|
||||
before_action :build_response
|
||||
after_action :return_response
|
||||
|
||||
|
@ -92,10 +93,6 @@ class AjaxController < ApplicationController
|
|||
return_response
|
||||
end
|
||||
|
||||
def find_active_announcements
|
||||
# We do not need announcements here
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_response
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
class InboxController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
|
||||
def show
|
||||
after_action :mark_inbox_entries_as_read, only: %i[show]
|
||||
|
||||
def show # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
||||
find_author
|
||||
find_inbox_entries
|
||||
|
||||
|
@ -11,15 +13,17 @@ class InboxController < ApplicationController
|
|||
# rubocop disabled because of a false positive
|
||||
flash[:info] = t(".author.info", author: @author) # rubocop:disable Rails/ActionControllerFlashBeforeRender
|
||||
redirect_to inbox_path(last_id: params[:last_id])
|
||||
return
|
||||
end
|
||||
|
||||
@delete_id = find_delete_id
|
||||
|
||||
@disabled = true if @inbox.empty?
|
||||
services = current_user.services.to_a
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.html { render "show", locals: { services: } }
|
||||
format.turbo_stream do
|
||||
render "show", layout: false, status: :see_other
|
||||
render "show", locals: { services: }, layout: false, status: :see_other
|
||||
|
||||
# rubocop disabled as just flipping a flag doesn't need to have validations to be run
|
||||
@inbox.update_all(new: false) # rubocop:disable Rails/SkipsModelValidations
|
||||
|
@ -34,10 +38,11 @@ class InboxController < ApplicationController
|
|||
user: current_user)
|
||||
|
||||
inbox = Inbox.create!(user: current_user, question_id: question.id, new: true)
|
||||
services = current_user.services
|
||||
|
||||
respond_to do |format|
|
||||
format.turbo_stream do
|
||||
render turbo_stream: turbo_stream.prepend("entries", partial: "inbox/entry", locals: { i: inbox })
|
||||
render turbo_stream: turbo_stream.prepend("entries", partial: "inbox/entry", locals: { i: inbox, services: })
|
||||
|
||||
inbox.update(new: false)
|
||||
end
|
||||
|
@ -77,4 +82,9 @@ class InboxController < ApplicationController
|
|||
.joins(:question)
|
||||
.where(questions: { user: @author_user, author_is_anonymous: false })
|
||||
end
|
||||
|
||||
def mark_inbox_entries_as_read
|
||||
# using .dup to not modify @inbox -- useful in tests
|
||||
@inbox&.dup&.update_all(new: false) # rubocop:disable Rails/SkipsModelValidations
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,13 @@
|
|||
class ManifestsController < ApplicationController
|
||||
include ThemeHelper
|
||||
|
||||
skip_before_action :banned?
|
||||
skip_before_action :find_active_announcements
|
||||
|
||||
def show
|
||||
expires_in 1.day
|
||||
return if fresh_when current_user&.theme
|
||||
|
||||
render json: {
|
||||
name: APP_CONFIG["site_name"],
|
||||
description: t("about.index.subtitle"),
|
||||
|
@ -12,17 +18,19 @@ class ManifestsController < ApplicationController
|
|||
display: "standalone",
|
||||
categories: %w[social],
|
||||
lang: I18n.locale,
|
||||
shortcuts: [
|
||||
webapp_shortcut(inbox_url, t("navigation.inbox"), "inbox")
|
||||
],
|
||||
shortcuts:,
|
||||
icons: webapp_icons,
|
||||
theme_color: theme_color,
|
||||
theme_color:,
|
||||
background_color: mobile_theme_color
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def shortcuts = [
|
||||
webapp_shortcut(inbox_url, t("navigation.inbox"), "inbox")
|
||||
]
|
||||
|
||||
def webapp_shortcut(url, name, icon_name)
|
||||
{
|
||||
name: name,
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
class NotificationsController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
|
||||
after_action :mark_notifications_as_read, only: %i[index]
|
||||
|
||||
TYPE_MAPPINGS = {
|
||||
"answer" => Notification::QuestionAnswered.name,
|
||||
"comment" => Notification::Commented.name,
|
||||
|
@ -14,8 +16,8 @@ class NotificationsController < ApplicationController
|
|||
def index
|
||||
@type = TYPE_MAPPINGS[params[:type]] || params[:type]
|
||||
@notifications = cursored_notifications_for(type: @type, last_id: params[:last_id])
|
||||
@notifications_last_id = @notifications.map(&:id).min
|
||||
@more_data_available = !cursored_notifications_for(type: @type, last_id: @notifications_last_id, size: 1).count.zero?
|
||||
paginate_notifications
|
||||
@counters = count_unread_by_type
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
@ -25,6 +27,22 @@ class NotificationsController < ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def paginate_notifications
|
||||
@notifications_last_id = @notifications.map(&:id).min
|
||||
@more_data_available = !cursored_notifications_for(type: @type, last_id: @notifications_last_id, size: 1).count.zero?
|
||||
end
|
||||
|
||||
def count_unread_by_type
|
||||
Notification.where(recipient: current_user, new: true)
|
||||
.group(:target_type)
|
||||
.count(:target_type)
|
||||
end
|
||||
|
||||
def mark_notifications_as_read
|
||||
# using .dup to not modify @notifications -- useful in tests
|
||||
@notifications&.dup&.update_all(new: false) # rubocop:disable Rails/SkipsModelValidations
|
||||
end
|
||||
|
||||
def cursored_notifications_for(type:, last_id:, size: nil)
|
||||
cursor_params = { last_id: last_id, size: size }.compact
|
||||
|
||||
|
|
|
@ -8,22 +8,8 @@ class Settings::ThemeController < ApplicationController
|
|||
def edit; end
|
||||
|
||||
def update
|
||||
update_attributes = params.require(:theme).permit(%i[
|
||||
primary_color primary_text
|
||||
danger_color danger_text
|
||||
success_color success_text
|
||||
warning_color warning_text
|
||||
info_color info_text
|
||||
dark_color dark_text
|
||||
light_color light_text
|
||||
raised_background raised_accent
|
||||
background_color body_text
|
||||
muted_text input_color
|
||||
input_text input_placeholder
|
||||
])
|
||||
|
||||
if current_user.theme.nil?
|
||||
current_user.theme = Theme.new update_attributes
|
||||
current_user.theme = Theme.new theme_attributes
|
||||
current_user.theme.user_id = current_user.id
|
||||
|
||||
if current_user.theme.save
|
||||
|
@ -31,7 +17,7 @@ class Settings::ThemeController < ApplicationController
|
|||
else
|
||||
flash[:error] = t(".error", errors: current_user.theme.errors.messages.flatten.join(" "))
|
||||
end
|
||||
elsif current_user.theme.update(update_attributes)
|
||||
elsif current_user.theme.update(theme_attributes)
|
||||
flash[:success] = t(".success")
|
||||
else
|
||||
flash[:error] = t(".error", errors: current_user.theme.errors.messages.flatten.join(" "))
|
||||
|
@ -43,4 +29,23 @@ class Settings::ThemeController < ApplicationController
|
|||
current_user.theme.destroy!
|
||||
redirect_to edit_settings_theme_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def theme_attributes
|
||||
params.require(:theme).permit(%i[
|
||||
primary_color primary_text
|
||||
danger_color danger_text
|
||||
success_color success_text
|
||||
warning_color warning_text
|
||||
info_color info_text
|
||||
dark_color dark_text
|
||||
light_color light_text
|
||||
raised_background raised_accent
|
||||
raised_text raised_accent_text
|
||||
background_color body_text
|
||||
muted_text input_color
|
||||
input_text input_placeholder
|
||||
])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,20 +3,13 @@
|
|||
class UserController < ApplicationController
|
||||
before_action :set_user
|
||||
before_action :hidden_social_graph_redirect, only: %i[followers followings]
|
||||
after_action :mark_notification_as_read, only: %i[show]
|
||||
|
||||
def show
|
||||
@answers = @user.cursored_answers(last_id: params[:last_id])
|
||||
@answers_last_id = @answers.map(&:id).min
|
||||
@more_data_available = !@user.cursored_answers(last_id: @answers_last_id, size: 1).count.zero?
|
||||
|
||||
if user_signed_in?
|
||||
notif = Notification.where(target_type: "Relationship", target_id: @user.active_follow_relationships.where(target_id: current_user.id).pluck(:id), recipient_id: current_user.id, new: true).first
|
||||
unless notif.nil?
|
||||
notif.new = false
|
||||
notif.save
|
||||
end
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.turbo_stream
|
||||
|
@ -24,36 +17,40 @@ class UserController < ApplicationController
|
|||
end
|
||||
|
||||
def followers
|
||||
@title = "Followers"
|
||||
@relationships = @user.cursored_follower_relationships(last_id: params[:last_id])
|
||||
@relationships_last_id = @relationships.map(&:id).min
|
||||
@more_data_available = !@user.cursored_follower_relationships(last_id: @relationships_last_id, size: 1).count.zero?
|
||||
paginate_relationships(:cursored_follower_relationships)
|
||||
@users = @relationships.map(&:source)
|
||||
@type = :follower
|
||||
own_relationships = find_own_relationships
|
||||
locals = {
|
||||
type: :follower,
|
||||
own_followings: own_relationships[Relationships::Follow],
|
||||
own_blocks: own_relationships[Relationships::Block],
|
||||
own_mutes: own_relationships[Relationships::Mute]
|
||||
}
|
||||
|
||||
respond_to do |format|
|
||||
format.html { render "show_follow" }
|
||||
format.turbo_stream { render "show_follow" }
|
||||
format.html { render "show_follow", locals: }
|
||||
format.turbo_stream { render "show_follow", locals: }
|
||||
end
|
||||
end
|
||||
|
||||
def followings
|
||||
@title = "Following"
|
||||
@relationships = @user.cursored_following_relationships(last_id: params[:last_id])
|
||||
@relationships_last_id = @relationships.map(&:id).min
|
||||
@more_data_available = !@user.cursored_following_relationships(last_id: @relationships_last_id, size: 1).count.zero?
|
||||
paginate_relationships(:cursored_following_relationships)
|
||||
@users = @relationships.map(&:target)
|
||||
@type = :friend
|
||||
own_relationships = find_own_relationships
|
||||
locals = {
|
||||
type: :friend,
|
||||
own_followings: own_relationships[Relationships::Follow],
|
||||
own_blocks: own_relationships[Relationships::Block],
|
||||
own_mutes: own_relationships[Relationships::Mute]
|
||||
}
|
||||
|
||||
respond_to do |format|
|
||||
format.html { render "show_follow" }
|
||||
format.turbo_stream { render "show_follow" }
|
||||
format.html { render "show_follow", locals: }
|
||||
format.turbo_stream { render "show_follow", locals: }
|
||||
end
|
||||
end
|
||||
|
||||
def questions
|
||||
@title = "Questions"
|
||||
|
||||
@questions = @user.cursored_questions(author_is_anonymous: false, direct: direct_param, last_id: params[:last_id])
|
||||
@questions_last_id = @questions.map(&:id).min
|
||||
@more_data_available = !@user.cursored_questions(author_is_anonymous: false, direct: direct_param, last_id: @questions_last_id, size: 1).count.zero?
|
||||
|
@ -66,10 +63,36 @@ class UserController < ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def mark_notification_as_read
|
||||
return unless user_signed_in?
|
||||
|
||||
Notification
|
||||
.where(
|
||||
target_type: "Relationship",
|
||||
target_id: @user.active_follow_relationships.where(target_id: current_user.id).pluck(:id),
|
||||
recipient_id: current_user.id,
|
||||
new: true
|
||||
).update(new: false)
|
||||
end
|
||||
|
||||
def set_user
|
||||
@user = User.where("LOWER(screen_name) = ?", params[:username].downcase).includes(:profile).first!
|
||||
end
|
||||
|
||||
def find_own_relationships
|
||||
return {} unless user_signed_in?
|
||||
|
||||
Relationship.where(source: current_user, target_id: @users.map(&:id))
|
||||
&.select(:target_id, :type)
|
||||
&.group_by(&:type)
|
||||
end
|
||||
|
||||
def paginate_relationships(method)
|
||||
@relationships = @user.public_send(method, last_id: params[:last_id])
|
||||
@relationships_last_id = @relationships.map(&:id).min
|
||||
@more_data_available = !@user.public_send(method, last_id: @relationships_last_id, size: 1).count.zero?
|
||||
end
|
||||
|
||||
def hidden_social_graph_redirect
|
||||
return if belongs_to_current_user? || !@user.privacy_hide_social_graph
|
||||
|
||||
|
|
|
@ -2,28 +2,30 @@
|
|||
|
||||
module ThemeHelper
|
||||
ATTRIBUTE_MAP = {
|
||||
"primary_color" => %w[primary primary-rgb],
|
||||
"primary_text" => "primary-text",
|
||||
"danger_color" => "danger",
|
||||
"danger_text" => "danger-text",
|
||||
"warning_color" => "warning",
|
||||
"warning_text" => "warning-text",
|
||||
"info_color" => "info",
|
||||
"info_text" => "info-text",
|
||||
"success_color" => "success",
|
||||
"success_text" => "success-text",
|
||||
"dark_color" => "dark",
|
||||
"dark_text" => "dark-text",
|
||||
"light_color" => "light",
|
||||
"light_text" => "light-text",
|
||||
"raised_background" => %w[raised-bg raised-bg-rgb],
|
||||
"raised_accent" => %w[raised-accent raised-accent-rgb],
|
||||
"background_color" => "background",
|
||||
"body_text" => "body-text",
|
||||
"input_color" => "input-bg",
|
||||
"input_text" => "input-text",
|
||||
"input_placeholder" => "input-placeholder",
|
||||
"muted_text" => "muted-text"
|
||||
"primary_color" => %w[primary primary-rgb],
|
||||
"primary_text" => "primary-text",
|
||||
"danger_color" => "danger",
|
||||
"danger_text" => "danger-text",
|
||||
"warning_color" => "warning",
|
||||
"warning_text" => "warning-text",
|
||||
"info_color" => "info",
|
||||
"info_text" => "info-text",
|
||||
"success_color" => "success",
|
||||
"success_text" => "success-text",
|
||||
"dark_color" => "dark",
|
||||
"dark_text" => "dark-text",
|
||||
"light_color" => "light",
|
||||
"light_text" => "light-text",
|
||||
"raised_background" => %w[raised-bg raised-bg-rgb],
|
||||
"raised_text" => "raised-text",
|
||||
"raised_accent" => %w[raised-accent raised-accent-rgb],
|
||||
"raised_accent_text" => "raised-accent-text",
|
||||
"background_color" => "background",
|
||||
"body_text" => "body-text",
|
||||
"input_color" => "input-bg",
|
||||
"input_text" => "input-text",
|
||||
"input_placeholder" => "input-placeholder",
|
||||
"muted_text" => "muted-text"
|
||||
}.freeze
|
||||
|
||||
def render_theme
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import { Controller } from '@hotwired/stimulus';
|
||||
import Croppr from 'croppr';
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ['input', 'controls', 'cropper', 'x', 'y', 'w', 'h'];
|
||||
|
||||
declare readonly inputTarget: HTMLInputElement;
|
||||
declare readonly controlsTarget: HTMLElement;
|
||||
declare readonly cropperTarget: HTMLImageElement;
|
||||
declare readonly xTarget: HTMLInputElement;
|
||||
declare readonly yTarget: HTMLInputElement;
|
||||
declare readonly wTarget: HTMLInputElement;
|
||||
declare readonly hTarget: HTMLInputElement;
|
||||
|
||||
static values = {
|
||||
aspectRatio: String
|
||||
};
|
||||
|
||||
declare readonly aspectRatioValue: string;
|
||||
|
||||
readImage(file: File, callback: (string) => void): void {
|
||||
callback((window.URL || window.webkitURL).createObjectURL(file));
|
||||
}
|
||||
|
||||
updateValues(data: Record<string, string>): void {
|
||||
this.xTarget.value = data.x;
|
||||
this.yTarget.value = data.y;
|
||||
this.wTarget.value = data.width;
|
||||
this.hTarget.value = data.height;
|
||||
}
|
||||
|
||||
change(): void {
|
||||
this.controlsTarget.classList.toggle('d-none');
|
||||
|
||||
if (this.inputTarget.files && this.inputTarget.files[0]) {
|
||||
this.readImage(this.inputTarget.files[0], (src) => {
|
||||
this.cropperTarget.src = src;
|
||||
|
||||
new Croppr(this.cropperTarget, {
|
||||
aspectRatio: parseFloat(this.aspectRatioValue),
|
||||
startSize: [100, 100, '%'],
|
||||
onCropStart: this.updateValues.bind(this),
|
||||
onCropMove: this.updateValues.bind(this),
|
||||
onCropEnd: this.updateValues.bind(this)
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
export function authorSearchHandler(event: Event): void {
|
||||
event.preventDefault();
|
||||
|
||||
const author = document.querySelector<HTMLInputElement>('#author')?.value;
|
||||
window.location.href = `/inbox/${encodeURIComponent(author)}`;
|
||||
}
|
|
@ -62,6 +62,7 @@ export function deleteAllQuestionsHandler(event: Event): void {
|
|||
export function deleteAllAuthorQuestionsHandler(event: Event): void {
|
||||
const button = event.target as Element;
|
||||
const count = button.getAttribute('data-ib-count');
|
||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||
|
||||
swal({
|
||||
title: I18n.translate('frontend.inbox.confirm_all.title', { count: count }),
|
||||
|
@ -75,7 +76,7 @@ export function deleteAllAuthorQuestionsHandler(event: Event): void {
|
|||
}, (returnValue) => {
|
||||
if (returnValue === null) return false;
|
||||
|
||||
post(`/ajax/delete_all_inbox/${location.pathname.split('/')[2]}`)
|
||||
post(`/ajax/delete_all_inbox/${urlSearchParams.get('author')}`)
|
||||
.then(async response => {
|
||||
const data = await response.json;
|
||||
|
||||
|
@ -89,4 +90,4 @@ export function deleteAllAuthorQuestionsHandler(event: Event): void {
|
|||
showErrorNotification(I18n.translate('frontend.error.message'));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,7 @@ import { deleteAllAuthorQuestionsHandler, deleteAllQuestionsHandler } from './de
|
|||
export default (): void => {
|
||||
registerEvents([
|
||||
{ type: 'click', target: '#ib-delete-all', handler: deleteAllQuestionsHandler, global: true },
|
||||
{ type: 'click', target: '#ib-delete-all-author', handler: deleteAllAuthorQuestionsHandler, global: true },
|
||||
{ type: 'submit', target: '#author-form', handler: authorSearchHandler, global: true }
|
||||
{ type: 'click', target: '#ib-delete-all-author', handler: deleteAllAuthorQuestionsHandler, global: true }
|
||||
]);
|
||||
|
||||
registerInboxEntryEvents();
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
import Croppr from 'croppr';
|
||||
|
||||
const readImage = (file, callback) => callback((window.URL || window.webkitURL).createObjectURL(file));
|
||||
|
||||
export function profilePictureChangeHandler(event: Event): void {
|
||||
const input = event.target as HTMLInputElement;
|
||||
|
||||
const cropControls = document.querySelector('#profile-picture-crop-controls');
|
||||
cropControls.classList.toggle('d-none');
|
||||
|
||||
if (input.files && input.files[0]) {
|
||||
readImage(input.files[0], (src) => {
|
||||
const updateValues = (data) => {
|
||||
document.querySelector<HTMLInputElement>('#profile_picture_x').value = data.x;
|
||||
document.querySelector<HTMLInputElement>('#profile_picture_y').value = data.y;
|
||||
document.querySelector<HTMLInputElement>('#profile_picture_w').value = data.width;
|
||||
document.querySelector<HTMLInputElement>('#profile_picture_h').value = data.height;
|
||||
}
|
||||
|
||||
const cropper = document.querySelector<HTMLImageElement>('#profile-picture-cropper');
|
||||
cropper.src = src;
|
||||
|
||||
new Croppr(cropper, {
|
||||
aspectRatio: 1,
|
||||
startSize: [100, 100, '%'],
|
||||
onCropStart: updateValues,
|
||||
onCropMove: updateValues,
|
||||
onCropEnd: updateValues
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function profileHeaderChangeHandler(event: Event): void {
|
||||
const input = event.target as HTMLInputElement;
|
||||
|
||||
const cropControls = document.querySelector('#profile-header-crop-controls');
|
||||
cropControls.classList.toggle('d-none');
|
||||
|
||||
if (input.files && input.files[0]) {
|
||||
readImage(input.files[0], (src) => {
|
||||
const updateValues = (data) => {
|
||||
document.querySelector<HTMLInputElement>('#profile_header_x').value = data.x;
|
||||
document.querySelector<HTMLInputElement>('#profile_header_y').value = data.y;
|
||||
document.querySelector<HTMLInputElement>('#profile_header_w').value = data.width;
|
||||
document.querySelector<HTMLInputElement>('#profile_header_h').value = data.height;
|
||||
}
|
||||
|
||||
const cropper = document.querySelector<HTMLImageElement>('#profile-header-cropper');
|
||||
cropper.src = src;
|
||||
|
||||
new Croppr(cropper, {
|
||||
aspectRatio: 7/30,
|
||||
startSize: [100, 100, '%'],
|
||||
onCropStart: updateValues,
|
||||
onCropMove: updateValues,
|
||||
onCropEnd: updateValues
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,11 +1,8 @@
|
|||
import registerEvents from "utilities/registerEvents";
|
||||
import { profileHeaderChangeHandler, profilePictureChangeHandler } from "./crop";
|
||||
import { userSubmitHandler } from "./password";
|
||||
|
||||
export default (): void => {
|
||||
registerEvents([
|
||||
{ type: 'submit', target: document.querySelector('#edit_user'), handler: userSubmitHandler },
|
||||
{ type: 'change', target: document.querySelector('#user_profile_picture[type=file]'), handler: profilePictureChangeHandler },
|
||||
{ type: 'change', target: document.querySelector('#user_profile_header[type=file]'), handler: profileHeaderChangeHandler }
|
||||
{ type: 'submit', target: document.querySelector('#edit_user'), handler: userSubmitHandler }
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import FormatPopupController from "retrospring/controllers/format_popup_controll
|
|||
import CollapseController from "retrospring/controllers/collapse_controller";
|
||||
import ThemeController from "retrospring/controllers/theme_controller";
|
||||
import CapabilitiesController from "retrospring/controllers/capabilities_controller";
|
||||
import CropperController from "retrospring/controllers/cropper_controller";
|
||||
|
||||
/**
|
||||
* This module sets up Stimulus and our controllers
|
||||
|
@ -23,6 +24,7 @@ export default function (): void {
|
|||
window['Stimulus'].register('character-count', CharacterCountController);
|
||||
window['Stimulus'].register('character-count-warning', CharacterCountWarningController);
|
||||
window['Stimulus'].register('collapse', CollapseController);
|
||||
window['Stimulus'].register('cropper', CropperController);
|
||||
window['Stimulus'].register('format-popup', FormatPopupController);
|
||||
window['Stimulus'].register('theme', ThemeController);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,9 @@ export const THEME_MAPPING = {
|
|||
'light_color': 'light',
|
||||
'light_text': 'light-text',
|
||||
'raised_background': 'raised-bg',
|
||||
'raised_text': 'raised-text',
|
||||
'raised_accent': 'raised-accent',
|
||||
'raised_accent_text': 'raised-accent-text',
|
||||
'background_color': 'background',
|
||||
'body_text': 'body-text',
|
||||
'input_color': 'input-bg',
|
||||
|
|
|
@ -11,11 +11,11 @@ class Notification < ApplicationRecord
|
|||
define_cursor_paginator :cursored_for_type, :for_type
|
||||
|
||||
def for(recipient, **kwargs)
|
||||
where(kwargs.merge!(recipient:)).order(:created_at).reverse_order
|
||||
where(kwargs.merge!(recipient:)).includes(:target).order(:created_at).reverse_order
|
||||
end
|
||||
|
||||
def for_type(recipient, type, **kwargs)
|
||||
where(kwargs.merge!(recipient:)).where(type:).order(:created_at).reverse_order
|
||||
where(kwargs.merge!(recipient:)).includes(:target).where(type:).order(:created_at).reverse_order
|
||||
end
|
||||
|
||||
def notify(recipient, target)
|
||||
|
|
|
@ -5,10 +5,11 @@ module User::AnswerMethods
|
|||
|
||||
define_cursor_paginator :cursored_answers, :ordered_answers
|
||||
|
||||
# @return [ActiveRecord::Relation<Answer>] List of a user's answers
|
||||
def ordered_answers
|
||||
answers
|
||||
.order(:created_at)
|
||||
.reverse_order
|
||||
.includes(comments: [:user, :smiles], question: [:user], smiles: [:user])
|
||||
.includes(comments: %i[user smiles], question: { user: :profile }, smiles: [:user])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,9 +5,10 @@ module User::InboxMethods
|
|||
|
||||
define_cursor_paginator :cursored_inbox, :ordered_inbox
|
||||
|
||||
# @return [ActiveRecord::Relation<Inbox>] the user's inbox entries
|
||||
def ordered_inbox
|
||||
inboxes
|
||||
.includes(:question, :user)
|
||||
.includes(:question, user: :profile)
|
||||
.order(:created_at)
|
||||
.reverse_order
|
||||
end
|
||||
|
|
|
@ -5,6 +5,7 @@ module User::QuestionMethods
|
|||
|
||||
define_cursor_paginator :cursored_questions, :ordered_questions
|
||||
|
||||
# @return [ActiveRecord::Relation<Question>] List of questions sent by the user
|
||||
def ordered_questions(author_is_anonymous: nil, direct: nil)
|
||||
questions
|
||||
.where({ author_is_anonymous:, direct: }.compact)
|
||||
|
|
|
@ -6,10 +6,12 @@ module User::RelationshipMethods
|
|||
define_cursor_paginator :cursored_following_relationships, :ordered_following_relationships
|
||||
define_cursor_paginator :cursored_follower_relationships, :ordered_follower_relationships
|
||||
|
||||
# @return [ActiveRecord::Relation<Relationships::Follow>] List of the user's following relationships
|
||||
def ordered_following_relationships
|
||||
active_follow_relationships.reverse_order.includes(target: [:profile])
|
||||
end
|
||||
|
||||
# @return [ActiveRecord::Relation<Relationships::Follow>] List of the user's follower relationships
|
||||
def ordered_follower_relationships
|
||||
passive_follow_relationships.reverse_order.includes(source: [:profile])
|
||||
end
|
||||
|
|
|
@ -5,8 +5,12 @@ module User::TimelineMethods
|
|||
|
||||
define_cursor_paginator :cursored_timeline, :timeline
|
||||
|
||||
# @return [Array] the users' timeline
|
||||
# @return [ActiveRecord::Relation<Answer>] the user's timeline
|
||||
def timeline
|
||||
Answer.where("user_id in (?) OR user_id = ?", following_ids, id).order(:created_at).reverse_order.includes(comments: %i[user smiles], question: [:user], user: [:profile], smiles: [:user])
|
||||
Answer
|
||||
.where("user_id in (?) OR user_id = ?", following_ids, id)
|
||||
.order(:created_at)
|
||||
.reverse_order
|
||||
.includes(comments: %i[user smiles], question: { user: :profile }, user: [:profile], smiles: [:user])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,6 +7,7 @@ class TypoedEmailValidator < ActiveModel::EachValidator
|
|||
INVALID_ENDINGS = [
|
||||
# with @:
|
||||
*%w[
|
||||
aoo.com
|
||||
fmail.com
|
||||
gail.com
|
||||
gamil.com
|
||||
|
@ -19,6 +20,7 @@ class TypoedEmailValidator < ActiveModel::EachValidator
|
|||
gmaile.com
|
||||
gmaill.com
|
||||
gmali.com
|
||||
gmaul.com
|
||||
gnail.com
|
||||
hotamil.com
|
||||
hotmai.com
|
||||
|
|
|
@ -40,9 +40,9 @@
|
|||
= render "shared/format_link"
|
||||
.card-footer.d-none{ id: "ib-options-#{i.id}" }
|
||||
%h4= t(".sharing.heading")
|
||||
- if current_user.services.count.positive?
|
||||
- if services.count.positive?
|
||||
.row
|
||||
- current_user.services.each do |service|
|
||||
- services.each do |service|
|
||||
.col-md-3.col-sm-4.col-xs-6
|
||||
%label
|
||||
%input{ type: "checkbox", name: "ib-share", checked: :checked, data: { ib_id: i.id, service: service.provider } }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#entries
|
||||
- @inbox.each do |i|
|
||||
= render "inbox/entry", i:
|
||||
= render "inbox/entry", services:, i:
|
||||
|
||||
- if @inbox.empty?
|
||||
%p.empty= t(".empty")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
= turbo_stream.append "entries" do
|
||||
- @inbox.each do |i|
|
||||
= render "inbox/entry", i:
|
||||
= render "inbox/entry", services:, i:
|
||||
|
||||
= turbo_stream.update "paginator" do
|
||||
- if @more_data_available
|
||||
|
|
|
@ -9,6 +9,5 @@
|
|||
= render 'shared/links'
|
||||
|
||||
:ruby
|
||||
@inbox.update_all(new: false)
|
||||
provide(:title, generate_title('Inbox'))
|
||||
parent_layout 'base'
|
||||
|
|
|
@ -8,5 +8,4 @@
|
|||
.d-block.d-sm-none= render "shared/links"
|
||||
|
||||
:ruby
|
||||
Notification.for(current_user).update_all(new: false)
|
||||
parent_layout 'base'
|
||||
|
|
|
@ -2,36 +2,38 @@
|
|||
.card-body
|
||||
= bootstrap_form_for(current_user, url: settings_profile_picture_path, html: { multipart: true }, method: :patch, data: { turbo: false }) do |f|
|
||||
|
||||
.d-flex#profile-picture-media
|
||||
.flex-shrink-0
|
||||
%img.avatar-lg.me-3{ src: current_user.profile_picture.url(:medium) }
|
||||
.flex-grow-1
|
||||
= f.file_field :profile_picture, accept: APP_CONFIG[:accepted_image_formats].join(",")
|
||||
%div{ data: { controller: "cropper", cropper_aspect_ratio_value: "1" } }
|
||||
.d-flex
|
||||
.flex-shrink-0
|
||||
%img.avatar-lg.me-3{ src: current_user.profile_picture.url(:medium) }
|
||||
.flex-grow-1
|
||||
= f.file_field :profile_picture, accept: APP_CONFIG[:accepted_image_formats].join(","), data: { cropper_target: "input", action: "cropper#change" }
|
||||
|
||||
.row.d-none#profile-picture-crop-controls
|
||||
.col-sm-10.col-md-8
|
||||
%strong= t(".adjust.profile_picture")
|
||||
%img#profile-picture-cropper{ src: current_user.profile_picture.url(:medium) }
|
||||
.row.d-none{ data: { cropper_target: "controls" } }
|
||||
.col-sm-10.col-md-8
|
||||
%strong= t(".adjust.profile_picture")
|
||||
%img{ src: current_user.profile_picture.url(:medium), data: { cropper_target: "cropper" } }
|
||||
|
||||
.row.mb-2#profile-header-media
|
||||
.col-xs-12.col-md-6
|
||||
%img.mw-100.me-3{ src: current_user.profile_header.url(:mobile) }
|
||||
.col-xs-12.col-md-6.mt-3.mt-sm-0.ps-3.pe-3
|
||||
= f.file_field :profile_header, accept: APP_CONFIG[:accepted_image_formats].join(",")
|
||||
- %i[profile_picture_x profile_picture_y profile_picture_w profile_picture_h].each do |attrib|
|
||||
= f.hidden_field attrib, id: attrib, data: { cropper_target: attrib.to_s.split("_").last }
|
||||
|
||||
.row.d-none#profile-header-crop-controls
|
||||
.col-sm-10.col-md-8
|
||||
%strong= t(".adjust.profile_header")
|
||||
%img#profile-header-cropper{ src: current_user.profile_header.url(:web) }
|
||||
%div{ data: { controller: "cropper", cropper_aspect_ratio_value: "0.23" } }
|
||||
.row.mb-2
|
||||
.col-xs-12.col-md-6
|
||||
%img.mw-100.me-3{ src: current_user.profile_header.url(:mobile) }
|
||||
.col-xs-12.col-md-6.mt-3.mt-sm-0.ps-3.pe-3
|
||||
= f.file_field :profile_header, accept: APP_CONFIG[:accepted_image_formats].join(","), data: { cropper_target: "input", action: "cropper#change" }
|
||||
|
||||
.row.d-none{ data: { cropper_target: "controls" } }
|
||||
.col-sm-10.col-md-8
|
||||
%strong= t(".adjust.profile_header")
|
||||
%img{ src: current_user.profile_header.url(:web), data: { cropper_target: "cropper" } }
|
||||
|
||||
- %i[profile_header_x profile_header_y profile_header_w profile_header_h].each do |attrib|
|
||||
= f.hidden_field attrib, id: attrib, data: { cropper_target: attrib.to_s.split("_").last }
|
||||
|
||||
= f.check_box :show_foreign_themes
|
||||
|
||||
- %i[profile_picture_x profile_picture_y profile_picture_w profile_picture_h].each do |attrib|
|
||||
= f.hidden_field attrib, id: attrib
|
||||
|
||||
- %i[profile_header_x profile_header_y profile_header_w profile_header_h].each do |attrib|
|
||||
= f.hidden_field attrib, id: attrib
|
||||
|
||||
= f.primary t(".submit_picture")
|
||||
.card
|
||||
.card-body
|
||||
|
|
|
@ -21,6 +21,23 @@
|
|||
= f.text_field :background_color, class: "color", data: { default: 0xF0EDF4, theme_target: "color", action: "theme#updatePreview" }
|
||||
.col-sm-6
|
||||
= f.text_field :body_text, class: "color", data: { default: 0x000000, theme_target: "color", action: "theme#updatePreview" }
|
||||
.card
|
||||
.card-body
|
||||
%h2= t(".raised.heading")
|
||||
%p= t(".raised.body")
|
||||
|
||||
.row
|
||||
.col-sm-6
|
||||
= f.text_field :raised_background, class: "color", data: { default: 0xFFFFFF, theme_target: "color", action: "theme#updatePreview" }
|
||||
.col-sm-6
|
||||
= f.text_field :raised_text, class: "color", data: { default: 0x000000, theme_target: "color", action: "theme#updatePreview" }
|
||||
.row
|
||||
.col-sm-6
|
||||
= f.text_field :raised_accent, class: "color", data: { default: 0xF7F7F7, theme_target: "color", action: "theme#updatePreview" }
|
||||
.col-sm-6
|
||||
= f.text_field :raised_accent_text, class: "color", data: { default: 0x000000, theme_target: "color", action: "theme#updatePreview" }
|
||||
.card-footer
|
||||
%p= t(".raised.accent.example")
|
||||
.card
|
||||
.card-body
|
||||
%h2= t(".colors.heading")
|
||||
|
@ -93,23 +110,11 @@
|
|||
|
||||
.row
|
||||
.col-sm-6
|
||||
= f.text_field :input_placeholder, class: "color", data: { default: 0x6C757D, theme_target: "color" }
|
||||
= f.text_field :input_placeholder, class: "color", data: { default: 0x6C757D, theme_target: "color", action: "theme#updatePreview" }
|
||||
.col-sm-6
|
||||
.form-group
|
||||
%label.form-label Example Input
|
||||
%input.form-control{ placeholder: "A test placeholder" }
|
||||
.card
|
||||
.card-body
|
||||
%h2= t(".raised.heading")
|
||||
%p= t(".raised.body")
|
||||
|
||||
.row
|
||||
.col-sm-6
|
||||
= f.text_field :raised_background, class: "color", data: { default: 0xFFFFFF, theme_target: "color" }
|
||||
.col-sm-6
|
||||
= f.text_field :raised_accent, class: "color", data: { default: 0xF7F7F7, theme_target: "color" }
|
||||
.card-footer
|
||||
%p= t(".raised.accent.example")
|
||||
.card
|
||||
.card-body
|
||||
.pull-left
|
||||
|
|
|
@ -9,4 +9,4 @@
|
|||
= user.profile.display_name
|
||||
.profile__screen-name
|
||||
= user.screen_name
|
||||
= render 'user/actions', user: user, type: type
|
||||
= render "user/actions", user:, type:, own_followings:, own_blocks:, own_mutes:
|
||||
|
|
|
@ -9,18 +9,18 @@
|
|||
.list-group
|
||||
= list_group_item t('.answer'),
|
||||
notifications_path('answer'),
|
||||
badge: Notification.for(current_user).where(target_type: 'Answer', new: true).count
|
||||
badge: @counters['Answer']
|
||||
= list_group_item t('.smile'),
|
||||
notifications_path('smile'),
|
||||
badge: Notification.for(current_user).where(target_type: 'Smile', new: true).count
|
||||
badge: @counters['Smile']
|
||||
= list_group_item t('.comment'),
|
||||
notifications_path('comment'),
|
||||
badge: Notification.for(current_user).where(target_type: 'Comment', new: true).count
|
||||
badge: @counters['Comment']
|
||||
= list_group_item t('.commentsmile'),
|
||||
notifications_path('commentsmile'),
|
||||
badge: Notification.for(current_user).where(target_type: 'CommentSmile', new: true).count
|
||||
badge: @counters['CommentSmile']
|
||||
= list_group_item t('.relationship'),
|
||||
notifications_path('relationship'),
|
||||
badge: Notification.for(current_user).where(target_type: 'Relationship', new: true).count
|
||||
badge: @counters['Relationship']
|
||||
|
||||
.d-none.d-sm-block= render 'shared/links'
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
.profile__actions
|
||||
- type ||= :nil
|
||||
- own_followings ||= nil
|
||||
- own_blocks ||= nil
|
||||
- own_mutes ||= nil
|
||||
- if user_signed_in? && user == current_user
|
||||
.d-grid
|
||||
%a.btn.btn-dark{ href: settings_profile_path } Edit profile
|
||||
- elsif user_signed_in?
|
||||
.d-grid.gap-2
|
||||
- if current_user.following? user
|
||||
- if own_followings&.include?(user.id) || current_user.following?(user)
|
||||
%button.btn.btn-primary{ type: :button, name: 'user-action', data: { action: :unfollow, type: type, target: user.screen_name } }
|
||||
= t("voc.unfollow")
|
||||
- else
|
||||
|
@ -19,7 +22,7 @@
|
|||
%a.dropdown-item.d-block.d-sm-none{ href: '#', data: { bs_target: '#modal-list-memberships', bs_toggle: :modal } }
|
||||
%i.fa.fa-list.fa-fw
|
||||
= t(".list")
|
||||
- if current_user.blocking?(user)
|
||||
- if own_blocks&.include?(user.id) || current_user.blocking?(user)
|
||||
%a.dropdown-item{ href: '#', data: { action: :unblock, target: user.screen_name } }
|
||||
%i.fa.fa-minus-circle.fa-fw
|
||||
%span.pe-none= t("voc.unblock")
|
||||
|
@ -27,7 +30,7 @@
|
|||
%a.dropdown-item{ href: '#', data: { action: :block, target: user.screen_name } }
|
||||
%i.fa.fa-minus-circle.fa-fw
|
||||
%span.pe-none= t("voc.block")
|
||||
- if current_user.muting?(user)
|
||||
- if own_mutes&.include?(user.id) || current_user.muting?(user)
|
||||
%a.dropdown-item{ href: '#', data: { action: :unmute, target: user.screen_name } }
|
||||
%i.fa.fa-volume-off.fa-fw
|
||||
%span.pe-none= t("voc.unmute")
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
.row.row-cols-1.row-cols-sm-2.row-cols-md-3#users
|
||||
- @users.each do |user|
|
||||
.col.pb-3
|
||||
= render 'shared/userbox', user: user, type: @type
|
||||
= render "shared/userbox", user:, type:, own_followings:, own_blocks:, own_mutes:
|
||||
|
||||
- if @more_data_available
|
||||
.d-flex.justify-content-center.justify-content-sm-start#paginator
|
||||
= button_to t("voc.load"), @type == :follower ? show_user_followers_path(@user) : show_user_followings_path(@user),
|
||||
= button_to t("voc.load"), type == :follower ? show_user_followers_path(@user) : show_user_followings_path(@user),
|
||||
class: "btn btn-light",
|
||||
method: :get,
|
||||
params: { last_id: @relationships_last_id },
|
||||
form: { data: { turbo_stream: true } }
|
||||
|
||||
- provide(:title, user_title(@user, 'friends and followers'))
|
||||
- parent_layout 'user/profile'
|
||||
- provide(:title, t(".title.#{type}", user: @user.profile.safe_name))
|
||||
- parent_layout "user/profile"
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
= turbo_stream.append "users" do
|
||||
- @users.each do |user|
|
||||
.col.pb-3
|
||||
= render 'shared/userbox', user: user, type: @type
|
||||
= render "shared/userbox", user:, type:, own_followings:, own_blocks:, own_mutes:
|
||||
|
||||
= turbo_stream.update "paginator" do
|
||||
- if @more_data_available
|
||||
= button_to t("voc.load"), @type == :follower ? show_user_followers_path(@user) : show_user_followings_path(@user),
|
||||
= button_to t("voc.load"), type == :follower ? show_user_followers_path(@user) : show_user_followings_path(@user),
|
||||
class: "btn btn-light",
|
||||
method: :get,
|
||||
params: { last_id: @relationships_last_id },
|
||||
|
|
|
@ -1 +1,6 @@
|
|||
QuestionGenerator.compile
|
||||
# frozen_string_literal: true
|
||||
|
||||
Rails.application.config.to_prepare do
|
||||
QuestionGenerator.question_base_path = File.expand_path("../questions", __dir__)
|
||||
QuestionGenerator.compile
|
||||
end
|
||||
|
|
|
@ -8,4 +8,20 @@ Sentry.init do |config|
|
|||
# of transactions for performance monitoring.
|
||||
# We recommend adjusting this value in production
|
||||
config.traces_sample_rate = 0.25
|
||||
|
||||
exception_fingerprints = {
|
||||
Excon::Error::ServiceUnavailable => 'external-service',
|
||||
Twitter::Error::InternalServerError => 'external-service',
|
||||
}
|
||||
config.before_send = lambda do |event, hint|
|
||||
# These are used for user-facing errors, not when something goes wrong
|
||||
next if hint[:exception].is_a?(Errors::Base)
|
||||
|
||||
exception_class = hint[:exception].class
|
||||
if exception_fingerprints.key?(exception_class)
|
||||
event.fingerprint = [exception_fingerprints[exception_class]]
|
||||
end
|
||||
|
||||
event
|
||||
end
|
||||
end
|
||||
|
|
|
@ -49,7 +49,9 @@ en:
|
|||
primary_color: "Primary colour"
|
||||
primary_text: "Primary text colour"
|
||||
raised_accent: "Raised accent colour"
|
||||
raised_accent_text: "Raised accent text colour"
|
||||
raised_background: "Raised background colour"
|
||||
raised_text: "Raised text colour"
|
||||
success_color: "Success colour"
|
||||
success_text: "Success text colour"
|
||||
warning_color: "Warning colour"
|
||||
|
|
|
@ -651,6 +651,10 @@ en:
|
|||
index:
|
||||
title: "Questions from %{author_identifier}"
|
||||
user:
|
||||
show_follow:
|
||||
title:
|
||||
follower: "%{user}'s followers"
|
||||
friend: "%{user}'s followings"
|
||||
actions:
|
||||
view_inbox: "View inbox"
|
||||
privilege: "Check %{user}'s privileges"
|
||||
|
|
|
@ -0,0 +1,311 @@
|
|||
Do:
|
||||
you:
|
||||
- recycle
|
||||
- have:
|
||||
- a:
|
||||
- nickname
|
||||
- any:
|
||||
- siblings
|
||||
- pets
|
||||
- like:
|
||||
- social networks
|
||||
- muffins
|
||||
- video games
|
||||
- the:
|
||||
- city:
|
||||
- or:
|
||||
- country
|
||||
- where you:
|
||||
- live
|
||||
- to:
|
||||
- travel
|
||||
- sing out loud when no one else is around
|
||||
- want:
|
||||
- old times back
|
||||
- to know more:
|
||||
about:
|
||||
- your:
|
||||
- future
|
||||
- relatives
|
||||
- history
|
||||
- new inventions
|
||||
- more:
|
||||
- money
|
||||
- friends
|
||||
- things than you need
|
||||
- think that:
|
||||
- late is better than never
|
||||
- prefer:
|
||||
to:
|
||||
- take baths or showers
|
||||
your:
|
||||
friends:
|
||||
like:
|
||||
- you:
|
||||
- the way you are
|
||||
- social networks
|
||||
- muffins
|
||||
- video games
|
||||
know:
|
||||
[much, too much]:
|
||||
about:
|
||||
- your:
|
||||
- life
|
||||
- hobbies
|
||||
- family
|
||||
- friends
|
||||
- you
|
||||
What:
|
||||
- was:
|
||||
the:
|
||||
best:
|
||||
- day of your life like
|
||||
last:
|
||||
song:
|
||||
- you listened on repeat
|
||||
thing:
|
||||
you:
|
||||
have:
|
||||
- bought
|
||||
- done
|
||||
- eaten
|
||||
your:
|
||||
favourite:
|
||||
song:
|
||||
- as a 5 year old
|
||||
- from a few weeks ago
|
||||
- would:
|
||||
you:
|
||||
do:
|
||||
if:
|
||||
you:
|
||||
had:
|
||||
- one million dollars
|
||||
- the ability to fly
|
||||
were:
|
||||
- a dragon
|
||||
woke up:
|
||||
with:
|
||||
- someone else next to you
|
||||
- some drawings in your face
|
||||
- do:
|
||||
you:
|
||||
do:
|
||||
- for fun
|
||||
- 'on':
|
||||
- the:
|
||||
- weekend
|
||||
like:
|
||||
more,:
|
||||
- dogs or cats
|
||||
- shower or bath
|
||||
- tea or coffee
|
||||
think:
|
||||
about:
|
||||
- the:
|
||||
- Internet
|
||||
- Bad Dragon
|
||||
- dragons
|
||||
- '"fact" accounts'
|
||||
- society
|
||||
- cats
|
||||
- surveillance
|
||||
- coyotes
|
||||
- raccoons
|
||||
- foxes
|
||||
- dogs
|
||||
- lizards
|
||||
- [activity, activities]:
|
||||
do:
|
||||
you:
|
||||
- enjoy the most
|
||||
- kind:
|
||||
of:
|
||||
animals:
|
||||
- do you have
|
||||
- habit:
|
||||
do:
|
||||
you:
|
||||
really:
|
||||
find:
|
||||
cute:
|
||||
- in a person
|
||||
- is:
|
||||
your:
|
||||
- first memory
|
||||
- dream job
|
||||
- favourite:
|
||||
- season
|
||||
- video game
|
||||
- board game
|
||||
- sports team
|
||||
- activity
|
||||
- beverage
|
||||
- Internet browser
|
||||
- piece of music
|
||||
- console
|
||||
- snack
|
||||
- food
|
||||
- animal
|
||||
- programming language:
|
||||
- ''
|
||||
- and why is it:
|
||||
- PHP
|
||||
- Rust
|
||||
- C++
|
||||
- Lisp
|
||||
- Pascal
|
||||
- Swift
|
||||
- Ruby
|
||||
- website:
|
||||
- ''
|
||||
- and why is it:
|
||||
- Reddit
|
||||
- Twitter
|
||||
- Facebook
|
||||
- YouTube
|
||||
the:
|
||||
[best, worst]:
|
||||
thing:
|
||||
- about:
|
||||
the:
|
||||
- Internet
|
||||
your:
|
||||
- favourite:
|
||||
- series
|
||||
- movie
|
||||
- book
|
||||
- country
|
||||
- hometown
|
||||
- one can do:
|
||||
- if:
|
||||
- "they're bored"
|
||||
- ever
|
||||
fast:
|
||||
food:
|
||||
- chain
|
||||
one:
|
||||
- thing you would like to become better at
|
||||
- was:
|
||||
the:
|
||||
last:
|
||||
thing:
|
||||
you:
|
||||
- did
|
||||
- ate
|
||||
- looked for
|
||||
[best, worst]:
|
||||
thing:
|
||||
- "you've eaten so far"
|
||||
- languages do you know
|
||||
- apps do you use daily
|
||||
- 'is heavier: a kilogram of steel, or a kilogram of feathers'
|
||||
Can:
|
||||
you:
|
||||
- swim
|
||||
- speak:
|
||||
- different:
|
||||
- languages
|
||||
- play:
|
||||
- any:
|
||||
- sports
|
||||
- the:
|
||||
- piano
|
||||
- guitar
|
||||
- trumpet
|
||||
- saxophone
|
||||
- baseball
|
||||
- ski
|
||||
- cook
|
||||
- dance
|
||||
- yodel
|
||||
- draw
|
||||
Are:
|
||||
you:
|
||||
- religious
|
||||
Have:
|
||||
you:
|
||||
ever:
|
||||
- been:
|
||||
- to:
|
||||
- Austria
|
||||
- Germany
|
||||
- Japan
|
||||
- Switzerland
|
||||
- France
|
||||
- Sweden
|
||||
- Norway
|
||||
- Finland
|
||||
- Australia
|
||||
- Italy
|
||||
- Russia
|
||||
- China
|
||||
- the:
|
||||
- USA
|
||||
- United Kingdom
|
||||
- caught:
|
||||
- "doing things you shouldn't do"
|
||||
- cheating
|
||||
- mistaken for:
|
||||
- someone else
|
||||
- listened to:
|
||||
- classical music
|
||||
- music:
|
||||
- "from the 80's"
|
||||
- dubstep
|
||||
- nightcore
|
||||
- metal
|
||||
- had:
|
||||
- an:
|
||||
- accident
|
||||
- written:
|
||||
- a love letter
|
||||
- code
|
||||
- in Japanese
|
||||
How:
|
||||
has:
|
||||
your:
|
||||
day:
|
||||
- been
|
||||
old:
|
||||
are:
|
||||
- you
|
||||
many:
|
||||
- open tabs do you currently have
|
||||
- followers is too many
|
||||
Where:
|
||||
do:
|
||||
you:
|
||||
- work
|
||||
- live
|
||||
Which:
|
||||
food:
|
||||
do:
|
||||
you:
|
||||
- love
|
||||
- hate
|
||||
Who:
|
||||
is:
|
||||
the:
|
||||
- most famous person you have met
|
||||
your:
|
||||
- favourite:
|
||||
- Retrospring user
|
||||
- actor
|
||||
- artist
|
||||
- comedian
|
||||
- musician
|
||||
Why:
|
||||
do:
|
||||
- they call it oven when you of in the cold food of out hot eat the food
|
||||
Would:
|
||||
you:
|
||||
rather:
|
||||
live:
|
||||
- in:
|
||||
- a city or in the countryside
|
||||
- a flat or in a house
|
||||
lose:
|
||||
- an arm or a leg
|
||||
be:
|
||||
- the best player on a horrible team or the worst player on a great team
|
|
@ -157,14 +157,14 @@ Rails.application.routes.draw do
|
|||
get "/@:username/q/:id", to: "question#show", as: :question
|
||||
get "/@:username/followers", to: "user#followers", as: :show_user_followers
|
||||
get "/@:username/followings", to: "user#followings", as: :show_user_followings
|
||||
get "/@:username/friends", to: redirect("/@%{username}/followings/p/%{page}")
|
||||
get "/@:username/friends", to: redirect("/@%{username}/followings")
|
||||
get "/@:username/questions", to: "user#questions", as: :show_user_questions
|
||||
get "/:username", to: "user#show", as: :user_alt
|
||||
get "/:username/a/:id", to: "answer#show", as: :answer_alt
|
||||
get "/:username/q/:id", to: "question#show", as: :question_alt
|
||||
get "/:username/followers", to: "user#followers", as: :show_user_followers_alt
|
||||
get "/:username/followings", to: "user#followings", as: :show_user_followings_alt
|
||||
get "/:username/friends", to: redirect("/%{username}/followings/p/%{page}")
|
||||
get "/:username/friends", to: redirect("/%{username}/followings")
|
||||
get "/:username/questions", to: "user#questions", as: :show_user_questions_alt
|
||||
|
||||
get "/feedback/consent", to: "feedback#consent", as: "feedback_consent"
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddRaisedAndAccentTextToThemes < ActiveRecord::Migration[6.1]
|
||||
def up
|
||||
add_column :themes, :raised_text, :integer, default: 0x000000, null: false
|
||||
add_column :themes, :raised_accent_text, :integer, default: 0x000000, null: false
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :themes, :raised_text
|
||||
remove_column :themes, :raised_accent_text
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class UseBodyTextForRaisedTextsInThemes < ActiveRecord::Migration[6.1]
|
||||
def up
|
||||
execute <<~SQUIRREL
|
||||
UPDATE themes
|
||||
SET raised_text = body_text,
|
||||
raised_accent_text = body_text
|
||||
WHERE body_text != 0;
|
||||
SQUIRREL
|
||||
end
|
||||
|
||||
def down; end
|
||||
end
|
|
@ -181,7 +181,7 @@ ActiveRecord::Schema.define(version: 2023_02_03_054229) do
|
|||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id"
|
||||
t.index ["resource_type", "resource_id"], name: "index_roles_on_resource"
|
||||
t.index ["resource_type", "resource_id"], name: "index_roles_on_resource_type_and_resource_id"
|
||||
end
|
||||
|
||||
create_table "rpush_apps", force: :cascade do |t|
|
||||
|
@ -301,6 +301,8 @@ ActiveRecord::Schema.define(version: 2023_02_03_054229) do
|
|||
t.integer "light_color", default: 16316922
|
||||
t.integer "light_text", default: 0
|
||||
t.integer "input_placeholder", default: 7107965, null: false
|
||||
t.integer "raised_text", default: 0, null: false
|
||||
t.integer "raised_accent_text", default: 0, null: false
|
||||
t.index ["user_id", "created_at"], name: "index_themes_on_user_id_and_created_at"
|
||||
end
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ services:
|
|||
- 1234:1234
|
||||
|
||||
redis:
|
||||
image: redis:3.2.11-alpine
|
||||
image: redis:6.2.10-alpine
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@ module Retrospring
|
|||
|
||||
def month = 1
|
||||
|
||||
def day = 23
|
||||
def day = 31
|
||||
|
||||
def patch = 0
|
||||
def patch = 1
|
||||
|
||||
def suffix = ""
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^4.11.0",
|
||||
"@typescript-eslint/parser": "^4.11.0",
|
||||
"esbuild": "^0.17.4",
|
||||
"esbuild": "^0.17.5",
|
||||
"eslint": "^7.16.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"stylelint": "^14.16.1",
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
<div class="dialog">
|
||||
<div>
|
||||
<h1>This page takes way too long to load!</h1>
|
||||
<img src="images/errors/original/angry_unicorn.png" alt="Unicorn">
|
||||
<img src="/images/errors/original/angry_unicorn.png" alt="Unicorn">
|
||||
</div>
|
||||
<p>Sorry about that. Please try refreshing and contact us if the problem persists.</p>
|
||||
</div>
|
||||
|
|
|
@ -47,6 +47,9 @@ self.addEventListener('install', function (event) {
|
|||
});
|
||||
|
||||
self.addEventListener('fetch', function (event) {
|
||||
const url = new URL(event.request.url);
|
||||
if (event.request.method !== 'GET' || !OFFLINE_CACHE_PATHS.includes(url.pathname)) return;
|
||||
|
||||
event.respondWith(
|
||||
(async () => {
|
||||
try {
|
||||
|
|
|
@ -58,6 +58,10 @@ describe InboxController, type: :controller do
|
|||
end
|
||||
end
|
||||
|
||||
it "updates the inbox entry status" do
|
||||
expect { subject }.to change { inbox_entry.reload.new? }.from(true).to(false)
|
||||
end
|
||||
|
||||
context "when requested the turbo stream format" do
|
||||
subject { get :show, format: :turbo_stream }
|
||||
|
||||
|
@ -175,9 +179,7 @@ describe InboxController, type: :controller do
|
|||
inbox: [],
|
||||
inbox_last_id: nil,
|
||||
more_data_available: false,
|
||||
inbox_count: 0,
|
||||
delete_id: "ib-delete-all",
|
||||
disabled: true
|
||||
inbox_count: 0
|
||||
}
|
||||
end
|
||||
end
|
||||
|
@ -209,9 +211,7 @@ describe InboxController, type: :controller do
|
|||
inbox: [],
|
||||
inbox_last_id: nil,
|
||||
more_data_available: false,
|
||||
inbox_count: 0,
|
||||
delete_id: "ib-delete-all",
|
||||
disabled: true
|
||||
inbox_count: 0
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,5 +33,9 @@ describe NotificationsController do
|
|||
expect(response).to render_template(:index)
|
||||
expect(controller.instance_variable_get(:@notifications)).to have_attributes(size: 2)
|
||||
end
|
||||
|
||||
it "marks notifications as read" do
|
||||
expect { subject }.to change { Notification.for(user).where(new: true).count }.from(2).to(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,12 +15,14 @@ FactoryBot.define do
|
|||
dark_color { 6_710_886 }
|
||||
dark_text { 15_658_734 }
|
||||
raised_background { 16_777_215 }
|
||||
raised_text { 3_355_443 }
|
||||
background_color { 13_026_795 }
|
||||
body_text { 3_355_443 }
|
||||
muted_text { 3_355_443 }
|
||||
input_color { 15_789_556 }
|
||||
input_text { 6_710_886 }
|
||||
raised_accent { 16_250_871 }
|
||||
raised_accent_text { 3_355_443 }
|
||||
light_color { 16_316_922 }
|
||||
light_text { 0 }
|
||||
end
|
||||
|
|
|
@ -22,32 +22,34 @@ describe UseCase::DataExport::Theme, :data_export do
|
|||
expect(json_file("theme.json")).to eq(
|
||||
{
|
||||
theme: {
|
||||
id: theme.id,
|
||||
user_id: user.id,
|
||||
primary_color: 9342168,
|
||||
primary_text: 16777215,
|
||||
danger_color: 14257035,
|
||||
danger_text: 16777215,
|
||||
success_color: 12573067,
|
||||
success_text: 16777215,
|
||||
warning_color: 14261899,
|
||||
warning_text: 16777215,
|
||||
info_color: 9165273,
|
||||
info_text: 16777215,
|
||||
dark_color: 6710886,
|
||||
dark_text: 15658734,
|
||||
raised_background: 16777215,
|
||||
background_color: 13026795,
|
||||
body_text: 3355443,
|
||||
muted_text: 3355443,
|
||||
created_at: "2022-12-10T13:37:42.000Z",
|
||||
updated_at: "2022-12-10T13:37:42.000Z",
|
||||
input_color: 15789556,
|
||||
input_text: 6710886,
|
||||
raised_accent: 16250871,
|
||||
light_color: 16316922,
|
||||
light_text: 0,
|
||||
input_placeholder: 7107965
|
||||
id: theme.id,
|
||||
user_id: user.id,
|
||||
primary_color: 9342168,
|
||||
primary_text: 16777215,
|
||||
danger_color: 14257035,
|
||||
danger_text: 16777215,
|
||||
success_color: 12573067,
|
||||
success_text: 16777215,
|
||||
warning_color: 14261899,
|
||||
warning_text: 16777215,
|
||||
info_color: 9165273,
|
||||
info_text: 16777215,
|
||||
dark_color: 6710886,
|
||||
dark_text: 15658734,
|
||||
raised_background: 16777215,
|
||||
raised_text: 3355443,
|
||||
background_color: 13026795,
|
||||
body_text: 3355443,
|
||||
muted_text: 3355443,
|
||||
created_at: "2022-12-10T13:37:42.000Z",
|
||||
updated_at: "2022-12-10T13:37:42.000Z",
|
||||
input_color: 15789556,
|
||||
input_text: 6710886,
|
||||
raised_accent: 16250871,
|
||||
raised_accent_text: 3355443,
|
||||
light_color: 16316922,
|
||||
light_text: 0,
|
||||
input_placeholder: 7107965
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -81,6 +81,7 @@ RSpec.describe User, type: :model do
|
|||
# nor .mail (.email is, however)
|
||||
include_examples "invalid email", "fritz.fantom@proton.mail"
|
||||
# common typos:
|
||||
include_examples "invalid email", "fritz.fantom@aoo.com"
|
||||
include_examples "invalid email", "fritz.fantom@fmail.com"
|
||||
include_examples "invalid email", "fritz.fantom@gamil.com"
|
||||
include_examples "invalid email", "fritz.fantom@gemail.com"
|
||||
|
@ -93,6 +94,7 @@ RSpec.describe User, type: :model do
|
|||
include_examples "invalid email", "fritz.fantom@gmaile.com"
|
||||
include_examples "invalid email", "fritz.fantom@gmaill.com"
|
||||
include_examples "invalid email", "fritz.fantom@gmali.com"
|
||||
include_examples "invalid email", "fritz.fantom@gmaul.com"
|
||||
include_examples "invalid email", "fritz.fantom@gnail.com"
|
||||
include_examples "invalid email", "fritz.fantom@hotamil.com"
|
||||
include_examples "invalid email", "fritz.fantom@hotmai.com"
|
||||
|
|
228
yarn.lock
228
yarn.lock
|
@ -49,115 +49,115 @@
|
|||
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz#1bfafe4b7ed0f3e4105837e056e0a89b108ebe36"
|
||||
integrity sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==
|
||||
|
||||
"@esbuild/android-arm64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.4.tgz#0a900a7e448cc038ae5a751255257fc67163ed32"
|
||||
integrity sha512-91VwDrl4EpxBCiG6h2LZZEkuNvVZYJkv2T9gyLG/mhGG1qrM7i5SwUcg/hlSPnL/4hDT0TFcF35/XMGSn0bemg==
|
||||
"@esbuild/android-arm64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.5.tgz#a145f43018e639bed94ed637369e2dcdd6bf9ea2"
|
||||
integrity sha512-KHWkDqYAMmKZjY4RAN1PR96q6UOtfkWlTS8uEwWxdLtkRt/0F/csUhXIrVfaSIFxnscIBMPynGfhsMwQDRIBQw==
|
||||
|
||||
"@esbuild/android-arm@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.4.tgz#fe32ce82eb6064d3dc13c0d8ca0e440bbc776c93"
|
||||
integrity sha512-R9GCe2xl2XDSc2XbQB63mFiFXHIVkOP+ltIxICKXqUPrFX97z6Z7vONCLQM1pSOLGqfLrGi3B7nbhxmFY/fomg==
|
||||
"@esbuild/android-arm@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.5.tgz#9fa2deff7fc5d180bb4ecff70beea3a95ac44251"
|
||||
integrity sha512-crmPUzgCmF+qZXfl1YkiFoUta2XAfixR1tEnr/gXIixE+WL8Z0BGqfydP5oox0EUOgQMMRgtATtakyAcClQVqQ==
|
||||
|
||||
"@esbuild/android-x64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.4.tgz#6ae1056f6ecf1963c1d076cf5f0109b52d8049f6"
|
||||
integrity sha512-mGSqhEPL7029XL7QHNPxPs15JVa02hvZvysUcyMP9UXdGFwncl2WU0bqx+Ysgzd+WAbv8rfNa73QveOxAnAM2w==
|
||||
"@esbuild/android-x64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.5.tgz#145fc61f810400e65a56b275280d1422a102c2ef"
|
||||
integrity sha512-8fI/AnIdmWz/+1iza2WrCw8kwXK9wZp/yZY/iS8ioC+U37yJCeppi9EHY05ewJKN64ASoBIseufZROtcFnX5GA==
|
||||
|
||||
"@esbuild/darwin-arm64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.4.tgz#5064d81ee5b8d646a5b7cc3e53c98cb983c4af55"
|
||||
integrity sha512-tTyJRM9dHvlMPt1KrBFVB5OW1kXOsRNvAPtbzoKazd5RhD5/wKlXk1qR2MpaZRYwf4WDMadt0Pv0GwxB41CVow==
|
||||
"@esbuild/darwin-arm64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.5.tgz#61fb0546aa4bae0850817d6e0d008b1cb3f64b49"
|
||||
integrity sha512-EAvaoyIySV6Iif3NQCglUNpnMfHSUgC5ugt2efl3+QDntucJe5spn0udNZjTgNi6tKVqSceOw9tQ32liNZc1Xw==
|
||||
|
||||
"@esbuild/darwin-x64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.4.tgz#67f0213b3333248b32a97a7fc3fee880c2157674"
|
||||
integrity sha512-phQuC2Imrb3TjOJwLN8EO50nb2FHe8Ew0OwgZDH1SV6asIPGudnwTQtighDF2EAYlXChLoMJwqjAp4vAaACq6w==
|
||||
"@esbuild/darwin-x64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.5.tgz#54b770f0c49f524ae9ba24c85d6dea8b521f610d"
|
||||
integrity sha512-ha7QCJh1fuSwwCgoegfdaljowwWozwTDjBgjD3++WAy/qwee5uUi1gvOg2WENJC6EUyHBOkcd3YmLDYSZ2TPPA==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.4.tgz#8eaaa126d9ff24822c730f06a71ac2d1091dc1c2"
|
||||
integrity sha512-oH6JUZkocgmjzzYaP5juERLpJQSwazdjZrTPgLRmAU2bzJ688x0vfMB/WTv4r58RiecdHvXOPC46VtsMy/mepg==
|
||||
"@esbuild/freebsd-arm64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.5.tgz#be1dd18b7b9411f10bdc362ba8bff16386175367"
|
||||
integrity sha512-VbdXJkn2aI2pQ/wxNEjEcnEDwPpxt3CWWMFYmO7CcdFBoOsABRy2W8F3kjbF9F/pecEUDcI3b5i2w+By4VQFPg==
|
||||
|
||||
"@esbuild/freebsd-x64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.4.tgz#314eff900a71abf64d4e5bea31e430d8ebd78d79"
|
||||
integrity sha512-U4iWGn/9TrAfpAdfd56eO0pRxIgb0a8Wj9jClrhT8hvZnOnS4dfMPW7o4fn15D/KqoiVYHRm43jjBaTt3g/2KA==
|
||||
"@esbuild/freebsd-x64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.5.tgz#c9c1960fa3e1eada4e5d4be2a11a2f04ce14198f"
|
||||
integrity sha512-olgGYND1/XnnWxwhjtY3/ryjOG/M4WfcA6XH8dBTH1cxMeBemMODXSFhkw71Kf4TeZFFTN25YOomaNh0vq2iXg==
|
||||
|
||||
"@esbuild/linux-arm64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.4.tgz#5bed6bb8eb1d331644f8b31c87b8df57f204e84e"
|
||||
integrity sha512-UkGfQvYlwOaeYJzZG4cLV0hCASzQZnKNktRXUo3/BMZvdau40AOz9GzmGA063n1piq6VrFFh43apRDQx8hMP2w==
|
||||
"@esbuild/linux-arm64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.5.tgz#34d96d11c6899017ecae42fb97de8e0c3282902f"
|
||||
integrity sha512-8a0bqSwu3OlLCfu2FBbDNgQyBYdPJh1B9PvNX7jMaKGC9/KopgHs37t+pQqeMLzcyRqG6z55IGNQAMSlCpBuqg==
|
||||
|
||||
"@esbuild/linux-arm@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.4.tgz#6eaa41f37e231d113da715a1d9cc820e5523aeb6"
|
||||
integrity sha512-S2s9xWTGMTa/fG5EyMGDeL0wrWVgOSQcNddJWgu6rG1NCSXJHs76ZP9AsxjB3f2nZow9fWOyApklIgiTGZKhiw==
|
||||
"@esbuild/linux-arm@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.5.tgz#86332e6293fd713a54ab299a5e2ed7c60c9e1c07"
|
||||
integrity sha512-YBdCyQwA3OQupi6W2/WO4FnI+NWFWe79cZEtlbqSESOHEg7a73htBIRiE6uHPQe7Yp5E4aALv+JxkRLGEUL7tw==
|
||||
|
||||
"@esbuild/linux-ia32@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.4.tgz#3fc352bb54e0959fda273cd2253b1c72ca41b8c2"
|
||||
integrity sha512-3lqFi4VFo/Vwvn77FZXeLd0ctolIJH/uXkH3yNgEk89Eh6D3XXAC9/iTPEzeEpsNE5IqGIsFa5Z0iPeOh25IyA==
|
||||
"@esbuild/linux-ia32@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.5.tgz#7bd9185c844e7dfce6a01dfdec584e115602a8c4"
|
||||
integrity sha512-uCwm1r/+NdP7vndctgq3PoZrnmhmnecWAr114GWMRwg2QMFFX+kIWnp7IO220/JLgnXK/jP7VKAFBGmeOYBQYQ==
|
||||
|
||||
"@esbuild/linux-loong64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.4.tgz#86d54f690be53669cd2a38a5333ecf2608c11189"
|
||||
integrity sha512-HqpWZkVslDHIwdQ9D+gk7NuAulgQvRxF9no54ut/M55KEb3mi7sQS3GwpPJzSyzzP0UkjQVN7/tbk88/CaX4EQ==
|
||||
"@esbuild/linux-loong64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.5.tgz#2907d4120c7b3642b96be6014f77e7624c378eea"
|
||||
integrity sha512-3YxhSBl5Sb6TtBjJu+HP93poBruFzgXmf3PVfIe4xOXMj1XpxboYZyw3W8BhoX/uwxzZz4K1I99jTE/5cgDT1g==
|
||||
|
||||
"@esbuild/linux-mips64el@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.4.tgz#3dbd897bd8f047fef35e69bd253b8f07ca7fe483"
|
||||
integrity sha512-d/nMCKKh/SVDbqR9ju+b78vOr0tNXtfBjcp5vfHONCCOAL9ad8gN9dC/u+UnH939pz7wO+0u/x9y1MaZcb/lKA==
|
||||
"@esbuild/linux-mips64el@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.5.tgz#fc98be741e8080ecd13b404d5fca5302d3835bf4"
|
||||
integrity sha512-Hy5Z0YVWyYHdtQ5mfmfp8LdhVwGbwVuq8mHzLqrG16BaMgEmit2xKO+iDakHs+OetEx0EN/2mUzDdfdktI+Nmg==
|
||||
|
||||
"@esbuild/linux-ppc64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.4.tgz#defaff6db9a60f08936fc0c59e0eabfb1055968a"
|
||||
integrity sha512-lOD9p2dmjZcNiTU+sGe9Nn6G3aYw3k0HBJies1PU0j5IGfp6tdKOQ6mzfACRFCqXjnBuTqK7eTYpwx09O5LLfg==
|
||||
"@esbuild/linux-ppc64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.5.tgz#ea12e8f6b290a613ac4903c9e00835c69ced065c"
|
||||
integrity sha512-5dbQvBLbU/Y3Q4ABc9gi23hww1mQcM7KZ9KBqabB7qhJswYMf8WrDDOSw3gdf3p+ffmijMd28mfVMvFucuECyg==
|
||||
|
||||
"@esbuild/linux-riscv64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.4.tgz#270a09f6f4205a8a8c8ed3c7dbabdcebaafa8a84"
|
||||
integrity sha512-mTGnwWwVshAjGsd8rP+K6583cPDgxOunsqqldEYij7T5/ysluMHKqUIT4TJHfrDFadUwrghAL6QjER4FeqQXoA==
|
||||
"@esbuild/linux-riscv64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.5.tgz#ce47b15fd4227eeb0590826e41bdc430c5bfd06c"
|
||||
integrity sha512-fp/KUB/ZPzEWGTEUgz9wIAKCqu7CjH1GqXUO2WJdik1UNBQ7Xzw7myIajpxztE4Csb9504ERiFMxZg5KZ6HlZQ==
|
||||
|
||||
"@esbuild/linux-s390x@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.4.tgz#197695bece68f514dcdcc286562b5d48c5dad5f9"
|
||||
integrity sha512-AQYuUGp50XM29/N/dehADxvc2bUqDcoqrVuijop1Wv72SyxT6dDB9wjUxuPZm2HwIM876UoNNBMVd+iX/UTKVQ==
|
||||
"@esbuild/linux-s390x@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.5.tgz#962fa540d7498967270eb1d4b9ac6c4a4f339735"
|
||||
integrity sha512-kRV3yw19YDqHTp8SfHXfObUFXlaiiw4o2lvT1XjsPZ++22GqZwSsYWJLjMi1Sl7j9qDlDUduWDze/nQx0d6Lzw==
|
||||
|
||||
"@esbuild/linux-x64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.4.tgz#db50cdfb071c0d367025c1c98563aab1318f800e"
|
||||
integrity sha512-+AsFBwKgQuhV2shfGgA9YloxLDVjXgUEWZum7glR5lLmV94IThu/u2JZGxTgjYby6kyXEx8lKOqP5rTEVBR0Rw==
|
||||
"@esbuild/linux-x64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.5.tgz#9fa52884c3d876593a522aa1d4df43b717907050"
|
||||
integrity sha512-vnxuhh9e4pbtABNLbT2ANW4uwQ/zvcHRCm1JxaYkzSehugoFd5iXyC4ci1nhXU13mxEwCnrnTIiiSGwa/uAF1g==
|
||||
|
||||
"@esbuild/netbsd-x64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.4.tgz#e4d5d8022f8eddbd7d9899d58265915444f46f3b"
|
||||
integrity sha512-zD1TKYX9553OiLS/qkXPMlWoELYkH/VkzRYNKEU+GwFiqkq0SuxsKnsCg5UCdxN3cqd+1KZ8SS3R+WG/Hxy2jQ==
|
||||
"@esbuild/netbsd-x64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.5.tgz#47bb187b86aad9622051cb80c27e439b7d9e3a9a"
|
||||
integrity sha512-cigBpdiSx/vPy7doUyImsQQBnBjV5f1M99ZUlaJckDAJjgXWl6y9W17FIfJTy8TxosEF6MXq+fpLsitMGts2nA==
|
||||
|
||||
"@esbuild/openbsd-x64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.4.tgz#9b770e1e7745824cbe155f5a742fc781855a7e68"
|
||||
integrity sha512-PY1NjEsLRhPEFFg1AV0/4Or/gR+q2dOb9s5rXcPuCjyHRzbt8vnHJl3vYj+641TgWZzTFmSUnZbzs1zwTzjeqw==
|
||||
"@esbuild/openbsd-x64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.5.tgz#abc55c35a1ed2bc3c5ede2ef50a3b2f87395009a"
|
||||
integrity sha512-VdqRqPVIjjZfkf40LrqOaVuhw9EQiAZ/GNCSM2UplDkaIzYVsSnycxcFfAnHdWI8Gyt6dO15KHikbpxwx+xHbw==
|
||||
|
||||
"@esbuild/sunos-x64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.4.tgz#4c6d2290f8bf39ab9284f5a1b9a2210858e2d6e6"
|
||||
integrity sha512-B3Z7s8QZQW9tKGleMRXvVmwwLPAUoDCHs4WZ2ElVMWiortLJFowU1NjAhXOKjDgC7o9ByeVcwyOlJ+F2r6ZgmQ==
|
||||
"@esbuild/sunos-x64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.5.tgz#b83c080a2147662599a5d18b2ff47f07c93e03a0"
|
||||
integrity sha512-ItxPaJ3MBLtI4nK+mALLEoUs6amxsx+J1ibnfcYMkqaCqHST1AkF4aENpBehty3czqw64r/XqL+W9WqU6kc2Qw==
|
||||
|
||||
"@esbuild/win32-arm64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.4.tgz#424954b6d598f40e2c5a0d85e3af07147fb41909"
|
||||
integrity sha512-0HCu8R3mY/H5V7N6kdlsJkvrT591bO/oRZy8ztF1dhgNU5xD5tAh5bKByT1UjTGjp/VVBsl1PDQ3L18SfvtnBQ==
|
||||
"@esbuild/win32-arm64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.5.tgz#2a4c41f427d9cf25b75f9d61493711a482106850"
|
||||
integrity sha512-4u2Q6qsJTYNFdS9zHoAi80spzf78C16m2wla4eJPh4kSbRv+BpXIfl6TmBSWupD8e47B1NrTfrOlEuco7mYQtg==
|
||||
|
||||
"@esbuild/win32-ia32@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.4.tgz#2c94e9c3a82c779d3f07b3fb5c482a2e3fecedb1"
|
||||
integrity sha512-VUjhVDQycse1gLbe06pC/uaA0M+piQXJpdpNdhg8sPmeIZZqu5xPoGWVCmcsOO2gaM2cywuTYTHkXRozo3/Nkg==
|
||||
"@esbuild/win32-ia32@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.5.tgz#7c14e3250725d0e2c21f89c98eb6abb520cba0e0"
|
||||
integrity sha512-KYlm+Xu9TXsfTWAcocLuISRtqxKp/Y9ZBVg6CEEj0O5J9mn7YvBKzAszo2j1ndyzUPk+op+Tie2PJeN+BnXGqQ==
|
||||
|
||||
"@esbuild/win32-x64@0.17.4":
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.4.tgz#9b7760cdc77678bdbc5b582fae2cf3de449df048"
|
||||
integrity sha512-0kLAjs+xN5OjhTt/aUA6t48SfENSCKgGPfExADYTOo/UCn0ivxos9/anUVeSfg+L+2O9xkFxvJXIJfG+Q4sYSg==
|
||||
"@esbuild/win32-x64@0.17.5":
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.5.tgz#a8f3d26d8afc5186eccda265ceb1820b8e8830be"
|
||||
integrity sha512-XgA9qWRqby7xdYXuF6KALsn37QGBMHsdhmnpjfZtYxKxbTOwfnDM6MYi2WuUku5poNaX2n9XGVr20zgT/2QwCw==
|
||||
|
||||
"@eslint/eslintrc@^0.4.3":
|
||||
version "0.4.3"
|
||||
|
@ -835,33 +835,33 @@ es-to-primitive@^1.2.1:
|
|||
is-date-object "^1.0.1"
|
||||
is-symbol "^1.0.2"
|
||||
|
||||
esbuild@^0.17.4:
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.4.tgz#af4f8f78604c67f8e6afbdee36a3f4211ecfc859"
|
||||
integrity sha512-zBn9MeCwT7W5F1a3lXClD61ip6vQM+H8Msb0w8zMT4ZKBpDg+rFAraNyWCDelB/2L6M3g6AXHPnsyvjMFnxtFw==
|
||||
esbuild@^0.17.5:
|
||||
version "0.17.5"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.5.tgz#cd76d75700d49ac050ad9eedfbed777bd6a9d930"
|
||||
integrity sha512-Bu6WLCc9NMsNoMJUjGl3yBzTjVLXdysMltxQWiLAypP+/vQrf+3L1Xe8fCXzxaECus2cEJ9M7pk4yKatEwQMqQ==
|
||||
optionalDependencies:
|
||||
"@esbuild/android-arm" "0.17.4"
|
||||
"@esbuild/android-arm64" "0.17.4"
|
||||
"@esbuild/android-x64" "0.17.4"
|
||||
"@esbuild/darwin-arm64" "0.17.4"
|
||||
"@esbuild/darwin-x64" "0.17.4"
|
||||
"@esbuild/freebsd-arm64" "0.17.4"
|
||||
"@esbuild/freebsd-x64" "0.17.4"
|
||||
"@esbuild/linux-arm" "0.17.4"
|
||||
"@esbuild/linux-arm64" "0.17.4"
|
||||
"@esbuild/linux-ia32" "0.17.4"
|
||||
"@esbuild/linux-loong64" "0.17.4"
|
||||
"@esbuild/linux-mips64el" "0.17.4"
|
||||
"@esbuild/linux-ppc64" "0.17.4"
|
||||
"@esbuild/linux-riscv64" "0.17.4"
|
||||
"@esbuild/linux-s390x" "0.17.4"
|
||||
"@esbuild/linux-x64" "0.17.4"
|
||||
"@esbuild/netbsd-x64" "0.17.4"
|
||||
"@esbuild/openbsd-x64" "0.17.4"
|
||||
"@esbuild/sunos-x64" "0.17.4"
|
||||
"@esbuild/win32-arm64" "0.17.4"
|
||||
"@esbuild/win32-ia32" "0.17.4"
|
||||
"@esbuild/win32-x64" "0.17.4"
|
||||
"@esbuild/android-arm" "0.17.5"
|
||||
"@esbuild/android-arm64" "0.17.5"
|
||||
"@esbuild/android-x64" "0.17.5"
|
||||
"@esbuild/darwin-arm64" "0.17.5"
|
||||
"@esbuild/darwin-x64" "0.17.5"
|
||||
"@esbuild/freebsd-arm64" "0.17.5"
|
||||
"@esbuild/freebsd-x64" "0.17.5"
|
||||
"@esbuild/linux-arm" "0.17.5"
|
||||
"@esbuild/linux-arm64" "0.17.5"
|
||||
"@esbuild/linux-ia32" "0.17.5"
|
||||
"@esbuild/linux-loong64" "0.17.5"
|
||||
"@esbuild/linux-mips64el" "0.17.5"
|
||||
"@esbuild/linux-ppc64" "0.17.5"
|
||||
"@esbuild/linux-riscv64" "0.17.5"
|
||||
"@esbuild/linux-s390x" "0.17.5"
|
||||
"@esbuild/linux-x64" "0.17.5"
|
||||
"@esbuild/netbsd-x64" "0.17.5"
|
||||
"@esbuild/openbsd-x64" "0.17.5"
|
||||
"@esbuild/sunos-x64" "0.17.5"
|
||||
"@esbuild/win32-arm64" "0.17.5"
|
||||
"@esbuild/win32-ia32" "0.17.5"
|
||||
"@esbuild/win32-x64" "0.17.5"
|
||||
|
||||
escape-string-regexp@^1.0.5:
|
||||
version "1.0.5"
|
||||
|
|
Loading…
Reference in New Issue