Commit 1710706f authored by f's avatar f
Browse files

add layouts and fields

parent d658c9a3
# frozen_string_literal: true
require 'thor'
require_relative 'commands/layout'
require_relative 'commands/field'
module Sutty
module Cli
......@@ -31,6 +33,75 @@ module Sutty
end
end
desc 'field NAME', 'Adds a field with a type to a layout'
long_desc <<~EOD
A field is a data type with a name, from which Sutty can build a
form on the panel and use it to validate posts.
After you add a field, edit the layout file and add labels and
help description in different languages.
EOD
method_option :help,
aliases: '-h',
type: :boolean,
desc: 'Display usage information'
method_option :layout,
aliases: '-l',
type: :string,
desc: 'Layout to add',
required: true,
enum: Sutty::Cli::Commands::Layout.layouts
method_option :type,
aliases: '-t',
type: :string,
desc: 'Field type',
required: true,
enum: Sutty::Cli::Commands::Field.fields
method_option :required,
aliases: '-r',
type: :boolean,
desc: 'Field is required'
method_option :inverse,
aliases: '-i',
type: :string,
desc: 'Inverse relation',
required: Sutty::Cli::Commands::Field.inverse_required?
method_option :filter,
aliases: '-F',
type: :string,
desc: 'Filter relations by this field'
method_option :value,
aliases: '-v',
type: :string,
desc: 'Filter relations by this field value',
required: Sutty::Cli::Commands::Field.value_required?
def field(name)
if options[:help]
invoke :help, ['field']
else
Sutty::Cli::Commands::Field.new(name, options).execute
end
end
desc 'layout NAME', 'Start a new layout'
method_option :help, aliases: '-h', type: :boolean,
desc: 'Display usage information'
def layout(name)
if options[:help]
invoke :help, ['layout']
else
Sutty::Cli::Commands::Layout.new(name, options).execute
end
end
desc 'theme NAME', 'Start a new theme'
method_option :help, aliases: '-h', type: :boolean,
desc: 'Display usage information'
......
# frozen_string_literal: true
require_relative '../command'
require 'tty-file'
require 'tty-logger'
require 'pry'
module Sutty
module Cli
module Commands
class Field < Sutty::Cli::Command
attr_reader :name, :options
INVERSE_REQUIRED = %w[has_many belongs_to has_and_belongs_to_many].freeze
VALUE_REQUIRED = %w[-F --filter].freeze
def initialize(name, options)
@name = name
@options = options
end
def execute(input: $stdin, output: $stdout)
unless data_layout_contents.scan(/\n#{name}:\n/).empty?
logger.info "The #{name} field is already present, please edit #{data_layout}"
return true
end
TTY::File.safe_append_to_file(data_layout) do
ERB.new(template_contents, trim_mode: '<>', eoutvar: '@output_buffer').result(context)
end
end
def self.fields
@@fields ||= Dir.glob(source_dir.to_s + '/*.yml.erb').map do |f|
File.basename f, '.yml.erb'
end
end
def self.inverse_required?
ARGV.any? { |f| INVERSE_REQUIRED.include? f }
end
def self.value_required?
ARGV.any? { |f| VALUE_REQUIRED.include? f }
end
private
def self.source_dir
@@source_dir ||= Pathname(__dir__).join('..', 'templates', 'field')
end
def source_dir
self.class.source_dir
end
def context
return @context if @context
@context = OpenStruct.new(**options.transform_keys(&:to_sym))
@context[:name] = name
@context = @context.instance_eval('binding')
end
def template
@template ||= source_dir.join(options[:type] + '.yml.erb')
end
def template_contents
@template_contents ||= File.binread template
end
def data_layout
@data_layout ||= File.join('_data', 'layouts', options[:layout] + '.yml')
end
def data_layout_contents
@data_layout_contents ||= File.binread data_layout
end
def logger
@logger ||= TTY::Logger.new
end
end
end
end
end
# frozen_string_literal: true
require_relative '../command'
require 'tty-file'
module Sutty
module Cli
module Commands
class Layout < Sutty::Cli::Command
attr_reader :name
def initialize(name, options)
@name = name
@options = options
end
def execute(input: $stdin, output: $stdout)
TTY::File.create_file data_layout, "---\n"
TTY::File.create_file html_layout, "---\nlayout: default\n---\n\n"
end
def self.layouts
@@layouts ||= Dir.glob(File.join('_data', 'layouts') + '/*.yml').map do |d|
File.basename d, '.yml'
end
end
private
def data_layout
@data_layout ||= File.join('_data', 'layouts', name + '.yml')
end
def html_layout
@html_layout ||= File.join('_layouts', name + '.html')
end
end
end
end
end
<%= name %>:
type: 'array'
<% if required %>
required: true
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'belongs_to'
<% if required %>
required: true
<% end %>
inverse: '<%= inverse %>'
<% if filter %>
filter:
<%= filter %>: <%= value %>
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'boolean'
<% if required %>
required: true
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'color'
<% if required %>
required: true
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'content'
<% if required %>
required: true
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'date'
<% if required %>
required: true
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'email'
<% if required %>
required: true
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'encrypted_text'
<% if required %>
required: true
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'event'
<% if required %>
required: true
<% end %>
zone:
label:
es: 'Zona horaria'
en: 'Time zone'
help:
es: 'Ayuda'
en: 'Ayuda'
date:
label:
es: 'Fecha'
en: 'Date'
help:
es: 'Ayuda'
en: 'Ayuda'
time:
label:
es: 'Horario'
en: 'Time'
help:
es: 'Ayuda'
en: 'Ayuda'
dtstart:
label:
es: 'Comienzo del evento'
en: 'Event start'
help:
es: 'Ayuda'
en: 'Ayuda'
dtend:
label:
es: 'Fin del evento'
en: 'Event end'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'file'
<% if required %>
required: true
<% end %>
path:
label:
es: 'Archivo'
en: 'File'
help:
es: 'Ayuda'
en: 'Ayuda'
description:
label:
es: 'Descripción'
en: 'Description'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'geo'
<% if required %>
required: true
<% end %>
label:
es: 'Coordenadas geográficas'
lat:
label:
es: 'Latitud'
help:
es: 'Latitud'
lng:
label:
es: 'Longitud'
help:
es: 'Longitud'
<%= name %>:
type: 'has_and_belongs_to_many'
<% if required %>
required: true
<% end %>
inverse: '<%= inverse %>'
<% if filter %>
filter:
<%= filter %>: <%= value %>
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'has_many'
<% if required %>
required: true
<% end %>
inverse: '<%= inverse %>'
<% if filter %>
filter:
<%= filter %>: <%= value %>
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'image'
<% if required %>
required: true
<% end %>
path:
label:
es: 'Archivo'
en: 'File'
help:
es: 'Ayuda'
en: 'Ayuda'
description:
label:
es: 'Descripción'
en: 'Description'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'locales'
<% if required %>
required: true
<% end %>
label:
es: 'Traducciones'
en: 'Translations'
help:
es: 'Vínculo a los artículos en otros idiomas'
en: 'Link to the post in other languages'
<%= name %>:
type: 'markdown'
<% if required %>
required: true
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
<%= name %>:
type: 'markdown_content'
<% if required %>
required: true
<% end %>
label:
es: 'Nombre'
en: 'Name'
help:
es: 'Ayuda'
en: 'Ayuda'
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment