integración del editor :D
This commit is contained in:
parent
ef66f6ad5a
commit
d69fdfe364
7 changed files with 328 additions and 72 deletions
|
@ -1,4 +1,4 @@
|
||||||
const origin = "http://panel.sutty.local:3000" || location.origin
|
const origin = location.origin
|
||||||
|
|
||||||
function uploadFile (file) {
|
function uploadFile (file) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -439,7 +439,7 @@ function stringifyAllowedStyle (element) {
|
||||||
return element.style.cssText
|
return element.style.cssText
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("turbolinks:load", () => {
|
||||||
for (const editorEl of document.querySelectorAll(".editor")) {
|
for (const editorEl of document.querySelectorAll(".editor")) {
|
||||||
setupEditor(editorEl)
|
setupEditor(editorEl)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
//= require_tree .
|
|
||||||
|
|
||||||
$black: black;
|
$black: black;
|
||||||
$white: white;
|
$white: white;
|
||||||
$grey: grey;
|
$grey: grey;
|
||||||
$cyan: #13fefe;
|
$cyan: #13fefe;
|
||||||
$magenta: #f206f9;
|
$magenta: #f206f9;
|
||||||
|
|
||||||
|
$colors: (
|
||||||
|
"black": $black,
|
||||||
|
"white": $white,
|
||||||
|
"cyan": $cyan,
|
||||||
|
"magenda": $magenta
|
||||||
|
);
|
||||||
|
|
||||||
// Redefinir variables de Bootstrap
|
// Redefinir variables de Bootstrap
|
||||||
$primary: $magenta;
|
$primary: $magenta;
|
||||||
$jumbotron-bg: transparent;
|
$jumbotron-bg: transparent;
|
||||||
|
@ -16,6 +21,9 @@ $form-feedback-icon-valid-color: $black;
|
||||||
$component-active-bg: $magenta;
|
$component-active-bg: $magenta;
|
||||||
|
|
||||||
@import "bootstrap";
|
@import "bootstrap";
|
||||||
|
@import "editor";
|
||||||
|
@import "actiontext";
|
||||||
|
@import "helpers";
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--foreground: #{$black};
|
--foreground: #{$black};
|
||||||
|
|
187
app/assets/stylesheets/helpers.scss
Normal file
187
app/assets/stylesheets/helpers.scss
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
// Viene de sutty-base-jekyll-theme
|
||||||
|
$prefixes: ("", "-webkit-", "-ms-", "-o-", "-moz-");
|
||||||
|
$overflows: auto, hidden, scroll;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Usar en animaciones, empiezan rápido y desaceleran hacia el final.
|
||||||
|
*/
|
||||||
|
$bezier: cubic-bezier(0.75, 0, 0.25, 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ocultar la barra de scroll, útil para sliders horizontales.
|
||||||
|
*/
|
||||||
|
.no-scrollbar {
|
||||||
|
scrollbar-width: none;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@each $cursor in (pointer none) {
|
||||||
|
.cursor-#{$cursor} {
|
||||||
|
cursor: $cursor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@each $direction in (top, right, bottom, left) {
|
||||||
|
.#{$direction}-0 {
|
||||||
|
#{$direction}: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@each $value in $overflows {
|
||||||
|
.overflow-#{$value} { overflow: $value !important; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@each $axis in (y, x) {
|
||||||
|
@each $value in $overflows {
|
||||||
|
.overflow-#{$axis}-#{$value} { overflow-#{$axis}: $value !important; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Poder aumentar o disminuir el alto de la tipografía, se usa de la
|
||||||
|
* misma forma que los modificadores de padding y margin.
|
||||||
|
*/
|
||||||
|
@each $size, $length in $spacers {
|
||||||
|
.f-#{$size} {
|
||||||
|
font-size: $length !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-column-#{$size} {
|
||||||
|
column-count: $size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modificadores de Bootstrap que no tienen versión responsive.
|
||||||
|
*/
|
||||||
|
@each $grid-breakpoint, $_ in $grid-breakpoints {
|
||||||
|
@include media-breakpoint-up($grid-breakpoint) {
|
||||||
|
// border
|
||||||
|
.border-#{$grid-breakpoint} { border: $border-width solid $border-color !important; }
|
||||||
|
.border-#{$grid-breakpoint}-top { border-top: $border-width solid $border-color !important; }
|
||||||
|
.border-#{$grid-breakpoint}-right { border-right: $border-width solid $border-color !important; }
|
||||||
|
.border-#{$grid-breakpoint}-bottom { border-bottom: $border-width solid $border-color !important; }
|
||||||
|
.border-#{$grid-breakpoint}-left { border-left: $border-width solid $border-color !important; }
|
||||||
|
.border-#{$grid-breakpoint}-0 { border: 0 !important; }
|
||||||
|
.border-#{$grid-breakpoint}-top-0 { border-top: 0 !important; }
|
||||||
|
.border-#{$grid-breakpoint}-right-0 { border-right: 0 !important; }
|
||||||
|
.border-#{$grid-breakpoint}-bottom-0 { border-bottom: 0 !important; }
|
||||||
|
.border-#{$grid-breakpoint}-left-0 { border-left: 0 !important; }
|
||||||
|
|
||||||
|
// alineación
|
||||||
|
.text-#{$grid-breakpoint}-left { text-align: left !important; }
|
||||||
|
.text-#{$grid-breakpoint}-right { text-align: right !important; }
|
||||||
|
.text-#{$grid-breakpoint}-center { text-align: center !important; }
|
||||||
|
|
||||||
|
// posición
|
||||||
|
@each $position in $positions {
|
||||||
|
.position-#{$grid-breakpoint}-#{$position} { position: $position !important; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// anchos y altos
|
||||||
|
@each $prop, $abbrev in (width: w, height: h) {
|
||||||
|
@each $size, $length in $sizes {
|
||||||
|
.#{$abbrev}-#{$grid-breakpoint}-#{$size} { #{$prop}: $length !important; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// versión responsive de f
|
||||||
|
@each $size, $length in $spacers {
|
||||||
|
.f-#{$grid-breakpoint}-#{$size} {
|
||||||
|
font-size: $length !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-column-#{$grid-breakpoint}-#{$size} {
|
||||||
|
column-count: $size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crea una propiedad con prefijos de navegador
|
||||||
|
*/
|
||||||
|
@mixin vendor-prefix($property, $definition...) {
|
||||||
|
@each $prefix in $prefixes {
|
||||||
|
#{$prefix}$property: $definition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Crea clases para asignar colores según la lista de colores.
|
||||||
|
*/
|
||||||
|
@each $color, $_ in $colors {
|
||||||
|
.background-#{$color} {
|
||||||
|
background-color: var(--#{$color});
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
background-color: var(--#{$color});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollbar-#{$color} {
|
||||||
|
scrollbar-color: var(--#{$color}) transparent;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 5px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: var(--#{$color});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-#{$color} {
|
||||||
|
border-color: var(--#{$color}) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover-bg-#{$color} {
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--#{$color});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover-#{$color} {
|
||||||
|
&:hover {
|
||||||
|
color: var(--#{$color});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$color} {
|
||||||
|
color: var(--#{$color});
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
color: var(--#{$color});
|
||||||
|
}
|
||||||
|
|
||||||
|
::-moz-selection,
|
||||||
|
::selection {
|
||||||
|
background: var(--#{$color});
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
* {
|
||||||
|
fill: var(--#{$color});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
border-color: var(--#{$color});
|
||||||
|
color: var(--#{$color});
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border-color: var(--#{$color});
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--#{$color});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,63 +0,0 @@
|
||||||
= form_with do
|
|
||||||
.editor
|
|
||||||
.editor-toolbar
|
|
||||||
.editor-primary-toolbar
|
|
||||||
%button.btn{:data => {:button => "bold"}} Bold
|
|
||||||
%button.btn{:data => {:button => "italic"}} Italic
|
|
||||||
%button.btn{:data => {:button => "deleted"}} Deleted
|
|
||||||
%button.btn{:data => {:button => "underline"}} Underline
|
|
||||||
%button.btn{:data => {:button => "mark"}} Subrayar
|
|
||||||
%button.btn{:data => {:button => "h1"}} H1
|
|
||||||
%button.btn{:data => {:button => "h2"}} H2
|
|
||||||
%button.btn{:data => {:button => "h3"}} H3
|
|
||||||
%button.btn{:data => {:button => "h4"}} H4
|
|
||||||
%button.btn{:data => {:button => "h5"}} H5
|
|
||||||
%button.btn{:data => {:button => "h6"}} H6
|
|
||||||
%button.btn{:data => {:button => "ul"}} Lista desordenada
|
|
||||||
%button.btn{:data => {:button => "ol"}} Lista ordenada
|
|
||||||
%button.btn{:data => {:button => "left"}} Left
|
|
||||||
%button.btn{:data => {:button => "center"}} Center
|
|
||||||
%button.btn{:data => {:button => "right"}} Right
|
|
||||||
%button.btn{:data => {:button => "img"}} Imágen
|
|
||||||
%button.btn{:data => {:button => "video"}} Video
|
|
||||||
%button.btn{:data => {:button => "audio"}} Audio
|
|
||||||
%button.btn{:data => {:button => "pdf"}} PDF
|
|
||||||
// TODO: generar IDs para labels
|
|
||||||
|
|
||||||
// HAML cringe
|
|
||||||
.editor-auxiliary-toolbar{:data => {:editor => {:auxiliary => {:toolbar => ""}}}}
|
|
||||||
%div{:data => {:editor => {:auxiliary => "mark"}}}
|
|
||||||
%label{:for => "mark-color"} Color de resaltado:
|
|
||||||
%input{:type => "color", :data => {:prop => "mark-color"}}/
|
|
||||||
|
|
||||||
%div{:data => {:editor => {:auxiliary => "img"}}}
|
|
||||||
%label{:for => "img-file"} Archivo de la imágen:
|
|
||||||
%input{:type => "file", :data => {:prop => "img-file"}}/
|
|
||||||
%label{:for => "img-alt"} Descripción de imágen:
|
|
||||||
%input{:placeholder => "Un álbum", :type => "text", :data => {:prop => "img-alt"}}/
|
|
||||||
|
|
||||||
%div{:data => {:editor => {:auxiliary => "audio"}}}
|
|
||||||
%label{:for => "audio-file"} Archivo de la audio:
|
|
||||||
%input{:type => "file", :data => {:prop => "audio-file"}}/
|
|
||||||
|
|
||||||
%div{:data => {:editor => {:auxiliary => "video"}}}
|
|
||||||
%label{:for => "video-file"} Archivo de la video:
|
|
||||||
%input{:type => "file", :data => {:prop => "video-file"}}/
|
|
||||||
|
|
||||||
%div{:data => {:editor => {:auxiliary => "pdf"}}}
|
|
||||||
%label{:for => "pdf-file"} Archivo de la PDF:
|
|
||||||
%input{:type => "file", :data => {:prop => "pdf-file"}}/
|
|
||||||
|
|
||||||
%div{:data => {:editor => {:auxiliary => "link"}}}
|
|
||||||
%label{:for => "link-href"} URL de link:
|
|
||||||
%input{:type => "url", :data => {:prop => "link-href"}}/
|
|
||||||
|
|
||||||
.editor-content{:contenteditable => "true"}
|
|
||||||
%h1
|
|
||||||
Hola
|
|
||||||
%em mundo
|
|
||||||
%p Como te va?
|
|
||||||
%div{:data => {:align => "right"}}
|
|
||||||
%p Esto está a la derecha
|
|
||||||
%textarea{:cols => "80", :disabled => "disabled", :rows => "15"}
|
|
||||||
|
|
|
@ -1,8 +1,72 @@
|
||||||
.form-group.markdown-content
|
.form-group
|
||||||
= label_tag "post_#{attribute}", post_label_t(attribute, post: post)
|
= label_tag "post_#{attribute}", post_label_t(attribute, post: post)
|
||||||
= render 'posts/attribute_feedback',
|
= render 'posts/attribute_feedback',
|
||||||
post: post, attribute: attribute, metadata: metadata
|
post: post, attribute: attribute, metadata: metadata
|
||||||
|
|
||||||
|
.editor
|
||||||
= text_area_tag "post[#{attribute}]", metadata.value,
|
= text_area_tag "post[#{attribute}]", metadata.value,
|
||||||
dir: dir, lang: locale,
|
dir: dir, lang: locale,
|
||||||
**field_options(attribute, metadata, class: 'content')
|
**field_options(attribute, metadata), class: 'd-none'
|
||||||
.editor.mt-1
|
|
||||||
|
.editor-toolbar
|
||||||
|
.editor-primary-toolbar.scrollbar-black
|
||||||
|
%button.btn{ data: { button: 'bold' } }= t('editor.bold')
|
||||||
|
%button.btn{ data: { button: 'italic' } }= t('editor.italic')
|
||||||
|
%button.btn{ data: { button: 'deleted' } }= t('editor.deleted')
|
||||||
|
%button.btn{ data: { button: 'underline' } }= t('editor.underline')
|
||||||
|
%button.btn{ data: { button: 'mark' } }= t('editor.mark')
|
||||||
|
%button.btn{ data: { button: 'h1' } }= t('editor.h1')
|
||||||
|
%button.btn{ data: { button: 'h2' } }= t('editor.h2')
|
||||||
|
%button.btn{ data: { button: 'h3' } }= t('editor.h3')
|
||||||
|
%button.btn{ data: { button: 'h4' } }= t('editor.h4')
|
||||||
|
%button.btn{ data: { button: 'h5' } }= t('editor.h5')
|
||||||
|
%button.btn{ data: { button: 'h6' } }= t('editor.h6')
|
||||||
|
%button.btn{ data: { button: 'ul' } }= t('editor.ul')
|
||||||
|
%button.btn{ data: { button: 'ol' } }= t('editor.ol')
|
||||||
|
%button.btn{ data: { button: 'left' } }= t('editor.left')
|
||||||
|
%button.btn{ data: { button: 'center' } }= t('editor.center')
|
||||||
|
%button.btn{ data: { button: 'right' } }= t('editor.right')
|
||||||
|
%button.btn{ data: { button: 'img' } }= t('editor.img')
|
||||||
|
%button.btn{ data: { button: 'video' } }= t('editor.video')
|
||||||
|
%button.btn{ data: { button: 'audio' } }= t('editor.audio')
|
||||||
|
%button.btn{ data: { button: 'pdf' } }= t('editor.pdf')
|
||||||
|
|
||||||
|
-#
|
||||||
|
HAML cringe
|
||||||
|
TODO: generar IDs para labels
|
||||||
|
.editor-auxiliary-toolbar.scrollbar-black{ data: { editor: { auxiliary: { toolbar: '' } } } }
|
||||||
|
.form-group{ data: { editor: { auxiliary: 'mark' } } }
|
||||||
|
%label{ for: 'mark-color' }= t('editor.color')
|
||||||
|
%input{ type: 'color', data: { prop: 'mark-color' } }/
|
||||||
|
|
||||||
|
%div{ data: { editor: { auxiliary: 'img' } } }
|
||||||
|
.row
|
||||||
|
.col.form-group.d-flex.align-items-end
|
||||||
|
.custom-file
|
||||||
|
%input.custom-file-input{ type: 'file', data: { prop: 'img-file' }, accept: 'image/*' }/
|
||||||
|
%label.custom-file-label{ for: 'img-file' }= t('editor.file.img')
|
||||||
|
.col.form-group
|
||||||
|
%label{ for: 'img-alt' }= t('editor.description')
|
||||||
|
%input.form-control{ type: 'text', data: { prop: 'img-alt' } }/
|
||||||
|
|
||||||
|
-# https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Containers
|
||||||
|
.form-group{ data: { editor: { auxiliary: 'audio' } } }
|
||||||
|
.custom-file
|
||||||
|
%input.custom-file-input{ type: 'file', data: { prop: 'audio-file' }, accept: 'audio/flac,audio/mp4,audio/ogg,audio/webm,audio/mp3' }/
|
||||||
|
%label.custom-file-label{ for: 'audio-file' }= t('editor.file.audio')
|
||||||
|
|
||||||
|
.form-group{ data: { editor: { auxiliary: 'video' } } }
|
||||||
|
.custom-file
|
||||||
|
%input.custom-file-input{ type: 'file', data: { prop: 'video-file' }, accept: 'video/mp4,video/ogg,video/webm' }/
|
||||||
|
%label.custom-file-label{ for: 'video-file' }= t('editor.file.video')
|
||||||
|
|
||||||
|
.form-group{ data: { editor: { auxiliary: 'pdf' } } }
|
||||||
|
.custom-file
|
||||||
|
%input.custom-file-input{ type: 'file', data: { prop: 'pdf-file' }, accept: 'application/pdf' }/
|
||||||
|
%label.custom-file-label{ for: 'pdf-file' }= t('editor.file.pdf')
|
||||||
|
|
||||||
|
.form-group{ data: { editor: { auxiliary: 'link' } } }
|
||||||
|
%label{ for: 'link-href' }= t('editor.url')
|
||||||
|
%input.form-control{ type: 'url', data: { prop: 'link-href' } }/
|
||||||
|
|
||||||
|
.editor-content.form-control.h-auto{ contenteditable: 'true' }
|
||||||
|
|
|
@ -551,3 +551,33 @@ en:
|
||||||
title: Encrypted content
|
title: Encrypted content
|
||||||
description: The field contents are encrypted before being stored and won't be available on the public website or its source code. You can save private information here and it will only be readable to this site's users through Sutty's panel.
|
description: The field contents are encrypted before being stored and won't be available on the public website or its source code. You can save private information here and it will only be readable to this site's users through Sutty's panel.
|
||||||
decryption_error: There was an error trying to decrypt the content, Sutty's team has been notified!
|
decryption_error: There was an error trying to decrypt the content, Sutty's team has been notified!
|
||||||
|
editor:
|
||||||
|
bold: Bold
|
||||||
|
italic: Emphasis
|
||||||
|
deleted: Strikethrough
|
||||||
|
underline: Underline
|
||||||
|
mark: Mark
|
||||||
|
h1: Heading 1
|
||||||
|
h2: Heading 2
|
||||||
|
h3: Heading 3
|
||||||
|
h4: Heading 4
|
||||||
|
h5: Heading 5
|
||||||
|
h6: Heading 6
|
||||||
|
ul: Unordered list
|
||||||
|
ol: Ordered list
|
||||||
|
left: Left
|
||||||
|
right: Right
|
||||||
|
center: Center
|
||||||
|
img: Image
|
||||||
|
video: Video
|
||||||
|
audio: Audio
|
||||||
|
pdf: PDF
|
||||||
|
color: Color
|
||||||
|
img: Image
|
||||||
|
file:
|
||||||
|
img: Select and upload image
|
||||||
|
video: Select and upload video
|
||||||
|
audio: Select and upload audio
|
||||||
|
pdf: Select and upload PDF
|
||||||
|
description: Description for blind people and search engines
|
||||||
|
url: Address
|
||||||
|
|
|
@ -564,3 +564,33 @@ es:
|
||||||
title: Contenido cifrado
|
title: Contenido cifrado
|
||||||
description: El contenido de este campo se guarda cifrado y no estará disponible en el sitio ni en su código fuente. Puedes guardar información privada aquí y sólo estará disponible para quienes tengan acceso a ese sitio en el panel de Sutty.
|
description: El contenido de este campo se guarda cifrado y no estará disponible en el sitio ni en su código fuente. Puedes guardar información privada aquí y sólo estará disponible para quienes tengan acceso a ese sitio en el panel de Sutty.
|
||||||
decryption_error: Hubo un error al decifrar la información, ¡el equipo de Sutty ya fue notificado!
|
decryption_error: Hubo un error al decifrar la información, ¡el equipo de Sutty ya fue notificado!
|
||||||
|
editor:
|
||||||
|
bold: Fuerte
|
||||||
|
italic: Énfasis
|
||||||
|
deleted: Tachado
|
||||||
|
underline: Subrayado
|
||||||
|
mark: Resaltado
|
||||||
|
h1: Título 1
|
||||||
|
h2: Título 2
|
||||||
|
h3: Título 3
|
||||||
|
h4: Título 4
|
||||||
|
h5: Título 5
|
||||||
|
h6: Título 6
|
||||||
|
ul: Lista itemizada
|
||||||
|
ol: Lista numerada
|
||||||
|
left: Izquierda
|
||||||
|
right: Derecha
|
||||||
|
center: Centro
|
||||||
|
img: Imágen
|
||||||
|
video: Video
|
||||||
|
audio: Audio
|
||||||
|
pdf: PDF
|
||||||
|
color: Color
|
||||||
|
img: Imágen
|
||||||
|
file:
|
||||||
|
img: Seleccionar y subir imágen
|
||||||
|
video: Seleccionar y subir video
|
||||||
|
audio: Seleccionar y subir audio
|
||||||
|
pdf: Seleccionar y subir archivo PDF
|
||||||
|
description: Descripción para personas no videntes y buscadores
|
||||||
|
url: Dirección
|
||||||
|
|
Loading…
Reference in a new issue