diff --git a/.env.sample b/.env.sample index 54b510d..8c7329e 100644 --- a/.env.sample +++ b/.env.sample @@ -8,7 +8,7 @@ NGROK_SUBDOMAIN= REDIS_DB=0 REDIS_PORT=6379 REDIS_TTL=18000 -REDIS_URL=redis://localhost +REDIS_URL=redis://localhost:6379/1 SENTRY_DSN= SIDEKIQ_NAMESPACE=sidekiq_dev SMTP_DEFAULT_FROM= diff --git a/Gemfile b/Gemfile index 4708f22..51b8251 100644 --- a/Gemfile +++ b/Gemfile @@ -20,6 +20,8 @@ gem "rails-observers", "~> 0.1.5" # removal candidate gem "redis", "~> 4.1" gem "redis-namespace", "~> 1.7" # removal candidate gem "redis-rails", "~> 5.0" # removal candidate +gem "rubycritic", "~> 4.5", require: false +gem "rubycritic-small-badge", "~> 0.2.1", require: false gem "sass-rails", "~> 6.0" # removal candidate gem "sentry-raven", "~> 3.0" gem "sidekiq", "~> 6.0" @@ -27,7 +29,7 @@ gem "skylight", "~> 4.3" gem "stimulus_reflex", "~> 3.2" gem "turbolinks", "~> 5.2" gem "view_component", "~> 2.7" -gem "webpacker", "~> 4.0" +gem "webpacker", "~> 5.1" group :development, :test do gem "bullet", "~> 6.1" diff --git a/Gemfile.lock b/Gemfile.lock index f91c474..ab0755f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -70,6 +70,10 @@ GEM activerecord (>= 3.2, < 7.0) rake (>= 10.4, < 14.0) ast (2.4.0) + axiom-types (0.1.1) + descendants_tracker (~> 0.0.4) + ice_nine (~> 0.11.0) + thread_safe (~> 0.3, >= 0.3.1) backport (1.1.2) bcrypt (3.1.13) benchmark (0.1.0) @@ -93,23 +97,29 @@ GEM code_analyzer (0.5.1) sexp_processor coderay (1.1.2) + coercible (1.0.0) + descendants_tracker (~> 0.0.1) colorize (0.8.1) concurrent-ruby (1.1.6) connection_pool (2.2.2) crass (1.0.6) database_consistency (0.8.0) activerecord (>= 3.2) + descendants_tracker (0.0.4) + thread_safe (~> 0.3, >= 0.3.1) devise (4.7.1) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0) responders warden (~> 1.2.3) + docile (1.3.2) dotenv (2.7.5) dotenv-rails (2.7.5) dotenv (= 2.7.5) railties (>= 3.2, < 6.1) e2mmap (0.1.0) + equalizer (0.0.11) equatable (0.6.1) erb_lint (0.0.33) activesupport @@ -130,6 +140,15 @@ GEM ruby_parser (>= 3.14.1) ffaker (2.15.0) ffi (1.12.2) + flay (2.12.1) + erubis (~> 2.7.0) + path_expander (~> 1.0) + ruby_parser (~> 3.0) + sexp_processor (~> 4.0) + flog (4.6.4) + path_expander (~> 1.0) + ruby_parser (~> 3.1, > 3.1.0) + sexp_processor (~> 4.8) friendly_id (5.3.0) activerecord (>= 4.0.0) globalid (0.4.2) @@ -138,11 +157,13 @@ GEM html_tokenizer (0.0.7) i18n (1.8.2) concurrent-ruby (~> 1.0) + ice_nine (0.11.2) jaro_winkler (1.5.4) jbuilder (2.10.0) activesupport (>= 5.0.0) json (2.3.0) jwt (2.2.1) + kwalify (0.7.2) launchy (2.5.0) addressable (~> 2.7) letter_opener (1.7.0) @@ -203,12 +224,14 @@ GEM pastel (0.7.3) equatable (~> 0.6) tty-color (~> 0.5) + path_expander (1.1.0) pg (1.2.3) pry (0.13.1) coderay (~> 1.1) method_source (~> 1.0) pry-rails (0.3.9) pry (>= 0.10.4) + psych (3.1.0) public_suffix (4.0.5) puma (4.3.5) nio4r (~> 2.0) @@ -279,6 +302,13 @@ GEM redis-store (>= 1.2, < 2) redis-store (1.8.2) redis (>= 4, < 5) + reek (6.0.1) + kwalify (~> 0.7.0) + parser (>= 2.5.0.0, < 2.8, != 2.5.1.1) + psych (~> 3.1.0) + rainbow (>= 2.0, < 4.0) + repo-small-badge (0.2.7) + victor (~> 0.2.8) require_all (3.0.0) responders (3.0.0) actionpack (>= 5.0) @@ -301,6 +331,19 @@ GEM ruby_dep (1.5.0) ruby_parser (3.14.2) sexp_processor (~> 4.9) + rubycritic (4.5.0) + flay (~> 2.8) + flog (~> 4.4) + launchy (>= 2.0.0) + parser (>= 2.6.0) + rainbow (~> 3.0) + reek (~> 6.0, < 7.0) + ruby_parser (~> 3.8) + simplecov (>= 0.17.0) + tty-which (~> 0.4.0) + virtus (~> 1.0) + rubycritic-small-badge (0.2.1) + repo-small-badge (~> 0.2.7) sass-rails (6.0.0) sassc-rails (~> 2.1, >= 2.1.1) sassc (2.3.0) @@ -311,6 +354,7 @@ GEM sprockets (> 3.0) sprockets-rails tilt + semantic_range (2.3.0) sentry-raven (3.0.0) faraday (>= 1.0) sexp_processor (4.14.1) @@ -319,6 +363,10 @@ GEM rack (~> 2.0) rack-protection (>= 2.0.0) redis (>= 4.1.0) + simplecov (0.18.5) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov-html (0.12.2) skylight (4.3.0) skylight-core (= 4.3.0) skylight-core (4.3.0) @@ -374,6 +422,7 @@ GEM tty-cursor (~> 0.7) tty-color (0.5.1) tty-cursor (0.7.1) + tty-which (0.4.2) turbolinks (5.2.1) turbolinks-source (~> 5.2) turbolinks-source (5.2.0) @@ -382,14 +431,21 @@ GEM unicode-display_width (1.7.0) unicode_utils (1.4.0) uniform_notifier (1.13.0) + victor (0.2.8) view_component (2.7.0) activesupport (>= 5.0.0, < 7.0) + virtus (1.0.5) + axiom-types (~> 0.1) + coercible (~> 1.0) + descendants_tracker (~> 0.0, >= 0.0.3) + equalizer (~> 0.0, >= 0.0.9) warden (1.2.8) rack (>= 2.0.6) - webpacker (4.2.2) - activesupport (>= 4.2) + webpacker (5.1.1) + activesupport (>= 5.2) rack-proxy (>= 0.6.1) - railties (>= 4.2) + railties (>= 5.2) + semantic_range (>= 2.3.0) websocket-driver (0.7.2) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.4) @@ -432,6 +488,8 @@ DEPENDENCIES redis (~> 4.1) redis-namespace (~> 1.7) redis-rails (~> 5.0) + rubycritic (~> 4.5) + rubycritic-small-badge (~> 0.2.1) sass-rails (~> 6.0) sentry-raven (~> 3.0) sidekiq (~> 6.0) @@ -445,7 +503,7 @@ DEPENDENCIES turbolinks (~> 5.2) tzinfo-data view_component (~> 2.7) - webpacker (~> 4.0) + webpacker (~> 5.1) RUBY VERSION ruby 2.6.6p146 diff --git a/Rakefile b/Rakefile index 9a5ea73..0255ee0 100644 --- a/Rakefile +++ b/Rakefile @@ -2,5 +2,15 @@ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. require_relative "config/application" +require "rubycritic_small_badge" +require "rubycritic/rake_task" Rails.application.load_tasks + +RubyCriticSmallBadge.configure do |config| + config.minimum_score = 90 +end +RubyCritic::RakeTask.new do |task| + task.options = %(--custom-format RubyCriticSmallBadge::Report +--minimum-score #{RubyCriticSmallBadge.config.minimum_score}) +end diff --git a/app/components/application_component.rb b/app/components/application_component.rb new file mode 100644 index 0000000..fdbea0c --- /dev/null +++ b/app/components/application_component.rb @@ -0,0 +1,12 @@ +class ApplicationComponent < ViewComponent::Base + private + + def find_or_fallback(supplied, valid, fallback) + if valid.include?(supplied) + supplied + else + raise ArgumentError if Rails.env.development? + fallback + end + end +end diff --git a/app/components/badge_component.html.erb b/app/components/badge_component.html.erb new file mode 100644 index 0000000..29adc8b --- /dev/null +++ b/app/components/badge_component.html.erb @@ -0,0 +1,8 @@ +
+
+ <%= tag.small(class: "text-xs text-red-500 tracking-widest font-medium") { org_name } if org_name %> +

<%= badge.title %>

+ <%= image_tag badge.asset_url, class: "mt-3", alt: badge.title %> + <%# <%= tag.p(class: "text-gray-600") { badge.description } if badge.description %> +
+
diff --git a/app/components/badge_component.rb b/app/components/badge_component.rb new file mode 100644 index 0000000..ccd6f91 --- /dev/null +++ b/app/components/badge_component.rb @@ -0,0 +1,13 @@ +class BadgeComponent < ApplicationComponent + def initialize(badge:) + @badge = badge + end + + private + + attr_reader :badge + + def org_name + badge.organization ? badge.organization.name : false + end +end diff --git a/app/components/example_component.html.erb b/app/components/example_component.html.erb deleted file mode 100644 index 4917f30..0000000 --- a/app/components/example_component.html.erb +++ /dev/null @@ -1 +0,0 @@ -
Add Example template here
diff --git a/app/components/example_component.rb b/app/components/example_component.rb deleted file mode 100644 index 10aaa26..0000000 --- a/app/components/example_component.rb +++ /dev/null @@ -1,6 +0,0 @@ -class ExampleComponent < ViewComponent::Base - def initialize(title:, content:) - @title = title - @content = content - end -end diff --git a/app/components/flash_component.html.erb b/app/components/flash_component.html.erb new file mode 100644 index 0000000..402100b --- /dev/null +++ b/app/components/flash_component.html.erb @@ -0,0 +1,8 @@ +<% flash.each do |msg_type, message| %> +
+
+ + <%= message %> +
+
+<% end %> diff --git a/app/components/flash_component.rb b/app/components/flash_component.rb new file mode 100644 index 0000000..da515bb --- /dev/null +++ b/app/components/flash_component.rb @@ -0,0 +1,22 @@ +class FlashComponent < ApplicationComponent + def initialize(flash: nil) + @flash = flash + end + + private + + attr_reader :flash + + def class_for(flash_type) + { + success: "alert-success", + error: "alert-danger", + alert: "alert-warning", + notice: "alert-info" + }.stringify_keys[flash_type.to_s] || flash_type.to_s + end + + def render? + flash + end +end diff --git a/app/components/footer_component.html.erb b/app/components/footer_component.html.erb new file mode 100644 index 0000000..9430855 --- /dev/null +++ b/app/components/footer_component.html.erb @@ -0,0 +1,12 @@ + diff --git a/app/components/footer_component.rb b/app/components/footer_component.rb new file mode 100644 index 0000000..bfbcd31 --- /dev/null +++ b/app/components/footer_component.rb @@ -0,0 +1,2 @@ +class FooterComponent < ApplicationComponent +end diff --git a/app/components/form/errors_component.html.erb b/app/components/form/errors_component.html.erb new file mode 100644 index 0000000..833b9da --- /dev/null +++ b/app/components/form/errors_component.html.erb @@ -0,0 +1,10 @@ +
+

+ <%= pluralize(object.errors.count, "error") %> prohibited saving: +

+ +
diff --git a/app/components/form/errors_component.rb b/app/components/form/errors_component.rb new file mode 100644 index 0000000..bda95ee --- /dev/null +++ b/app/components/form/errors_component.rb @@ -0,0 +1,13 @@ +class Form::ErrorsComponent < ApplicationComponent + def initialize(object: nil) + @object = object + end + + private + + attr_reader :object + + def render? + object&.errors&.any? + end +end diff --git a/app/components/header/navbar_component.html.erb b/app/components/header/navbar_component.html.erb new file mode 100644 index 0000000..e00c25d --- /dev/null +++ b/app/components/header/navbar_component.html.erb @@ -0,0 +1,6 @@ + diff --git a/app/components/header/navbar_component.rb b/app/components/header/navbar_component.rb new file mode 100644 index 0000000..a9327d2 --- /dev/null +++ b/app/components/header/navbar_component.rb @@ -0,0 +1,4 @@ +module Header + class NavbarComponent < ApplicationComponent + end +end diff --git a/app/components/header_component.html.erb b/app/components/header_component.html.erb new file mode 100644 index 0000000..ade2e7f --- /dev/null +++ b/app/components/header_component.html.erb @@ -0,0 +1,14 @@ +
+
+ + <%= image_pack_tag 'ruby.svg', class: "w-10" %> + Rubyists.dev + + <%#= render(Header::NavbarComponent.new) %> + +
+
diff --git a/app/components/header_component.rb b/app/components/header_component.rb new file mode 100644 index 0000000..efd59d8 --- /dev/null +++ b/app/components/header_component.rb @@ -0,0 +1,2 @@ +class HeaderComponent < ApplicationComponent +end diff --git a/app/components/page_component.html.erb b/app/components/page_component.html.erb new file mode 100644 index 0000000..64fff24 --- /dev/null +++ b/app/components/page_component.html.erb @@ -0,0 +1,10 @@ +
+
+ <%= tag.h1(class: "sm:text-3xl text-2xl font-medium text-center title-font text-white mb-4") { title } if title %> + <%= tag.p(class: "text-base leading-relaxed xl:w-2/4 lg:w-3/4 mx-auto") { subtitle } if subtitle %> +
+
+ <%= body %> +
+ <%= actions %> +
diff --git a/app/components/page_component.rb b/app/components/page_component.rb new file mode 100644 index 0000000..9c33ca7 --- /dev/null +++ b/app/components/page_component.rb @@ -0,0 +1,11 @@ +class PageComponent < ApplicationComponent + with_content_areas :title, :subtitle, :body, :actions + + # def initialize(body_width: "lg:w-1/2 md:w-2/3") + # @body_width = body_width + # end + + private + + # attr_reader :body_width +end diff --git a/app/controllers/badges_controller.rb b/app/controllers/badges_controller.rb new file mode 100644 index 0000000..d43a749 --- /dev/null +++ b/app/controllers/badges_controller.rb @@ -0,0 +1,75 @@ +class BadgesController < ApplicationController + before_action :set_badge, only: [:show, :edit, :update, :destroy] + + # GET /badges + # GET /badges.json + def index + @badges = Badge.all + end + + # GET /badges/1 + # GET /badges/1.json + def show + end + + # GET /badges/new + def new + @badge = Badge.new + end + + # GET /badges/1/edit + def edit + end + + # POST /badges + # POST /badges.json + def create + @badge = Badge.new(badge_params) + + respond_to do |format| + if @badge.save + format.html { redirect_to @badge, notice: "Badge was successfully created." } + format.json { render :show, status: :created, location: @badge } + else + format.html { render :new } + format.json { render json: @badge.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /badges/1 + # PATCH/PUT /badges/1.json + def update + respond_to do |format| + if @badge.update(badge_params) + format.html { redirect_to @badge, notice: "Badge was successfully updated." } + format.json { render :show, status: :ok, location: @badge } + else + format.html { render :edit } + format.json { render json: @badge.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /badges/1 + # DELETE /badges/1.json + def destroy + @badge.destroy + respond_to do |format| + format.html { redirect_to badges_url, notice: "Badge was successfully destroyed." } + format.json { head :no_content } + end + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_badge + @badge = Badge.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def badge_params + params.require(:badge).permit(:title, :asset_url, :source_url, :belongs_to) + end +end diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb new file mode 100644 index 0000000..124946d --- /dev/null +++ b/app/controllers/categories_controller.rb @@ -0,0 +1,75 @@ +class CategoriesController < ApplicationController + before_action :set_category, only: [:show, :edit, :update, :destroy] + + # GET /categories + # GET /categories.json + def index + @categories = Category.all + end + + # GET /categories/1 + # GET /categories/1.json + def show + end + + # GET /categories/new + def new + @category = Category.new + end + + # GET /categories/1/edit + def edit + end + + # POST /categories + # POST /categories.json + def create + @category = Category.new(category_params) + + respond_to do |format| + if @category.save + format.html { redirect_to @category, notice: "Category was successfully created." } + format.json { render :show, status: :created, location: @category } + else + format.html { render :new } + format.json { render json: @category.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /categories/1 + # PATCH/PUT /categories/1.json + def update + respond_to do |format| + if @category.update(category_params) + format.html { redirect_to @category, notice: "Category was successfully updated." } + format.json { render :show, status: :ok, location: @category } + else + format.html { render :edit } + format.json { render json: @category.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /categories/1 + # DELETE /categories/1.json + def destroy + @category.destroy + respond_to do |format| + format.html { redirect_to categories_url, notice: "Category was successfully destroyed." } + format.json { head :no_content } + end + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_category + @category = Category.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def category_params + params.require(:category).permit(:name, :categorizations_count) + end +end diff --git a/app/controllers/organizations_controller.rb b/app/controllers/organizations_controller.rb new file mode 100644 index 0000000..fb7af9b --- /dev/null +++ b/app/controllers/organizations_controller.rb @@ -0,0 +1,75 @@ +class OrganizationsController < ApplicationController + before_action :set_organization, only: [:show, :edit, :update, :destroy] + + # GET /organizations + # GET /organizations.json + def index + @organizations = Organization.all + end + + # GET /organizations/1 + # GET /organizations/1.json + def show + end + + # GET /organizations/new + def new + @organization = Organization.new + end + + # GET /organizations/1/edit + def edit + end + + # POST /organizations + # POST /organizations.json + def create + @organization = Organization.new(organization_params) + + respond_to do |format| + if @organization.save + format.html { redirect_to @organization, notice: "Organization was successfully created." } + format.json { render :show, status: :created, location: @organization } + else + format.html { render :new } + format.json { render json: @organization.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /organizations/1 + # PATCH/PUT /organizations/1.json + def update + respond_to do |format| + if @organization.update(organization_params) + format.html { redirect_to @organization, notice: "Organization was successfully updated." } + format.json { render :show, status: :ok, location: @organization } + else + format.html { render :edit } + format.json { render json: @organization.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /organizations/1 + # DELETE /organizations/1.json + def destroy + @organization.destroy + respond_to do |format| + format.html { redirect_to organizations_url, notice: "Organization was successfully destroyed." } + format.json { head :no_content } + end + end + + private + + # Use callbacks to share common setup or constraints between actions. + def set_organization + @organization = Organization.find(params[:id]) + end + + # Only allow a list of trusted parameters through. + def organization_params + params.require(:organization).permit(:name, :url, :type) + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 98559e8..de6be79 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,10 +1,2 @@ module ApplicationHelper - def bootstrap_class_for(flash_type) - { - success: "alert-success", - error: "alert-danger", - alert: "alert-warning", - notice: "alert-info" - }.stringify_keys[flash_type.to_s] || flash_type.to_s - end end diff --git a/app/helpers/badges_helper.rb b/app/helpers/badges_helper.rb new file mode 100644 index 0000000..a42504e --- /dev/null +++ b/app/helpers/badges_helper.rb @@ -0,0 +1,2 @@ +module BadgesHelper +end diff --git a/app/helpers/categories_helper.rb b/app/helpers/categories_helper.rb new file mode 100644 index 0000000..e06f315 --- /dev/null +++ b/app/helpers/categories_helper.rb @@ -0,0 +1,2 @@ +module CategoriesHelper +end diff --git a/app/helpers/organizations_helper.rb b/app/helpers/organizations_helper.rb new file mode 100644 index 0000000..24cc9a8 --- /dev/null +++ b/app/helpers/organizations_helper.rb @@ -0,0 +1,2 @@ +module OrganizationsHelper +end diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js index 842d687..1bf9a4e 100644 --- a/app/javascript/controllers/index.js +++ b/app/javascript/controllers/index.js @@ -20,3 +20,16 @@ application.load( ) ) StimulusReflex.initialize(application, { consumer, controller, debug: false }) + +import { + Dropdown, + Modal, + Tabs, + Popover, + Toggle +} from 'tailwindcss-stimulus-components' +application.register('dropdown', Dropdown) +application.register('modal', Modal) +application.register('tabs', Tabs) +application.register('popover', Popover) +application.register('toggle', Toggle) diff --git a/app/javascript/images/ruby.svg b/app/javascript/images/ruby.svg new file mode 100644 index 0000000..978383c --- /dev/null +++ b/app/javascript/images/ruby.svg @@ -0,0 +1,259 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/javascript/packs/application.css b/app/javascript/packs/application.css new file mode 100644 index 0000000..044bc68 --- /dev/null +++ b/app/javascript/packs/application.css @@ -0,0 +1,815 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --base-500: #a0aec0; + --base-200: #e2e8f0; + --base-300: #e2e8f0; + --base-400: #cbd5e0; + --main-500: #667eea; + --main-400: #7f9cf5; + --main-200: #c3dafe; + --main-100: #ebf4ff; + --solid: #fff; + --solid-900: #4a5568; + --sidebar-bg: #edf2f7; + --sidebar-color: #4a5568; + --shadow: 0 10px 15px -3px rgba(36, 69, 101, 0.19), + 0 4px 6px -2px rgb(208, 220, 232); + --shadow-active: 0 0 0 2px currentColor, + 0 10px 15px -3px rgba(36, 69, 101, 0.19), 0 4px 6px -2px rgb(208, 220, 232); + --opener: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='white' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 24 24'%3E%3Cpath d='M3 12h18M3 6h18M3 18h18'/%3E%3C/svg%3E"); + --opener-active: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='white' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round' class='css-i6dzq1' viewBox='0 0 24 24'%3E%3Cpath d='M19 12H5M12 19l-7-7 7-7'/%3E%3C/svg%3E"); +} + +.dark-mode { + --base-500: #718096; + --base-200: #2d3748; + --base-300: #4a5568; + --base-400: #4a5568; + --main-500: #667eea; + --main-200: #4a5568; + --main-100: #2d3648; + --solid: #1a202c; + --solid-900: #d1dcec; + --sidebar-bg: #2d3648; + --sidebar-color: #fff; + --shadow: 0 10px 15px -3px rgb(26, 32, 45), 0 4px 6px -2px rgb(48, 58, 84); + --shadow-active: 0 0 0 2px currentColor, 0 10px 15px -3px rgba(0, 0, 0, 0.35), + 0 4px 6px -2px rgb(76, 82, 90); +} + +.red:not(.dark-mode) { + --main-200: #fed7d7; + --main-100: #fed7d7; +} + +.red { + --main-500: #f56565; + --main-400: #fc8181; +} + +.orange { + --main-500: #ed8936; + --main-400: #f6ad55; +} + +.orange:not(.dark-mode) { + --main-200: #feebc8; + --main-100: #fffaf0; +} + +.green { + --main-500: #48bb78; + --main-400: #68d391; +} + +.green:not(.dark-mode) { + --main-200: #c6f6d5; + --main-100: #c6f6d5; +} + +.teal { + --main-500: #38b2ac; + --main-400: #4fd1c5; +} + +.teal:not(.dark-mode) { + --main-200: #b2f5ea; + --main-100: #e6fffa; +} + +.blue { + --main-500: #4299e1; + --main-400: #63b3ed; +} + +.blue:not(.dark-mode) { + --main-200: #bee3f8; + --main-100: #ebf8ff; +} + +.purple { + --main-500: #9f7aea; + --main-400: #b794f4; +} + +.purple:not(.dark-mode) { + --main-200: #e9d8fd; + --main-100: #faf5ff; +} + +.pink { + --main-500: #ed64a6; + --main-400: #f687b3; +} + +.pink:not(.dark-mode) { + --main-200: #fed7e2; + --main-100: #fff5f7; +} + +button { + user-select: none; +} + +button, +button:focus { + outline: 0; +} + +body { + margin: 0; + font-family: 'Raleway', -apple-system, BlinkMacSystemFont, 'Segoe UI', + 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', + 'Helvetica Neue', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + overflow: hidden; +} + +iframe { + width: 100%; + height: 100%; + border: 0; + background-color: var(--solid); +} + +.app { + height: 100vh; +} + +.app.dark-mode { + background-color: #1a202c; +} + +.main { + height: calc(100vh - 148px); + overflow: auto; + transition: 0.3s; +} +::-webkit-scrollbar-thumb, +::-webkit-scrollbar-track, +::-webkit-scrollbar { + display: none; +} + +.sidebar { + height: 100vh; + width: 160px; + z-index: 1; + position: fixed; + overflow: auto; + left: 0; + transform: translateX(-100%); + padding: 20px; + top: 0; + background-color: var(--sidebar-bg); + display: flex; + flex-direction: column; + align-items: center; + transition: transform 0.3s; +} + +.app.has-sidebar .sidebar { + box-shadow: 2px 68px 10px rgba(194, 206, 219, 0.68); +} +.dark-mode.has-sidebar .sidebar { + box-shadow: 2px 68px 10px rgba(26, 32, 44, 0.8); +} + +.block-category { + margin-bottom: 10px; + color: var(--sidebar-color); + font-size: 13px; + text-transform: uppercase; + font-weight: 600; + margin-bottom: 10px; +} + +.block-item { + padding: 0; + border: 0; + border-radius: 4px; + box-shadow: var(--shadow); + overflow: hidden; + color: var(--main-500); +} + +.block-item.is-active { + background-color: var(--main-500); + box-shadow: var(--shadow-active); +} + +.block-item.is-active > svg { + opacity: 0.8; +} + +.block-item + .block-item { + margin-top: 20px; +} +.blocks + .blocks { + margin-top: 30px; +} +svg { + width: 100%; +} + +.app.has-sidebar .toolbar { + padding: 0 16px 0 176px; +} + +.toolbar { + background-color: var(--main-500); + transition: padding 0.3s; + padding: 0 16px; + height: 64px; + display: flex; + align-items: center; +} + +.app.has-sidebar .sidebar { + transform: translateX(0); +} + +.switcher { + display: flex; + padding: 0 10px; + height: 32px; + border-radius: 20px; + background-color: #fff; + align-items: center; + margin-right: 16px; +} + +.theme-button { + width: 20px; + height: 20px; + border-radius: 50%; +} + +.theme-button.is-active { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='white' stroke-width='3' fill='none' stroke-linecap='round' stroke-linejoin='round' class='css-i6dzq1' viewBox='0 0 24 24'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E"); + background-size: 10px; + content: ''; + background-repeat: no-repeat; + background-size: 14px; + background-position: center; +} + +.theme-button + .theme-button { + margin-left: 5px; +} + +.opener { + color: #fff; + display: flex; + align-items: center; + font-weight: 600; + flex-shrink: 0; + position: relative; +} + +.opener::before { + background-image: var(--opener); + display: inline-block; + width: 18px; + flex-shrink: 0; + height: 18px; + content: ''; + background-size: cover; + background-repeat: no-repeat; + margin-right: 4px; +} + +.app.has-sidebar .opener::before { + background-image: var(--opener-active); +} + +.mode { + background-color: rgba(255, 255, 255, 0.192); + border-radius: 30px; + width: 58px; + position: relative; + height: 32px; + flex-shrink: 0; + margin-left: 16px; +} + +.mode::before { + width: 32px; + height: 100%; + content: ''; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='white' stroke-width='2.4' fill='white' stroke-linecap='round' stroke-linejoin='round' class='css-i6dzq1' viewBox='0 0 24 24'%3E%3Ccircle cx='12' cy='12' r='5'/%3E%3Cpath d='M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42'/%3E%3C/svg%3E"); + background-size: cover; + left: 0; + position: absolute; + top: 0; + background-repeat: no-repeat; + background-size: 50%; + transition: 0.3s; + background-position: center; +} + +.mode::after { + width: 20px; + height: 20px; + position: absolute; + right: 6px; + top: 6px; + background-color: var(--main-500); + content: ''; + border-radius: 50%; + transition: transform 0.3s; +} + +.app.dark-mode .mode { + background-color: rgba(0, 0, 0, 0.171); +} +.app.dark-mode .mode::after { + transform: translateX(-24px); +} +.app.dark-mode .mode::before { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='white' stroke-width='2' fill='white' stroke-linecap='round' stroke-linejoin='round' class='css-i6dzq1' viewBox='0 0 24 24'%3E%3Cpath d='M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z'/%3E%3C/svg%3E"); + transform: translateX(26px); +} + +.device { + color: #fff; + opacity: 0.3; + transition: 0.3s; +} + +.device.is-active { + opacity: 1; +} + +.device + .device { + margin-left: 8px; +} + +.view { + position: relative; +} + +.app.desktop .view { + height: 100%; +} + +.device > svg { + width: 24px; +} + +.app.phone .view iframe { + height: 736px; + width: 414px; + margin: 60px auto 0; + border: 2px solid var(--base-300); +} + +.app.phone .view { + width: 450px; + height: 880px; + background-color: var(--sidebar-bg); + border-radius: 30px; + border: 2px solid var(--base-300); + margin: 60px auto; +} + +.app.phone:not(.dark-mode) .view::before, +.app.phone:not(.dark-mode) .view::after { + opacity: 0.6; +} + +.app.phone .view::before { + position: absolute; + left: 50%; + bottom: 20px; + transform: translateX(-50%); + border: 2px solid var(--base-400); + content: ''; + width: 40px; + border-radius: 50%; + height: 40px; +} + +.app.phone .view::after { + content: ''; + position: absolute; + left: 50%; + transform: translateX(-50%); + top: 23px; + width: 100px; + height: 16px; + border-radius: 40px; + border: 2px solid var(--base-400); +} + +.app.tablet .view { + margin: 60px auto; + width: 868px; + height: 1164px; + background-color: var(--sidebar-bg); + border-radius: 30px; + border: 2px solid var(--base-300); +} + +.app.tablet .view iframe { + height: 1024px; + width: 768px; + margin: 50px auto 0; + border: 2px solid var(--base-300); +} + +.app.tablet .view::before { + position: absolute; + left: 50%; + bottom: 20px; + transform: translateX(-50%); + border: 2px solid var(--base-400); + content: ''; + width: 50px; + border-radius: 50%; + height: 50px; +} + +.markup { + display: none; +} + +.toolbar > :nth-child(2) { + margin-left: auto; +} + +.copy-the-block { + border: 1px solid rgba(255, 255, 255, 0.4); + padding: 0 12px; + flex-shrink: 0; + border-radius: 20px; + margin-right: 14px; + display: flex; + font-weight: 600; + align-items: center; + color: #fff; + height: 32px; + overflow: hidden; + position: relative; + justify-content: center; + width: 130px; + text-align: center; + font-size: 13px; + transition: 0.3s; +} + +.copy-to-clipboard { + white-space: nowrap; + width: auto; +} + +.copy-the-block > svg { + width: 16px; + flex-shrink: 0; + margin-right: 6px; +} + +.copy-to-clipboard > svg { + width: 13px; +} + +.knyttneve { + position: fixed; + bottom: 20px; + right: 20px; + color: #fff; + border-radius: 20px; + height: 32px; + width: 210px; + font-size: 13px; + text-align: center; + overflow: hidden; + font-weight: 500; +} + +.knyttneve span { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + text-align: center; + display: flex; + align-items: center; + justify-content: center; + transition: 0.3s; +} + +.id { + transform: translateY(-100%); +} + +.knyttneve:hover .id { + transform: none; +} + +.follow svg { + width: 14px; + margin-right: 8px; + height: 14px; +} + +.knyttneve:hover .follow { + transform: translateY(100%); +} + +.copy-textarea { + position: absolute; + right: -9999990px; + top: -999999999px; + opacity: 0; +} + +.codes { + float: right; + display: none; + width: 100%; + transition: 0.3s; +} + +.app.has-sidebar .codes { + width: calc(100% - 160px); +} + +.dark-mode .view.show-code, +.dark-mode .codes pre { + background-color: #1a202c !important; +} + +.view.show-code, +.codes pre { + background-color: #fff !important; +} + +.codes pre { + padding: 20px !important; + font-size: 13.6px; + line-height: 1.8; +} + +.react-syntax-highlighter-line-number { + opacity: 0.2; + pointer-events: none; + user-select: none; + font-size: 12px; +} + +pre, +code { + font-family: 'Space Mono', monospace; + font-variant-ligatures: no-contextual; +} + +.view.show-code iframe { + display: none; +} + +.view.show-code .codes { + display: block; +} + +.github { + padding: 8px 12px; + border-radius: 50px; + position: fixed; + right: 20px; + bottom: 20px; + background-color: var(--solid-900); + color: #fff; + display: inline-flex; + font-weight: 600; + align-items: center; + justify-content: center; +} + +.github svg { + width: 24px; + flex-shrink: 0; + margin-right: 6px; +} + +.dark-mode .github { + color: #1a202c; + background-color: #fff; +} + +.clipboard-wrapper { + display: flex; + flex-direction: row-reverse; + align-items: center; + position: relative; +} + +.clipboard-tooltip { + color: #68717d; + font-size: 13px; + background-color: #fff; + padding: 2px 5px; + letter-spacing: 0.2px; + border-radius: 4px; + position: absolute; + right: 100%; + opacity: 0; + transition: opacity 0.4s, margin-right 0.4s; +} + +.clipboard-tooltip.is-copied { + margin-right: 6px; + opacity: 1; +} + +@media (max-width: 1060px) { + .device { + display: none; + } + + .switcher { + margin-right: 0; + } +} + +.keyboard-nav { + position: fixed; + right: 158px; + bottom: 18px; + display: flex; + flex-direction: column; + align-items: center; +} + +.keyboard-nav-row { + display: flex; +} + +.keyboard-button { + width: 20px; + height: 20px; + opacity: 1; + border-radius: 4px; + flex-shrink: 0; + margin: 1px; + opacity: 0.5; + background-color: var(--base-300); + color: var(--solid-900); + padding: 3px; + position: relative; +} + +.keyboard-nav:hover .keyboard-button:not(:hover) { + opacity: 0.2; +} + +.keyboard-button:hover { + opacity: 1; +} + +.keyboard-button:before { + content: attr(data-info); + position: absolute; + color: var(--solid-900); + pointer-events: none; + font-size: 8px; + text-transform: uppercase; + transition: opacity 0.3s; + text-align: center; + white-space: nowrap; + padding: 1px 4px; + background-color: var(--base-200); + border-radius: 4px; + opacity: 0; + pointer-events: none; + z-index: -1; +} + +.keyboard-button.is-active { + animation-name: keyboard; + animation-duration: 0.2s; + animation-fill-mode: forwards; +} + +@keyframes keyboard { + 0% { + box-shadow: 0; + } + 50% { + box-shadow: 0 0 0 5px var(--main-500); + z-index: 1; + } +} + +.keyboard-button:hover:before { + opacity: 1; + z-index: 1; +} + +.k-up:before { + left: 50%; + transform: translateX(-50%); + top: 24px; +} + +.k-down:before { + left: 50%; + transform: translateX(-50%); + top: -18px; +} + +.k-left:before { + right: -70px; + top: 4px; +} + +.k-right:before { + left: -76px; + top: 4px; +} + +.keyboard-button:hover:before { + opacity: 1; +} + +@media (max-width: 960px) { + .copy-to-clipboard { + display: none; + } + + .keyboard-nav { + display: none; + } +} + +@media (max-width: 760px) { + .copy-the-block { + display: none; + } + + .opener { + width: 40px; + height: 100%; + overflow: hidden; + color: transparent; + white-space: nowrap; + } + + .opener::before { + width: 24px; + height: 24px; + } + + .mode { + margin-left: auto; + } + + .sidebar { + z-index: 2; + } + + .switcher { + position: fixed; + bottom: 24px; + z-index: 1; + background-color: #fff; + border: 1px solid var(--base-200); + left: 20px; + } + + .dark-mode .switcher { + background-color: #1a202c; + } +} + +@media (max-width: 380px) { + .github { + width: 36px; + height: 36px; + overflow: hidden; + border-radius: 50%; + color: transparent; + white-space: nowrap; + } + + .github svg { + position: absolute; + top: 50%; + left: 50%; + color: #fff; + transform: translate(-50%, -50%); + } + + .dark-mode .github { + color: transparent; + } + + .dark-mode .github svg { + color: #1a202c; + } +} diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 67e93c2..55ccb01 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -12,7 +12,9 @@ require('channels') // them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>) // or the `imagePath` JavaScript helper below. // -// const images = require.context('../images', true) -// const imagePath = (name) => images(name, true) +const images = require.context('../images', true) +const imagePath = name => images(name, true) import 'controllers' + +require('typeface-raleway') diff --git a/app/javascript/packs/application.scss b/app/javascript/packs/application.scss deleted file mode 100644 index a31e444..0000000 --- a/app/javascript/packs/application.scss +++ /dev/null @@ -1,3 +0,0 @@ -@import 'tailwindcss/base'; -@import 'tailwindcss/components'; -@import 'tailwindcss/utilities'; diff --git a/app/models/badge.rb b/app/models/badge.rb new file mode 100644 index 0000000..cc19d6f --- /dev/null +++ b/app/models/badge.rb @@ -0,0 +1,45 @@ +# == Schema Information +# +# Table name: badges +# +# id :bigint not null, primary key +# asset_url :string +# description :string +# source_url :string +# title :string not null +# created_at :datetime not null +# updated_at :datetime not null +# organization_id :bigint +# +# Indexes +# +# index_badges_on_organization_id (organization_id) +# +class Badge < ApplicationRecord + # extends ................................................................... + + # includes .................................................................. + + # relationships ............................................................. + belongs_to :organization + has_many :categorizations, as: :categorizable + + # validations ............................................................... + validates :title, presence: true + validates :description, length: {maximum: 100} + validates_uniqueness_of :asset_url, scope: :title + + # callbacks ................................................................. + + # scopes .................................................................... + + # additional config (i.e. accepts_nested_attribute_for etc...) .............. + + # class methods ............................................................. + + # public instance methods ................................................... + + # protected instance methods ................................................ + + # private instance methods .................................................. +end diff --git a/app/models/categorization.rb b/app/models/categorization.rb new file mode 100644 index 0000000..9c929cb --- /dev/null +++ b/app/models/categorization.rb @@ -0,0 +1,46 @@ +# == Schema Information +# +# Table name: categorizations +# +# id :bigint not null, primary key +# categorizable_type :string not null +# created_at :datetime not null +# updated_at :datetime not null +# categorizable_id :bigint not null +# category_id :bigint not null +# +# Indexes +# +# categorizationable_id_type_idx (categorizable_id,categorizable_type) +# index_categorizations_on_categorizable_id (categorizable_id) +# index_categorizations_on_categorizable_type (categorizable_type) +# index_categorizations_on_category_id (category_id) +# +class Categorization < ApplicationRecord + # extends ................................................................... + + # includes .................................................................. + + # relationships ............................................................. + belongs_to :category + belongs_to :categorizable, polymorphic: true + + # validations ............................................................... + validates :category, presence: true + validates :categorizable_type, presence: true + validates :categorizable_id, presence: true + + # callbacks ................................................................. + + # scopes .................................................................... + + # additional config (i.e. accepts_nested_attribute_for etc...) .............. + + # class methods ............................................................. + + # public instance methods ................................................... + + # protected instance methods ................................................ + + # private instance methods .................................................. +end diff --git a/app/models/category.rb b/app/models/category.rb new file mode 100644 index 0000000..3710586 --- /dev/null +++ b/app/models/category.rb @@ -0,0 +1,40 @@ +# == Schema Information +# +# Table name: categories +# +# id :bigint not null, primary key +# categorizations_count :integer default(0), not null +# name :string not null +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_categories_on_name (name) +# +class Category < ApplicationRecord + # extends ................................................................... + + # includes .................................................................. + + # relationships ............................................................. + has_many :categorizations, dependent: :destroy, class_name: "Categorization", as: :categorizable + + # validations ............................................................... + validates :name, length: {in: 1..40}, presence: true + validates :categorizations_count, numericality: true + + # callbacks ................................................................. + + # scopes .................................................................... + + # additional config (i.e. accepts_nested_attribute_for etc...) .............. + + # class methods ............................................................. + + # public instance methods ................................................... + + # protected instance methods ................................................ + + # private instance methods .................................................. +end diff --git a/app/models/organization.rb b/app/models/organization.rb new file mode 100644 index 0000000..89b1c72 --- /dev/null +++ b/app/models/organization.rb @@ -0,0 +1,40 @@ +# == Schema Information +# +# Table name: organizations +# +# id :bigint not null, primary key +# company :boolean default(FALSE), not null +# name :string not null +# pricing_strategy :integer default("free"), not null +# url :string +# created_at :datetime not null +# updated_at :datetime not null +# +class Organization < ApplicationRecord + # extends ................................................................... + + # includes .................................................................. + + # relationships ............................................................. + has_many :badges + + # validations ............................................................... + validates :name, length: {in: 1..40}, presence: true + validates :company, presence: true + validates :pricing_strategy, presence: true + + # callbacks ................................................................. + + # scopes .................................................................... + + # additional config (i.e. accepts_nested_attribute_for etc...) .............. + enum pricing_strategy: {free: 0, hybrid: 1, paid: 2} + + # class methods ............................................................. + + # public instance methods ................................................... + + # protected instance methods ................................................ + + # private instance methods .................................................. +end diff --git a/app/views/badges/_badge.json.jbuilder b/app/views/badges/_badge.json.jbuilder new file mode 100644 index 0000000..25d5ce8 --- /dev/null +++ b/app/views/badges/_badge.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! badge, :id, :title, :asset_url, :source_url, :belongs_to, :created_at, :updated_at +json.url badge_url(badge, format: :json) diff --git a/app/views/badges/_form.html.erb b/app/views/badges/_form.html.erb new file mode 100644 index 0000000..1f3cf92 --- /dev/null +++ b/app/views/badges/_form.html.erb @@ -0,0 +1,18 @@ +<%= form_with(model: badge, local: true) do |form| %> + <%= render(Form::ErrorsComponent.new(object: badge)) %> +
+ <%= form.text_field :title, class: "w-full bg-gray-800 rounded border border-gray-700 text-white focus:outline-none focus:border-red-500 text-base px-4 py-2", placeholder: "Title" %> +
+
+ <%= form.text_area :description, class: "block w-full h-48 px-4 py-2 text-base text-white bg-gray-800 border border-gray-700 rounded resize-none focus:outline-none focus:border-red-500", placeholder: "Description" %> +
+
+ <%= form.text_field :source_url, class: "w-full bg-gray-800 rounded border border-gray-700 text-white focus:outline-none focus:border-red-500 text-base px-4 py-2", placeholder: "Source URL" %> +
+
+ <%= form.text_field :asset_url, class: "w-full bg-gray-800 rounded border border-gray-700 text-white focus:outline-none focus:border-red-500 text-base px-4 py-2", placeholder: "Asset URL" %> +
+
+ <%= form.submit "Create Badge", class: "flex text-white bg-red-500 border-0 py-2 px-8 focus:outline-none hover:bg-red-600 rounded text-lg" %> +
+<% end %> diff --git a/app/views/badges/edit.html.erb b/app/views/badges/edit.html.erb new file mode 100644 index 0000000..abe777e --- /dev/null +++ b/app/views/badges/edit.html.erb @@ -0,0 +1,7 @@ +<%= render(PageComponent.new) do |component| %> + <%= component.with(:title) {"Editing Badge"} %> + <% component.with(:body) do %> + <%= render 'form', badge: @badge %> + <%= link_to 'Show', @badge %> | <%= link_to 'Back', badges_path %> + <% end %> +<% end %> diff --git a/app/views/badges/index.html.erb b/app/views/badges/index.html.erb new file mode 100644 index 0000000..ecb1f8b --- /dev/null +++ b/app/views/badges/index.html.erb @@ -0,0 +1,13 @@ +

<%= notice %>

+ +<%= render(PageComponent.new) do |component| %> + <%= component.with(:title) {"Badges"} %> + <% component.with(:body) do %> + <%= render(BadgeComponent.with_collection(@badges)) %> + <% end %> + <% component.with(:actions) do %> +
+ <%= link_to 'New Badge', new_badge_path, class: "mx-auto mt-16 text-white bg-red-500 border-0 py-2 px-8 focus:outline-none hover:bg-red-600 rounded text-lg" %> +
+ <% end %> +<% end %> diff --git a/app/views/badges/index.json.jbuilder b/app/views/badges/index.json.jbuilder new file mode 100644 index 0000000..48b4254 --- /dev/null +++ b/app/views/badges/index.json.jbuilder @@ -0,0 +1 @@ +json.array! @badges, partial: "badges/badge", as: :badge diff --git a/app/views/badges/new.html.erb b/app/views/badges/new.html.erb new file mode 100644 index 0000000..2e904b3 --- /dev/null +++ b/app/views/badges/new.html.erb @@ -0,0 +1,7 @@ +<%= render(PageComponent.new) do |component| %> + <%= component.with(:title) {"New Badge"} %> + <% component.with(:body) do %> + <%= render 'form', badge: @badge %> + <%= link_to 'Back', badges_path %> + <% end %> +<% end %> diff --git a/app/views/badges/show.html.erb b/app/views/badges/show.html.erb new file mode 100644 index 0000000..3166acc --- /dev/null +++ b/app/views/badges/show.html.erb @@ -0,0 +1,24 @@ +

<%= notice %>

+ +

+ Title: + <%= @badge.title %> +

+ +

+ Asset url: + <%= @badge.asset_url %> +

+ +

+ Source url: + <%= @badge.source_url %> +

+ +

+ Belongs to: + <%= @badge.belongs_to %> +

+ +<%= link_to 'Edit', edit_badge_path(@badge) %> | +<%= link_to 'Back', badges_path %> diff --git a/app/views/badges/show.json.jbuilder b/app/views/badges/show.json.jbuilder new file mode 100644 index 0000000..e4cfb7c --- /dev/null +++ b/app/views/badges/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! "badges/badge", badge: @badge diff --git a/app/views/categories/_category.json.jbuilder b/app/views/categories/_category.json.jbuilder new file mode 100644 index 0000000..add821b --- /dev/null +++ b/app/views/categories/_category.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! category, :id, :name, :categorizations_count, :created_at, :updated_at +json.url category_url(category, format: :json) diff --git a/app/views/categories/_form.html.erb b/app/views/categories/_form.html.erb new file mode 100644 index 0000000..8be6545 --- /dev/null +++ b/app/views/categories/_form.html.erb @@ -0,0 +1,27 @@ +<%= form_with(model: category, local: true) do |form| %> + <% if category.errors.any? %> +
+

<%= pluralize(category.errors.count, "error") %> prohibited this category from being saved:

+ + +
+ <% end %> + +
+ <%= form.label :name %> + <%= form.text_field :name %> +
+ +
+ <%= form.label :categorizations_count %> + <%= form.text_field :categorizations_count %> +
+ +
+ <%= form.submit %> +
+<% end %> diff --git a/app/views/categories/edit.html.erb b/app/views/categories/edit.html.erb new file mode 100644 index 0000000..b969417 --- /dev/null +++ b/app/views/categories/edit.html.erb @@ -0,0 +1,6 @@ +

Editing Category

+ +<%= render 'form', category: @category %> + +<%= link_to 'Show', @category %> | +<%= link_to 'Back', categories_path %> diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb new file mode 100644 index 0000000..43c7b09 --- /dev/null +++ b/app/views/categories/index.html.erb @@ -0,0 +1,29 @@ +

<%= notice %>

+ +

Categories

+ + + + + + + + + + + + <% @categories.each do |category| %> + + + + + + + + <% end %> + +
NameCategorizations count
<%= category.name %><%= category.categorizations_count %><%= link_to 'Show', category %><%= link_to 'Edit', edit_category_path(category) %><%= link_to 'Destroy', category, method: :delete, data: { confirm: 'Are you sure?' } %>
+ +
+ +<%= link_to 'New Category', new_category_path %> diff --git a/app/views/categories/index.json.jbuilder b/app/views/categories/index.json.jbuilder new file mode 100644 index 0000000..aa5baad --- /dev/null +++ b/app/views/categories/index.json.jbuilder @@ -0,0 +1 @@ +json.array! @categories, partial: "categories/category", as: :category diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb new file mode 100644 index 0000000..91d5ef7 --- /dev/null +++ b/app/views/categories/new.html.erb @@ -0,0 +1,5 @@ +

New Category

+ +<%= render 'form', category: @category %> + +<%= link_to 'Back', categories_path %> diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb new file mode 100644 index 0000000..5daa610 --- /dev/null +++ b/app/views/categories/show.html.erb @@ -0,0 +1,14 @@ +

<%= notice %>

+ +

+ Name: + <%= @category.name %> +

+ +

+ Categorizations count: + <%= @category.categorizations_count %> +

+ +<%= link_to 'Edit', edit_category_path(@category) %> | +<%= link_to 'Back', categories_path %> diff --git a/app/views/categories/show.json.jbuilder b/app/views/categories/show.json.jbuilder new file mode 100644 index 0000000..30e6b47 --- /dev/null +++ b/app/views/categories/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! "categories/category", category: @category diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb index f77700b..9bffc14 100644 --- a/app/views/home/index.html.erb +++ b/app/views/home/index.html.erb @@ -1 +1,9 @@ -

Home#index

+
+
+

+ Rubyists.dev +

+ + <%= link_to "Badges", badges_path, class: "flex-shrink-0 px-8 py-2 mt-10 text-lg text-white bg-red-500 border-0 rounded focus:outline-none hover:bg-red-600 sm:mt-0" %> +
+
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index ff26828..2f8f7be 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -5,18 +5,19 @@ <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= action_cable_meta_tag %> - <%= stylesheet_pack_tag "application", media: "all", "data-turbolinks-track": "reload" %> <%= javascript_pack_tag "application", "data-turbolinks-track": "reload", defer: true %> + <%= stylesheet_pack_tag "application", media: "all", "data-turbolinks-track": "reload" %> - <% flash.each do |msg_type, message| %> -
-
- - <%= message %> -
-
- <% end %> - <%= yield %> +
+ <%= render(HeaderComponent.new) %> + <%= render(FlashComponent.new(flash: flash)) %> +
+
+ <%= yield %> +
+
+ <%= render(FooterComponent.new) %> +
diff --git a/app/views/organizations/_form.html.erb b/app/views/organizations/_form.html.erb new file mode 100644 index 0000000..06d5667 --- /dev/null +++ b/app/views/organizations/_form.html.erb @@ -0,0 +1,32 @@ +<%= form_with(model: organization, local: true) do |form| %> + <% if organization.errors.any? %> +
+

<%= pluralize(organization.errors.count, "error") %> prohibited this organization from being saved:

+ + +
+ <% end %> + +
+ <%= form.label :name %> + <%= form.text_field :name %> +
+ +
+ <%= form.label :url %> + <%= form.text_field :url %> +
+ +
+ <%= form.label :type %> + <%= form.text_field :type %> +
+ +
+ <%= form.submit %> +
+<% end %> diff --git a/app/views/organizations/_organization.json.jbuilder b/app/views/organizations/_organization.json.jbuilder new file mode 100644 index 0000000..6ab1d12 --- /dev/null +++ b/app/views/organizations/_organization.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! organization, :id, :name, :url, :type, :created_at, :updated_at +json.url organization_url(organization, format: :json) diff --git a/app/views/organizations/edit.html.erb b/app/views/organizations/edit.html.erb new file mode 100644 index 0000000..0514ab1 --- /dev/null +++ b/app/views/organizations/edit.html.erb @@ -0,0 +1,6 @@ +

Editing Organization

+ +<%= render 'form', organization: @organization %> + +<%= link_to 'Show', @organization %> | +<%= link_to 'Back', organizations_path %> diff --git a/app/views/organizations/index.html.erb b/app/views/organizations/index.html.erb new file mode 100644 index 0000000..ac8facd --- /dev/null +++ b/app/views/organizations/index.html.erb @@ -0,0 +1,31 @@ +

<%= notice %>

+ +

Organizations

+ + + + + + + + + + + + + <% @organizations.each do |organization| %> + + + + + + + + + <% end %> + +
NameUrlType
<%= organization.name %><%= organization.url %><%= organization.type %><%= link_to 'Show', organization %><%= link_to 'Edit', edit_organization_path(organization) %><%= link_to 'Destroy', organization, method: :delete, data: { confirm: 'Are you sure?' } %>
+ +
+ +<%= link_to 'New Organization', new_organization_path %> diff --git a/app/views/organizations/index.json.jbuilder b/app/views/organizations/index.json.jbuilder new file mode 100644 index 0000000..ca6445d --- /dev/null +++ b/app/views/organizations/index.json.jbuilder @@ -0,0 +1 @@ +json.array! @organizations, partial: "organizations/organization", as: :organization diff --git a/app/views/organizations/new.html.erb b/app/views/organizations/new.html.erb new file mode 100644 index 0000000..be2be97 --- /dev/null +++ b/app/views/organizations/new.html.erb @@ -0,0 +1,5 @@ +

New Organization

+ +<%= render 'form', organization: @organization %> + +<%= link_to 'Back', organizations_path %> diff --git a/app/views/organizations/show.html.erb b/app/views/organizations/show.html.erb new file mode 100644 index 0000000..a051359 --- /dev/null +++ b/app/views/organizations/show.html.erb @@ -0,0 +1,19 @@ +

<%= notice %>

+ +

+ Name: + <%= @organization.name %> +

+ +

+ Url: + <%= @organization.url %> +

+ +

+ Type: + <%= @organization.type %> +

+ +<%= link_to 'Edit', edit_organization_path(@organization) %> | +<%= link_to 'Back', organizations_path %> diff --git a/app/views/organizations/show.json.jbuilder b/app/views/organizations/show.json.jbuilder new file mode 100644 index 0000000..78a9433 --- /dev/null +++ b/app/views/organizations/show.json.jbuilder @@ -0,0 +1 @@ +json.partial! "organizations/organization", organization: @organization diff --git a/config/cable.yml b/config/cable.yml index ca29a5b..a82a127 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -1,10 +1,14 @@ +default: &default + adapter: redis + url: <%= ENV.fetch("REDIS_URL", "redis://localhost:6379/0") %> + development: - adapter: async + <<: *default + channel_prefix: rubyists_development test: - adapter: test + adapter: async production: - adapter: redis - url: <%= ENV.fetch('REDIS_URL') %>/<%= ENV.fetch('REDIS_DB') %> + <<: *default channel_prefix: rubyists_production diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 88a9049..16b0fb4 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -2,16 +2,10 @@ # Sidekiq::Extensions.enable_delay! -defaults = { - url: ENV["REDIS_URL"], - db: ENV["REDIS_DB"], - namespace: ENV["SIDEKIQ_NAMESPACE"] -} - Sidekiq.configure_server do |config| - config.redis = defaults.merge(size: 50) + config.redis = {url: ENV["REDIS_URL"], size: ENV.fetch("REDIS_MAX_THREADS", 5).to_i} end Sidekiq.configure_client do |config| - config.redis = defaults.merge(size: 10) + config.redis = {url: ENV["REDIS_URL"], size: ENV.fetch("REDIS_MAX_THREADS", 5).to_i} end diff --git a/config/routes.rb b/config/routes.rb index 28c6ace..a2c04b9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,9 @@ # frozen_string_literal: true Rails.application.routes.draw do + resources :categories + resources :badges + resources :organizations # authenticate :user, lambda { |u| u.admin? } do # mount Sidekiq::Web => "/sidekiq" # end diff --git a/config/webpacker.yml b/config/webpacker.yml index 8581ac0..364147d 100644 --- a/config/webpacker.yml +++ b/config/webpacker.yml @@ -17,7 +17,7 @@ default: &default cache_manifest: false # Extract and emit a css file - extract_css: false + extract_css: true static_assets_extensions: - .jpg @@ -53,7 +53,7 @@ development: compile: true # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules - check_yarn_integrity: true + check_yarn_integrity: false # Reference: https://webpack.js.org/configuration/dev-server/ dev_server: diff --git a/db/migrate/20200529110858_create_organizations.rb b/db/migrate/20200529110858_create_organizations.rb new file mode 100644 index 0000000..3429bcd --- /dev/null +++ b/db/migrate/20200529110858_create_organizations.rb @@ -0,0 +1,12 @@ +class CreateOrganizations < ActiveRecord::Migration[6.0] + def change + create_table :organizations do |t| + t.string :name, null: false + t.string :url + t.boolean :company, null: false, default: false + t.integer :pricing_strategy, null: false, default: 0 + + t.timestamps + end + end +end diff --git a/db/migrate/20200529111031_create_badges.rb b/db/migrate/20200529111031_create_badges.rb new file mode 100644 index 0000000..e7e1751 --- /dev/null +++ b/db/migrate/20200529111031_create_badges.rb @@ -0,0 +1,13 @@ +class CreateBadges < ActiveRecord::Migration[6.0] + def change + create_table :badges do |t| + t.string :title, null: false + t.string :asset_url + t.string :source_url + t.string :description + t.references :organization, index: true + + t.timestamps + end + end +end diff --git a/db/migrate/20200529111615_create_categories.rb b/db/migrate/20200529111615_create_categories.rb new file mode 100644 index 0000000..5e412b2 --- /dev/null +++ b/db/migrate/20200529111615_create_categories.rb @@ -0,0 +1,9 @@ +class CreateCategories < ActiveRecord::Migration[6.0] + def change + create_table :categories do |t| + t.string :name, null: false, index: true + t.integer :categorizations_count, null: false, default: 0 + t.timestamps + end + end +end diff --git a/db/migrate/20200529111720_create_categorizations.rb b/db/migrate/20200529111720_create_categorizations.rb new file mode 100644 index 0000000..411e4ed --- /dev/null +++ b/db/migrate/20200529111720_create_categorizations.rb @@ -0,0 +1,12 @@ +class CreateCategorizations < ActiveRecord::Migration[6.0] + def change + create_table :categorizations do |t| + t.string :categorizable_type, null: false, index: true + t.bigint :categorizable_id, null: false, index: true + t.references :category, index: true, null: false + t.timestamps + end + + add_index :categorizations, [:categorizable_id, :categorizable_type], name: "categorizationable_id_type_idx" + end +end diff --git a/db/schema.rb b/db/schema.rb index 8daa167..d5f0cd6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_05_29_065227) do +ActiveRecord::Schema.define(version: 2020_05_29_111720) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -46,6 +46,37 @@ t.datetime "updated_at", precision: 6, null: false end + create_table "badges", force: :cascade do |t| + t.string "title", null: false + t.string "asset_url" + t.string "source_url" + t.string "description" + t.bigint "organization_id" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["organization_id"], name: "index_badges_on_organization_id" + end + + create_table "categories", force: :cascade do |t| + t.string "name", null: false + t.integer "categorizations_count", default: 0, null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["name"], name: "index_categories_on_name" + end + + create_table "categorizations", force: :cascade do |t| + t.string "categorizable_type", null: false + t.bigint "categorizable_id", null: false + t.bigint "category_id", null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["categorizable_id", "categorizable_type"], name: "categorizationable_id_type_idx" + t.index ["categorizable_id"], name: "index_categorizations_on_categorizable_id" + t.index ["categorizable_type"], name: "index_categorizations_on_categorizable_type" + t.index ["category_id"], name: "index_categorizations_on_category_id" + end + create_table "friendly_id_slugs", force: :cascade do |t| t.string "slug", null: false t.integer "sluggable_id", null: false @@ -57,6 +88,15 @@ t.index ["sluggable_type", "sluggable_id"], name: "index_friendly_id_slugs_on_sluggable_type_and_sluggable_id" end + create_table "organizations", force: :cascade do |t| + t.string "name", null: false + t.string "url" + t.boolean "company", default: false, null: false + t.integer "pricing_strategy", default: 0, null: false + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + create_table "services", force: :cascade do |t| t.bigint "user_id", null: false t.string "provider" diff --git a/db/seeds.rb b/db/seeds.rb index 1beea2a..9541163 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,7 +1,79 @@ -# This file should contain all the record creation needed to seed the database with its default values. -# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). -# -# Examples: -# -# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) -# Character.create(name: 'Luke', movie: movies.first) +code_climate = Organization.create!(name: "Code Climate", url: "https://codeclimate.com", company: true, pricing_strategy: :hybrid) +hakiri = Organization.create!(name: "Hakiri", url: "https://hakiri.io", company: true, pricing_strategy: :hybrid) +depfu = Organization.create!(name: "Depfu", url: "https://depfu.com", company: true, pricing_strategy: :hybrid) +snyk = Organization.create!(name: "Snyk", url: "https://snyk.io", company: true, pricing_strategy: :hybrid) +circleci = Organization.create!(name: "CircleCI", url: "https://circleci.com", company: true, pricing_strategy: :hybrid) +travis = Organization.create!(name: "Travis CI", url: "https://travis-ci.org", company: true, pricing_strategy: :hybrid) +codacy = Organization.create!(name: "Codacy", url: "https://codacy.com", company: true, pricing_strategy: :hybrid) +codebeat = Organization.create!(name: "Codebeat", url: "https://codebeat.co", company: true, pricing_strategy: :hybrid) + +Badge.create!( + [ + { + title: "Maintainability", + asset_url: "https://api.codeclimate.com/v1/badges/015a1b40a1400b2f6658/maintainability", + source_url: "https://codeclimate.com/github/andrewmcodes/rubyists.dev/maintainability", + organization: code_climate + }, + { + title: "Test Coverage", + asset_url: "https://api.codeclimate.com/v1/badges/015a1b40a1400b2f6658/test_coverage", + source_url: "https://codeclimate.com/github/andrewmcodes/rubyists.dev/test_coverage", + organization: code_climate + }, + { + title: "security", + asset_url: "https://hakiri.io/github/andrewmcodes/rubyists.dev/master.svg", + source_url: "https://hakiri.io/github/andrewmcodes/rubyists.dev/master", + organization: hakiri + }, + { + title: "Depfu Status", + asset_url: "https://badges.depfu.com/badges/df001d8bf70aa2e0a1b099af9a181d8e/status.svg", + source_url: "https://depfu.com", + organization: depfu + }, + { + title: "Bundler: Count of outdated dependencies", + asset_url: "https://badges.depfu.com/badges/035f8ba9007bb88cfddf642ff4a31beb/count.svg", + source_url: "https://depfu.com/github/andrewmcodes/rubyists.dev?project_id=13364", + organization: depfu + }, + { + title: "Yarn: Count of outdated dependencies", + asset_url: "https://badges.depfu.com/badges/df001d8bf70aa2e0a1b099af9a181d8e/count.svg", + source_url: "https://depfu.com/github/andrewmcodes/rubyists.dev?project_id=13365", + organization: depfu + }, + { + title: "Known Vulnerabilities", + asset_url: "https://snyk.io/test/github/andrewmcodes/rubyists.dev/badge.svg", + source_url: "https://snyk.io/test/github/andrewmcodes/rubyists.dev", + organization: snyk + }, + { + title: "CircleCI", + asset_url: "https://circleci.com/gh/andrewmcodes/rubyists.dev.svg?style=svg", + source_url: "https://circleci.com/gh/andrewmcodes/rubyists.dev", + organization: circleci + }, + { + title: "Build Status", + asset_url: "https://travis-ci.org/andrewmcodes/rubyists.dev.svg?branch=master", + source_url: "https://travis-ci.org/andrewmcodes/rubyists.dev", + organization: travis + }, + { + title: "Codebeat Badge", + asset_url: "https://codebeat.co/badges/d01df093-17b0-4043-86f0-87a6c0fb0d02", + source_url: "https://codebeat.co/projects/github-com-andrewmcodes-rubyists-dev-master", + organization: codebeat + }, + { + title: "Codacy Badge", + asset_url: "https://app.codacy.com/project/badge/Grade/6b88d9ceaba9469aa8f622e499e84f35", + source_url: "https://www.codacy.com/manual/andrewmcodes/rubyists.dev?utm_source=github.com&utm_medium=referral&utm_content=andrewmcodes/rubyists.dev&utm_campaign=Badge_Grade", + organization: codacy + } + ] +) diff --git a/package.json b/package.json index c2a697d..f993741 100644 --- a/package.json +++ b/package.json @@ -15,11 +15,13 @@ "@rails/actioncable": "^6.0.0", "@rails/activestorage": "^6.0.0", "@rails/ujs": "^6.0.0", - "@rails/webpacker": "4.2.2", + "@rails/webpacker": "^5.1.1", "stimulus": "^1.1.1", "stimulus_reflex": "^3.2.2-pre0", "tailwindcss": "^1.4.6", - "turbolinks": "^5.2.0" + "tailwindcss-stimulus-components": "^1.1.0", + "turbolinks": "^5.2.0", + "typeface-raleway": "^0.0.75" }, "devDependencies": { "prettier-standard": "^16.3.0", diff --git a/tailwind.config.js b/tailwind.config.js index aa29807..afc7990 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -9,7 +9,20 @@ module.exports = { ] }, theme: { - extend: {} + fontSize: { + xs: '.75rem', + sm: '.875rem', + base: '1rem', + lg: '1.125rem', + xl: '1.25rem', + '2xl': '1.5rem', + '3xl': '1.875rem', + '4xl': '2.25rem', + '5xl': '3rem', + '6xl': '4rem', + '8xl': '6rem', + '10xl': '8rem' + } }, variants: {}, plugins: [] diff --git a/test/components/badge_component_test.rb b/test/components/badge_component_test.rb new file mode 100644 index 0000000..65d170b --- /dev/null +++ b/test/components/badge_component_test.rb @@ -0,0 +1,10 @@ +require "test_helper" + +class BadgeComponentTest < ViewComponent::TestCase + test "component renders something useful" do + # assert_equal( + # %(Hello, components!), + # render_inline(BadgeComponent.new(message: "Hello, components!")).css("span").to_html + # ) + end +end diff --git a/test/components/flash_component_test.rb b/test/components/flash_component_test.rb new file mode 100644 index 0000000..2381544 --- /dev/null +++ b/test/components/flash_component_test.rb @@ -0,0 +1,10 @@ +require "test_helper" + +class FlashComponentTest < ViewComponent::TestCase + test "component renders something useful" do + # assert_equal( + # %(Hello, components!), + # render_inline(FlashComponent.new(message: "Hello, components!")).css("span").to_html + # ) + end +end diff --git a/test/components/footer_component_test.rb b/test/components/footer_component_test.rb new file mode 100644 index 0000000..dd460b9 --- /dev/null +++ b/test/components/footer_component_test.rb @@ -0,0 +1,10 @@ +require "test_helper" + +class FooterComponentTest < ViewComponent::TestCase + test "component renders something useful" do + # assert_equal( + # %(Hello, components!), + # render_inline(FooterComponent.new(message: "Hello, components!")).css("span").to_html + # ) + end +end diff --git a/test/components/form/errors_component_test.rb b/test/components/form/errors_component_test.rb new file mode 100644 index 0000000..ca6f016 --- /dev/null +++ b/test/components/form/errors_component_test.rb @@ -0,0 +1,10 @@ +require "test_helper" + +class Form::ErrorsComponentTest < ViewComponent::TestCase + test "component renders something useful" do + # assert_equal( + # %(Hello, components!), + # render_inline(Form::ErrorsComponent.new(message: "Hello, components!")).css("span").to_html + # ) + end +end diff --git a/test/components/header_component_test.rb b/test/components/header_component_test.rb new file mode 100644 index 0000000..4f0de76 --- /dev/null +++ b/test/components/header_component_test.rb @@ -0,0 +1,10 @@ +require "test_helper" + +class HeaderComponentTest < ViewComponent::TestCase + test "component renders something useful" do + # assert_equal( + # %(Hello, components!), + # render_inline(HeaderComponent.new(message: "Hello, components!")).css("span").to_html + # ) + end +end diff --git a/test/components/navbar_component_test.rb b/test/components/navbar_component_test.rb new file mode 100644 index 0000000..b66426d --- /dev/null +++ b/test/components/navbar_component_test.rb @@ -0,0 +1,10 @@ +require "test_helper" + +class NavbarComponentTest < ViewComponent::TestCase + test "component renders something useful" do + # assert_equal( + # %(Hello, components!), + # render_inline(NavbarComponent.new(message: "Hello, components!")).css("span").to_html + # ) + end +end diff --git a/test/components/page_component_test.rb b/test/components/page_component_test.rb new file mode 100644 index 0000000..b639b22 --- /dev/null +++ b/test/components/page_component_test.rb @@ -0,0 +1,10 @@ +require "test_helper" + +class PageComponentTest < ViewComponent::TestCase + test "component renders something useful" do + # assert_equal( + # %(Hello, components!), + # render_inline(PageComponent.new(message: "Hello, components!")).css("span").to_html + # ) + end +end diff --git a/test/controllers/badges_controller_test.rb b/test/controllers/badges_controller_test.rb new file mode 100644 index 0000000..46244d4 --- /dev/null +++ b/test/controllers/badges_controller_test.rb @@ -0,0 +1,48 @@ +require "test_helper" + +class BadgesControllerTest < ActionDispatch::IntegrationTest + setup do + @badge = badges(:one) + end + + test "should get index" do + get badges_url + assert_response :success + end + + test "should get new" do + get new_badge_url + assert_response :success + end + + test "should create badge" do + assert_difference("Badge.count") do + post badges_url, params: {badge: {asset_url: @badge.asset_url, belongs_to: @badge.belongs_to, source_url: @badge.source_url, title: @badge.title}} + end + + assert_redirected_to badge_url(Badge.last) + end + + test "should show badge" do + get badge_url(@badge) + assert_response :success + end + + test "should get edit" do + get edit_badge_url(@badge) + assert_response :success + end + + test "should update badge" do + patch badge_url(@badge), params: {badge: {asset_url: @badge.asset_url, belongs_to: @badge.belongs_to, source_url: @badge.source_url, title: @badge.title}} + assert_redirected_to badge_url(@badge) + end + + test "should destroy badge" do + assert_difference("Badge.count", -1) do + delete badge_url(@badge) + end + + assert_redirected_to badges_url + end +end diff --git a/test/controllers/categories_controller_test.rb b/test/controllers/categories_controller_test.rb new file mode 100644 index 0000000..cf59fb8 --- /dev/null +++ b/test/controllers/categories_controller_test.rb @@ -0,0 +1,48 @@ +require "test_helper" + +class CategoriesControllerTest < ActionDispatch::IntegrationTest + setup do + @category = categories(:one) + end + + test "should get index" do + get categories_url + assert_response :success + end + + test "should get new" do + get new_category_url + assert_response :success + end + + test "should create category" do + assert_difference("Category.count") do + post categories_url, params: {category: {categorizations_count: @category.categorizations_count, name: @category.name}} + end + + assert_redirected_to category_url(Category.last) + end + + test "should show category" do + get category_url(@category) + assert_response :success + end + + test "should get edit" do + get edit_category_url(@category) + assert_response :success + end + + test "should update category" do + patch category_url(@category), params: {category: {categorizations_count: @category.categorizations_count, name: @category.name}} + assert_redirected_to category_url(@category) + end + + test "should destroy category" do + assert_difference("Category.count", -1) do + delete category_url(@category) + end + + assert_redirected_to categories_url + end +end diff --git a/test/controllers/organizations_controller_test.rb b/test/controllers/organizations_controller_test.rb new file mode 100644 index 0000000..f5df38f --- /dev/null +++ b/test/controllers/organizations_controller_test.rb @@ -0,0 +1,48 @@ +require "test_helper" + +class OrganizationsControllerTest < ActionDispatch::IntegrationTest + setup do + @organization = organizations(:one) + end + + test "should get index" do + get organizations_url + assert_response :success + end + + test "should get new" do + get new_organization_url + assert_response :success + end + + test "should create organization" do + assert_difference("Organization.count") do + post organizations_url, params: {organization: {name: @organization.name, type: @organization.type, url: @organization.url}} + end + + assert_redirected_to organization_url(Organization.last) + end + + test "should show organization" do + get organization_url(@organization) + assert_response :success + end + + test "should get edit" do + get edit_organization_url(@organization) + assert_response :success + end + + test "should update organization" do + patch organization_url(@organization), params: {organization: {name: @organization.name, type: @organization.type, url: @organization.url}} + assert_redirected_to organization_url(@organization) + end + + test "should destroy organization" do + assert_difference("Organization.count", -1) do + delete organization_url(@organization) + end + + assert_redirected_to organizations_url + end +end diff --git a/test/fixtures/badges.yml b/test/fixtures/badges.yml new file mode 100644 index 0000000..bae569b --- /dev/null +++ b/test/fixtures/badges.yml @@ -0,0 +1,29 @@ +# == Schema Information +# +# Table name: badges +# +# id :bigint not null, primary key +# asset_url :string +# description :string +# source_url :string +# title :string not null +# created_at :datetime not null +# updated_at :datetime not null +# organization_id :bigint +# +# Indexes +# +# index_badges_on_organization_id (organization_id) +# + +one: + title: MyString + asset_url: MyString + source_url: MyString + belongs_to: + +two: + title: MyString + asset_url: MyString + source_url: MyString + belongs_to: diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml new file mode 100644 index 0000000..a6b12c5 --- /dev/null +++ b/test/fixtures/categories.yml @@ -0,0 +1,22 @@ +# == Schema Information +# +# Table name: categories +# +# id :bigint not null, primary key +# categorizations_count :integer default(0), not null +# name :string not null +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_categories_on_name (name) +# + +one: + name: MyString + categorizations_count: + +two: + name: MyString + categorizations_count: diff --git a/test/fixtures/categorizations.yml b/test/fixtures/categorizations.yml new file mode 100644 index 0000000..6044886 --- /dev/null +++ b/test/fixtures/categorizations.yml @@ -0,0 +1,28 @@ +# == Schema Information +# +# Table name: categorizations +# +# id :bigint not null, primary key +# categorizable_type :string not null +# created_at :datetime not null +# updated_at :datetime not null +# categorizable_id :bigint not null +# category_id :bigint not null +# +# Indexes +# +# categorizationable_id_type_idx (categorizable_id,categorizable_type) +# index_categorizations_on_categorizable_id (categorizable_id) +# index_categorizations_on_categorizable_type (categorizable_type) +# index_categorizations_on_category_id (category_id) +# + +one: + belongs_to: + categorizable_type: MyString + categorizable_id: + +two: + belongs_to: + categorizable_type: MyString + categorizable_id: diff --git a/test/fixtures/organizations.yml b/test/fixtures/organizations.yml new file mode 100644 index 0000000..5fac02e --- /dev/null +++ b/test/fixtures/organizations.yml @@ -0,0 +1,22 @@ +# == Schema Information +# +# Table name: organizations +# +# id :bigint not null, primary key +# company :boolean default(FALSE), not null +# name :string not null +# pricing_strategy :integer default("free"), not null +# url :string +# created_at :datetime not null +# updated_at :datetime not null +# + +one: + name: MyString + url: MyString + type: + +two: + name: MyString + url: MyString + type: diff --git a/test/models/badge_test.rb b/test/models/badge_test.rb new file mode 100644 index 0000000..1fc32fe --- /dev/null +++ b/test/models/badge_test.rb @@ -0,0 +1,24 @@ +# == Schema Information +# +# Table name: badges +# +# id :bigint not null, primary key +# asset_url :string +# description :string +# source_url :string +# title :string not null +# created_at :datetime not null +# updated_at :datetime not null +# organization_id :bigint +# +# Indexes +# +# index_badges_on_organization_id (organization_id) +# +require "test_helper" + +class BadgeTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/categorization_test.rb b/test/models/categorization_test.rb new file mode 100644 index 0000000..e99e8b8 --- /dev/null +++ b/test/models/categorization_test.rb @@ -0,0 +1,25 @@ +# == Schema Information +# +# Table name: categorizations +# +# id :bigint not null, primary key +# categorizable_type :string not null +# created_at :datetime not null +# updated_at :datetime not null +# categorizable_id :bigint not null +# category_id :bigint not null +# +# Indexes +# +# categorizationable_id_type_idx (categorizable_id,categorizable_type) +# index_categorizations_on_categorizable_id (categorizable_id) +# index_categorizations_on_categorizable_type (categorizable_type) +# index_categorizations_on_category_id (category_id) +# +require "test_helper" + +class CategorizationTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/category_test.rb b/test/models/category_test.rb new file mode 100644 index 0000000..7f3b093 --- /dev/null +++ b/test/models/category_test.rb @@ -0,0 +1,21 @@ +# == Schema Information +# +# Table name: categories +# +# id :bigint not null, primary key +# categorizations_count :integer default(0), not null +# name :string not null +# created_at :datetime not null +# updated_at :datetime not null +# +# Indexes +# +# index_categories_on_name (name) +# +require "test_helper" + +class CategoryTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/organization_test.rb b/test/models/organization_test.rb new file mode 100644 index 0000000..f6a8d7b --- /dev/null +++ b/test/models/organization_test.rb @@ -0,0 +1,19 @@ +# == Schema Information +# +# Table name: organizations +# +# id :bigint not null, primary key +# company :boolean default(FALSE), not null +# name :string not null +# pricing_strategy :integer default("free"), not null +# url :string +# created_at :datetime not null +# updated_at :datetime not null +# +require "test_helper" + +class OrganizationTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/system/badges_test.rb b/test/system/badges_test.rb new file mode 100644 index 0000000..83bc9d9 --- /dev/null +++ b/test/system/badges_test.rb @@ -0,0 +1,49 @@ +require "application_system_test_case" + +class BadgesTest < ApplicationSystemTestCase + setup do + @badge = badges(:one) + end + + test "visiting the index" do + visit badges_url + assert_selector "h1", text: "Badges" + end + + test "creating a Badge" do + visit badges_url + click_on "New Badge" + + fill_in "Asset url", with: @badge.asset_url + fill_in "Belongs to", with: @badge.belongs_to + fill_in "Source url", with: @badge.source_url + fill_in "Title", with: @badge.title + click_on "Create Badge" + + assert_text "Badge was successfully created" + click_on "Back" + end + + test "updating a Badge" do + visit badges_url + click_on "Edit", match: :first + + fill_in "Asset url", with: @badge.asset_url + fill_in "Belongs to", with: @badge.belongs_to + fill_in "Source url", with: @badge.source_url + fill_in "Title", with: @badge.title + click_on "Update Badge" + + assert_text "Badge was successfully updated" + click_on "Back" + end + + test "destroying a Badge" do + visit badges_url + page.accept_confirm do + click_on "Destroy", match: :first + end + + assert_text "Badge was successfully destroyed" + end +end diff --git a/test/system/categories_test.rb b/test/system/categories_test.rb new file mode 100644 index 0000000..93495c9 --- /dev/null +++ b/test/system/categories_test.rb @@ -0,0 +1,45 @@ +require "application_system_test_case" + +class CategoriesTest < ApplicationSystemTestCase + setup do + @category = categories(:one) + end + + test "visiting the index" do + visit categories_url + assert_selector "h1", text: "Categories" + end + + test "creating a Category" do + visit categories_url + click_on "New Category" + + fill_in "Categorizations count", with: @category.categorizations_count + fill_in "Name", with: @category.name + click_on "Create Category" + + assert_text "Category was successfully created" + click_on "Back" + end + + test "updating a Category" do + visit categories_url + click_on "Edit", match: :first + + fill_in "Categorizations count", with: @category.categorizations_count + fill_in "Name", with: @category.name + click_on "Update Category" + + assert_text "Category was successfully updated" + click_on "Back" + end + + test "destroying a Category" do + visit categories_url + page.accept_confirm do + click_on "Destroy", match: :first + end + + assert_text "Category was successfully destroyed" + end +end diff --git a/test/system/organizations_test.rb b/test/system/organizations_test.rb new file mode 100644 index 0000000..1c88aa1 --- /dev/null +++ b/test/system/organizations_test.rb @@ -0,0 +1,47 @@ +require "application_system_test_case" + +class OrganizationsTest < ApplicationSystemTestCase + setup do + @organization = organizations(:one) + end + + test "visiting the index" do + visit organizations_url + assert_selector "h1", text: "Organizations" + end + + test "creating a Organization" do + visit organizations_url + click_on "New Organization" + + fill_in "Name", with: @organization.name + fill_in "Type", with: @organization.type + fill_in "Url", with: @organization.url + click_on "Create Organization" + + assert_text "Organization was successfully created" + click_on "Back" + end + + test "updating a Organization" do + visit organizations_url + click_on "Edit", match: :first + + fill_in "Name", with: @organization.name + fill_in "Type", with: @organization.type + fill_in "Url", with: @organization.url + click_on "Update Organization" + + assert_text "Organization was successfully updated" + click_on "Back" + end + + test "destroying a Organization" do + visit organizations_url + page.accept_confirm do + click_on "Destroy", match: :first + end + + assert_text "Organization was successfully destroyed" + end +end diff --git a/yarn.lock b/yarn.lock index ed497dc..4fabae3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32,7 +32,7 @@ invariant "^2.2.4" semver "^5.5.0" -"@babel/core@^7.7.2": +"@babel/core@^7.9.0": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.1.tgz#2a0ad0ea693601820defebad2140206503d89af3" integrity sha512-u8XiZ6sMXW/gPmoP5ijonSUln4unazG291X0XAQ5h0s8qnAFr6BRRZGUEK+jtRWdmB0NTJQt7Uga25q8GetIIg== @@ -285,7 +285,7 @@ "@babel/helper-remap-async-to-generator" "^7.10.1" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@^7.10.1", "@babel/plugin-proposal-class-properties@^7.7.0": +"@babel/plugin-proposal-class-properties@^7.10.1", "@babel/plugin-proposal-class-properties@^7.8.3": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.1.tgz#046bc7f6550bb08d9bd1d4f060f5f5a4f1087e01" integrity sha512-sqdGWgoXlnOdgMXU+9MbhzwFRgxVLeiGBqTrnuS7LC2IBU31wSsESbTUreT2O418obpfPdGUR2GbEufZF1bpqw== @@ -325,7 +325,7 @@ "@babel/helper-plugin-utils" "^7.10.1" "@babel/plugin-syntax-numeric-separator" "^7.10.1" -"@babel/plugin-proposal-object-rest-spread@^7.10.1", "@babel/plugin-proposal-object-rest-spread@^7.6.2": +"@babel/plugin-proposal-object-rest-spread@^7.10.1", "@babel/plugin-proposal-object-rest-spread@^7.9.0": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.1.tgz#cba44908ac9f142650b4a65b8aa06bf3478d5fb6" integrity sha512-Z+Qri55KiQkHh7Fc4BW6o+QBuTagbOp9txE+4U1i79u9oWlf2npkiDx+Rf3iK3lbcHBuNy9UOkwuR5wOMH3LIQ== @@ -380,7 +380,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" -"@babel/plugin-syntax-dynamic-import@^7.2.0", "@babel/plugin-syntax-dynamic-import@^7.8.0": +"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== @@ -488,7 +488,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" -"@babel/plugin-transform-destructuring@^7.10.1", "@babel/plugin-transform-destructuring@^7.6.0": +"@babel/plugin-transform-destructuring@^7.10.1", "@babel/plugin-transform-destructuring@^7.8.8": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.1.tgz#abd58e51337815ca3a22a336b85f62b998e71907" integrity sha512-V/nUc4yGWG71OhaTH705pU8ZSdM6c1KmmLP8ys59oOYbT7RpMYAR3MsVOt6OHL0WzG7BlTU076va9fjJyYzJMA== @@ -621,7 +621,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" -"@babel/plugin-transform-regenerator@^7.10.1", "@babel/plugin-transform-regenerator@^7.7.0": +"@babel/plugin-transform-regenerator@^7.10.1", "@babel/plugin-transform-regenerator@^7.8.7": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.1.tgz#10e175cbe7bdb63cc9b39f9b3f823c5c7c5c5490" integrity sha512-B3+Y2prScgJ2Bh/2l9LJxKbb8C8kRfsG4AdPT+n7ixBHIxJaIG8bi8tgjxUMege1+WqSJ+7gu1YeoMVO3gPWzw== @@ -635,7 +635,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.1" -"@babel/plugin-transform-runtime@^7.6.2": +"@babel/plugin-transform-runtime@^7.9.0": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.1.tgz#fd1887f749637fb2ed86dc278e79eb41df37f4b1" integrity sha512-4w2tcglDVEwXJ5qxsY++DgWQdNJcCCsPxfT34wCUwIf2E7dI7pMpH8JczkMBbgBTNzBX62SZlNJ9H+De6Zebaw== @@ -697,7 +697,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.10.1" "@babel/helper-plugin-utils" "^7.10.1" -"@babel/preset-env@^7.7.1": +"@babel/preset-env@^7.9.0": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.10.1.tgz#099e1b76379739bdcbfab3d548dc7e7edb2ac808" integrity sha512-bGWNfjfXRLnqbN2T4lB3pMfoic8dkRrmHpVZamSFHzGy5xklyHTobZ28TVUD2grhE5WDnu67tBj8oslIhkiOMQ== @@ -778,7 +778,7 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": +"@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.1.tgz#b6eb75cac279588d3100baecd1b9894ea2840822" integrity sha512-nQbbCbQc9u/rpg1XCxoMYQTbSMVZjCDxErQ1ClCn9Pvcmv1lGads19ep0a2VsEiIJeHqjZley6EQGEC3Yo1xMA== @@ -894,48 +894,48 @@ resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.0.3.tgz#e68a03278e30daea6a110aac5dfa33c60c53055d" integrity sha512-CM9OEvoN9eXkaX7PXEnbsQLULJ97b9rVmwliZbz/iBOERLJ68Rk3ClJe+fQEMKU4CBZfky2lIRnfslOdUs9SLQ== -"@rails/webpacker@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@rails/webpacker/-/webpacker-4.2.2.tgz#b9dd3235fdf4d0badbda8e33f6ebee742a9f3abb" - integrity sha512-jzw7qMfSCLdrt9j1X+2IvXjf63huXYqeIPwLujXa9pYFvxtEstbVYRDivuLhiDokzih+PrYpB+dLTGBNgVsnpw== - dependencies: - "@babel/core" "^7.7.2" - "@babel/plugin-proposal-class-properties" "^7.7.0" - "@babel/plugin-proposal-object-rest-spread" "^7.6.2" - "@babel/plugin-syntax-dynamic-import" "^7.2.0" - "@babel/plugin-transform-destructuring" "^7.6.0" - "@babel/plugin-transform-regenerator" "^7.7.0" - "@babel/plugin-transform-runtime" "^7.6.2" - "@babel/preset-env" "^7.7.1" - "@babel/runtime" "^7.7.2" - babel-loader "^8.0.6" +"@rails/webpacker@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@rails/webpacker/-/webpacker-5.1.1.tgz#3c937aa719e46341f037a3f37349ef58085950df" + integrity sha512-ho5Stv9naZgG4HbHNFPqbA1OLPJyj6QXfgAc7VGCu4kkMe/RnVFLoLJFW6TZ9wYelKodBjRA2tKKiCaugv0sZw== + dependencies: + "@babel/core" "^7.9.0" + "@babel/plugin-proposal-class-properties" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.9.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.8.8" + "@babel/plugin-transform-regenerator" "^7.8.7" + "@babel/plugin-transform-runtime" "^7.9.0" + "@babel/preset-env" "^7.9.0" + "@babel/runtime" "^7.9.2" + babel-loader "^8.1.0" babel-plugin-dynamic-import-node "^2.3.0" - babel-plugin-macros "^2.6.1" - case-sensitive-paths-webpack-plugin "^2.2.0" - compression-webpack-plugin "^3.0.0" - core-js "^3.4.0" - css-loader "^3.2.0" - file-loader "^4.2.0" + babel-plugin-macros "^2.8.0" + case-sensitive-paths-webpack-plugin "^2.3.0" + compression-webpack-plugin "^3.1.0" + core-js "^3.6.4" + css-loader "^3.4.2" + file-loader "^6.0.0" flatted "^2.0.1" glob "^7.1.6" js-yaml "^3.13.1" - mini-css-extract-plugin "^0.8.0" - node-sass "^4.13.0" + mini-css-extract-plugin "^0.9.0" + node-sass "^4.13.1" optimize-css-assets-webpack-plugin "^5.0.3" path-complete-extname "^1.0.0" - pnp-webpack-plugin "^1.5.0" - postcss-flexbugs-fixes "^4.1.0" + pnp-webpack-plugin "^1.6.4" + postcss-flexbugs-fixes "^4.2.0" postcss-import "^12.0.1" postcss-loader "^3.0.0" postcss-preset-env "^6.7.0" - postcss-safe-parser "^4.0.1" - regenerator-runtime "^0.13.3" - sass-loader "7.3.1" - style-loader "^1.0.0" - terser-webpack-plugin "^2.2.1" - webpack "^4.41.2" + postcss-safe-parser "^4.0.2" + regenerator-runtime "^0.13.5" + sass-loader "^8.0.2" + style-loader "^1.1.3" + terser-webpack-plugin "^2.3.5" + webpack "^4.42.1" webpack-assets-manifest "^3.1.1" - webpack-cli "^3.3.10" + webpack-cli "^3.3.11" webpack-sources "^1.4.3" "@samverschueren/stream-to-observable@^0.3.0": @@ -969,24 +969,6 @@ resolved "https://registry.yarnpkg.com/@stimulus/webpack-helpers/-/webpack-helpers-1.1.1.tgz#eff60cd4e58b921d1a2764dc5215f5141510f2c2" integrity sha512-XOkqSw53N9072FLHvpLM25PIwy+ndkSSbnTtjKuyzsv8K5yfkFB2rv68jU1pzqYa9FZLcvZWP4yazC0V38dx9A== -"@tailwindcss/custom-forms@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@tailwindcss/custom-forms/-/custom-forms-0.2.1.tgz#40e5ed1fff6d29d8ed1c508a0b2aaf8da96962e0" - integrity sha512-XdP5XY6kxo3x5o50mWUyoYWxOPV16baagLoZ5uM41gh6IhXzhz/vJYzqrTb/lN58maGIKlpkxgVsQUNSsbAS3Q== - dependencies: - lodash "^4.17.11" - mini-svg-data-uri "^1.0.3" - traverse "^0.6.6" - -"@tailwindcss/ui@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@tailwindcss/ui/-/ui-0.3.0.tgz#846e489c61bdeb60bdd4e2c32033db770ad8d429" - integrity sha512-LucyddG60/XAGN7aau+Jn84dsl2BFMZya7o/rGVKSXBVXUv+9SoaGmkbPdl0G3kkpcfQrGndDPSkdUgVTS0y8g== - dependencies: - "@tailwindcss/custom-forms" "^0.2.1" - hex-rgb "^4.1.0" - postcss-selector-parser "^6.0.2" - "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" @@ -1585,7 +1567,7 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA== -babel-loader@^8.0.6: +babel-loader@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== @@ -1603,7 +1585,7 @@ babel-plugin-dynamic-import-node@^2.3.0, babel-plugin-dynamic-import-node@^2.3.3 dependencies: object.assign "^4.1.0" -babel-plugin-macros@^2.6.1: +babel-plugin-macros@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== @@ -2042,7 +2024,7 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001043, can resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001066.tgz#0a8a58a10108f2b9bf38e7b65c237b12fd9c5f04" integrity sha512-Gfj/WAastBtfxLws0RCh2sDbTK/8rJuSeZMecrSkNGYxPcv7EzblmDGfWQCFEQcSqYE2BRgQiJh8HOD07N5hIw== -case-sensitive-paths-webpack-plugin@^2.2.0: +case-sensitive-paths-webpack-plugin@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.3.0.tgz#23ac613cc9a856e4f88ff8bb73bbb5e989825cf7" integrity sha512-/4YgnZS8y1UXXmC02xD5rRrBEu6T5ub+mQHLNRj0fzTRbgdBYhsNo2V5EqwgqrExjxsjtF/OpAKAMkKsxbD5XQ== @@ -2358,7 +2340,7 @@ compressible@~2.0.16: dependencies: mime-db ">= 1.43.0 < 2" -compression-webpack-plugin@^3.0.0: +compression-webpack-plugin@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-3.1.0.tgz#9f510172a7b5fae5aad3b670652e8bd7997aeeca" integrity sha512-iqTHj3rADN4yHwXMBrQa/xrncex/uEQy8QHlaTKxGchT/hC0SdlJlmL/5eRqffmWq2ep0/Romw6Ld39JjTR/ug== @@ -2657,7 +2639,7 @@ core-js-compat@^3.6.2: browserslist "^4.8.5" semver "7.0.0" -core-js@^3.4.0: +core-js@^3.6.4: version "3.6.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== @@ -2792,7 +2774,7 @@ css-has-pseudo@^0.10.0: postcss "^7.0.6" postcss-selector-parser "^5.0.0-rc.4" -css-loader@^3.2.0: +css-loader@^3.4.2: version "3.5.3" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.5.3.tgz#95ac16468e1adcd95c844729e0bb167639eb0bcf" integrity sha512-UEr9NH5Lmi7+dguAm+/JSPovNjYbm2k3TK58EiwQHzOHH5Jfq1Y+XoP2bQO6TMn7PptMd0opxxedAWcaSTRKHw== @@ -3829,13 +3811,13 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -file-loader@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.3.0.tgz#780f040f729b3d18019f20605f723e844b8a58af" - integrity sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA== +file-loader@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.0.0.tgz#97bbfaab7a2460c07bcbd72d3a6922407f67649f" + integrity sha512-/aMOAYEFXDdjG0wytpTL5YQLfZnnTmLNjn+AIrJ/6HVnTfDqLsVKUUwkDf4I4kgex36BvjuXEn/TX9B/1ESyqQ== dependencies: - loader-utils "^1.2.3" - schema-utils "^2.5.0" + loader-utils "^2.0.0" + schema-utils "^2.6.5" file-uri-to-path@1.0.0: version "1.0.0" @@ -4485,11 +4467,6 @@ hex-color-regex@^1.1.0: resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -hex-rgb@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/hex-rgb/-/hex-rgb-4.1.0.tgz#2d5d3a2943bd40e7dc9b0d5b98903d7d17035967" - integrity sha512-n7xsIfyBkFChITGPh6FLtxNzAt2HxZLcQIY9hYH4gm2gmMQJHMguMH3E+jnmvUbSTF5QrmFnGab5Ippi+D7e/g== - hmac-drbg@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -5531,7 +5508,7 @@ loader-utils@1.2.3: emojis-list "^2.0.0" json5 "^1.0.1" -loader-utils@^1.0.1, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: +loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== @@ -5964,21 +5941,16 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -mini-css-extract-plugin@^0.8.0: - version "0.8.2" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.2.tgz#a875e169beb27c88af77dd962771c9eedc3da161" - integrity sha512-a3Y4of27Wz+mqK3qrcd3VhYz6cU0iW5x3Sgvqzbj+XmlrSizmvu8QQMl5oMYJjgHOC4iyt+w7l4umP+dQeW3bw== +mini-css-extract-plugin@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e" + integrity sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A== dependencies: loader-utils "^1.1.0" normalize-url "1.9.1" schema-utils "^1.0.0" webpack-sources "^1.1.0" -mini-svg-data-uri@^1.0.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.2.3.tgz#e16baa92ad55ddaa1c2c135759129f41910bc39f" - integrity sha512-zd6KCAyXgmq6FV1mR10oKXYtvmA9vRoB6xPSTUJTbFApCtkefDnYueVR1gkof3KcdLZo1Y8mjF2DFmQMIxsHNQ== - minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -6258,7 +6230,7 @@ node-releases@^1.1.53: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.57.tgz#f6754ce225fad0611e61228df3e09232e017ea19" integrity sha512-ZQmnWS7adi61A9JsllJ2gdj2PauElcjnOwTp2O011iGzoakTxUsDGSe+6vD7wXbKdqhSFymC0OSx35aAMhrSdw== -node-sass@^4.13.0: +node-sass@^4.13.1: version "4.14.1" resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.14.1.tgz#99c87ec2efb7047ed638fb4c9db7f3a42e2217b5" integrity sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g== @@ -6907,7 +6879,7 @@ please-upgrade-node@^3.1.1: dependencies: semver-compare "^1.0.0" -pnp-webpack-plugin@^1.5.0: +pnp-webpack-plugin@^1.6.4: version "1.6.4" resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg== @@ -7081,7 +7053,7 @@ postcss-env-function@^2.0.2: postcss "^7.0.2" postcss-values-parser "^2.0.0" -postcss-flexbugs-fixes@^4.1.0: +postcss-flexbugs-fixes@^4.2.0: version "4.2.1" resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz#9218a65249f30897deab1033aced8578562a6690" integrity sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ== @@ -7513,7 +7485,7 @@ postcss-replace-overflow-wrap@^3.0.0: dependencies: postcss "^7.0.2" -postcss-safe-parser@^4.0.1: +postcss-safe-parser@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz#a6d4e48f0f37d9f7c11b2a581bf00f8ba4870b96" integrity sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g== @@ -8097,7 +8069,7 @@ regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4: +regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.5: version "0.13.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== @@ -8428,15 +8400,15 @@ sass-graph@2.2.5: scss-tokenizer "^0.2.3" yargs "^13.3.2" -sass-loader@7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-7.3.1.tgz#a5bf68a04bcea1c13ff842d747150f7ab7d0d23f" - integrity sha512-tuU7+zm0pTCynKYHpdqaPpe+MMTQ76I9TPZ7i4/5dZsigE350shQWe5EZNl5dBidM49TPET75tNqRbcsUZWeNA== +sass-loader@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-8.0.2.tgz#debecd8c3ce243c76454f2e8290482150380090d" + integrity sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ== dependencies: clone-deep "^4.0.1" - loader-utils "^1.0.1" - neo-async "^2.5.0" - pify "^4.0.1" + loader-utils "^1.2.3" + neo-async "^2.6.1" + schema-utils "^2.6.1" semver "^6.3.0" sax@~1.2.4: @@ -8453,7 +8425,7 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.5.0, schema-utils@^2.6.1, schema-utils@^2.6.5, schema-utils@^2.6.6: +schema-utils@^2.6.1, schema-utils@^2.6.5, schema-utils@^2.6.6: version "2.6.6" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.6.tgz#299fe6bd4a3365dc23d99fd446caff8f1d6c330c" integrity sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA== @@ -8949,7 +8921,7 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" -"stimulus@>= 1.1", stimulus@^1.1.1: +"stimulus@>= 1.1", stimulus@^1.1.0, stimulus@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/stimulus/-/stimulus-1.1.1.tgz#53c2fded6849e7b85eed3ed8dd76e33abd74bec5" integrity sha512-R0mBqKp48YnRDZOxZ8hiOH4Ilph3Yj78CIFTBkCwyHs4iGCpe7xlEdQ7cjIxb+7qVCSxFKgxO+mAQbsNgt/5XQ== @@ -9180,7 +9152,7 @@ strip-json-comments@^3.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180" integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w== -style-loader@^1.0.0: +style-loader@^1.1.3: version "1.2.1" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.2.1.tgz#c5cbbfbf1170d076cfdd86e0109c5bba114baa1a" integrity sha512-ByHSTQvHLkWE9Ir5+lGbVOXhxX10fbprhLvdg96wedFZb4NDekDPxVKv5Fwmio+QcMlkkNfuK+5W1peQ5CUhZg== @@ -9264,6 +9236,13 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" +tailwindcss-stimulus-components@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/tailwindcss-stimulus-components/-/tailwindcss-stimulus-components-1.1.0.tgz#75bc472352bd3073d0990903734f23beac19b5e5" + integrity sha512-T6VY+ZNrtJtKO4qW/IQEoF7hmLGRlxOPfykWqoF9b/zbcdT50hAwo7o61R82Pa6IsnPbT35FWp83FqmRTwbYFQ== + dependencies: + stimulus "^1.1.0" + tailwindcss@^1.4.6: version "1.4.6" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-1.4.6.tgz#17b37166ccda08d7e7f9ca995ea48ce1e0089700" @@ -9318,7 +9297,7 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser-webpack-plugin@^2.2.1: +terser-webpack-plugin@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.6.tgz#a4014b311a61f87c6a1b217ef4f5a75bd0665a69" integrity sha512-I8IDsQwZrqjdmOicNeE8L/MhwatAap3mUrtcAKJuilsemUNcX+Hier/eAzwStVqhlCxq0aG3ni9bK/0BESXkTg== @@ -9451,11 +9430,6 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" -traverse@^0.6.6: - version "0.6.6" - resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" - integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc= - trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -9582,6 +9556,11 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typeface-raleway@^0.0.75: + version "0.0.75" + resolved "https://registry.yarnpkg.com/typeface-raleway/-/typeface-raleway-0.0.75.tgz#cc79688aa3175452744ecd19540b54dad153e8f3" + integrity sha512-mUvT/klCTGA2HporaIMNY3ap45YxBErxFv/1pv82LhbFdNc3m+6ddfoexP6xxwMZ5yZ2VmDhMqk1yikDEoxU/Q== + uglify-js@^3.1.4: version "3.9.4" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.9.4.tgz#867402377e043c1fc7b102253a22b64e5862401b" @@ -9944,7 +9923,7 @@ webpack-bundle-analyzer@^3.8.0: opener "^1.5.1" ws "^6.0.0" -webpack-cli@^3.3.10: +webpack-cli@^3.3.11: version "3.3.11" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.11.tgz#3bf21889bf597b5d82c38f215135a411edfdc631" integrity sha512-dXlfuml7xvAFwYUPsrtQAA9e4DOe58gnzSxhgrO/ZM/gyXTBowrsYeubyN4mqGhYdpXMFNyQ6emjJS9M7OBd4g== @@ -10027,7 +10006,7 @@ webpack-sources@^1.0.0, webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack- source-list-map "^2.0.0" source-map "~0.6.1" -webpack@^4.41.2: +webpack@^4.42.1: version "4.43.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6" integrity sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g==