WIP: elegir el diseño del sitio

This commit is contained in:
f 2019-07-17 19:18:48 -03:00
parent cff18bf861
commit 1cc4c4de64
No known key found for this signature in database
GPG key ID: 2AE5A13E321F953D
25 changed files with 348 additions and 19 deletions

View file

@ -50,6 +50,7 @@ gem 'hamlit-rails'
gem 'jekyll'
gem 'jquery-rails'
gem 'mini_magick'
gem 'mobility'
gem 'pundit'
gem 'rails-i18n'
gem 'rails_warden'

View file

@ -212,10 +212,13 @@ GEM
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mimemagic (0.3.3)
mini_magick (4.9.3)
mini_magick (4.9.4)
mini_mime (1.0.1)
mini_portile2 (2.4.0)
minitest (5.11.3)
mobility (0.8.7)
i18n (>= 0.6.10, < 2)
request_store (~> 1.0)
multi_json (1.13.1)
net-scp (2.0.0)
net-ssh (>= 2.6.5, < 6.0.0)
@ -277,6 +280,8 @@ GEM
ffi (~> 1.0)
rbnacl (4.0.2)
ffi
request_store (1.4.1)
rack (>= 1.4)
responders (3.0.0)
actionpack (>= 5.0)
railties (>= 5.0)
@ -409,6 +414,7 @@ DEPENDENCIES
letter_opener
listen (>= 3.0.5, < 3.2)
mini_magick
mobility
pry
puma (~> 3.7)
pundit

View file

@ -137,6 +137,6 @@ class SitesController < ApplicationController
private
def site_params
params.require(:site).permit(:name)
params.require(:site).permit(:name, :design_id)
end
end

19
app/models/design.rb Normal file
View file

@ -0,0 +1,19 @@
# frozen_string_literal: true
# El diseño de un sitio es la plantilla/tema. En este modelo cargamos
# las propiedades para poder verlas desde el panel y elegir un diseño
# para el sitio.
#
# TODO: Agregar captura de pantalla con ActiveStorage
class Design < ApplicationRecord
extend Mobility
translates :name, type: :string, locale_accessors: true
translates :description, type: :text, locale_accessors: true
has_many :sites
validates :name, presence: true, uniqueness: true
validates :gem, presence: true, uniqueness: true
validates :description, presence: true
end

View file

@ -6,9 +6,12 @@ class Site < ApplicationRecord
include FriendlyId
validates :name, uniqueness: true, hostname: true
validates :design_id, presence: true
friendly_id :name, use: %i[finders]
belongs_to :design
has_many :roles
has_many :usuaries, -> { where('roles.rol = ?', 'usuarie') },
through: :roles

View file

@ -1,6 +1,29 @@
= form_for @site do |f|
= form_for site do |f|
.form-group
= f.label :name
%h2= f.label :name
%p.lead= t('.help.name')
= f.text_field :name, class: 'form-control'
.form-group
%h2= t('.design.title')
%p.lead= t('.help.design')
.row
-# Demasiado complejo para un f.collection_radio_buttons
- Design.all.each do |design|
.col
%h3
= f.radio_button :design_id, design.id,
checked: design.id == site.design_id,
disabled: design.disabled
= f.label "design_id_#{design.id}", design.name
= sanitize_markdown design.description,
tags: %w[p a strong em]
.btn-group{ role: 'group', 'aria-label': t('.design.actions') }
- if design.url
= link_to t('.design.url'), design.url,
target: '_blank', class: 'btn btn-info'
- if design.license
= link_to t('.design.license'), design.license,
target: '_blank', class: 'btn btn-info'
.form-group
= f.submit submit, class: 'btn btn-success'

View file

@ -7,4 +7,4 @@
.col
%h1= t('.title', site: @site.name)
= render 'form', submit: t('.submit')
= render 'form', site: @site, submit: t('.submit')

View file

@ -6,4 +6,4 @@
.col
%h1= t('.title')
= render 'form', submit: t('.submit')
= render 'form', site: @site, submit: t('.submit')

View file

@ -0,0 +1,97 @@
# frozen_string_literal: true
Mobility.configure do |config|
# Sets the default backend to use in models. This can be overridden in
# models by passing +backend: ...+ to +translates+.
config.default_backend = :key_value
# By default, Mobility uses the +translates+ class method in models to
# describe translated attributes, but you can configure this method to
# be whatever you like. This may be useful if using Mobility alongside
# another translation gem which uses the same method name.
config.accessor_method = :translates
# To query on translated attributes, you need to append a scope to
# your model. The name of this scope is +i18n+ by default, but this
# can be changed to something else.
config.query_method = :i18n
# Uncomment and remove (or add) items to (from) this list to
# completely disable/enable plugins globally (so they cannot be used
# and are never even loaded). Note that if you remove an item from the
# list, you will not be able to use the plugin at all, and any options
# for the plugin will be ignored by models. (In most cases, you
# probably don't want to change this.)
#
# config.plugins = %i[
# query
# cache
# dirty
# fallbacks
# presence
# default
# attribute_methods
# fallthrough_accessors
# locale_accessors
# ]
# The translation cache is on by default, but you can turn it off by
# uncommenting this line. (This may be helpful in debugging.)
#
# config.default_options[:cache] = false
# Dirty tracking is disabled by default. Uncomment this line to enable
# it. If you enable this, you should also enable +locale_accessors+
# by default (see below).
#
# config.default_options[:dirty] = true
# No fallbacks are used by default. To define default fallbacks,
# uncomment and set the default fallback option value here. A "true"
# value will use whatever is defined by +I18n.fallbacks+ (if defined),
# or alternatively will fallback to your +I18n.default_locale+.
#
config.default_options[:fallbacks] = true
# The Presence plugin converts empty strings to nil when fetching and
# setting translations. By default it is on, uncomment this line to
# turn it off.
#
# config.default_options[:presence] = false
# Set a default value to use if the translation is nil. By default
# this is off, uncomment and set a default to use it across all models
# (you probably don't want to do that).
#
# config.default_options[:default] = ...
# Uncomment to enable locale_accessors by default on models. A true
# value will use the locales defined either in
# Rails.application.config.i18n.available_locales or
# I18n.available_locales. If you want something else, pass an array
# of locales instead.
#
# config.default_options[:locale_accessors] = true
# Uncomment to enable fallthrough accessors by default on models. This
# will allow you to call any method with a suffix like _en or _pt_br,
# and Mobility will catch the suffix and convert it into a locale in
# +method_missing+. If you don't need this kind of open-ended
# fallthrough behavior, it's better to use locale_accessors instead
# (which define methods) since method_missing is very slow. (You can
# use both fallthrough and locale accessor plugins together without
# conflict.)
#
# Note: The dirty plugin enables fallthrough_accessors by default.
#
# config.default_options[:fallthrough_accessors] = true
# You can also include backend-specific default options. For example,
# if you want to default to using the text-type translation table with
# the KeyValue backend, you can set that as a default by uncommenting
# this line, or change it to :string to default to the string-type
# translation table instead. (For other backends, this option is
# ignored.)
#
# config.default_options[:type] = :text
end

View file

@ -158,6 +158,15 @@ en:
edit:
title: 'Edit %{site}'
submit: 'Save changes'
form:
help:
name: "Your site's name. It can only contain numbers and letters."
design: 'Select the design for your site. You can change it later. We add more designs from time to time.'
design:
title: 'Design'
actions: 'Information about this design'
url: 'Preview'
licencia: 'Read the license'
fetch:
title: 'Upgrade the site'
help:

View file

@ -163,6 +163,15 @@ es:
edit:
title: 'Editar %{site}'
submit: 'Guardar cambios'
form:
help:
name: 'El nombre de tu sitio. Solo puede contener letras y números.'
design: 'Elegí el diseño que va a tener tu sitio aquí. Podés cambiarlo luego. De tanto en tanto vamos sumando diseños nuevos.'
design:
title: 'Diseño'
actions: 'Información sobre este diseño'
url: 'Vista previa'
licencia: 'Leer la licencia'
fetch:
title: 'Actualizar el sitio'
help:

View file

@ -0,0 +1,15 @@
# frozen_string_literal: true
# Crea la tabla de diseños
class CreateDesigns < ActiveRecord::Migration[5.2]
def change
create_table :designs do |t|
t.timestamps
t.string :name, unique: true
t.text :description
t.string :gem, unique: true
t.string :url
t.string :license
end
end
end

View file

@ -0,0 +1,9 @@
# frozen_string_literal: true
# Agrega la columna de idioma a cada usuarie para que pueda ver el sitio
# y escribir artículos en su idioma.
class AddLangToUsuaries < ActiveRecord::Migration[5.2]
def change
add_column :usuaries, :lang, :string, default: 'es'
end
end

View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
# Tabla de traducción de textos utilizada por Mobility
class CreateTextTranslations < ActiveRecord::Migration[5.2]
def change
create_table :mobility_text_translations do |t|
t.string :locale, null: false
t.string :key, null: false
t.text :value
t.references :translatable, polymorphic: true, index: false
t.timestamps null: false
end
add_index :mobility_text_translations, %i[translatable_id translatable_type locale key], unique: true, name: :index_mobility_text_translations_on_keys
add_index :mobility_text_translations, %i[translatable_id translatable_type key], name: :index_mobility_text_translations_on_translatable_attribute
end
end

View file

@ -0,0 +1,17 @@
# frozen_string_literal: true
# Tabla de traducción de cadenas usada por Mobility
class CreateStringTranslations < ActiveRecord::Migration[5.2]
def change
create_table :mobility_string_translations do |t|
t.string :locale, null: false
t.string :key, null: false
t.string :value
t.references :translatable, polymorphic: true, index: false
t.timestamps null: false
end
add_index :mobility_string_translations, %i[translatable_id translatable_type locale key], unique: true, name: :index_mobility_string_translations_on_keys
add_index :mobility_string_translations, %i[translatable_id translatable_type key], name: :index_mobility_string_translations_on_translatable_attribute
add_index :mobility_string_translations, %i[translatable_type key value locale], name: :index_mobility_string_translations_on_query_keys
end
end

View file

@ -0,0 +1,8 @@
# frozen_string_literal: true
# Los sitios tienen un diseño
class AddDesignToSites < ActiveRecord::Migration[5.2]
def change
add_belongs_to :sites, :design, index: true
end
end

View file

@ -0,0 +1,8 @@
# frozen_string_literal: true
# Algunos diseños están deshabilitados
class AddDisabledToDesigns < ActiveRecord::Migration[5.2]
def change
add_column :designs, :disabled, :boolean, default: false
end
end

View file

@ -12,7 +12,43 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20_190_712_165_059) do
ActiveRecord::Schema.define(version: 20_190_717_214_308) do
create_table 'designs', force: :cascade do |t|
t.datetime 'created_at', null: false
t.datetime 'updated_at', null: false
t.string 'name'
t.text 'description'
t.string 'gem'
t.string 'url'
t.string 'license'
t.boolean 'disabled', default: false
end
create_table 'mobility_string_translations', force: :cascade do |t|
t.string 'locale', null: false
t.string 'key', null: false
t.string 'value'
t.string 'translatable_type'
t.integer 'translatable_id'
t.datetime 'created_at', null: false
t.datetime 'updated_at', null: false
t.index %w[translatable_id translatable_type key], name: 'index_mobility_string_translations_on_translatable_attribute'
t.index %w[translatable_id translatable_type locale key], name: 'index_mobility_string_translations_on_keys', unique: true
t.index %w[translatable_type key value locale], name: 'index_mobility_string_translations_on_query_keys'
end
create_table 'mobility_text_translations', force: :cascade do |t|
t.string 'locale', null: false
t.string 'key', null: false
t.text 'value'
t.string 'translatable_type'
t.integer 'translatable_id'
t.datetime 'created_at', null: false
t.datetime 'updated_at', null: false
t.index %w[translatable_id translatable_type key], name: 'index_mobility_text_translations_on_translatable_attribute'
t.index %w[translatable_id translatable_type locale key], name: 'index_mobility_text_translations_on_keys', unique: true
end
create_table 'roles', force: :cascade do |t|
t.datetime 'created_at', null: false
t.datetime 'updated_at', null: false
@ -29,6 +65,8 @@ ActiveRecord::Schema.define(version: 20_190_712_165_059) do
t.datetime 'created_at', null: false
t.datetime 'updated_at', null: false
t.string 'name'
t.integer 'design_id'
t.index ['design_id'], name: 'index_sites_on_design_id'
t.index ['name'], name: 'index_sites_on_name', unique: true
end
@ -56,6 +94,7 @@ ActiveRecord::Schema.define(version: 20_190_712_165_059) do
t.string 'invited_by_type'
t.integer 'invited_by_id'
t.integer 'invitations_count', default: 0
t.string 'lang', default: 'es'
t.index ['confirmation_token'], name: 'index_usuaries_on_confirmation_token', unique: true
t.index ['email'], name: 'index_usuaries_on_email', unique: true
t.index ['invitation_token'], name: 'index_usuaries_on_invitation_token', unique: true

View file

@ -1,9 +1,9 @@
# frozen_string_literal: true
# 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)
designs = YAML.safe_load(File.read('db/seeds/designs.yml'))
designs.each do |d|
design = Design.find_or_create_by(gem: d['gem'])
design.update_attributes d
end

22
db/seeds/designs.yml Normal file
View file

@ -0,0 +1,22 @@
---
- name_en: 'My own design'
name_es: 'Mi propio diseño'
gem: 'sutty-theme-none'
url: 'https://sutty.nl'
disabled: true
description_en: "Your own design. [This feature is in development, help us!]()"
description_es: "Tu propio diseño. [Esta posibilidad está en desarrollo, ¡ayudanos!]()"
- name_en: 'Minima'
name_es: 'Mínima'
gem: 'minima'
url: 'https://jekyll.github.io/minima/'
description_en: "Minima is the default design for Jekyll sites. It's made for general-purpose writing."
description_es: 'Mínima es el diseño oficial de los sitios Jekyll, hecho para escritura de propósitos generales.'
license: 'https://github.com/jekyll/minima/blob/master/LICENSE.txt'
- name_en: 'EDSL'
name_es: 'EDSL'
gem: 'sutty-theme-edsl'
url: 'https://endefensadelsl.org/'
description_en: "_En defensa del software libre_'s design"
description_es: 'El diseño de En defensa del software libre'
license: 'https://endefensadelsl.org/ppl_deed_es.html'

View file

@ -33,7 +33,8 @@ class SitesControllerTest < ActionDispatch::IntegrationTest
post sites_url, headers: @authorization, params: {
site: {
name: name
name: name,
design_id: create(:design).id
}
}

12
test/factories/design.rb Normal file
View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
FactoryBot.define do
factory :design do
name { SecureRandom.hex }
description { SecureRandom.hex }
license { SecureRandom.hex }
gem { SecureRandom.hex }
url { SecureRandom.hex }
disabled { false }
end
end

View file

@ -3,5 +3,6 @@
FactoryBot.define do
factory :site do
name { "test-#{SecureRandom.hex}" }
design
end
end

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
class DesignTest < ActiveSupport::TestCase
test 'se pueden crear' do
design = create :design
assert design.valid?
assert design.persisted?
end
end

View file

@ -27,26 +27,30 @@ class SiteTest < ActiveSupport::TestCase
test 'el nombre del sitio puede contener subdominios' do
site = build :site, name: 'hola.chau'
site.validate
assert site.valid?
assert_not site.errors.messages[:name].present?
end
test 'el nombre del sitio no puede terminar con punto' do
site = build :site, name: 'hola.chau.'
site.validate
assert_not site.valid?
assert site.errors.messages[:name].present?
end
test 'el nombre del sitio no puede contener wildcard' do
site = build :site, name: '*.chau'
site.validate
assert_not site.valid?
assert site.errors.messages[:name].present?
end
test 'el nombre del sitio solo tiene letras, numeros y guiones' do
site = build :site, name: 'A_Z!'
site.validate
assert_not site.valid?
assert site.errors.messages[:name].present?
end
test 'al destruir un sitio se eliminan los archivos' do