5
0
Fork 0
mirror of https://0xacab.org/sutty/sutty synced 2024-05-18 23:40:48 +00:00

Compare commits

...

2213 commits

Author SHA1 Message Date
fauno eef6ff58c8 ci: test [skip ci] 2024-05-18 14:32:08 +00:00
fauno 8aed41990e Merge branch 'issue-14949' into 'rails'
Ocultar schema si es de subnivel #14949

See merge request sutty/sutty!240
2024-05-18 14:31:05 +00:00
fauno e04640c8c6 ci: test [skip ci] 2024-05-18 14:24:14 +00:00
fauno 00df57a096 Merge branch 'issue-15154' into 'rails'
Issue #15154

See merge request sutty/sutty!249
2024-05-18 14:23:56 +00:00
fauno 186f979157 ci: test [skip ci] 2024-05-18 14:22:34 +00:00
fauno fa82fc8a1a Merge branch 'issue-14329' into 'rails'
fix: permitir sitios sin layouts #14329

See merge request sutty/sutty!260
2024-05-18 14:22:11 +00:00
fauno 2407ec11d9 ci: test [skip ci] 2024-05-09 15:19:09 +00:00
f 0d1ca35e6b
ci: probar que podemos pushear! 2024-05-09 12:18:25 -03:00
f 6972aafa75
ci: pushear assets 2024-05-09 12:03:38 -03:00
f eb80a83ddd
fix: editor 0.1.29 2024-05-09 12:01:34 -03:00
f 08b07a5158
fix: permitir sitios sin layouts #14329 2024-05-03 12:42:05 -03:00
f 30621bb219
Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2024-05-02 18:49:54 -03:00
f 330e82041b
fix: no filtrar información privada en YAML.dump 2024-05-02 18:49:29 -03:00
fauno 957de1f0f4 Merge branch 'issue-13439' into 'rails'
fix: deshabilitar la interfaz de orden para invitades #13439

See merge request sutty/sutty!188
2024-05-02 20:16:38 +00:00
fauno a93e0c3402 Merge branch 'issue-15092' into 'rails'
feat: empresa recuperada #15092

See merge request sutty/sutty!241
2024-05-02 20:13:56 +00:00
f 368cb065ea
ci: el token correcto [skip ci] 2024-05-02 17:13:15 -03:00
f c2bc0aa0c3
Merge branch 'rails' into issue-13439 2024-05-02 17:11:36 -03:00
f 5334a2e046
ci: forzar compilación 2024-05-02 17:05:09 -03:00
f f8e281141a
ci: forzar recompilación 2024-05-02 16:40:46 -03:00
f 5810d0c3df
ci: pushear de vuelta a la rama 2024-05-02 16:34:54 -03:00
f 074549613c
ci: compilar assets en producción y testing 2024-05-02 16:34:41 -03:00
f 6ceef5465f
chore: haml-lint 2024-05-02 16:25:20 -03:00
f d6eaef97f4
Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-15154 2024-05-02 16:23:45 -03:00
fauno 3881a3091a Merge branch 'issue-4101' into 'rails'
Issue #13588

See merge request sutty/sutty!251
2024-05-02 19:19:18 +00:00
f fe78c354a7
ci: instalar dependencias antes de usarlas 2024-05-02 16:18:34 -03:00
fauno aa29893704 Merge branch 'issue-174' into 'rails'
feat: poder traer algunas opciones de configuración desde la plantilla #174

See merge request sutty/sutty!254
2024-05-02 19:13:20 +00:00
fauno fa93610a03 Merge branch 'issue-13578' into 'rails'
Issue 13578

See merge request sutty/sutty!252
2024-05-02 19:11:17 +00:00
fauno bf0a0494cd Merge branch 'issue-14540' into 'rails'
feat: soportar varias instancias de distributed press #14540

See merge request sutty/sutty!224
2024-05-02 19:10:17 +00:00
f b5da595789
Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-174 2024-05-02 16:08:37 -03:00
fauno 239b43153d Merge branch 'issue-15109-1' into 'rails'
activitypub

Closes #15549, #15548, #15547, #15546, #15545, #15544, #15543, #15542, #15541, #15540, #15539, #15538, #15537, #15536, #15535, #15534, #15533, #15532, #15531, #15530, #15529, #15528, #15527, #15526, #15525, #15524, #15523, #15522, #15521, #15520, #15519, #15518, #15517, #15516, #15515, #15514, #15513, #15512, #15511, #15510, #15509, #15508, #15507, #15506, #15505, #15504, #15503, #15502, #15501, #15500, #15499, #15498, #15497, #15496, #15495, #15494, #15493, #15492, #15491, #15490, #15489, #15488, #15487, #15486, #15485, #15484, #15483, #15482, #15481, #15480, #15479, #15478, #15477, #15473, #15472, #15471, #15470, #15469, #15468, #15467, #15466, #15465, #15464, #15463, #15462, #15461, #15460, #15459, #15458, #15457, #15456, #15455, #15454, #15453, #15452, #15451, #15450, #15449, #15448, #15447, #15446, #15445, #15444, #15443, #15442, #15441, #15440, #15439, #15438, #15437, #15436, #15435, #15434, #15433, #15432, #15431, #15430, #15429, #15428, #15427, #15426, #15425, #15424, #15423, #15422, #15421, #15420, #15419, #15418, #15417, #15416, #15415, #15414, #15413, #15412, #15411, #15410, #15409, #15408, #15407, #15406, #15405, #15404, #15403, #15402, #15401, #15400, #15399, #15398, #15397, #15396, #15395, #15394, #15393, #15392, #15391, #15390, #15389, #15388, #15387, #15386, #15385, #15384, #15383, #15664, #15663, #15662, #15661, #15660, #15658, #15657, #15656, #15737, #15738, #15739, #15759, #15758, #15757, #15756, #15755, #15754, #15753, #15752, #15751, #15750, #15749, #15748, #15747, #15746, #15745, #15744, #15743, #15742, #15741, #15740, #15764, #15765, #15766, #15767, #15770, #15771, #15772, #15773, #15775, #15789, #15791, #15788, #15818, #15817, #15816, #15815, #15814, #15813, #15812, #15811, #15810, #15809, #15808, #15807, #15806, #15805, #15804, #15803, #15802, #15801, #15800, #15799, #15798, #15797, #15796, #15795, #15794, #15793, #15792, #15882, #15839, #15838, #15832, #15831, #15830, #15829, #15828, #15827, #15824, #15776, #15736, #15735, #15731, #15730, #15729, #15623, #15622, #15621, #15618, #15612, #15352, #15351, #15382, #15381, #15380, #15379, #15378, #15377, #15376, #15375, #15374, #15373, #15372, #15371, #15370, #15369, #15368, #15367, #15366, #15553, #15554, #15363, #15564, #15567, #15560, #15559, #15558, #15557, #15556, #15555, #15593, #15708, #15707, #15706, #15705, #15704, #15702, #15701, #15700, #15699, #15698, #15697, #15696, #15695, #15694, #15693, #15692, #15691, #15690, #15689, #15688, #15687, #15686, #15685, #15684, #15683, #15682, #15681, #15680, #15679, #15678, #15677, #15676, #15675, #15674, #15673, #15672, #15671, #15670, #15669, #15668, #15667, #15666, and #15665

See merge request sutty/sutty!253
2024-05-02 19:06:23 +00:00
f c2cc08007e
chore: rubocop 2024-05-02 16:05:35 -03:00
f b11282997b
fix: redundante 2024-05-02 16:02:34 -03:00
f 770935206f
Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-15109-1 2024-05-02 16:01:18 -03:00
fauno 08db600726 Merge branch 'issue-14339' into 'rails'
fix: reportar errores de ssh una sola vez

Closes #16059, #16058, #16052, #15871, #15870, #15869, #15868, #15867, #15866, #15865, #15864, #15863, #15862, #15861, #15860, #15859, #15858, #15857, #15856, #15855, #15849, #15848, #15847, #15846, #15845, #14662, #14561, and #14339

See merge request sutty/sutty!255
2024-05-02 18:59:12 +00:00
f 8fba98f9fd
chore: rubocop 2024-05-02 15:57:49 -03:00
f 7a03269aa3
Merge branch 'rails' into issue-14339 2024-05-02 15:55:50 -03:00
f 395f9a95bd
Merge branch 'rails' into issue-15109-1 2024-05-02 15:55:22 -03:00
f 9c0ea76c21
ci: instalar gemas [skip ci] 2024-05-02 15:54:54 -03:00
f 0a43916c9d
Merge branch 'rails' into issue-15109-1 2024-05-02 15:50:07 -03:00
f 4f12d12118
ci: usar los locks para identificar la cache [skip ci] 2024-05-02 15:49:20 -03:00
f a2209a655a
Merge branch 'rails' into issue-15109-1 2024-05-02 15:40:32 -03:00
fauno ad8280d37c Merge branch 'issue-14966' into 'rails'
Issue 14966

Closes #15097

See merge request sutty/sutty!239
2024-05-02 18:36:51 +00:00
fauno 1dd60bb834 Merge branch 'issue-16117' into 'rails'
fix: solo permitir los mismos tipos de archivo que jekyll

Closes #16117

See merge request sutty/sutty!259
2024-05-02 18:29:26 +00:00
fauno 2a37844f28 Merge branch 'issue-13611' into 'rails'
feat: recargar automáticamente el estado de publicación #13611

Closes #16126, #16125, #16116, #16074, #16073, #16064, #16063, #16051, #16050, #16024, #16023, #16016, #16015, #16004, #16003, #15975, #15974, #15973, #15894, #15893, #15884, #15883, #15881, and #15880

See merge request sutty/sutty!248
2024-05-02 18:24:08 +00:00
f 79be9538bb
fix: ignorar los errores de abort de htmx
el problema es que cuando se envía un abort a htmx, se loguea un mensaje
de todas formas.

closes #15880

closes #15881

closes #15883

closes #15884

closes #15893

closes #15894

closes #15973

closes #15974

closes #15975

closes #16003

closes #16004

closes #16015

closes #16016

closes #16023

closes #16024

closes #16050

closes #16051

closes #16063

closes #16064

closes #16073

closes #16074

closes #16116

closes #16125

closes #16126
2024-04-30 17:45:33 -03:00
f 5f0672bcae
feat: recargar el botón de publicar por separado #16180 2024-04-30 17:44:33 -03:00
f 8de05ccce6
fix: solo permitir los mismos tipos de archivo que jekyll
closes #16117
2024-04-22 14:54:40 -03:00
f 044b14c355
fixup! feat: editor 0.1.27 2024-04-22 11:15:09 -03:00
f 7d5a8f8d48
Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2024-04-22 11:06:57 -03:00
f 14c5530b50
feat: editor 0.1.27 2024-04-22 11:06:25 -03:00
fauno 0ca6689b53 Merge branch 'issue-15097' into 'rails'
feat: dropdown #15097

Closes #15097

See merge request sutty/sutty!243
2024-04-19 22:07:29 +00:00
Jazzari 3336c2d5b6 Merge branch 'issue-14700' into 'rails'
`Site#Reload` deberia devolver `self` #14700

See merge request sutty/sutty!231
2024-04-19 17:19:27 +00:00
Jazzari f3362eb27c Merge branch 'issue-14550' into 'rails'
No enviar Gateways Ipfs en mail de notificacion #14550

See merge request sutty/sutty!232
2024-04-19 17:06:57 +00:00
f 452ca43508
fix: doble negación 2024-04-19 13:07:49 -03:00
f 2eb3145e1c
fix: los atributos filtrados son por modelo 2024-04-15 17:28:30 -03:00
f 83add8dd7d
fix: usar una versión más corta del hash 2024-04-15 17:26:40 -03:00
f e8cf50b9d2
fix: convertir a yaml 2024-04-15 17:10:19 -03:00
f 7f437f9e06
fix: filtrar información personal también 2024-04-15 17:00:58 -03:00
f fb4228b873
fix: no filtrar información privada! 2024-04-15 16:58:55 -03:00
f 4ccf37c370
fix: informar la tarea que falló de forma genérica
closes #16052

closes #16058

closes #16059
2024-04-15 11:54:28 -03:00
fauno 73166355a7 Merge branch 'issue-15188' into 'rails'
feat: recordar la ubicación #15188

See merge request sutty/sutty!256
2024-04-15 14:24:34 +00:00
f 7a71e1de88
fix: no fallar si no hay sitio #16007 2024-04-12 15:31:47 -03:00
f 11660bc688
fix: editor 2024-04-12 10:01:53 -03:00
f c80984888c
feat: recordar la ubicación #15188 2024-04-10 15:16:09 -03:00
f 5e1def1028
feat: deshabilitar el botón mientras está compilando también
para no lanzar más de una compilación por vez
2024-04-10 13:32:37 -03:00
f 847af3374c
fix: no multiplicar el botón! 2024-04-10 13:26:22 -03:00
f 53fe2847a1
fixup! BREAKING CHANGE: usar global ids en los jobs 2024-04-10 13:22:17 -03:00
f 7cca88b4f3
fix: al salir de la página, cancelar todas las peticiones de htmx
closes #15880

closes #15881

closes #15883

closes #15884

closes #15893

closes #15894

closes #15973

closes #15974

closes #15975

closes #16003

closes #16004
2024-04-10 12:15:30 -03:00
f 629549c916
fix: rehabilitar el botón también 2024-04-10 11:49:30 -03:00
f b0bf0c0c53
BREAKING CHANGE: usar global ids en los jobs 2024-04-10 11:00:18 -03:00
f 6dbc8fa0c1
fix: reintentar compilaciones 2024-04-09 14:16:27 -03:00
f 94d7b32ce6
fix: handle_error no es compatible con activejob 2024-04-09 14:16:01 -03:00
f fe51ef2193
fixup! fix: activejob usa su propio método 2024-03-28 10:15:21 -03:00
f 3f7f887841
fix: activejob gestiona errores por su cuenta
closes #15351

closes #15352

closes #15612

closes #15618

closes #15621

closes #15622

closes #15623

closes #15729

closes #15730

closes #15731

closes #15735

closes #15736

closes #15776

closes #15824

closes #15827

closes #15828

closes #15829

closes #15830

closes #15831

closes #15832

closes #15838

closes #15839

closes #15882
2024-03-28 10:13:13 -03:00
f ca4017dbd0
fix: activejob usa su propio método
closes #15621

closes #15622

closes #15623

closes #15729

closes #15730

closes #15731

closes #15735

closes #15736

closes #15824

closes #15838

closes #15839

closes #15882
2024-03-28 10:09:20 -03:00
f 142962160a
fix: reintentar en algunos errores
closes #15351

closes #15352

closes #15612

closes #15618

closes #15621

closes #15622

closes #15623

closes #15729

closes #15730

closes #15731

closes #15735

closes #15736

closes #15776

closes #15824

closes #15827

closes #15828

closes #15829

closes #15830

closes #15831

closes #15832

closes #15838

closes #15839

closes #15882
2024-03-27 14:06:23 -03:00
f ba3cc9cad9
chore: rubocop 2024-03-27 13:42:27 -03:00
f c9ef117138
fix: reportar errores de ssh una sola vez
closes #14339

closes #14561

closes #14662

closes #15845

closes #15846

closes #15847

closes #15848

closes #15849

closes #15855

closes #15856

closes #15857

closes #15858

closes #15859

closes #15860

closes #15861

closes #15862

closes #15863

closes #15864

closes #15865

closes #15866

closes #15867

closes #15868

closes #15869

closes #15870

closes #15871
2024-03-27 13:36:56 -03:00
f c501107856
fix: indicar que no hay que reportar el error
closes #15621

closes #15622

closes #15623

closes #15729

closes #15730

closes #15731

closes #15735

closes #15736

closes #15824

closes #15838

closes #15839
2024-03-27 12:56:54 -03:00
f 0975d8d5cf
fix: no fallar si no hay ninguno 2024-03-26 15:48:30 -03:00
f 263dce1435
feat: poder traer algunas opciones de configuración desde la plantilla #174 2024-03-26 15:29:58 -03:00
jazzari 1130bb791c fix: borrado espacio extra en línea 14 de _row.haml #14949 2024-03-26 15:01:59 -03:00
f 34a858f26a
fix: botones apaisados 2024-03-26 13:08:11 -03:00
f b10eef7644
fix: botones en una sola línea 2024-03-26 13:03:46 -03:00
f a79354ceb1
fix: atrasar la carga de js 2024-03-26 12:28:53 -03:00
f 2fdfbb2eaa
fix: si no hay sitio para el panel usar el primer sitio 2024-03-26 12:28:40 -03:00
f a27d68cf54
fix: las llaves estaban mal nombradas!! #13578 2024-03-26 12:28:19 -03:00
f 0d28748b8b
fix: i18n 2024-03-26 11:42:29 -03:00
f d577075615
feat: informar que se va a modificar el archivo #4101 2024-03-25 15:33:10 -03:00
f 3f9714f6d0
fix: permitir cargar blobs en previsualización de videos y audios 2024-03-25 15:30:44 -03:00
f 88cc5f9cb0
fix: reintentar antes de reportar el error #15824 2024-03-25 14:17:26 -03:00
f 718b864356
fixup! fix: espaciar el procesamiento de tareas 2024-03-25 13:33:52 -03:00
f d7de351e1a
fix: espaciar el procesamiento de tareas
closes #15621

closes #15622

closes #15623

closes #15729

closes #15730

closes #15731

closes #15735

closes #15736

closes #15824
2024-03-25 13:32:08 -03:00
f 316b192d1e
fix: poder aceptar o rechazar invitaciones #15154 2024-03-25 12:42:26 -03:00
f 1128f04954
fix: mostrar los botones de invitación en una sola línea 2024-03-25 12:42:15 -03:00
f 95231511b7
fix: poder ver el estado 2024-03-22 18:54:18 -03:00
f 736f0552f7
fix: poder importar htmx en producción 2024-03-22 18:46:21 -03:00
f fb38600884
feat: recargar automáticamente el estado de publicación #13611 2024-03-22 18:34:24 -03:00
f 366494b615
fix: typo
closes #15792

closes #15793

closes #15794

closes #15795

closes #15796

closes #15797

closes #15798

closes #15799

closes #15800

closes #15801

closes #15802

closes #15803

closes #15804

closes #15805

closes #15806

closes #15807

closes #15808

closes #15809

closes #15810

closes #15811

closes #15812

closes #15813

closes #15814

closes #15815

closes #15816

closes #15817

closes #15818
2024-03-22 18:28:34 -03:00
f 07fd2cff93
fix: usar locks en moderaciones de instancia
closes #15788
2024-03-22 17:31:53 -03:00
f dbf15397e5
fix: mostrar los desplegables como accionables #15600 2024-03-22 15:44:28 -03:00
f 071f20762c
fix: bloquear antes de empezar a modificar
closes #15791
2024-03-22 13:09:13 -03:00
f dad5f5f00c
fix: solo bloquear cuando ya está en la base de datos
closes #15791
2024-03-22 13:07:15 -03:00
f 5db263ef6c
fix: recordar que hay que volver a correr la tarea manualmente #15789 2024-03-22 12:54:27 -03:00
f b6fdc8a580
fix: permitir hostnames numéricos
closes #15789
2024-03-22 12:38:54 -03:00
f cc654be121
fixup! fix: no fallar si no hay registros sobre los que actuar #15725 2024-03-22 12:01:08 -03:00
f 0561b022de
fix: no fallar si no hay registros sobre los que actuar #15725 2024-03-22 11:59:37 -03:00
f 4853263374
fix: pedir locks antes de guardar
closes #15621

closes #15622

closes #15623

closes #15729

closes #15730

closes #15731

closes #15735

closes #15736
2024-03-22 11:53:23 -03:00
f ad637189b5
fixup! fix: poder ir a la cola de moderación 2024-03-21 18:25:36 -03:00
f 2aa2b9f3bb
fix: poder ir a la cola de moderación 2024-03-21 18:13:10 -03:00
f e05a8aafda
fix: enviar los botones de reporte a la derecha #15600 2024-03-21 11:14:36 -03:00
f 8dae40cb0e
fix: confirmar al rechazar #15600 2024-03-20 17:53:00 -03:00
f eda075fd4b
fix: la acción no se puede hacer porque es el estado actual #15600 2024-03-20 17:52:31 -03:00
f e2fdce91f3
fix: agrupar espacialmente acciones #15600 2024-03-20 17:51:23 -03:00
f 0578b03ee7
fix: reportar implicar bloquear #15600 2024-03-20 17:50:39 -03:00
f 0a1b86c111
fix: se pueden rechazar comentarios luego de aprobarlos #15600 2024-03-20 17:49:09 -03:00
f 28053b2a56
fix: las cuentas reportadas también están bloqueadas #15649 2024-03-20 16:19:15 -03:00
f eafa6fad37
fix: cargar el objeto por id y modificarlo
closes #15775

closes #15773

closes #15772

closes #15771

closes #15770

closes #15767

closes #15766

closes #15765

closes #15764
2024-03-19 17:02:19 -03:00
f 1ef7996ce9
fix: agrupar errores para que no nos inunden 2024-03-19 13:21:41 -03:00
f d33e7b37a1
fix: lock
closes #15740

closes #15741

closes #15742

closes #15743

closes #15744

closes #15745

closes #15746

closes #15747

closes #15748

closes #15749

closes #15750

closes #15751

closes #15752

closes #15753

closes #15754

closes #15755

closes #15756

closes #15757

closes #15758

closes #15759
2024-03-19 13:16:28 -03:00
f 029d4e7c97
fix: object_id
closes #15739

closes #15738

closes #15737
2024-03-19 13:01:26 -03:00
f 0ed702992b
fix: prevenir objetos multiplicados!
parece que la forma en que estabamos creando indices unicos ya no
funciona (??) asi que a veces estabamos creando objetos duplicados en
threads. de paso actorfetchjob ya no es necesario.

closes #15621

closes #15622

closes #15623

closes #15729

closes #15730

closes #15731
2024-03-19 12:39:41 -03:00
f 8d6d215e1a
fix: si falla el reporte marcarlo para reenvío 2024-03-19 11:21:03 -03:00
f 93ebb6431a
fix: buscar un código de respuesta general 2024-03-19 11:20:49 -03:00
f 48d8d2d8d8
fix: la lógica estaba al revés #15647 2024-03-19 10:59:10 -03:00
f c047858a6f
fixup! feat: fedipact 2024-03-19 09:49:34 -03:00
f b90f886446
feat: fedipact 2024-03-19 09:47:24 -03:00
f 979f3c1b3a
fix: ayuda para la lista customizada #15643 2024-03-18 18:12:02 -03:00
f d13e56e692
fix: descripción para las listas de bloqueo #15643 2024-03-18 18:09:32 -03:00
f e2abe224d4
fix: fallbacks #15659 2024-03-18 17:54:07 -03:00
f 7c9e9758c5
fix: informar la uri que falló #15712 2024-03-18 17:51:29 -03:00
f dae0346f0d
fix: pasar el sitio como argumento 2024-03-18 17:28:49 -03:00
f ab43c84ab1
fix: indicar el filtro activo #15652 2024-03-18 17:13:32 -03:00
f 8034d20612
fix: ignorar comentarios y cuentas sin contenido aun 2024-03-18 16:55:20 -03:00
f 376339aee5
fix: correr las consultas de todas formas 2024-03-18 16:45:00 -03:00
f bd0df0a53a
fixup! fix: qué pasa con los objetos 2024-03-18 15:47:38 -03:00
f 75b6314e1d
fix: qué pasa con los objetos 2024-03-18 15:46:03 -03:00
f e6d4b4d3f1
fix: validar que el contenido del objeto sea el que queremos 2024-03-18 15:10:16 -03:00
f e50ae70ebb
fix: no actualizar si el contenido estaba cacheado 2024-03-18 15:06:41 -03:00
f ceeb0009ef
fix: descubrir el tipo de objeto siempre
closes #15656

closes #15657

closes #15658

closes #15660

closes #15661

closes #15662

closes #15663

closes #15664

closes #15665

closes #15666

closes #15667

closes #15668

closes #15669

closes #15670

closes #15671

closes #15672

closes #15673

closes #15674

closes #15675

closes #15676

closes #15677

closes #15678

closes #15679

closes #15680

closes #15681

closes #15682

closes #15683

closes #15684

closes #15685

closes #15686

closes #15687

closes #15688

closes #15689

closes #15690

closes #15691

closes #15692

closes #15693

closes #15694

closes #15695

closes #15696

closes #15697

closes #15698

closes #15699

closes #15700

closes #15701

closes #15702

closes #15704

closes #15705

closes #15706

closes #15707

closes #15708
2024-03-18 14:40:11 -03:00
f bcfb7a5a7f
fix: asignar la remote flag #15648 2024-03-18 12:55:27 -03:00
f 9dc0ed7684
fix: reusar el reporto remoto #15648 2024-03-18 12:48:09 -03:00
f 7b87aaa93d
feat: referenciar objetos #15642 2024-03-18 11:55:38 -03:00
f 1623d618ee
fix: mostrar link externo al comentario #15638 2024-03-18 11:21:13 -03:00
f bdb5175fcd
fixup! fix: quizás no hay actor aun (?) 2024-03-17 12:10:07 -03:00
f 883da8d881
fix: quizás no hay actor aun (?) 2024-03-17 12:06:55 -03:00
f e8ce721af0
fix: traducción faltante 2024-03-16 19:20:32 -03:00
f a65a9f2f50
feat: aprobar o rechazar en segundo plano 2024-03-16 19:16:30 -03:00
f 769eae6157
feat: sincronizar en segundo plano 2024-03-16 19:05:12 -03:00
f b972e53e48
feat: guardar la mención de le autore 2024-03-16 17:53:29 -03:00
f f6b2895b58
fix: aprobar las peticiones de seguimiento automáticamente 2024-03-16 16:36:00 -03:00
f 8ff5626e99
feat: no permitir entrar al evento si falla la request 2024-03-16 15:12:55 -03:00
f 8f91b748ff
fix: mostrar botones de acción en masa 2024-03-16 14:27:28 -03:00
f 1dae918a17
feat: poder gestionar la cola de tareas 2024-03-16 14:17:28 -03:00
f adfd6c78bb
feat: procesar actividades en segundo plano
en lugar de hacerlo en el momento, respondemos lo más rápido posible a
la social inbox, ya que un webhook fallado genera un error en la social
inbox, que genera un error en la instancia remota, que va a volver a
intentar muchas veces.

ahora recibimos una vez, si falla el procesamiento, lo detenemos para
que alguien humane actúe al respecto.
2024-03-16 14:15:32 -03:00
f 3a0f1584c1
fix: poder volver al sitio 2024-03-16 11:32:16 -03:00
f 26e8656616
fixup! fix: no mostrar likes #15596 2024-03-15 18:08:34 -03:00
f 00270b7829
fix: no mostrar likes #15596 2024-03-15 18:05:05 -03:00
f 364b63a075
fix: notificar correctamente la excepción #15608 2024-03-15 17:57:21 -03:00
f fcbff3e1c1
fix: enviar el reporte firmado por el sitio #15605
pasaban dos cosas:

1. para firmar correctamente, el cliente necesita recibir el path
   completo por su parámetro `endpoint`

2. la petición tiene que ser hecha por le misme actore que hace el
   reporte, como estábamos firmando con el sitio, mastodon creía que era
   un relay y esperaba que se envíen firmas ld
2024-03-15 16:52:42 -03:00
f 6412fc108e
fix: no se puede rechazar luego de aprobar todavía 2024-03-15 14:31:54 -03:00
f 5db7506752
fix: no se puede pausar todavía #15600 2024-03-15 14:26:22 -03:00
f 0fe043dd79
fix: informar errores de json
closes #15593
2024-03-15 14:14:27 -03:00
f 86ba17328d
feat: migas de pan para actores 2024-03-15 14:01:00 -03:00
f d7f898c1ae
Merge branch 'issue-15578' of 0xacab.org:sutty/sutty into issue-15109-1 2024-03-15 13:56:26 -03:00
f 30d32a6e3b
feat: confirmar el reporte remoto #15604 2024-03-15 13:43:00 -03:00
maki 8473927cee fix: breadcrumbs 2024-03-15 12:23:04 -03:00
f f4379b45c2
feat: announce y like 2024-03-14 18:02:21 -03:00
f 1e44fba4b3
fix: aprobar la actividad, no el objeto 2024-03-14 17:08:55 -03:00
f d92953e5fa
fix: poder volver a pausa si se edita el comentario 2024-03-14 17:08:38 -03:00
f 96d70100e4
feat: auto-aprobar solicitudes de seguimiento 2024-03-14 17:07:58 -03:00
f 5969662a7d
fixup! fix: arreglar las relaciones entre actividades y objetos 2024-03-14 15:42:44 -03:00
f 5bf26a7fb2
fix: arreglar las relaciones entre actividades y objetos 2024-03-14 12:38:08 -03:00
maki 33cfdd1995 fix: breadcrumbs en todas las acciones 2024-03-14 12:21:50 -03:00
maki 1de9d1a126 feat: breadcrumbs en Actividades de Moderación #15578 2024-03-14 12:02:37 -03:00
f c57794b54e
fixup! fix: eliminar actores cuando no se pudo completar el objeto #15576 2024-03-14 11:58:13 -03:00
f cfe70e3a89
fix: no cachear formularios #15570 2024-03-14 11:57:06 -03:00
f 30f2f0a442
fix: gestionar las excepciones desde un solo lugar #15564 2024-03-14 11:45:33 -03:00
f 9d71c5fa0c
fix: eliminar actores cuando no se pudo completar el objeto #15576 2024-03-14 11:20:04 -03:00
f b6ed91df11
fix: siempre relacionar la instancia con el sitio #15563 2024-03-13 17:52:45 -03:00
f 1b9e039fda
fix: errores de decompresión #15332 2024-03-13 17:42:36 -03:00
f 97653d98b6
fix: prevenir deadlocks
closes #15555

closes #15556

closes #15557

closes #15558

closes #15559

closes #15560
2024-03-13 17:02:01 -03:00
f 79e6ce7872
fixup! fix: facilitar la búsqueda de instancias en la lista #15563 2024-03-13 16:56:51 -03:00
f ac38343a21
fix: facilitar la búsqueda de instancias en la lista #15563 2024-03-13 16:55:34 -03:00
f 93140f37aa
fix: cachear correctamente
closes #15567
2024-03-13 16:46:04 -03:00
f 061fc81cb0
fixup! fix: prevenir doble renderización 2024-03-13 16:44:24 -03:00
f 4dd75eedad
fix: prevenir doble renderización
closes #15564
2024-03-13 16:39:58 -03:00
f 630f6b31fc
fixup! fixup! fix: serializar correctamente 2024-03-13 16:28:59 -03:00
f ad9f9c3d61
fixup! fix: serializar correctamente 2024-03-13 16:27:33 -03:00
f 56c583e0f4
fix: serializar correctamente
closes #15363
2024-03-13 16:11:40 -03:00
f 882ab1679c
fix: a veces el objeto no existe (?)
closes #15554
2024-03-13 15:52:33 -03:00
f f794e8057b
feat: no hacer acciones en cascada #15327 #15328 2024-03-13 15:29:34 -03:00
f ef482aaedf
fix: el método es de clase
closes #15553
2024-03-13 11:41:22 -03:00
f 40edccf8bb
fixup! fix: no ignorar ningún evento 2024-03-13 11:15:31 -03:00
f 32042f32e2
fix: no ignorar ningún evento
closes #15366

closes #15367

closes #15368

closes #15369

closes #15370

closes #15371

closes #15372

closes #15373

closes #15374

closes #15375

closes #15376

closes #15377

closes #15378

closes #15379

closes #15380

closes #15381

closes #15382

closes #15383

closes #15384

closes #15385

closes #15386

closes #15387

closes #15388

closes #15389

closes #15390

closes #15391

closes #15392

closes #15393

closes #15394

closes #15395

closes #15396

closes #15397

closes #15398

closes #15399

closes #15400

closes #15401

closes #15402

closes #15403

closes #15404

closes #15405

closes #15406

closes #15407

closes #15408

closes #15409

closes #15410

closes #15411

closes #15412

closes #15413

closes #15414

closes #15415

closes #15416

closes #15417

closes #15418

closes #15419

closes #15420

closes #15421

closes #15422

closes #15423

closes #15424

closes #15425

closes #15426

closes #15427

closes #15428

closes #15429

closes #15430

closes #15431

closes #15432

closes #15433

closes #15434

closes #15435

closes #15436

closes #15437

closes #15438

closes #15439

closes #15440

closes #15441

closes #15442

closes #15443

closes #15444

closes #15445

closes #15446

closes #15447

closes #15448

closes #15449

closes #15450

closes #15451

closes #15452

closes #15453

closes #15454

closes #15455

closes #15456

closes #15457

closes #15458

closes #15459

closes #15460

closes #15461

closes #15462

closes #15463

closes #15464

closes #15465

closes #15466

closes #15467

closes #15468

closes #15469

closes #15470

closes #15471

closes #15472

closes #15473

closes #15477

closes #15478

closes #15479

closes #15480

closes #15481

closes #15482

closes #15483

closes #15484

closes #15485

closes #15486

closes #15487

closes #15488

closes #15489

closes #15490

closes #15491

closes #15492

closes #15493

closes #15494

closes #15495

closes #15496

closes #15497

closes #15498

closes #15499

closes #15500

closes #15501

closes #15502

closes #15503

closes #15504

closes #15505

closes #15506

closes #15507

closes #15508

closes #15509

closes #15510

closes #15511

closes #15512

closes #15513

closes #15514

closes #15515

closes #15516

closes #15517

closes #15518

closes #15519

closes #15520

closes #15521

closes #15522

closes #15523

closes #15524

closes #15525

closes #15526

closes #15527

closes #15528

closes #15529

closes #15530

closes #15531

closes #15532

closes #15533

closes #15534

closes #15535

closes #15536

closes #15537

closes #15538

closes #15539

closes #15540

closes #15541

closes #15542

closes #15543

closes #15544

closes #15545

closes #15546

closes #15547

closes #15548

closes #15549
2024-03-13 11:07:59 -03:00
f 45d56502c1
fix: aprobar 2024-03-12 17:44:40 -03:00
f d44bcc4098
fix: typo 2024-03-12 17:30:47 -03:00
f 4fde9793d7
fix: permitir que la tarea se reporte como hecha 2024-03-12 17:09:21 -03:00
f 3c07ddf12c
fixup! fixup! fixup! feat: modificar el estado de moderación en masa #15328 #15327 2024-03-12 15:59:42 -03:00
f 12f77e4658
fix: actualizar cliente 2024-03-12 15:57:04 -03:00
f 20c6d6af50
feat: eliminar todos los comentarios de une actore eliminade 2024-03-12 14:33:07 -03:00
f e783390747
fixup! fixup! feat: modificar el estado de moderación en masa #15328 #15327 2024-03-12 14:28:26 -03:00
f d2d327dc84
fixup! feat: modificar el estado de moderación en masa #15328 #15327 2024-03-12 14:24:38 -03:00
f bf75d50cc3
feat: modificar el estado de moderación en masa #15328 #15327 2024-03-12 13:57:31 -03:00
f 522cef8c9a
feat: acciones en masa para actividades 2024-03-08 15:56:22 -03:00
f 071102fa3b
feat: al moderar una cuenta, también moderar sus comentarios 2024-03-08 15:31:41 -03:00
f 6b74bc454d
fix: sin dummy data en posts 2024-03-08 15:20:19 -03:00
f 42be495465
fix: no prometer que el reporte es anónimo
le admin de la instancia remota siempre puede d0xear
2024-03-08 15:19:21 -03:00
f 8faa6d8ea8
feat: ser más informative con los comentarios 2024-03-08 15:18:19 -03:00
f cb30a3d02c
fix: ser informatives 2024-03-08 15:07:32 -03:00
f 995c80fed1
fix: no colgar toda la cola si algo falla en la api 2024-03-08 14:53:33 -03:00
f 4dff318030
feat: al desactivar un fediblock, ignorar otros fediblocks 2024-03-08 14:10:21 -03:00
f fc77f8e9f4
fix: form es opcional #15329 2024-03-08 13:08:24 -03:00
f 550dba08c5
fix: migraciones 2024-03-08 11:24:57 -03:00
f 21401d93b6
fixup! feat: eliminar más actores 2024-03-07 17:46:32 -03:00
f 2370cf7310
feat: eliminar más actores 2024-03-07 17:44:40 -03:00
f b0b8e6877e
fixup! feat: cuando une actore es eliminade, hay que eliminar sus estados de moderación 2024-03-07 17:21:03 -03:00
f 5a7331e00e
feat: cuando une actore es eliminade, hay que eliminar sus estados de moderación 2024-03-07 17:17:58 -03:00
f 66e59ee5ad
feat: algunos tipos son actores 2024-03-07 16:54:09 -03:00
f 453798dcc7
fix: el método es público 2024-03-07 16:38:26 -03:00
f a8f184ecbf
feat: validar que las uris sean uris 2024-03-06 17:45:21 -03:00
f 7aa14bd292
fix: poder ir al perfil 2024-03-06 17:36:13 -03:00
f 00f865f315
fix: comentario en perfil de actore 2024-03-06 17:22:01 -03:00
f 2e04bc8eac
fix: las actividades están duplicadas con respecto a su estado
por ejemplo, el borrado de une actore puede estar dirigido a todos los
sitios, con lo que se crea varias veces (aunque se ejecuta solo una)
2024-03-06 17:15:21 -03:00
f 5f5b929aa8
fix: traducciones 2024-03-06 15:59:48 -03:00
f 019101ba1e
feat: almacenar el perfil de le actore en la base de datos 2024-03-06 15:54:47 -03:00
f 5c22015fe2
fix: el reporte remoto es opcional 2024-03-06 15:47:27 -03:00
f b334d49654
fix: actualizar al estado remoto 2024-03-06 15:41:46 -03:00
f 38ba8795de
fix: el reporte remoto es opcional 2024-03-06 15:36:00 -03:00
f ea34b2c676
fix: hostnames 2024-03-06 15:03:17 -03:00
f fbd741960b
fix: crear hooks y blocklists después de publicar 2024-03-06 14:42:08 -03:00
f 19d998086c
fix: raise 2024-03-06 14:31:32 -03:00
f 44ef583a23
fix: send es un nombre reservado 2024-03-06 14:12:04 -03:00
f e9b1d8d6b3
Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2024-03-06 13:04:03 -03:00
Sutty 4081f62ad1
fix: gitlab solo acepta 200 caracteres en el título
(cherry picked from commit 6ea20a4d55)
2024-03-06 13:03:56 -03:00
Sutty 053ec5674f
fix: no cambiar el hostname si se lo asignó manualmente
(cherry picked from commit 48defa9058)
2024-03-06 13:03:49 -03:00
fauno e1e55c84f4 Merge branch 'issue-14953' into 'rails'
fix: eliminar los guiones bajos al principio del nombre de archivo #14953

See merge request sutty/sutty!237
2024-03-05 19:41:19 +00:00
f 8b846a0aac
Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-14953 2024-03-05 16:40:35 -03:00
f ae31da8bdb
Merge branch 'issue-14953' of 0xacab.org:sutty/sutty into issue-14953 2024-03-05 16:40:21 -03:00
fauno 2c35ffe502 Merge branch 'issue-14946' into 'rails'
Issue 14946

See merge request sutty/sutty!236
2024-03-05 19:38:33 +00:00
f 0da69de6a7
feat: filtros comunes 2024-03-05 16:25:56 -03:00
f 2df9f721cd
feat: ver los artículos de le actore 2024-03-05 16:10:53 -03:00
f b1dee5d567
fix: dejar de cargar datos de prueba 2024-03-05 16:10:36 -03:00
f 5b53a9813f
feat: enviar una sola vez el reporte remoto y volver a enviarlo si le agregamos reportes 2024-03-05 16:00:47 -03:00
f 30fd6c28ee
feat: enviar un reporte por actore 2024-03-05 15:46:33 -03:00
f 054dbc31e0
fix: no fallar si la actividad ya había cambiado de estado 2024-03-05 14:19:33 -03:00
f ff428c6527
feat: poder reportar comentarios 2024-03-05 14:18:06 -03:00
f 67a56c540a
feat: no mostrar opciones que no se pueden ejecutar con el filtro actual 2024-03-04 17:45:16 -03:00
f c49182e278
feat: poder bloquear en masa 2024-03-04 17:14:46 -03:00
f 1fe6199cea
fix: todavía no se puede pausar luego de aprobar 2024-03-04 16:53:23 -03:00
f 0e2a4c4288
fix: todavía no se puede volver de una actividad rechazada 2024-03-04 16:52:28 -03:00
f ccd3df2038
feat: aprobar o rechazar actividades 2024-03-04 16:46:43 -03:00
f b798980865
feat: acciones masivas para comentarios 2024-03-04 15:14:33 -03:00
f b201c3de18
feat: filtros y acciones para comentarios 2024-03-04 15:11:29 -03:00
f 3967a63163
feat: extraer en un componente 2024-03-04 15:10:20 -03:00
f a7d33976ec
fixup! fix: no se pueden anidar formularios 2024-03-04 14:59:17 -03:00
f 8e681cdba7
fix: sincronizar controladores 2024-03-04 14:47:20 -03:00
f 5211c9bd28
fix: formularios 2024-03-04 14:39:06 -03:00
f 27d7589f9a
fix: no se pueden anidar formularios
usando el atributo form, podemos crear un formulario vacío y colocar
inputs por fuera de su contexto.

de lo contrario el primer botón de acción individual no funciona
2024-03-04 14:26:41 -03:00
f 0b3f4e33fb
fix: siempre es un botón
https://blog.saeloun.com/2021/08/24/rails-7-button-to-rendering/
2024-03-04 14:25:19 -03:00
f a2204779af
feat: filtrar por estado del comentario 2024-03-04 13:59:01 -03:00
f 5fabe9cd83
feat: acciones sobre comentarios 2024-03-04 13:49:07 -03:00
f d8487ea7e9
fixup! fix: limpiar html remoto 2024-03-04 13:17:21 -03:00
f 6110172324
feat: poder cambiar el nivel de summary 2024-03-04 13:12:22 -03:00
f 01c042b512
fix: limpiar html remoto 2024-03-04 13:11:34 -03:00
f b8e7e53ebd
feat: limpieza de texto 2024-03-04 13:10:32 -03:00
f d1a87177a5
fix: eliminar indice unico
en realidad lo queremos mantener...
2024-03-04 12:01:32 -03:00
f b255acf2fd
feat: comentarios por actore 2024-03-04 12:01:18 -03:00
f 85c45d4823
fix: no duplicar código 2024-03-01 17:29:08 -03:00
f 22f730b805
fix: guardar el tipo correcto de objeto si lo soportamos 2024-03-01 17:14:24 -03:00
f 9e1bda5570
Merge branch 'issue-14966' of 0xacab.org:sutty/sutty into issue-15109-1 2024-03-01 16:57:41 -03:00
fauno f705111584 Merge branch 'issue-15200' into 'rails'
Movido metodo lfs_cleanup en cleanup_service.rb a site::repository

See merge request sutty/sutty!246
2024-03-01 19:56:57 +00:00
f 09e56b88ed
fix: detectar si viene vacío 2024-03-01 16:51:40 -03:00
f 2e1087107a
fix: indexar por el tipo actual 2024-03-01 16:47:23 -03:00
f 4bef309621
fix: soportar flags 2024-03-01 16:47:11 -03:00
f 163f3fa737
fix: namespace 2024-03-01 16:47:00 -03:00
f 567f0a10fb
fix: no fallar si no se puede hacer la acción 2024-03-01 16:12:34 -03:00
f f8b4586633
feat: poder cambiar el estado a varies actores 2024-03-01 16:11:33 -03:00
f 3fa19ee8b0
feat: reportar desde el panel 2024-03-01 16:10:49 -03:00
f 67d9731b1e
feat: enviar reportes remotos 2024-03-01 15:04:07 -03:00
jazzari 291c477aec fix: corregido metodo lfs_cleanup 2024-03-01 13:11:04 -03:00
jazzari 6c3b2ab022 fix: movido metodo lfs_cleanup en cleanup_service.rb a site::repository 2024-03-01 12:19:51 -03:00
f 6c61aec60e
feat: al modificar un fediblock, cambiar el estado a todes les actores 2024-02-29 16:45:06 -03:00
f cbba822f31
feat: recordar el estado del details 2024-02-29 16:28:20 -03:00
f 3ba23a8b8c
feat: poder ir al perfil desde la lista 2024-02-29 15:54:53 -03:00
f cf46988d9d
fixup! feat: cambiar el estado de les actores desde el panel 2024-02-29 15:53:32 -03:00
f 5370a542ff
feat: cambiar el estado de les actores desde el panel 2024-02-28 19:10:37 -03:00
f 0539eb8f22
feat: avisar cuando no se encontró nada 2024-02-28 18:51:41 -03:00
f 2edafc8901
feat: ver la cuenta de cuentas por moderar 2024-02-28 18:50:01 -03:00
f 25c9963284
feat: mostrar las cuentas en la cola de moderación 2024-02-28 18:35:34 -03:00
f 0e2f6276eb
feat: siempre actualizar la fecha de le actore al guardar una actividad 2024-02-28 18:31:28 -03:00
f e07da7858e
feat: cambiar a orden descendiente por fecha de modificación 2024-02-28 18:27:15 -03:00
f 6d9a64f728
feat: moderar en la social inbox 2024-02-28 17:58:00 -03:00
f 6eaf00c7ad
fix: recibir actividades correctamente 2024-02-28 17:52:24 -03:00
f aeb8f88493
feat: crear el estado de moderación si no existe 2024-02-28 17:44:21 -03:00
f f524724c0f
feat: moderar actores 2024-02-28 17:34:34 -03:00
f eafe8bcdd5
feat: poder seleccionar todas las cuentas 2024-02-28 17:26:22 -03:00
f ef9169c891
fix: traducción faltante 2024-02-28 17:12:33 -03:00
f dd20c6ce84
fixup! feat: mostrar la cantidad de instancias 2024-02-28 16:42:39 -03:00
f 17705f66ad
feat: tarjeta cacheada de instancia 2024-02-28 16:42:18 -03:00
f 448564aa46
fix: hacer la tarea sincrónicamente 2024-02-28 16:36:50 -03:00
f f9d02cc63e
feat: recordar el filtro que estábamos usando 2024-02-28 16:32:03 -03:00
f 259d1c1e90
feat: optimizar acceso a información y ordenar por hostname 2024-02-28 16:23:18 -03:00
f 43d190ba74
feat: mostrar la cantidad de instancias 2024-02-28 16:13:51 -03:00
f 1ee41f2d5e
feat: al activar o desactivar un fediblock, vincular con todas las
instancias
2024-02-28 16:04:37 -03:00
f 15800e1096
BREAKING CHANGE: renombrar instancias por hostnames 2024-02-28 15:47:40 -03:00
f 7521f598a6
fix: poder deseleccionar todos los fediblocks 2024-02-28 15:45:58 -03:00
f 670d6063e5
fix: generar un rol dentro del sitio 2024-02-28 15:04:52 -03:00
f ee10e170ec
fix: el rol todavía no está guardado 2024-02-28 15:01:36 -03:00
f f1de4c8073
fix: ignorar instancias que ya no existen 2024-02-28 12:32:59 -03:00
f d5cf0fffe0
feat: no mostrar comentarios a invitades 2024-02-28 12:09:16 -03:00
f dc82b8cef2
feat: asignar rol a deploys al crear o modificar el sitio 2024-02-28 12:05:09 -03:00
f aae04f3739
feat: al activar el fediverso, activar las listas de bloqueo 2024-02-28 11:54:41 -03:00
f 342521c897
fix: guardar los datos de la instancia 2024-02-27 16:57:08 -03:00
f 34ead9ea4a
feat: establecer prioridades para las tareas 2024-02-27 16:53:48 -03:00
f d5f48c6007
feat: al actualizar las blocklists, bloquear las instancias en los sitios que las tengan habilitadas 2024-02-27 16:40:08 -03:00
f 4bc11c7007
feat: gestionar listas de bloqueo desde el panel 2024-02-27 16:39:02 -03:00
jazzari d4fa056db4 fix: corregido summary en compo details 2024-02-27 16:08:11 -03:00
f 6f66bd43e5
Merge branch 'issue-14966' of 0xacab.org:sutty/sutty into issue-15109-1 2024-02-27 15:40:46 -03:00
jazzari e239bd8b85 fix: corregido usuarios en compo instance 2024-02-27 15:25:25 -03:00
jazzari bbbbad18a0 fix: corregido margen en summary de compo details 2024-02-27 15:21:31 -03:00
f ad61113285
Merge branch 'issue-14966' of 0xacab.org:sutty/sutty into issue-15109-1 2024-02-27 15:14:35 -03:00
jazzari 0dba9e5500 fix: corregida alineación de checkbox general en details comentarios 2024-02-27 15:05:16 -03:00
jazzari cda5fc1215 fix: corregido enlace en block_list y texto en es.yml 2024-02-27 14:37:07 -03:00
f ec328d31b9
feat: cargar las fediblocks en la pantalla 2024-02-27 14:23:57 -03:00
f 67fec65df1
Merge branch 'issue-14966' of 0xacab.org:sutty/sutty into issue-15109-1 2024-02-27 14:15:48 -03:00
jazzari c0b64fc3da fix: corregido enlace a listas de bloqueo en compo block_list 2024-02-27 14:08:48 -03:00
f 24fe1f0090
Merge branch 'issue-14966' of 0xacab.org:sutty/sutty into issue-15109-1 2024-02-27 14:06:08 -03:00
f ebdd95151e
feat: relacionar sitios con fediblocks 2024-02-27 13:43:46 -03:00
f 8654228edc
feat: actualizar los fediblocks todos los días 2024-02-27 13:25:40 -03:00
jazzari 5a30da4232 fix: corregido parrafo en Presentación de componente Remote_profile 2024-02-27 13:14:25 -03:00
jazzari ae0ca386c3 fix: correciones varias en componente remote_profile 2024-02-27 13:07:51 -03:00
jazzari e728c09cc2 fix: corregida traducción de usuarios de instancia 2024-02-27 12:35:25 -03:00
f df6c048882
feat: fediblock 2024-02-27 12:32:09 -03:00
f f53ab11339
fixup! feat: poder seleccionar todas las instancias 2024-02-27 12:29:42 -03:00
jazzari 570459fef3 fix: corregido posición de botones de moderación en details de Instancias y Cuentas 2024-02-27 12:25:09 -03:00
jazzari 7837e2e85f fix: corregido espacio en componente block_list 2024-02-27 12:18:18 -03:00
jazzari 85cfed59fc fix: corregido posición de sumary en details y boton de bloqueo de instancias 2024-02-27 12:14:44 -03:00
f ca4b3360cd
fixup! feat: poder seleccionar todas las instancias 2024-02-26 17:38:00 -03:00
f 9b2efaafac
feat: hacer una acción con las seleccionadas 2024-02-26 17:37:44 -03:00
f 761d68604b
feat: poder seleccionar todas las instancias 2024-02-26 17:03:18 -03:00
f e78f71f25a
fix: acciones 2024-02-26 16:52:02 -03:00
f cc7175ab99
feat: poder filtrar por estado de la instancia 2024-02-26 16:51:33 -03:00
f a1b5e385b0
fix: los guards se ejecutan todo el tiempo 2024-02-26 16:50:03 -03:00
f 591d56581e
Merge branch 'issue-14966' of 0xacab.org:sutty/sutty into issue-15109-1 2024-02-26 16:38:40 -03:00
f ffdcb5fae8
feat: poder cambiar el estado de moderación a instancias 2024-02-26 16:12:56 -03:00
f dc11e6efc7
feat: cada sitio tiene un estado de moderación para la instancia 2024-02-26 12:27:56 -03:00
f 64cef8a13e
feat: relacionar actividades con instancias de origen 2024-02-26 10:39:00 -03:00
f 380d484c00
feat: poder encontrar instancias a partir de actividades 2024-02-24 13:05:39 -03:00
f a76c652f98
fix: permitir guardar le actore si la instancia ya existía 2024-02-24 12:47:11 -03:00
f 9e54d6311c
feat: obtener información de le actore 2024-02-24 12:46:55 -03:00
f f836427979
feat: obtener información sobre la instancia 2024-02-24 11:09:57 -03:00
jazzari ea6d794b57 fix: corregido checkbox general en comentarios, cuentas e instancias 2024-02-23 14:57:07 -03:00
jazzari e632bd249b fix: corregido compo comentario en cuenta de origen y fecha 2024-02-23 14:47:24 -03:00
f 4e31a6858d
Merge branch 'issue-14966' of 0xacab.org:sutty/sutty into issue-15109-1 2024-02-23 13:54:19 -03:00
jazzari 2f19aae793 feat: agregado enlace a listas de bloquedo y quitado estilo en css 2024-02-23 13:52:31 -03:00
f bdd8c1ba26
Merge branch 'issue-14966' into issue-15109-1 2024-02-23 13:31:24 -03:00
f 77137f311c
docs: recordar que tenemos que validar mejor 2024-02-23 12:56:39 -03:00
f e3aabf4b91
feat: poder obtener el id desde un objeto 2024-02-23 12:54:31 -03:00
f 2c8dbc885c
fix: evitar advertencias 2024-02-23 12:53:56 -03:00
f a4062c5f54
feat: eliminar un objeto elimina todas las actividades pendientes 2024-02-23 12:52:01 -03:00
f a51cb4dbdd
fix: copiar el contexto desde la acción al objeto 2024-02-23 12:36:03 -03:00
f 836e5d5935
fix: las actividades pueden existir previamente 2024-02-23 12:27:37 -03:00
f fd1d2382fa
feat: luego de rechazar podemos reportar 2024-02-22 18:42:36 -03:00
f 3a382390b1
fix: la social inbox no confirma acciones! 2024-02-22 18:42:20 -03:00
f 9b401f8c12
fix: el hostname puede estar en varios lados 2024-02-22 18:13:53 -03:00
f c02a976206
feat: poder acceder a la inbox 2024-02-22 18:08:48 -03:00
f c23d931dd4
fix: usar el método correcto 2024-02-22 18:05:21 -03:00
f f50e2d430d
fix: dump 2024-02-22 18:01:09 -03:00
f 1022d57fd3
fix: los scopes en las rutas son raros 2024-02-22 17:58:51 -03:00
f b0e07d5d02
fix: require 2024-02-22 17:56:12 -03:00
f c415c79c5c
fix: por alguna razón usamos REDIS_SERVER 2024-02-22 17:46:58 -03:00
f a7662d005c
fix: copiar estilo de botón desde el modo oscuro 2024-02-22 17:28:19 -03:00
f 969d641a91
fix: touch 2024-02-22 16:04:10 -03:00
jazzari af1afe8f50 fix: agregado html_safe a summary en remote_profile 2024-02-22 15:50:57 -03:00
jazzari e62e26c87c fix: agregado checkbox general a comentarios 2024-02-22 15:36:42 -03:00
f 1404d2006d
fixup! feat: asociar rol con deploy nos permite acceder al token 2024-02-22 13:32:30 -03:00
f 476ab951bb
fixup! feat: rutas 2024-02-22 13:31:31 -03:00
f 023b239150
fix: no hay botones verdes 2024-02-22 11:46:39 -03:00
maki df88f80b30 fix: comentario en un details si tiene summary 2024-02-21 18:08:54 -03:00
maki 1b8685b7ca fix: yaml roto 2024-02-21 18:01:10 -03:00
f 6b12e5141c
feat: al deshacer una actividad resolvemos la pendiente 2024-02-21 17:54:18 -03:00
f e62d6c6c1d
fix: asignar un tipo por defecto para el objeto 2024-02-21 17:53:27 -03:00
maki b489b713ac fix: faltaba poner la hora de los comentarios 2024-02-21 17:52:53 -03:00
maki e4e604f56d fix: separadores en actividades de moderación 2024-02-21 17:34:46 -03:00
maki a7bd712a7c fix: tamaño botones de moderación de comentarios 2024-02-21 17:33:58 -03:00
f 7a936c1143
fix: no actualizar si ya estaba cacheado y el contenido existía 2024-02-21 17:22:31 -03:00
f 2ae2b8e9e8
fix: las actividades de borrado eliminan el contenido también 2024-02-21 17:09:15 -03:00
f dca266714d
fix: no completar el contenido si el objeto tiene actividades canceladas 2024-02-21 17:08:11 -03:00
f fc7c2e5b74
fix: undo auto-cancela la actividad 2024-02-21 17:05:17 -03:00
f e53f31f359
fixup! fix: deleted es un método reservado 2024-02-21 17:04:39 -03:00
f b562b006bc
fix: versión requerida por aasm 2024-02-21 17:03:59 -03:00
f a13f42c22f
fixup! fixup! fix: no es necesario vincular actores con objetos 2024-02-21 16:43:31 -03:00
f 3292d7ebe3
fix: vaciar el contenido antes de cambiar de estado 2024-02-21 16:42:28 -03:00
f a4133c6001
fix: asegurarse que todos los registros existan 2024-02-21 16:42:14 -03:00
f f8f0eb9d3c
fix: no buscar csrf 2024-02-21 16:42:02 -03:00
f f517889992
fixup! fix: no es necesario vincular actores con objetos 2024-02-21 15:45:15 -03:00
f 39bbc3a2bd
fix: deleted es un método reservado 2024-02-21 15:44:41 -03:00
f d98f893a71
fix: algunas actividades no tienen destinatarie 2024-02-21 15:44:29 -03:00
f ddaee30da7
fix: primero guardar el objeto antes de obtener su contenido 2024-02-21 15:44:16 -03:00
f 5dbff20e2b
fixup! chore: rubocop 2024-02-21 15:44:04 -03:00
f 0443cb0fc3
fix: responder con forbidden cuando los registros no sean validos 2024-02-21 15:43:10 -03:00
f 03c0b71b5f
fix: no es necesario vincular actores con objetos 2024-02-21 15:42:56 -03:00
f 34e63ff2dc
feat: actualizar el tipo también 2024-02-21 14:07:11 -03:00
maki 1fba54d80b fix: checkboxes 2024-02-21 13:50:29 -03:00
f 732012e14b
docs: orden en que se crean los registros 2024-02-21 13:13:34 -03:00
f b477487b65
fixup! feat: obtener el contenido del objeto más adelante 2024-02-21 13:13:24 -03:00
f a9bdabf409
fix: se puede volver a pausar después de rechazarla 2024-02-21 13:07:27 -03:00
f e733c45b63
fix: las actividades se pueden rechazar 2024-02-21 13:06:06 -03:00
f 7b8730c34c
feat: las actividades se aprueban cuando las confirma la SI 2024-02-21 13:04:15 -03:00
f 091d5ac41d
chore: rubocop 2024-02-21 12:46:38 -03:00
f fb4401fd53
feat: no actualizar si no es necesario
cuando la respuesta viene desde la caché, no es es necesario modificar
el objeto.
2024-02-21 12:32:39 -03:00
f 051d8c6d56
feat: obtener el contenido del objeto más adelante 2024-02-21 12:30:01 -03:00
f fc7a524a85
fix: aasm 2024-02-20 17:18:39 -03:00
f 9a479a157b
feat: volver a pausar un objeto aprobado cuando se lo actualiza 2024-02-20 17:18:15 -03:00
f 8ff556c9ed
fix: al actualizar un objeto, pausar la actividad 2024-02-20 17:16:08 -03:00
f 88e93e3b5b
feat: al eliminar una actividad, vaciar su objeto 2024-02-20 17:15:57 -03:00
f 9fa4335314
feat: recibir y almacenar actividades 2024-02-20 17:15:43 -03:00
f 8921de81ae
feat: rutas 2024-02-20 17:14:04 -03:00
f 27c0ca655e
feat: modelo de datos de activitypub #15109 2024-02-20 17:12:13 -03:00
maki bd41144ecf fix: textarea 2024-02-20 15:41:49 -03:00
maki 6c97c587b2 Merge remote-tracking branch 'refs/remotes/origin/issue-14966' into issue-14966 2024-02-20 15:14:10 -03:00
maki 71d0985a39 fix: botón no debería ocupar todo el ancho del div 2024-02-20 15:13:54 -03:00
jazzari 5c2f2b9c61 fix: agregada línea de separación de tarjetas en compo accounts 2024-02-20 15:12:42 -03:00
maki 3d543a22fd fix: la flecha del details tenía que apuntar para la izq ups 2024-02-20 14:58:59 -03:00
maki 195fdb5672 fix: que el separador entre details se vea en modo oscuro también 2024-02-20 14:52:23 -03:00
maki f968c60bdf fix: líneas de separación entre secciones de Actividades de moderación 2024-02-20 14:29:48 -03:00
maki 9064325f7f fix: flecha del details apunta donde tiene que apuntar 2024-02-20 14:26:55 -03:00
jazzari 5ee9c49529 fix: corregidos botones y espacios en details de instancias 2024-02-20 14:23:16 -03:00
maki ecab598595 fix: no se veían los botones en modo oscuro 2024-02-19 14:21:32 -03:00
maki 9554ad1627 fix: sintaxis 2024-02-19 13:57:39 -03:00
f b4117d7c34
chore: rubocop 2024-02-17 14:11:17 -03:00
f b24f49fe26
feat: crear webhooks en la social inbox #15109 2024-02-16 16:01:17 -03:00
f b792cb2d43
feat: poder reutilizar webhooks 2024-02-16 15:59:37 -03:00
maki 2c61f3baa2 fix: comments_btn_box recibe comment como parámetro 2024-02-16 15:38:26 -03:00
maki 4114c1abe6 fix: p reemplazado por dl 2024-02-16 15:35:26 -03:00
maki e7595b8688 fix: la descripción ya traía etiqueta p, redundancia borrada 2024-02-16 15:33:28 -03:00
f 6d0ea6fa5d
feat: acceder a la social inbox desde el sitio 2024-02-16 14:54:50 -03:00
f cdf0685c67
feat: asociar rol con deploy nos permite acceder al token 2024-02-16 14:53:59 -03:00
f 6841945b39
feat: dependencias 2024-02-16 14:52:37 -03:00
maki e769c6ed5c fix: responsive de moderation_queue/_comment.haml
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 18:14:37 -03:00
maki 9634f75870 fix: html_safe en comentarios y descripciones
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 17:56:12 -03:00
maki 476f0c005f fix: remote profile asociado al comentario dentro de posts/_moderation_queue.haml
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 17:47:04 -03:00
jazzari 564dc060f0 fix: quitado flex de compo block_lists
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 17:24:25 -03:00
maki 0eba045fa5 Merge remote-tracking branch 'refs/remotes/origin/issue-14966' into issue-14966
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 17:18:47 -03:00
maki 78e478c004 fix: fecha con formato según idioma 2024-02-15 17:18:38 -03:00
jazzari e3cdafe2a6 fix: corregida clase en compo textarea 2024-02-15 17:17:06 -03:00
maki 90b14ce2b2 fix: cambio de p por lead
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 17:07:36 -03:00
maki b053bbad80 Merge remote-tracking branch 'refs/remotes/origin/issue-14966' into issue-14966
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 16:46:42 -03:00
maki 243a998451 fix: row va dentro del if para no quedar vacía si false 2024-02-15 16:46:04 -03:00
jazzari e11de6c835 fix: cambiada variable global por local en botonera de profiles
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 16:27:05 -03:00
jazzari 643139aaff fix: corregida indentacion en botones de comentarios 2024-02-15 16:24:06 -03:00
jazzari f2724c27fb fix: corregidos parámetros de compo checkbox 2024-02-15 16:20:46 -03:00
jazzari 700e71ff97 fix: corregido details en application.scss
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 16:15:57 -03:00
jazzari 68b8aee1f2 fix: quitada sanitizacion y quitado row extra
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 16:06:49 -03:00
jazzari d0e1d87c98 fix: quitada sanitizacion en comentarios y remote_profile
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 15:14:11 -03:00
jazzari 2de7568676 fix: corregido cuenta de origen de comentarios
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-15 15:05:27 -03:00
maki 1deb4053a7 fix: condicional en En Respuesta A en _comment.haml
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-14 15:10:18 -03:00
maki 8dfa3860a5 fix: span sin p y texto hardcodeado en _instance.haml
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-14 14:58:10 -03:00
maki fdc6ad95b8 fix: span sin p en _comment.haml 2024-02-14 14:51:27 -03:00
maki 58012f662e fix: row sin col
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-14 14:44:33 -03:00
maki fb19938361 fix: quitar bordes blancos de _comment.haml
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-14 14:38:34 -03:00
jazzari d829b5b4ae feat: agregada traducciones en en.yml
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-12 12:02:06 -03:00
jazzari 8bfdf3ed0a fix: corregido cursor de apertura de details
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-12 11:29:00 -03:00
jazzari faf3bf3fcf fix: corregido codigo de details en application.scss
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-12 11:27:24 -03:00
jazzari 529711c47d fix: corregido compo _remote_profile para hacerlo semantico con dl
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-09 16:54:16 -03:00
jazzari ba26b505e4 fix: corregidos márgenes en vistas de moderación
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-09 15:03:47 -03:00
jazzari 3f288ab6e4 fix: creados componentes botoneras de comentarios, instancias y cuentas, y movidos a app/views/components
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-09 14:45:12 -03:00
jazzari 31294ccbc7 fix: movido componente block_lists a app/views/components y corregido es.yml
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-09 14:15:11 -03:00
jazzari 754538024e feat: agregado componente checkbox
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-09 13:17:00 -03:00
jazzari 111f2d6503 fix: creados componentes de filtros para comentarios, cuentas e instancias
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-09 12:01:04 -03:00
jazzari 47de966f69 fix: cambiadas variables globales por locales
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-08 17:59:10 -03:00
jazzari ffc3f4a72a fix: corregido texto de comentarios en componente moderation_queue
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-08 15:02:09 -03:00
jazzari 33cf101b59 fix: quitada alineación centrada varios
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-08 14:41:50 -03:00
jazzari a32a3ce7db fix: corregidos colores de botones y details
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-07 17:59:57 -03:00
jazzari d5bfbc578f fix: correcciones varias de CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-07 17:12:00 -03:00
f 471b829690
feat: actualizar cliente de DP 2024-02-07 16:24:52 -03:00
jazzari 6095040008 fix: corregidos filtros vista remote_profile
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-07 15:06:04 -03:00
jazzari 9ffd49aae2 fix: corregida vista remote_profile 2024-02-07 15:03:48 -03:00
jazzari dbdce703c3 fix: corregidos botones en comentarios, instancias y cuentas #15028
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-07 14:42:25 -03:00
maki f9a7d8d21a feat: título para actividades de moderación #15091
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-06 17:27:07 -03:00
maki ab1186d08a feat: apartado de instancias dentro de actividades de moderación #15091 2024-02-06 17:22:44 -03:00
maki 6b0d2ded91 feat: apartado de cuentas dentro de actividades de moderación #15091
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-06 16:50:26 -03:00
maki c8267c44e8 fix: error de merge y error de indentación
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-06 14:08:15 -03:00
maki d0441f6e7c Merge remote-tracking branch 'refs/remotes/origin/issue-14966' into issue-14966 2024-02-06 13:59:03 -03:00
maki 462d9a698e para pullear 2024-02-06 13:56:20 -03:00
jazzari fc99ec79d3 fix: correciones de CI varias
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-06 12:57:42 -03:00
jazzari b949855f08 feat: creado componente lista personalizada de bloqueo de instancias #15104
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-05 16:19:35 -03:00
jazzari db0364522d fix: agregado checkbox a compo listas de bloqueo #15103
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-05 15:39:53 -03:00
jazzari 6374a616d4 feat: agregado componente listas de bloqueo de instancias #15103
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-05 15:22:28 -03:00
jazzari f995279298 fix: corregidos filtros desplegables de comentarios, cuentas e instancias #15097
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-05 14:51:17 -03:00
jazzari eb9ca6d6f6 Merge branch 'issue-15097' into issue-14966
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-05 14:11:07 -03:00
f 58ee39828a
feat: dropdown #15097
implement #15097
2024-02-05 13:16:57 -03:00
jazzari 600a87c5ec feat: agregado filtros de cuentas #15102
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-05 13:13:06 -03:00
jazzari cfe90c531e feat: agregado filtros instancias #15083
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-05 13:03:29 -03:00
jazzari c668c3ad3f fix: corregido submenu en partial filter_base #15079
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-05 12:30:13 -03:00
jazzari 40346df76d fix: movidas arrays de parametros de botones y filtros a helper moderation_queue_helper.rb #15077
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-05 12:22:23 -03:00
jazzari cfae99ca7b feat: agregada botonera instancias #15081
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-02 15:06:36 -03:00
jazzari da1f7f7754 fix: corregida botonera remote_profile #15080
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-02 14:45:25 -03:00
f b2483634a4
feat: empresa recuperada #15092
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 18:18:50 -03:00
maki a9efe78c0b feat: aparecen todos los details en actividades de moderación, con los títulos correspondientes, sin contenido (salvo comentarios) #15091
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 14:53:25 -03:00
maki 683062da02 feat: textos con traducciones para los títulos de los details de actividades de moderación #15091
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 14:47:40 -03:00
maki e9552776af feat: pantalla de actividades de moderación dividida en desplegables #15091 2024-02-01 14:40:14 -03:00
jazzari bbd5426da5 fix: eliminada botonera remote_profile_box para usar componente general button_box #15028
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 12:17:51 -03:00
jazzari 819ed25e29 fix: eliminadas botoneras de comentarios y remote_profile y unificadas en componente button_box #15028
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-02-01 12:02:40 -03:00
jazzari 94a86eca9b fix: corregidos colores botonera de comentarios #15028
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-31 17:10:34 -03:00
maki 4f6464837a fix: a ver si esto arregla
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-31 15:53:05 -03:00
maki 836687651e fix: código demás 2024-01-31 15:51:53 -03:00
maki b233a74f61 fix: agregada dummy_data en el método edit de posts_controller #15076 #15039
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-31 15:47:19 -03:00
maki b763084474 feat: dummy data #15076 2024-01-31 15:41:12 -03:00
maki a17a3dc700 Merge remote-tracking branch 'refs/remotes/origin/issue-14966' into issue-14966
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-29 16:36:05 -03:00
maki 1b0fb009f4 feat: traer información de perfil remoto vinculado al comentario #15039 2024-01-29 16:35:53 -03:00
jazzari 957e79e682 fix: corregidas variables en partials
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-29 15:32:47 -03:00
jazzari 2f803f9ea6 fix: corregidas lineas segun CI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-29 13:48:11 -03:00
jazzari 4b67968d3b fix: corregido botonera de filtros en componente moderation_queue
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-29 13:28:58 -03:00
jazzari 5a6b0373a2 feat: agregado componente caja de filtros de comentarios y compo filtro_base
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-26 15:23:38 -03:00
maki 9e8a83b706 fix: html de comentarios sanitizado #15039
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-26 15:15:48 -03:00
jazzari 1eb2230b2a fix: corregida posición de botonera de moderacion de comentarios
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-25 17:05:06 -03:00
jazzari f6a93b5bc2 fix: corregida llamada en _moderation_queue para mostrar comentarios en vista posts/edit
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-25 16:15:20 -03:00
jazzari d3e5434a00 fix: agregadas traduccion y estilos a componente _comment
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-25 15:48:25 -03:00
maki d9d50cb81e fix: arreglando conflictos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-23 17:17:06 -03:00
maki f78fb43681 feat: esqueleto básico maquetado de comentario para cola de moderación #15039 2024-01-23 17:13:42 -03:00
jazzari 36290d24fb Merge remote-tracking branch 'refs/remotes/origin/issue-14966' into issue-14966 2024-01-23 17:11:03 -03:00
jazzari 2c7081a57f feat: agregado componente remote_profile y botonera 2024-01-23 17:04:38 -03:00
maki 0a742f5481 Merge remote-tracking branch 'refs/remotes/origin/issue-14966' into issue-14966
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-23 16:29:24 -03:00
maki 9cb1e6fd36 feat: index de cola de moderación, con metadatos pero sin maquetar #15039 2024-01-23 16:29:11 -03:00
jazzari 1edf052109 fix: corregido padding en moderation_queue view
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-22 17:38:32 -03:00
jazzari 45d98b3169 fix: corregidas clases en botonera
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-22 16:05:57 -03:00
jazzari 9fa45b01ac feat: agregadas traducción inglés botones de moderación
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-22 15:35:19 -03:00
jazzari d895b9c808 feat: agregados componentes comentario, botonera y boton_base
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-22 14:17:24 -03:00
jazzari ef7d9d2a1e fix: eliminados espacios en blanco en varias lineas
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-19 15:06:20 -03:00
jazzari 28ddaca35a fix: corregido details de post edit
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-19 13:41:23 -03:00
maki ee98b562dc Merge remote-tracking branch 'refs/remotes/origin/issue-14966' into issue-14966
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-17 17:38:53 -03:00
maki 5d26c6746e fix: traducciones #15002 2024-01-17 17:37:53 -03:00
jazzari ad8e5bc811 fix: corregido edit in es.yml
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-17 17:37:02 -03:00
maki f098de102e feat: agregadas views de moderation_queue #15001
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-17 17:16:52 -03:00
jazzari 4c902c8aaf feat: agregado clase details a application.scss #15000
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-17 16:39:20 -03:00
maki ed0c237d60 agregada partial de details #15000
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-17 16:14:02 -03:00
maki 49039c24b7 agregada vista de remote profile básica #15003 2024-01-17 16:12:04 -03:00
maki 3a44c9629f agregadas traducciones a posts/edit #15002
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-17 15:55:31 -03:00
jazzari 2796d3f2ca fix: quitada linea agregada segun CI:haml #14949
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-15 15:11:55 -03:00
jazzari 4c58aea47a fix: agregada linea segun CI:haml #14949
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-15 14:50:11 -03:00
jazzari 66676f009d fix: corregido ocultar schema si es de subnivel #14949
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-15 14:36:07 -03:00
f 2a2878e469
refactor: cargar los datos desde archivos más legibles
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-12 17:55:15 -03:00
f decbd2fb52
chore: rubocop 2024-01-12 17:44:49 -03:00
f e20ef9dd21
feat: no es necesario pasar los archivos como parametros 2024-01-12 17:44:26 -03:00
f 6efae5f8f0
feat: correr rubocop y haml-lint sobre los archivos 2024-01-12 17:39:20 -03:00
f 9ce510223e
feat: controladores e información de prueba #14966 2024-01-12 17:37:37 -03:00
f 5e6cbba28e
fix: prevención
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-12 17:36:31 -03:00
f 4192e8b8f9
fix: cargar distributed press 2024-01-12 17:34:27 -03:00
f 29b0622ea8
fix: el método es público para poder instalar gemas
closes #14964
2024-01-12 17:10:27 -03:00
f 60fa25e5a8
fix: no fallar en File#touch 2024-01-12 17:10:26 -03:00
f 56e4684ef1
fix: todos los botones son secundarios
closes #14967
2024-01-12 17:10:19 -03:00
f f8a46d6459
fix: instalar bundler audit 2024-01-12 10:29:47 -03:00
f bbc9374194
fix: compilar assets en el panel de producción también 2024-01-12 10:26:52 -03:00
f f5e4376f1d
fix: no compilar assets en cronjobs 2024-01-12 10:25:58 -03:00
f 939d07430a
chore: vincular a #14958
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-11 18:33:30 -03:00
f eb2ce9d509
chore: vincular a #14957 2024-01-11 18:31:55 -03:00
fauno 9e04d6a235 Merge branch 'issue-14956' into 'rails'
fix: ignorar alertas de brakeman

See merge request sutty/sutty!238
2024-01-11 21:26:04 +00:00
f 1bed78345c
fix: ignorar alertas de brakeman
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
* las redirecciones son necesarias para poder reenviar a las páginas de
  agradecimiento y no podemos saber la url de antemano.

* Site.domain no es un atributo sino una configuración estática

* Site#tienda_url es un atributo estático

* no sabemos todos los parametros de antemano en los breadcrumbs
2024-01-11 18:19:20 -03:00
f 22bd58054a
fix: deprecar carga de archivo desde el sitio #14956 2024-01-11 18:14:21 -03:00
f c22276f74f
fix: especificar qué parametros de airbrake permitimos #14956 2024-01-11 18:13:52 -03:00
f 399d904f9e
fix: agregar configuración de bundler a la caché
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
(cherry picked from commit 7e43d8f332)
2024-01-11 17:31:47 -03:00
f 8f319eba6b
fix: instalar dependencias
(cherry picked from commit 1fbfd30017)
2024-01-11 17:31:47 -03:00
f 1fdc3404be
fix: traer la lista de archivos modificados
(cherry picked from commit 76644700d1)
2024-01-11 17:31:47 -03:00
f 6ec9907273
chore: rubocop 2024-01-11 17:31:15 -03:00
f 7e43d8f332
fix: agregar configuración de bundler a la caché 2024-01-11 17:31:15 -03:00
f 1fbfd30017
fix: instalar dependencias 2024-01-11 17:31:15 -03:00
f 7f3d87b317
chore: rubocop
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-11 17:29:32 -03:00
f 987e19f565
fixup! fixup! ci: por qué faltan las gemas?
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-11 17:24:51 -03:00
f 24120bfd90
fix: agregar configuración de bundler a la caché 2024-01-11 17:18:58 -03:00
f 1ede2af465
fix: instalar dependencias 2024-01-11 17:18:36 -03:00
f a78d02d84a
fixup! ci: por qué faltan las gemas?
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-11 17:10:55 -03:00
f 9c97e0f87c
ci: por qué faltan las gemas? 2024-01-11 17:08:05 -03:00
f 76644700d1
fix: traer la lista de archivos modificados
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-11 17:03:37 -03:00
f 5aef69cd94
fix: eliminar los guiones bajos al principio del nombre de archivo #14953
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
porque jekyll los toma como archivos ocultos
2024-01-11 16:54:34 -03:00
fauno 012e8f0f19 Merge branch 'issue-14944' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
entorno de trabajo funcional

See merge request sutty/sutty!235
2024-01-11 16:24:51 +00:00
f c7310b7339
fix: instalar bundler audit si no existe todavía
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-11 13:10:21 -03:00
f ae81640fcc
fix: instalar directorio para el socket 2024-01-11 13:10:21 -03:00
f b93bfd7fd3
feat: notificar cuando termina una tarea 2024-01-11 13:10:21 -03:00
f 9a1bd58aa5
fix: usar el contenedor local 2024-01-11 13:10:21 -03:00
f e82e93c883
fix: permitir que task se llame a si mismo
en ubuntu el comando se llama `task` en vez de `go-task`
2024-01-11 13:10:21 -03:00
f f488028455
BREAKING CHANGE: variables de entorno 2024-01-11 13:10:21 -03:00
f 089c09a26c
fix: la consola es interactiva 2024-01-11 13:10:21 -03:00
f 77672535dd
fix: evitar loop infinito 2024-01-11 13:10:21 -03:00
f c4600edb6a
fix: solo llamar a rails 2024-01-11 13:10:21 -03:00
f 0b87e9753e
fix: env para desarrollo
(cherry picked from commit c253457840)
2024-01-11 13:10:21 -03:00
f 034af360ee
ci: condicional 2024-01-11 13:10:20 -03:00
f c2cc490772
BREAKING CHANGE: deprecar makefile 2024-01-11 13:10:20 -03:00
f aa0aac20e6
ci: no fallar si no hay archivos 2024-01-11 13:10:20 -03:00
f 1dfd76704f
fix: origin 2024-01-11 13:10:20 -03:00
f b6d214c052
ci: deshabilitar hainish en ci 2024-01-11 13:10:20 -03:00
f 0569f7cab9
ci: caches 2024-01-11 13:10:20 -03:00
f e0a2149483
ci: no hacer nada si no hay nada que hacer 2024-01-11 13:10:20 -03:00
f 6d24e7c56a
ci: diffutils 2024-01-11 13:10:20 -03:00
f ad017f5598
ci: disable hainish + dry 2024-01-11 13:10:20 -03:00
f 2bf907aa00
ci: compilar assets al final 2024-01-11 13:10:20 -03:00
f 6a91a4179c
ci: stages 2024-01-11 13:10:20 -03:00
f 3837c92030
fix: escape 2024-01-11 13:10:20 -03:00
f bf637bcc5c
refactor: helper script 2024-01-11 13:10:20 -03:00
f d581fab4df
feat: lint 2024-01-11 13:10:20 -03:00
f ef22f29d17
feat: auditar dependencias 2024-01-11 13:10:20 -03:00
f ce2fd301b4
feat: reuse tasks 2024-01-11 13:10:20 -03:00
f baec1f93d0
feat: docs 2024-01-11 13:10:19 -03:00
f 9490d4d57c
fix: typo 2024-01-11 13:10:19 -03:00
f 8be6337db1
docs: readme 2024-01-11 13:10:19 -03:00
f 4e74204931
feat: servidor de desarrollo 2024-01-11 13:10:19 -03:00
f a46bb26491
fix: migraciones faltantes 2024-01-11 13:10:19 -03:00
f 27f3aff403
feat: database 2024-01-11 13:10:19 -03:00
f 49e97ca7b0
BREAKING CHANGE: deprecar tareas de makefile 2024-01-11 13:10:19 -03:00
f 416607df9c
feat: agregar hosts 2024-01-11 13:10:19 -03:00
f 064da6cf13
fix: ignorar task 2024-01-11 13:10:19 -03:00
f 29e6e28479
ci: assets [skip ci] 2024-01-11 13:10:19 -03:00
f 61703dea23
fix: dependencias 2024-01-11 13:10:19 -03:00
jazzari 3d86ad1fbe fix: quitado espacio sobrante en array #14550
All checks were successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
2024-01-10 15:36:02 -03:00
f c253457840
fix: env para desarrollo
All checks were successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
2024-01-10 11:39:07 -03:00
f ee7d1599e8
fix: limitar el nombre del archivo #14946
All checks were successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
2024-01-09 18:27:02 -03:00
f 8ce1aceb3f
fix: no es necesario usar hainish en un contenedor 2024-01-08 15:26:19 -03:00
f 2296c82f0b
fix: cachear node modules y tasks
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2024-01-08 15:12:29 -03:00
f 1956d8c886
fix: compilar assets a partir de contenedor de producción 2024-01-08 15:11:37 -03:00
f 167c128927
BREAKING CHANGE: deprecar alpine 3.14 2024-01-08 15:10:55 -03:00
f a03c549c3f
feat: generar assets 2024-01-08 15:07:59 -03:00
f 6ae3c2a29d
feat: copiar credentials 2024-01-08 15:06:07 -03:00
f dbd35e6589
feat: instalar node modules 2024-01-08 14:58:48 -03:00
f 3469cd5bbd
fix: solo copiar una vez 2024-01-08 14:58:19 -03:00
f d86a4b3404
fix: actualizar webpacker
ya no es necesario python2
2024-01-08 14:47:10 -03:00
f 42c80f8749
feat: clean 2024-01-08 14:40:05 -03:00
f 39b536dab7
feat: install gems 2024-01-08 14:38:44 -03:00
f 936c3f83c1
fix: más visible 2024-01-08 14:38:21 -03:00
f 497124bf27
fix: panel 2024-01-08 14:26:32 -03:00
f 156a801e7d
feat: taskfile 2024-01-08 14:17:48 -03:00
f b478d91d02
ci: assets [skip ci] 2024-01-08 13:59:44 -03:00
f b5d21a4c3e
Merge branch 'rails' into usar-sutty-editor
All checks were successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
2024-01-08 13:51:38 -03:00
fauno 0d22c8e5b1 Merge branch 'issue-14763' into 'rails'
fix: permitir cargar tiempo #14763

See merge request sutty/sutty!230
2024-01-08 16:45:54 +00:00
fauno 960b34385a Merge branch 'issue-14378' into 'rails'
ActiveStorage::Service::JekyllService#blob_for puede devolver nil

See merge request sutty/sutty!226
2024-01-02 18:39:26 +00:00
fauno f671287fc6 Merge branch 'issue-8521' into 'rails'
Las tareas de limpieza deberian correr git lfs prune tambien #8521

See merge request sutty/sutty!233
2024-01-02 18:35:23 +00:00
fauno 24726a2e51 Merge branch 'issue-14779' into 'rails'
Agregar el formulario de seguimiento automático del fediverso en el panel  #14779

See merge request sutty/sutty!234
2024-01-02 18:30:19 +00:00
f a14d38bb9d
Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2024-01-02 15:28:46 -03:00
f ab1619e6f7
Merge branch 'rails' into issue-14352
All checks were successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
2024-01-02 15:27:01 -03:00
fauno 8f1ea7d8c8 Merge branch 'issue-14323' into 'rails'
fix: no renderizar liquid dentro de los artículos #14323

See merge request sutty/sutty!204
2024-01-02 18:26:07 +00:00
fauno d8833e2596 Merge branch 'issue-13427' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker/1 Pipeline failed
ci/woodpecker/push/woodpecker/2 Pipeline failed
fix: poder informar errores con archivos subidos #13427

See merge request sutty/sutty!183
2024-01-02 18:22:53 +00:00
f 63095596c1
Merge branch 'rails' into issue-13428
All checks were successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
2024-01-02 15:21:14 -03:00
f c1187943e3
BREAKING CHANGE: deprecar jekyll-data 2024-01-02 15:15:37 -03:00
f 07f5e1c854
Merge branch 'issue-13159' into rails
Some checks failed
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline failed
2024-01-02 15:02:59 -03:00
f 58ce9a45d8
Merge branch 'rails' into issue-12994
All checks were successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
2024-01-02 15:00:47 -03:00
f c1874af5bf
Revert "fix: deshabilitar el modo oscuro #12994"
This reverts commit e504501678.
2024-01-02 15:00:43 -03:00
f e827405c12
Merge branch 'rails' into issue-12854
All checks were successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
2024-01-02 14:56:18 -03:00
f 3074b176a7
Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-12760
Some checks failed
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline failed
2024-01-02 14:49:52 -03:00
Elihu a173b1356f Merge branch 'issue-14746' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
fix: no cambiar el nombre de dominio #14746

See merge request sutty/sutty!229
2023-12-21 14:40:54 +00:00
f c007f3b0e3
no actualizar al cargar el listado de sitios
hace que todo tarde demasiado tiempo

(cherry picked from commit 15454596f2)
2023-12-19 14:56:01 -03:00
f c5cece436d
fix: usar la url de la base de datos en psql
All checks were successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
2023-12-19 14:36:47 -03:00
f 1a3c6a77ce
fix: correr psql dentro de hain 2023-12-19 14:33:17 -03:00
fauno 635bf1990f Merge branch 'issue-13498' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline failed
Issue #13498

See merge request sutty/sutty!189
2023-12-19 17:20:50 +00:00
jazzari d60ec0cf11 fix: corregido enlace a formulario en en.yml #14779
All checks were successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
2023-12-13 14:34:26 +01:00
jazzari e3b721320a feat: agregado formulario seguimiento automatico del fediverso #14779
All checks were successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
2023-12-12 19:02:53 +01:00
jazzari 2c99820f35 feat: agregado metodo de limpieza de git-lfs en cleanup_service.rb #8521
All checks were successful
ci/woodpecker/push/woodpecker/2 Pipeline was successful
ci/woodpecker/push/woodpecker/1 Pipeline was successful
2023-12-12 18:15:23 +01:00
jazzari c66a7660c1 fix: modificado metodo Gateways_urls para que devuelva solamente links en deploy_distributed_press.rb #14550 2023-12-07 17:24:04 +01:00
jazzari 61e20a3a13 fix: corregido metodo Reload en site.rb #14700 2023-12-07 16:05:20 +01:00
jazzari e889f29d17 fix: modificado metodo Reload en site.rb #14700 2023-12-07 15:37:46 +01:00
f 96bc688e2d
fix: permitir cargar tiempo #14763
jekyll-activity-pub podría establecer una fecha de creación del sitio
2023-12-06 18:24:38 -03:00
f 89063d50c0
fix: no cambiar el nombre de dominio #14746 2023-12-04 17:50:53 -03:00
f 72d8171c36
fix: img-fluid sutty/editor#99 2023-11-29 18:20:20 -03:00
f 959da50dac
Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-13498 2023-11-29 10:49:11 -03:00
fauno 2387da24e1 Merge branch 'issue-14696' into 'rails'
fix: deshabilitar njalla #14696

See merge request sutty/sutty!227
2023-11-24 18:26:17 +00:00
f aaf2ca8757
fix: deshabilitar njalla #14696 2023-11-23 18:41:49 -03:00
jazzari c86507e628 fix: agregado metodo page_not_found en disk_controller_decorator.rb #14378 2023-11-22 15:15:49 +01:00
jazzari 32fdb4e796 fix: cambiado metodo blob_for para lanzar excepcion y disk_controller_decorator.rb para devolver not_found si no encuentra el blob #14378 2023-11-21 15:45:42 +01:00
fauno 63b2351c07 Merge branch 'issue-14555' into 'rails'
fix: notificar cuando falla la última compilación #14555

See merge request sutty/sutty!225
2023-11-21 13:36:46 +00:00
f c8e1d50232
fix: reversed logic 2023-11-17 18:40:34 -03:00
f 9709f419ca
fix: notificar cuando falla la última compilación #14555 2023-11-17 18:19:13 -03:00
fauno 26952ee314 Merge branch 'issue-13266' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Issue #13266

See merge request sutty/sutty!179
2023-11-10 14:54:38 +00:00
f f5af85a66e
fix: guardar el id como JSON
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-11-01 17:11:31 -03:00
f 5540232b7e
fix: la instancia puede repetirse 2023-11-01 17:09:32 -03:00
f b67193fbca
feat: soportar varias instancias de distributed press #14540 2023-11-01 17:02:32 -03:00
f b96363a59f
Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-12980
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-10-31 14:05:50 -03:00
fauno 9df84e7778 Merge branch 'issue-13780' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
#13780

See merge request sutty/sutty!210
2023-10-25 14:30:02 +00:00
f 341929a7bf
Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-13498
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-10-20 11:07:19 -03:00
Jazzari 22b9bc5efd Merge branch 'issue-13903' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Webhooks Controller | Webhooks

Closes #13903 and #14089

See merge request sutty/sutty!198
2023-10-12 16:03:31 +00:00
Jazzari 7f181712a5 Merge branch 'issue-13260' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: temporalmente deshabilitar el cambio de plantillas #13260

See merge request sutty/sutty!180
2023-10-06 21:36:52 +00:00
Jazzari 8d4e38ff56 Merge branch 'issue-13321' into 'rails'
fix: permitir el atributo start #13321

See merge request sutty/sutty!181
2023-10-06 21:36:23 +00:00
Jazzari 96c4be20d6 Merge branch 'issue-13628' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: generar un registro cuando falla distributed press #13628

See merge request sutty/sutty!194
2023-10-06 21:31:47 +00:00
Jazzari 4bb3d70ba4 Merge branch 'issue-13493' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: no permitir que les usuaries elijan un idioma que no existe

See merge request sutty/sutty!187
2023-10-06 21:05:24 +00:00
fauno 344fe3707f Merge branch 'issue-13612' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: indexar posts luego de crear el sitio #13610

See merge request sutty/sutty!192
2023-10-06 13:21:46 +00:00
Elihu 7e78fd861a Merge branch 'issue-14179' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Agregada fecha en Post con título duplicado #14179

See merge request sutty/sutty!209
2023-10-04 17:26:36 +00:00
Elihu 2406533e46 Merge branch 'issue-13864' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Fix Horror gramatical en Breadcrumbs

See merge request sutty/sutty!199
2023-10-03 16:20:21 +00:00
jazzari 86436aafd7 fix: typo en metadata_related_posts.rb #14179
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-10-02 14:36:36 -03:00
f cb2c1b0e7d
fix: usar la codificación correcta
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
los archivos con tildes fallaban
2023-09-29 10:10:18 -03:00
Elihu 22069cce68 Merge branch 'issue-13114' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
feat: avisar que hay que publicar al cambiar la configuracion #13114

See merge request sutty/sutty!172
2023-09-28 21:08:09 +00:00
Elihu c1b47e8da6 Merge branch 'issue-12714' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
paginacion #12714

See merge request sutty/sutty!185
2023-09-28 20:58:06 +00:00
fauno 99b20152c6 Merge branch 'issue-14131' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Fix: Corregir enlace a demostración Plantilla Mínima

See merge request sutty/sutty!201
2023-09-27 20:28:13 +00:00
fauno b99abb3a4f Merge branch 'issue-14309' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: informar cuando la plantilla no tiene gema #14309

See merge request sutty/sutty!207
2023-09-27 20:26:08 +00:00
f 0538b3bbfd
fix: no fallar si no hay origin
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-27 16:54:38 -03:00
fauno beec951cdf Merge branch 'issue-14169' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
activity pub #14169

See merge request sutty/sutty!202
2023-09-27 19:53:22 +00:00
f b119cba7e1
feat: reindexar los cambios luego de traerlos #13780 2023-09-27 16:47:00 -03:00
f 85e528e660
fix: solo hacer merge si hubo cambios para traer 2023-09-27 16:46:33 -03:00
f ab5ed0dec9
Merge branch 'issue-13780' into issue-12980 2023-09-27 16:44:08 -03:00
fauno 8f7dbfdc9e Merge branch 'issue-12919' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Git Push Job

See merge request sutty/sutty!196
2023-09-27 19:42:27 +00:00
f 997114a896
fix: ya estamos en el contexto del sitio
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-27 16:38:19 -03:00
f 1e13985ef8
fix: asumir que todos los sitios ya están indexados
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-27 16:31:23 -03:00
f 074cb49752
feat: reindexar cambios #13780
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-27 16:25:06 -03:00
f f18d0213df
feat: guardar el último commit indexado 2023-09-27 16:25:06 -03:00
f 8376e663ce
feat: almacenar el último commit indexado #13780 2023-09-27 16:25:06 -03:00
jazzari 5e05ba7d7b fix: fix typo #14179
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-27 15:52:33 -03:00
jazzari 134d1105f6 fix: agregada la fecha de creacion del post para seleccionar posts por título si están duplicados #14179 2023-09-27 15:48:53 -03:00
jazzari 59f8f8aabb fix: arreglado typo en breadcrumbs en en.yml #13864
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-27 14:29:28 -03:00
Elihu 9bd591ec27 Merge branch 'issue-13619' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: deprecar Dir#chdir #13619

Closes #13619, #13715, #13716, and #13717

See merge request sutty/sutty!193
2023-09-27 15:18:50 +00:00
f 65011fb804
fix: actualizar la fecha del gemfile
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-26 14:58:24 -03:00
fauno 6bd62b98d6 Merge branch 'issue-14334' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Ignorar reportes de Bots (Device_detector)

See merge request sutty/sutty!205
2023-09-26 16:33:11 +00:00
f bd3daaf8b8
Merge branch 'issue-13428' into issue-14352
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-25 14:58:07 -03:00
f d674ccdb0f
fix: el gemfile.lock puede modificar luego del gemfile #14352
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-25 14:52:59 -03:00
jazzari 5c43214e46 fix: arreglados cambios en Gemfile.lock #14334
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-25 14:32:28 -03:00
f bfd31d051f
fix: lanzar una excepción contundente
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-25 14:15:32 -03:00
f 01e7436576
fix: obtener el nombre del sitio 2023-09-25 14:10:34 -03:00
f de59cd9f34
fix: informar cuando la plantilla no tiene gema #14309 2023-09-25 14:08:37 -03:00
fauno 1014bbcbfe Merge branch 'sutty-base-jekyll-theme-issue-60' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
style: usar .editorconfig

See merge request sutty/sutty!206
2023-09-22 20:34:52 +00:00
jazzari 6866f827f6 fix: error de sintaxis y parámetros a device_detector #14334
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-22 15:10:46 -03:00
f f19a9fa42f
style: usar .editorconfig
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
sutty/jekyll/sutty-base-jekyll-theme#60
2023-09-22 14:31:53 -03:00
jazzari 74e371eb36 feat: ignorar reportes de bots con device_detector #14334
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-22 13:51:36 -03:00
f aeaf72c270
feat: poder pushear a cualquier remoto
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-22 13:20:20 -03:00
f c176a8a4b4
feat: poder obtener el usuario de cualquier remoto 2023-09-22 13:19:21 -03:00
f 7793c5f96d
fix: no enviar el env en la notificación
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-22 13:03:28 -03:00
f 52e22a53bf
fix: no sabemos el sitio
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-22 12:47:18 -03:00
f 0c7a37a1d8
fix: mantener rugged 1.5.0.1
versiones posteriores se rompen con urls ssh://

https://github.com/libgit2/libgit2/issues/6496
2023-09-22 12:46:32 -03:00
f 84f82cbb0f
fix: obtener el usuario del repositorio
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-22 12:21:55 -03:00
jazzari 4689d10e8d feat: instalada gema device_detector #14334 2023-09-21 16:22:45 -03:00
f b06b829357
fix: necesita un bloque
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-21 13:10:26 -03:00
f 7709b9f798
fix: capturar más errores 2023-09-21 13:09:10 -03:00
f e4dc6588f9
fix: informar qué está pasando
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-21 13:04:25 -03:00
f 69e1664084
fix: renombrar todos los repositorios remotos 2023-09-21 13:02:15 -03:00
f 62eb5ddaa2
Merge branch 'rails' into issue-12919 2023-09-21 12:26:31 -03:00
f a2d84bfa96
fix: renombrar el remote correctamente 2023-09-21 12:25:23 -03:00
f 21d570ebe8
fix: no renderizar liquid dentro de los artículos #14323
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-09-20 15:18:09 -03:00
f 99c919e5e6
fix: retrocompatibilidad
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-13 18:07:25 -03:00
f d27717ed3b
fix: agregar created_at al front matter
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-13 17:59:50 -03:00
f 35e8a08716
fixup! feat: fecha de creación 2023-09-13 17:53:51 -03:00
f 6b1eccade3
feat: fecha de creación
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-13 17:52:21 -03:00
f 8ae5dd5975
fix: no compartir la misma instancia
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
sutty/jekyll/jekyll-activitypub#42
2023-09-12 14:53:05 -03:00
fauno ae72297adf Merge branch 'issue-14128' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Corregir descripción de plantilla Revista/Magazine | Issue-14128

See merge request sutty/sutty!203
2023-09-05 13:19:58 +00:00
jazzari 7425428f44 feat: add magazine theme to seeds and fix description text #14128 2023-09-04 16:30:20 -03:00
f 10d958e50a
fix: compartir la misma fecha de creación y de actualización
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-04 12:44:57 -03:00
f 6aa0f7d6cf
feat: guardar la fecha de creación
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-09-01 20:11:46 -03:00
f 3dedd84db7
fix: enviar urls parseadas
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-31 14:58:16 -03:00
f 927f92d985
fix: typo
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-31 14:56:00 -03:00
f a6195fbccc
fix: simplificar 2023-08-31 14:52:49 -03:00
f f076838be5
fixup! fix: solo vincular urls que tienen protocolo 2023-08-31 14:47:44 -03:00
f d8e21c97e2
fix: solo vincular urls que tienen protocolo
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-31 14:41:34 -03:00
f cd7c217920
fix: poder asignar valor por defecto a los campos boolean
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-31 12:15:10 -03:00
f f337e4967b
fix: recolectar variables de entorno 2023-08-31 12:15:10 -03:00
f c9866a0eec
fix: mover métodos a deploy 2023-08-31 12:15:10 -03:00
f 2a4073178a
fix: actualizar la gema 2023-08-31 12:15:10 -03:00
f 26f57a8467
feat: métodos de deploy 2023-08-31 12:15:10 -03:00
f 4ade0944de
feat: los deploys pueden pasar opciones de compilación 2023-08-31 12:15:09 -03:00
f f019805314
fix: generar todos los deploys automáticamente 2023-08-31 12:15:09 -03:00
f 9ac404ae06
feat: habilitar/deshabilitar activity pub 2023-08-31 12:15:09 -03:00
f 8b0b0199f6
feat: correr un comando obteniendo la llave dentro de un archivo temporal 2023-08-31 12:15:09 -03:00
f 4de3352950
feat: generar la llave privada #14169 2023-08-31 12:15:09 -03:00
f c6c638fb60
feat: almacenar la llave privada 2023-08-31 12:15:09 -03:00
f ef64dbc049
ci: assets [skip ci] 2023-08-31 10:48:54 -03:00
f c09dfc3b67 ci: force ci to rebuild assets
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-25 10:11:36 -03:00
jazzari 1be1977c34 fix: fix minima design's link to demostration site #14131
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-23 14:13:25 -03:00
f 81d1f63a68 Merge branch 'rails' of 0xacab.org:sutty/sutty into rails
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-23 11:22:51 -03:00
f dd75a16335 fix: faltaron archivos en el merge 2023-08-23 11:22:09 -03:00
fauno ee59a5700c Merge branch 'issue-9357-2' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Issue #9357

See merge request sutty/sutty!186
2023-08-22 21:14:42 +00:00
f 25c6b65bf0 Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-9357-2
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-22 18:13:10 -03:00
f 5a004b1cad feat: enviar configuración luego de comitearla
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-16 17:35:33 -03:00
f 6bae3a68f1 feat: enviar cambios luego de commitearlos 2023-08-16 17:35:20 -03:00
f 4a7ac981e5 fix: no fallar si la firma es nil
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
closes #14089
2023-08-16 17:04:34 -03:00
f ef8ed271d7 fix: consistencia al llamar a headers
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-16 16:46:11 -03:00
f a2678c3e81 fix: no ignorar excepciones como record not found
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-16 16:35:36 -03:00
f b9083c492c fix: presencia
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-16 16:26:39 -03:00
f 42e6a0b6eb fix: typo 2023-08-16 16:24:33 -03:00
f a99e03ce15 feat: enviar los headers en el reporte 2023-08-16 16:23:39 -03:00
f 690efe329c fix: llamar a los headers consistentemente 2023-08-16 16:22:57 -03:00
f 5ef601139f fix: eliminar espacio en blanco 2023-08-16 16:21:48 -03:00
jazzari 114fe4b2d5 fix: fix in es.yml & en.yml and missing end #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-16 15:43:57 -03:00
jazzari cefd053d1d fix: add condition in elsif in token method #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-16 14:57:01 -03:00
jazzari 35dca9d756 fix: fix exception in platforms_answer method #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-16 13:39:29 -03:00
jazzari 5ac628b38a fix: fix typo and change response to platforms #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-16 12:58:14 -03:00
jazzari aeb2105dc7 fix: add rescue in token_from_signature method #13903
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-08-15 19:25:06 -03:00
jazzari c5406acb26 fix: add documentation and fix typos #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-15 16:59:16 -03:00
jazzari a098e1baa7 fix: change migration methods to add token to roles #13903 2023-08-15 16:14:34 -03:00
jazzari f2236bb305 feat: move methods to private #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-14 16:49:24 -03:00
jazzari 23732bbfe0 feat: add method to validate token from diff platforms in webhooks controller #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-14 12:50:18 -03:00
jazzari 63fd91ee48 feat: add token to existing records #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-08-10 16:13:13 -03:00
jazzari 705d15c0c1 fix: change token attribute from encrypted to normal in Rol model #13903 2023-08-10 16:05:14 -03:00
jazzari c19c834f10 fix: cambio nombre comuna token_cyphertext en modelo rol y asignación retroactiva #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-31 18:46:07 -03:00
jazzari 579e177684 feat: agregada columna token a model rol #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-31 17:32:14 -03:00
jazzari 06ebb63d93 fix: movido git lfs a método merge en repository.rb #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-31 14:18:07 -03:00
jazzari 9a78c628b4 fix: fix typo in es.yml #13864
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-31 12:29:27 -03:00
jazzari 9f94ee3bc7 fix: add response status to pull method #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-27 17:23:40 -03:00
jazzari 9f5364a738 fix: add documentation to pull job #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-27 17:02:48 -03:00
jazzari 8947942cb9 fix: commit message fixed #13903
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-27 16:46:32 -03:00
jazzari b7e93cd8c8 feat: controlador para gestionar los webhooks #13903
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-26 14:44:11 -03:00
f ae79432278 fix: renombrar el skel a upstream
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
si lo mantenemos como origin por defecto, el GitPushJob va a querer
enviar cambios a un repositorio común, rompiendo todo.
2023-07-21 17:33:23 -03:00
jazzari ca67665107 Merge branch 'issue-12919' into issue-12980
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Mergea cambios en repository.rb
2023-07-21 17:17:46 -03:00
jazzari b7dc448daa fix: fix git_sh method in site.repository.rb #12919
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-21 17:15:36 -03:00
jazzari 3e12bfbe9e fix: add git lfs fetch to repository#fetch method #12980 2023-07-21 17:12:26 -03:00
jazzari c2d64e11d7 fix: missing splat in git_sh method #12919
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-20 16:26:43 -03:00
jazzari ca9fa31cf1 fix: change git_sh method to accept array of params #12919
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-07-20 15:31:38 -03:00
jazzari d77b8ba67b feat: created job to make git pull #12980 2023-07-20 14:58:21 -03:00
jazzari 42b6744f81 feat: Job para hacer push #12919
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-18 15:47:26 -03:00
f ad4965226c Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-13619
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-06 12:45:19 -03:00
f bb7487e941 fix: correr chdir de a uno por thread
como jekyll no es multi-threaded, pero rails si, es posible que se
produzca una excepción en Dir.chdir si se intenta leer sitios
concurrentemente (por ejemplo, abrir dos pestañas del mismo sitio).

closes #13717

closes #13716

closes #13715

closes #13619
2023-07-06 12:43:28 -03:00
Jazzari 2c8ab01cc7 Merge branch 'issue-2183' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
#2183

See merge request sutty/sutty!195
2023-07-03 19:11:29 +00:00
f f05830c646 fix: primero hay que modificar los datos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-03 13:38:29 -03:00
f 63620b2d09 fix: commitear el cambio de nombre de archivo #2183
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-07-03 13:27:51 -03:00
f 6ff0a36b44 BREAKING CHANGE: Site::Repository#commit
poder añadir y eliminar archivos en el mismo commit
2023-07-03 13:23:54 -03:00
f 224bdeecca fix: no usar Dir.chdir 2023-07-03 13:10:39 -03:00
f 6d64fa1443 fix: generar un registro cuando falla distributed press #13628
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-06-15 18:51:16 -03:00
f d17db5428a fix: deprecar Dir#chdir #13619
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-15 18:28:34 -03:00
f 6e42472067 fix: darle bola a los mensajes de deprecación de bundler #13610
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
se configuraban las opciones que le pasábamos pero no se aplicaban en el
comando actual, con lo que quería instalar las gemas globalmente y
fallaba la creación de sitios.
2023-06-15 13:33:25 -03:00
f 8d7d1c10b1 fix: indexar posts luego de crear el sitio #13610
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
se producía una condición donde el sitio se quería indexar sin haber
terminado de instalar las gemas y todo fallaba.

no tenemos que usar más callbacks, solo servicios
2023-06-15 12:04:44 -03:00
f 4064d41855 fix: duplicar el hash
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-14 13:39:26 -03:00
f 83ebdea24b fix: soporte para ruby 3.1 #9357
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
closes #13603
2023-06-14 13:33:47 -03:00
fauno 0d0eeee2b1 Merge branch 'issue-13578' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Al cargar formulario de Artículo nuevo, si no carga js Airbrake falla issue-13578

See merge request sutty/sutty!191
2023-06-12 20:12:42 +00:00
jazzari 764fd70e06 fix: add try catch to application.js so can notify js errors with the console #13578
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-12 11:20:26 -03:00
f 504f30997e fix: no fallar si no hay sitio del panel
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-10 12:18:25 -03:00
f 679a3fde85 chore: force ci
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-06-09 13:26:41 -03:00
fauno e37d9ac0cc Merge branch 'assets' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
incorporar assets en el repositorio

See merge request sutty/sutty!88
2023-06-09 16:16:02 +00:00
fauno 885dd0ea67 Merge branch 'issue-1278' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Issue 1278

See merge request sutty/sutty!190
2023-06-09 16:14:57 +00:00
f 6c6566422e fix: arreglar dependencias
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-09 13:11:02 -03:00
jazzari 3d7394655c fix: agrego polizas & codigo de conducta #1278
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-06-09 12:44:40 -03:00
jazzari f546cb902a fix: no crea los sitios #1278 2023-06-09 12:13:43 -03:00
f eba42c9b79 fix: hacer el dump desde rails
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-24 16:52:29 -03:00
f 11d0431b34 fix: dblink no es una extensión que usemos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-24 15:53:01 -03:00
f 707695f97d fix: la replicación la configuramos en otro lado 2023-05-24 15:52:41 -03:00
Sutty 28b74492f0 fix: dump de producción #13498 2023-05-24 15:52:20 -03:00
f 2a983778b4 fixup! fix: deshabilitar la interfaz de orden para invitades #13439
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-24 11:41:16 -03:00
f 9fd9e5fa4e fix: deshabilitar la interfaz de orden para invitades #13439
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-24 10:58:08 -03:00
f 66a635fa4e fix: son atributos, no elementos sutty/editor#85
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-24 10:45:39 -03:00
f 4e002e042b fix: no permitir idiomas que no existen en el cambio de idioma #13493
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-24 10:06:11 -03:00
f e35bddf915 fix: no permitir que les usuaries elijan un idioma que no existe
porque se les rompe el panel después
2023-05-24 10:04:22 -03:00
f 2d3f174689 feat: alt text
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-23 18:33:50 -03:00
f 521922c131 fix: no compilar assets en 3.17
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-20 14:46:09 -03:00
f e7a6eb5751 fixup! feat: actualizar a ruby 3.1 rails 6.1
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-20 14:31:43 -03:00
f 0056adf737 fixup! feat: poder pasar la versión de ruby y gems por env 2023-05-20 14:30:44 -03:00
f 18b7f39248 feat: crear una rama para probar los cambios
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-20 14:28:03 -03:00
f 202992d1cd feat: actualizar a ruby 3.1 rails 6.1 2023-05-20 14:27:03 -03:00
f c12a6e1535 feat: poder pasar la versión de ruby y gems por env 2023-05-20 14:25:29 -03:00
f e0ed377940 feat: los assets todavía se compilan en alpine 3.14 2023-05-20 14:23:40 -03:00
f 5dcf87710b feat: generar contenedor con ruby 3.1 2023-05-20 14:19:28 -03:00
f d0f7843fbf fixup! feat: poder paginar solo algunos sitios #12714
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-19 14:40:42 -03:00
f 3540886554 feat: poder paginar solo algunos sitios #12714
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-05-19 14:37:46 -03:00
f 068bed5c0a Revert "deshabilitar el paginado temporalmente"
This reverts commit 9c4a0a86f3.
2023-05-19 14:34:24 -03:00
fauno 41acc89e37 Merge branch 'issue-9367' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Issue #9367

See merge request sutty/sutty!184
2023-05-15 20:04:27 +00:00
f 08ebcce786 Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-9367
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-05-15 17:03:35 -03:00
f b869a2a34e fix: poder informar errores con archivos subidos #13427
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-05-13 17:52:17 -03:00
f dc20e4c9ce fix: permite instalar gemas por primera vez #13428
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-05-13 17:51:41 -03:00
f 5d8c1556a8 fix: no fallar si no existe el Gemfile.lock #13428 2023-05-13 17:51:41 -03:00
f 8d9328cd66 fix: en algunos casos el directorio existía aunque vacío #13428 2023-05-13 17:51:41 -03:00
f 310bd31710 fix: no usar :send #13428 2023-05-13 17:51:40 -03:00
f 622d3b47db BREAKING CHANGE: deprecar Deploy#gems_dir por Site#bundle_path #13428 2023-05-13 17:51:00 -03:00
f 1c294d450e fix: deprecar Site#run_in_path #13428
ya no es necesario y Dir.chdir no es concurrente, con lo que nos
ahorramos posibles bugs.
2023-05-13 17:50:34 -03:00
f e473de6a4e fix: leer los archivos de datos correctamente #13428
los archivos de datos se leen con rutas relativas, lo que puede mezclar
el cwd en usos concurrentes.

depreca la dependencia en jekyll-data además!
2023-05-13 17:50:32 -03:00
f e9fd650ba9 fix: ignorar posts #13428
versiones de jekyll-locales menores a 0.2 dejan symlinks rotos en lugar
de la colección _posts.  con esto ignoramos la colección del todo,
porque solo usamos las que están en idiomas.

sutty obliga efectivamente a todos los sitios jekyll a usar
jekyll-locales o al menos colocar los posts en un directorio de idiomas.

una salvedad sería agregar esto en la configuración:

```yaml
locales:
- "posts"
```
2023-05-13 17:49:29 -03:00
fauno 5612658003 Merge branch 'issue-13094' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
fix: no es necesario marcar los campos que están bien #13094

See merge request sutty/sutty!168
2023-05-13 14:54:09 +00:00
fauno ad868121b5 Merge branch 'issue-13089-1' into 'rails'
Issue #13089

See merge request sutty/sutty!165
2023-05-13 14:53:42 +00:00
f 91bad0cdd4 Merge branch 'rails' of 0xacab.org:sutty/sutty into usar-sutty-editor
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-05-13 11:53:30 -03:00
fauno 2e0d981c2e Merge branch 'issue-13029' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
feat: agregar las columnas para la recolección de datos c

See merge request sutty/sutty!153
2023-05-13 14:51:06 +00:00
fauno 30f1c41709 Merge branch 'issue-skel.sutty.nl-7' into 'rails'
feat: no instalar otras gemas que las especificadas

See merge request sutty/sutty!154
2023-05-13 14:50:30 +00:00
fauno e7634cc91d Merge branch 'issue-12925' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
feat: establecer los metadatos para cambiar el idioma #12925

See merge request sutty/sutty!152
2023-05-13 14:48:54 +00:00
fauno 371f8e7593 Merge branch 'issue-13022' into 'rails'
Issue 13022

See merge request sutty/sutty!151
2023-05-13 14:47:31 +00:00
fauno 0c26c6deb5 Merge branch 'issue-13008' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
fix: typo #13008

See merge request sutty/sutty!149
2023-05-13 14:47:16 +00:00
fauno 8c44449e93 Merge branch 'issue-13009' into 'rails'
Issue 13009

See merge request sutty/sutty!148
2023-05-13 14:46:51 +00:00
fauno 7ca586abae Merge branch 'issue-12970' into 'rails'
fix: indicar qué acción vamos a hacer #12970

See merge request sutty/sutty!145
2023-05-13 14:46:08 +00:00
f 01bd8b00ba Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-12970
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-05-13 11:45:42 -03:00
fauno 77304a8313 Merge branch 'issue-12968' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
fix: instalar pnpm 7

See merge request sutty/sutty!144
2023-05-13 14:43:58 +00:00
fauno 8cc5bde155 Merge branch 'issue-13199' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
#13199

See merge request sutty/sutty!175
2023-05-13 14:40:35 +00:00
f 2a50dae51c Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-13199
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-05-13 11:40:06 -03:00
f 5febaf4cf1 Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-13199 2023-05-13 11:39:59 -03:00
fauno 0bb59adb79 Merge branch 'issue-13177' into 'rails'
#13177

See merge request sutty/sutty!176
2023-05-13 14:39:35 +00:00
f bfdc97592c Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-13177
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-05-13 11:39:08 -03:00
fauno 12fad00cc5 Merge branch 'issue-13178' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Issue #13178

See merge request sutty/sutty!174
2023-05-13 14:38:12 +00:00
f 88e9434248 Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-13178
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2023-05-13 11:37:41 -03:00
fauno 5cecb08907 Merge branch 'issue-13171' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Issue #13171

See merge request sutty/sutty!177
2023-05-13 14:35:13 +00:00
fauno 7deca064c8 Merge branch 'issue-13096' into 'rails'
feat: lista de links #13096

See merge request sutty/sutty!162
2023-05-13 14:34:32 +00:00
fauno f14b70733f Merge branch 'issue-10449' into 'rails'
fix: vincular a saber más #10449

See merge request sutty/sutty!173
2023-05-13 14:34:06 +00:00
fauno 413c0b963c Merge branch 'issue-13247' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: aceptar la invitación al confirmar la cuenta #13247

See merge request sutty/sutty!178
2023-05-12 18:11:51 +00:00
f 1839d48893 fix: permitir el atributo start #13321
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-29 18:10:28 -03:00
f a9bce070e8 fix: temporalmente deshabilitar el cambio de plantillas #13260
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-26 15:25:09 -03:00
f f38251af7a fix: permisos para posts indexados #13266
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-26 15:15:56 -03:00
f e9d33b625a feat: encontrar el post a partir de su indexación 2023-04-25 14:51:54 -03:00
f 0b2cc38691 feat: botón de contacto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-25 13:14:29 -03:00
f fb7fb080d1 feat: vincular al formulario de contacto desde la página de error 2023-04-25 13:12:07 -03:00
f 09ecc8f0b4 Merge branch 'rails' into issue-13096
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-25 11:24:38 -03:00
f 5c44a4f15e fix: el mensaje de ignorar no es el correcto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-24 19:01:19 -03:00
f 34947ffd4e fix: typo 2023-04-24 19:01:02 -03:00
f 18de36939f fix: usar el token correcto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-24 19:00:23 -03:00
f 838b398f28 fix: cambiar el token de confirmación
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-24 18:58:05 -03:00
f 3a7c9c6b62 fixup! fix: confirmar usuaries en la invitación #13247
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-24 18:12:40 -03:00
f e35d09e343 fix: si le usuarie creo su cuenta manualmente no necesita ser invitade 2023-04-24 18:07:57 -03:00
f 229914e849 fix: confirmar usuaries en la invitación #13247
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-24 17:44:04 -03:00
f 5c467e08b8 fix: aceptar la invitación también confirma el correo #13247
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
les usuaries que no confirmaron su correo quedaban en un loop si luego
eran invitades a un sitio.
2023-04-24 17:21:24 -03:00
f 1cf5ca5953 fix: aceptar la invitación al confirmar la cuenta #13247
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-24 17:03:38 -03:00
f 61bc23babe feat: agregar nodo en los logs
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-24 14:55:46 -03:00
f 47969cc410 fix: no sincronizar los sitios de testeo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-24 14:48:01 -03:00
f 3a99e1a867 fix: usar el hostname como url
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-24 14:42:02 -03:00
f b78dd1661a fix: guardar el hostname 2023-04-24 14:41:45 -03:00
f f1e53c04db fix: ir al contenedor de rsyncd
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-22 18:18:30 -03:00
f 4f74c6f6ca fix: no configurar ssh para rsyncd
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-21 15:48:09 -03:00
f 79398d0448 fixup! fix: cambiar las direcciones de sincronización a rsyncd
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-21 15:44:22 -03:00
f a6bba8c3cb fix: cambiar las direcciones de sincronización a rsyncd
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-21 15:42:16 -03:00
f 79fd1b7fbb BREAKING CHANGE: usar rsyncd en lugar de ssh #13171 2023-04-21 15:24:40 -03:00
f 834715d559 fix: traducir el botón de agregar #13177
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-21 14:17:09 -03:00
f d8c432b71a fix: ocupar menos espacio #13199
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-21 14:14:39 -03:00
f 04ad7e2324 fix: usar la fecha de creación del deploy
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
para saber si hubo publicaciones después de su creación.  no usamos la
fecha de modificación porque la configuración manual solo los crea o los
elimina y los métodos pueden automodificarse durante la publicación.
2023-04-21 13:47:02 -03:00
f 3f4517b427 fix: no cachear el estado
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-21 12:40:36 -03:00
f f1aefbcb34 fix: guionar titulo y descripciones largas #13096
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-21 12:36:40 -03:00
f 888660b66c Merge branch 'issue-13160' into issue-13096 2023-04-21 12:36:08 -03:00
f 8ed5aedf75 feat: componente de cabecera de sitio
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-21 12:31:46 -03:00
f 04c9ff5319 fix: detectar cambios de configuración por separado
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-21 12:22:30 -03:00
f da873d2efe fix: detectar si el sitio o los artículos fueron modificados luego de publicar 2023-04-21 12:22:30 -03:00
f 498c8cc5ad fix: usar los posts indexados para obtener la diferencia 2023-04-21 12:22:30 -03:00
f 0567e491ee fix: poder ver los mensajes en el orden correcto
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-20 18:35:21 -03:00
f 7e8bcc55a1 feat: indicar que se puede publicar el sitio #13178 2023-04-20 18:35:18 -03:00
f f35df41d1b fix: usar guionado en título y descripción #13160
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-20 18:33:33 -03:00
f 76ddbaf5ab fix: vincular a saber más #10449
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-20 18:32:20 -03:00
f 712514bc8c feat: avisar que hay que publicar al cambiar la configuracion #13114
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-20 18:31:38 -03:00
Maki 9e78a2df1d Merge branch 'issue-13163' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: no generar urls a partir de los protocolos #13163

See merge request sutty/sutty!171
2023-04-19 21:57:32 +00:00
f bd48b8561c fix: no generar urls a partir de los protocolos #13163
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
porque ipfs es ipns (!)
2023-04-19 18:04:22 -03:00
f 11fe98ecdc fix: ignorar los subdominios en los dominios alternativos #13159
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-19 14:57:59 -03:00
f 9e348bfdd8 fix: los subdominios para los sitios vienen de un certificado wildcard #13159 2023-04-19 14:57:59 -03:00
fauno 619019102f Merge branch 'issue-13092' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
No está traducido el botón de licencia en el selector de plantillas #13092

See merge request sutty/sutty!163
2023-04-19 13:59:58 +00:00
fauno 00d3b814d8 Merge branch 'issue-13071' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Issue #13071

See merge request sutty/sutty!166
2023-04-19 13:57:34 +00:00
fauno 4c0e29b233 Merge branch 'issue-13091-1' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
feat: reorder template designs according to complexity #13091

See merge request sutty/sutty!160
2023-04-19 13:56:25 +00:00
fauno b49f7e48ef Merge branch 'issue-13095' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: Traducir el placeholder del buscador #13095

See merge request sutty/sutty!167
2023-04-19 13:53:48 +00:00
f 6e5fcc17ff fix: palabra sobrante
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-18 17:38:45 -03:00
jazzari fbc822ba5d fix: attributes on label in view #13095
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-17 20:02:00 -03:00
f 5c97637738 feat: mostrar la lista de artículos organizada #13072
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-17 18:33:18 -03:00
f 35b79ed9b4 feat: organizar layouts #13072 2023-04-17 18:32:54 -03:00
f 7d9b96980a fix: establecer el color por defecto de los botones
si lo establecemos después de bootstrap, pisamos los colores de los
botones
2023-04-17 18:32:54 -03:00
jazzari 6921a33f61 fix: add id to input in view #13095
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-17 17:59:35 -03:00
jazzari 85f9590719 fix label in view #13095
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-17 17:49:39 -03:00
jazzari 219c0f4fb6 fix: label tag in view #13095
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-17 16:47:09 -03:00
jazzari 19bf8fb8bf fix: capitalization en yml & fix in view #13095
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-17 16:37:10 -03:00
jazzari fcbed5003e fix: add missing sign = in view #13095
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-17 16:15:09 -03:00
f 1fea5b771d fix: no es necesario marcar los campos que están bien #13094
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-17 15:42:32 -03:00
jazzari 6b9eead0ab fix: search placeholder in index.haml view #13095
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-17 15:13:37 -03:00
f 31b66373ae fix: mejorar el mensaje de espera, dando un accionable
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-17 15:03:00 -03:00
f 6651781cac feat: poder ir a la lista de publicaciones del sitio 2023-04-17 14:45:12 -03:00
f 82640345e2 Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-13096 2023-04-17 14:42:18 -03:00
fauno f2845a4c78 Merge branch 'issue-13034' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: al usar alert tenemos que cambiar i18n #13034

See merge request sutty/sutty!155
2023-04-17 16:32:17 +00:00
fauno a598050b1e Merge branch 'issue-13105' into 'rails'
fix: renovar el token #13105

See merge request sutty/sutty!156
2023-04-17 16:28:29 +00:00
jazzari 7ac8f58acb fix: change in help how create a new site en & es #13089
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-17 13:19:04 -03:00
f 0955dc62b4 fix: mejorar la ayuda del nombre #9986 2023-04-17 13:17:19 -03:00
jazzari 56d5ee3dfe fix: change key in line 433 from licencia to license in en.yml #13092
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-16 18:01:17 -03:00
f 07d6b14b87 fix: cortar los links largos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-15 19:24:45 -03:00
f 251dde865b fix: siempre devolver un array 2023-04-15 19:13:23 -03:00
f 5d541ebee6 fixup! feat: lista de links #13096
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-15 19:06:20 -03:00
f 4eb23a787b feat: lista de links #13096
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-15 18:36:56 -03:00
f 35ee19f6d8 fix: editor 0.1.23 2023-04-15 15:27:43 -03:00
f 2d6e3443d7 fix: estos cambios tampoco
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-15 15:16:31 -03:00
f 020fb250b4 fix: #find_each no respeta el orden 2023-04-15 15:12:08 -03:00
f fd41242985 fix: el orden es de mayor a menor prioridad
dejando espacio entre algunos para poder intercalar otras plantillas
2023-04-15 15:03:38 -03:00
f bc74f85ba2 fix: mejorar el título
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-15 14:56:58 -03:00
f bdac1fb0b8 fix: estos cambios no pertenecen a esta rama 2023-04-15 14:39:55 -03:00
jazzari d59fa43082 feat: reorder template designs according to complexity # 13091
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-15 14:08:05 -03:00
f 29f4c7a847 ci: estadío
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-15 12:31:52 -03:00
f 1231f3bdab ci: comillas 2023-04-15 12:31:12 -03:00
f e85ce7c883 ci: typo 2023-04-15 12:28:37 -03:00
f aa0cd9d6a3 ci: compilar assets también en gitlab
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-15 12:26:23 -03:00
f 6e56778768 fix: renovar el token #13105
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
`touch` no corre `before_save`, con lo que el token nunca se renovaba
2023-04-15 11:16:58 -03:00
f 8aed1edaff feat: ocupar todo el ancho
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-13 14:27:51 -03:00
f f5aae98b91 feat: mover el botón de publicación a una zona más visible #13071 2023-04-13 14:25:56 -03:00
f d942d4355b feat: editor 0.1.22 2023-04-12 13:08:16 -03:00
f f041706bc7 feat: poder cambiar al tema oscuro en firefox
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-12 12:28:03 -03:00
f 8457a07664 fix: al usar alert tenemos que cambiar i18n #13034
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-11 17:49:45 -03:00
f 991624b951 feat: no instalar otras gemas que las especificadas
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
sutty/skel.sutty.nl#7
2023-04-11 17:45:01 -03:00
f 8f1c38b8fc fix: correr la ci cuando cambia
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-11 16:39:10 -03:00
f 030a64a31c fix: generar una imagen por rama
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-11 16:37:24 -03:00
f 556a0541a5 feat: agregar las columnas para la recolección de datos #13029
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-11 16:19:49 -03:00
f 9aa99e2754 feat: establecer los metadatos para cambiar el idioma #12925
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-11 12:09:13 -03:00
f 9e177a2257 fix: correr lfs junto con las gemas
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
esto es una solución temporal!
2023-04-11 10:48:00 -03:00
f 1c5dd603e5 fix: hacer git lfs checkout despues de clonar el sitio #13022
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-11 10:42:33 -03:00
f d84975a61a feat: poder hacer git lfs checkout 2023-04-11 10:42:07 -03:00
f e504501678 fix: deshabilitar el modo oscuro #12994
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
hasta que lo podamos revisar mejor
2023-04-10 19:24:40 -03:00
f 83a16c7b94 fix: typo #13008
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-10 18:36:03 -03:00
f f2b6e2929c fix: informar cuáles formatos aceptamos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-10 18:29:13 -03:00
f 563060e113 feat: permitir subir webp 2023-04-10 18:22:49 -03:00
f 2086ade1a7 fix: solo permitir subir imágenes para web #13009 2023-04-10 18:21:33 -03:00
fauno 95d0c35d14 Merge branch 'issue-12958' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Issue 12958

See merge request sutty/sutty!146
2023-04-10 21:03:28 +00:00
f 1e79e26872 fix: ignorar las excepciones de publicaciones duplicadas
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-10 17:38:16 -03:00
f 482a637207 fix: perform_later
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-10 17:33:07 -03:00
f 6c1dcf5ded fix: evitar errores de serialización #12998
`que` falla silenciosamente cuando no puede serializar errores para
enviar, que es la mayor parte de las veces.

enviar los errores sincronicamente excepto los de airbrake
2023-04-10 17:31:26 -03:00
f 79f3958a06 fix: que no expone este metodo en activejob
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-10 16:53:35 -03:00
f a58936b22e fix: retomar la publicación de cambios #12958
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-10 13:28:32 -03:00
f 20e8e83ab6 feat: notificar errores de que 2023-04-10 13:28:01 -03:00
fauno aaa4608cf7 Merge branch 'issue-9359' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: enviar el período como parámetros del formulario #9359

See merge request sutty/sutty!115
2023-04-10 15:52:04 +00:00
fauno 1c3ad12db0 Merge branch 'issue-2123' into 'rails'
fix: recuperar el comportamiento esperado #2123

See merge request sutty/sutty!124
2023-04-10 15:51:48 +00:00
f 63ee0ec8f7 Merge branch 'rails' into issue-2123
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-10 12:51:12 -03:00
fauno 92bba68fd5 Merge branch 'issue-10031' into 'rails'
deploys #10031

Closes #12747, #10109, #10108, #10107, #10106, #10105, #10104, #10103, #10102, #10101, #10100, #10099, #10098, #10097, #10096, #10095, #10094, #10093, #10092, #10091, #10090, #10089, #10088, #10087, #10086, #10085, #10084, #10083, #10082, #10081, #10080, #10079, #10078, #10077, #10076, #10075, #10074, #10073, #10072, #10071, #10070, #10069, #10068, #10067, #10066, #10065, #10064, #10063, #10062, #10061, #10060, #10059, #10058, #10057, #10056, #10055, #10054, #10053, #10052, #10330, #10329, #10328, #10327, #10326, #10325, #10324, #10323, #10322, #10321, #10320, #10319, #10318, #10317, #10316, #10315, #10314, #10313, #10312, #10311, #10310, #10309, #10308, #10307, #10306, #10305, #10304, #10303, #10302, #10301, #10300, #10299, #10298, #10297, #10296, #10295, #10294, #10293, #10292, #10291, #10290, #10289, #10288, #10287, #10286, #10285, #10284, #10283, #10282, #10281, #10280, #10279, #10278, #10277, #10276, #10275, #10274, #10273, #10272, #10271, #10270, #10269, #10268, #10267, #10266, #10265, #10264, #10263, #10262, #10261, #10260, #10259, #10258, #10257, #10256, #10255, #10254, #10253, #10252, #10251, #10250, #10249, #10248, #10247, #10246, #10244, #10243, #10242, #10241, #10240, #10239, #10238, #10237, #10236, #10235, #10234, #10232, #10231, #10230, #10229, #10228, #10227, #10226, #10225, #10224, #10223, #10222, #10221, #10220, #10219, #10218, #10217, #10216, #10215, #10214, #10213, #10212, #10211, #10210, #10209, #10208, #10207, #10206, #10205, #10204, #10203, #10202, #10201, #10200, #10199, #10198, #10197, #10196, #10195, #10194, #10193, #10192, #10191, #10190, #10189, #10188, #10187, #10186, #10185, #10184, #10183, #10182, #10181, #10180, #10179, #10178, #10177, #10176, #10175, #10174, #10173, #10172, #10171, #10170, #10169, #10168, #10167, #10166, #10165, #10164, #10163, #10162, #10161, #10160, #10159, #10158, #10157, #10156, #10155, #10154, #10153, #10152, #10151, #10150, #10149, #10148, #10147, #10146, #10145, #10144, #10143, #10142, #10141, #10140, #10139, #10138, #10137, #10136, #10135, #10134, #10133, #10132, #10131, #10130, #10129, #10128, #10127, #10126, #10125, #3693, #3681, #3465, #3414, #3330, #3002, #2941, #2632, #2587, #2531, #2511, #2499, #2460, #2062, #2059, #2058, #2057, #1952, #1832, #1746, #1744, #1743, #1741, #1740, #1739, #1738, #1735, #1730, #1716, #1667, #1610, #1609, #1478, #1461, #1303, #1230, #1191, #1175, #1154, #1153, #1152, #1124, #1104, #10413, #10412, #10411, #10410, #10409, #10408, #10407, #10406, #10405, #10404, #10403, #10402, #10401, #10400, #10399, #10398, #10397, #10396, #10395, #10394, #10393, #10392, #10391, #10390, #10389, #10388, #10387, #10386, #10385, #10384, #10383, #10382, #10381, #10380, #10379, #10378, #10377, #10376, #10375, #10374, #10373, #10372, #10371, #10370, #10369, #10368, #10367, #10366, #10365, #10364, #10362, #10361, #10360, #10359, #10358, #10357, #10356, #10355, #10354, #10353, #10352, #10351, #10350, #10349, #10348, #10347, #10346, #10345, #10343, #10342, #10341, #10340, #10339, #10338, #10337, #10336, #10335, #10334, #10333, #10332, #10331, #10124, #10123, #10122, #10121, #10120, #10119, #10118, #10117, #10116, #10115, #10114, #10113, #10112, #10111, #10110, #9996, #9990, #9955, #9939, #9901, #9896, #9893, #9857, #9810, #9385, #9370, #9360, #9024, #8846, #8799, #8751, #8678, #8529, #8168, #7861, #7685, #7645, #7630, #7575, #7549, #7386, #6177, #6066, #5832, #5147, #504, #5022, #4949, #4947, #4899, #4896, #4874, #4860, #4804, #4798, #4740, #4679, #4677, #4668, #4641, #4574, #4537, #4536, #4416, #4407, #4312, #4215, #4201, #4175, #4042, #3915, #3858, #3833, #3819, #3811, #3764, and #3719

See merge request sutty/sutty!119
2023-04-10 15:50:24 +00:00
fauno b7546cfe39 Merge branch 'issue-12754' into 'rails'
fix: establecer un parámetro por defecto #12754

See merge request sutty/sutty!127
2023-04-10 15:49:24 +00:00
fauno 1555cdd644 Merge branch 'issue-12762' into 'rails'
feat: ordenar los sitios por actividad #12762

See merge request sutty/sutty!131
2023-04-10 15:48:57 +00:00
fauno 9e6ba61ab9 Merge branch 'issue-12773' into 'rails'
generar hidden services a demandab

Closes #12410, #12753, #10467, #10506, and #10509

See merge request sutty/sutty!132
2023-04-10 15:48:24 +00:00
f 2f745886f5 fix: reintentar si falló la generación en el pasado 2023-04-10 12:47:55 -03:00
f 0002ed53a9 BREAKING CHANGE: deprecar la api de onion 2023-04-10 12:47:55 -03:00
f 487765f7d8 feat: validar y agregar la dirección a la configuración del sitio 2023-04-10 12:47:55 -03:00
f 718463f0ea feat: generar direcciones tor a demanda #12773 2023-04-10 12:47:55 -03:00
f 252652c94b poder ver la salida si lo ejecutamos desde la terminal 2023-04-10 12:45:10 -03:00
fauno 8a93df9de9 Merge branch 'issue-10464' into 'rails'
Issue #10464

Closes #10509, #10506, #10467, #12753, and #12410

See merge request sutty/sutty!121
2023-04-10 12:43:12 -03:00
f ae7481550a feat: hacer limpieza de emergencia #12854
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-10 12:37:30 -03:00
f cd7aa1d124 fix: detectar cuándo estamos en hainish 2023-04-10 12:36:49 -03:00
f 2fac95d2e8 fix: obtener los sitios ordenados para ir actualizándolos en orden 2023-04-10 12:36:49 -03:00
f d99f02bd0c feat: informar qué se está haciendo 2023-04-10 12:36:49 -03:00
f 4442338a68 feat: realizar la limpieza en segundo plano 2023-04-10 12:36:49 -03:00
fauno 936c4ddccc Merge branch 'issue-10233' into 'rails'
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fix: demostrar otro sitio #10233

See merge request sutty/sutty!136
2023-04-10 15:36:15 +00:00
fauno 4be89dcbee Merge branch 'issue-12886' into 'rails'
fix: poder cambiar de idioma manteniendo los parametros #12886

See merge request sutty/sutty!137
2023-04-10 15:35:51 +00:00
fauno 4fa3f45e3c Merge branch 'issue-12795' into 'rails'
feat: pedir consentimiento #12795

See merge request sutty/sutty!133
2023-04-10 15:35:29 +00:00
f 414fd7348d fix: activarlo
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-10 12:33:24 -03:00
f c66d1f0f08 fix: mejorar la redacción 2023-04-10 12:33:24 -03:00
f 492d238f57 BREAKING CHANGE: eliminar campo que no se usó nunca 2023-04-10 12:33:24 -03:00
f 8f0f260a4f feat: almacenar los campos 2023-04-10 12:33:24 -03:00
f 87d51e8856 feat: pedir consentimiento #12795 2023-04-10 12:33:24 -03:00
fauno 69c5d8d7bb Merge branch 'issue-10464' into 'rails'
Issue #10464

Closes #10509, #10506, #10467, #12753, and #12410

See merge request sutty/sutty!121
2023-04-10 15:31:38 +00:00
f 1f9be2afec Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-10464
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-10 12:31:01 -03:00
fauno b65357cdec Merge branch 'issue-12755' into 'rails'
fix: instalar las gemas cuando sea necesario #12755

See merge request sutty/sutty!130
2023-04-10 15:27:46 +00:00
f ab126038af feat: devolver las urls con protocolos 2023-04-10 12:26:46 -03:00
f a56acfd6da fix: obtener los links luego de la publicación 2023-04-10 12:26:46 -03:00
f 943bf7b5bd fix: no pisar las datos de njalla con los de distributed press 2023-04-10 12:26:46 -03:00
f d2e4fe0964 fix: los registros en njalla no siempre son necesarios 2023-04-10 12:26:46 -03:00
f f6a08f1073 feat: eliminar registros en njalla 2023-04-10 12:26:46 -03:00
f b818408f3e feat: indicarle a distributed press que elimine el sitio
sutty/distributed-press-api-client#10
2023-04-10 12:26:45 -03:00
f b759398a4e BREAKING CHANGE: usar la última instancia de Distributed Press 2023-04-10 12:26:45 -03:00
f 95198832c4 feat: configurar la fuente de gemas del skel desde el panel 2023-04-10 12:26:45 -03:00
f bee1653830 fix: evitar métodos de publicación duplicados #12276 2023-04-10 12:26:45 -03:00
f ad0d7aac10 feat: tener en cuenta las dependencias suaves al armar el grafo 2023-04-10 12:26:45 -03:00
f b2c6d40b0f fix: deprecar DeployLocal#extra_env 2023-04-10 12:26:45 -03:00
f c774337fd3 feat: sincronizar dominios por idioma 2023-04-10 12:26:45 -03:00
f bef171d3ac fix: intentar crear siempre los registros en njalla 2023-04-10 12:26:45 -03:00
f 42c7e93ac9 fix: crear un registro para www también 2023-04-10 12:26:45 -03:00
f 57542c92a7 fix: typo 2023-04-10 12:26:44 -03:00
f da192ef14c fix: sincronizar aunque algunos destinos todavía no existan
por ejemplo la dependencia en hidden service hace que no se sincronice
el sitio principal.
2023-04-10 12:26:24 -03:00
f c53391b21c fix: mostrar los metodos fallidos en el correo de notificación
no salían porque la tabla se genera en base a expandir las urls y cuando
las urls venían vacías no se generaba la fila.
2023-04-10 12:26:24 -03:00
f 21dd6ffd55 fix: no fallar njalla si falló dp
closes #12410
2023-04-10 12:26:24 -03:00
f 1ff48bf458 fix: no intentar notificar si no hay sitio
closes #12753
2023-04-10 12:26:24 -03:00
f 3abd87e8e6 feat: guardar la api key de njalla en las credenciales 2023-04-10 12:26:24 -03:00
f ecd8c80e02 fix: capturar la excepción #10546 2023-04-10 12:26:24 -03:00
f f5274cf342 fix: no hacer falla la configuración si todavía no se generó el onion #10542 2023-04-10 12:26:24 -03:00
f 2a93218ef9 fix: siempre devolver el destino
closes ##10541

closes ##10540

closes ##10539

closes ##10538

closes ##10537

closes ##10536

closes ##10535

closes ##10534

closes ##10533
2023-04-10 12:26:24 -03:00
f 94980051b6 fix: volver a hacer depender la sincronizacion del zip 2023-04-10 12:26:24 -03:00
f 8b51eb99a3 fix: private depende de local para instalar las dependencias 2023-04-10 12:26:23 -03:00
f 54575b3bc3 fix: siempre avisar cuando terminó el deploy en la consola 2023-04-10 12:26:23 -03:00
f d40c401a72 fix: mostrar la salida 2023-04-10 12:26:23 -03:00
f ad5724be29 fix: siempre hay segundos 2023-04-10 12:26:23 -03:00
f 75621fb5c5 fix: traducir metodos de publicacion #10030 2023-04-10 12:26:22 -03:00
f 91750116a1 feat: darle url a full rsync 2023-04-10 12:25:53 -03:00
f 8b10cfb524 feat: darle url a deploy rsync 2023-04-10 12:25:53 -03:00
f 3dc10c46f8 feat: todavía no hay interfaz para estos deploys 2023-04-10 12:25:53 -03:00
f 78c2fd0053 fix: agregar dependencias a distributed press 2023-04-10 12:25:53 -03:00
f f0eab9a7b3 fix: volver a fallar si al hacer deploy todavia estan caidos los servicios 2023-04-10 12:25:53 -03:00
f 29e1d09986 feat: separar la creación de DP de njalla 2023-04-10 12:25:53 -03:00
f 2b340a4488 fix: crear el sitio remoto si no se pudo crear antes 2023-04-10 12:25:53 -03:00
f debf45b726 fix: no fallar si hay errores remotos
closes #10467

closes #10506

closes #10509
2023-04-10 12:25:53 -03:00
f 812fc0315c fix: requires 2023-04-10 12:25:53 -03:00
f 4666e67b5d fix: no crear subdominios para dominios personalizados
esto es por retrocompatibilidad para sitios que no usan
DeployAlternativeDomain
2023-04-10 12:25:53 -03:00
f 1b5adfb712 feat: crear temporalmente los dominios en njalla
el problema es que no podemos delegar `_dnslink.*.sutty.nl` hacia
distributed press, con lo que es necesario crear un subdominio por cada
sitio que lo active.
2023-04-10 12:25:53 -03:00
f 0b96fc44d6 feat: texto para el correo de notificación 2023-04-10 12:25:51 -03:00
f 56a3f2becb feat: un deploy puede tener varias urls 2023-04-10 12:25:18 -03:00
f c291fefa99 fix: link a saber más 2023-04-10 12:25:18 -03:00
f 4e1f14a528 feat: guardar un log y mostrarlo en output también 2023-04-10 12:25:18 -03:00
f 975bf39c2e fix: no fallar si tarda mucho dp 2023-04-10 12:25:18 -03:00
f 4c6818762d fix: faltaban algunos require 2023-04-10 12:25:18 -03:00
f 436b55d317 feat: textos para el panel 2023-04-10 12:25:18 -03:00
f 0bb0698bd4 fix: pnpm se instala localmente 2023-04-10 12:25:18 -03:00
f ea0539bb1f feat: usar pnpm si existe
relacionado con sutty/jekyll/sutty-base-jekyll-theme#53
2023-04-10 12:25:16 -03:00
f c789813a46 fix: actualizar api 2023-04-10 12:24:04 -03:00
f 4ebbd48fde feat: no vamos a expedir tokens efímeros por ahora 2023-04-10 12:24:04 -03:00
f f190fb2dc8 fix: permitir modificar el token
estos parches hacian que no se pueda modificar el token
2023-04-10 12:24:04 -03:00
f c44584596d feat: crear y publicar el sitio en distributed press v1 2023-04-10 12:24:04 -03:00
f 84b2968cdb feat: almacenar y renovar tokens de distributed press 2023-04-10 12:24:04 -03:00
Maki ecdbfeb568 agrego toggler para distributed press 2023-04-10 12:23:46 -03:00
f b7daa8e0eb feat: poder modificar la url de distributed press 2023-04-10 12:23:46 -03:00
f 6f4e91d318 soportar distributed press apiv0 #7839 2023-04-10 12:23:46 -03:00
f ba91ed56aa feat: separar rsync de full rsync
los segundos se usan para sincronizar todas las versiones de un sitio
con otro servidor de sutty.  los primeros solo sincronizan los archivos
a otro servidor, no necesariamente bajo el mismo nombre.
2023-04-10 12:23:44 -03:00
f 5974a40d02 feat: hacer sonar una campana 2023-04-10 12:23:37 -03:00
f d4f4627dab fix: capturar todas las posibles excepciones 2023-04-10 12:23:37 -03:00
f 58dffd00c9 fix: fallar el hidden service si no se generó el onion aun 2023-04-10 12:23:37 -03:00
f c6f48f55fc feat: mostrar una tabla con el resumen en la consola 2023-04-10 12:23:37 -03:00
f f90ca9cd12 fix: output para rsync 2023-04-10 12:23:35 -03:00
f 431b7223b6 feat: eliminar archivos al sincronizar 2023-04-10 12:23:18 -03:00
f 1e188bab02 fix: rsync no debería depender de zip
aunque el zip no se genere igual queremos poder sincronizar el sitio
2023-04-10 12:23:01 -03:00
f 4ebd9881f5 fix: mejorar gestión de symlink 2023-04-10 12:23:00 -03:00
f 92b97b508b no generar issues para log 2023-04-10 12:23:00 -03:00
f e8746ca385 notificar correctamente la excepción 2023-04-10 12:23:00 -03:00
f 875f1873d3 no fallar al cerrarse la salida 2023-04-10 12:22:59 -03:00
f 199199117d implementar la misma api en todos los deploys 2023-04-10 12:22:38 -03:00
f ea1ac09f96 fix: mejorar gestión de zip 2023-04-10 12:21:27 -03:00
f 3de6f14e63 fix: no pedir el tamaño si falló la compilación 2023-04-10 12:21:20 -03:00
f e5f96c435d feat: generar el sitio en orden #10464 2023-04-10 12:21:20 -03:00
f 607f19f680 feat: activar ordenamiento de metodos de publicacion 2023-04-10 12:20:53 -03:00
f 0ed01a61f7 feat: devolver una lista ordenada de metodos de publicacion 2023-04-10 12:20:53 -03:00
f db25750ab0 feat: usar un grafo dirigido para ordenar las dependencias #10464 2023-04-10 12:20:53 -03:00
f 4f8ea0d9a7 feat: los deploys son interdependientes 2023-04-10 12:20:51 -03:00
fauno 040120579c Merge branch 'issue-5085' into 'rails'
fix: ordenar layouts alfabéticamente #5085

See merge request sutty/sutty!138
2023-04-10 15:19:27 +00:00
fauno 07f4ae2473 Merge branch 'issue-10478' into 'rails'
fix: hacer que devise respete el idioma de la sesión #10478

See merge request sutty/sutty!140
2023-04-10 15:19:09 +00:00
fauno 2e95da98d4 Merge branch 'issue-9361' into 'rails'
feat: implementar un servicio liviano de git-lfs #9361

See merge request sutty/sutty!129
2023-04-10 15:18:45 +00:00
fauno c4d1f5f505 Merge branch 'issue-10492' into 'rails'
Issue 10492

See merge request sutty/sutty!139
2023-04-10 15:17:55 +00:00
fauno 4a97b15be0 Merge branch 'issue-159' into 'rails'
licencias #159

See merge request sutty/sutty!126
2023-04-10 15:17:02 +00:00
fauno 378214470d Merge branch 'issue-12952' into 'rails'
fix: enviar los correos de devise en el idioma de le usuarie #12952

See merge request sutty/sutty!142
2023-04-10 15:16:33 +00:00
fauno d69720096f Merge branch 'issue-10491' into 'rails'
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
fix: hacer que los locales sean bidireccionales #10491 #12064

See merge request sutty/sutty!125
2023-04-10 15:16:08 +00:00
fauno d48bac9c59 Merge branch 'issue-12950' into 'rails'
fix: mantener la notificación hasta que se confirme el correo #12950

See merge request sutty/sutty!143
2023-04-10 15:15:11 +00:00
f e4fdd611ee Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-10491
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-10 12:14:21 -03:00
fauno eab4e2dce6 Merge branch 'ci' into 'rails'
CI

See merge request sutty/sutty!90
2023-04-10 15:12:50 +00:00
fauno c853b17772 Merge branch 'distributed-press' into 'rails'
soportar distributed press apiv0 #7839

Closes #10509, #10506, and #10467

See merge request sutty/sutty!107
2023-04-10 15:10:24 +00:00
f 0cc36f2a1b fix: actualizar la información y guardar la url #12971
para evitar que falle el trabajo de análisis
2023-04-07 14:25:06 -03:00
f 6cab61891c fix: la tarea estaba mal nombrada 2023-04-06 20:30:47 -03:00
f 1996d2ad3f Merge branch 'rails' of 0xacab.org:sutty/sutty into distributed-press 2023-04-06 20:27:47 -03:00
f c45441430f fix: indicar qué acción vamos a hacer #12970 2023-04-06 15:09:14 -03:00
f 54aa022b8c fix: instalar pnpm 7
porque 8 es incompatible con node 14
2023-04-06 11:32:02 -03:00
f 34d26a0174 fix: instalar pnpm 7
porque 8 es incompatible con node 14
2023-04-06 11:27:28 -03:00
f dd3ef04fc4 feat: generar imágenes públicas
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-04-06 11:19:33 -03:00
f 6bc013c859 fix: no mostrar el campo si no hay locales 2023-04-05 19:30:59 -03:00
f 29be4b26b0 fix: no producir un error al no haber locales 2023-04-05 19:30:44 -03:00
f 8d31170086 fix: usar el idioma de le usuarie 2023-04-04 13:34:19 -03:00
f 38d6f6d842 fix: mantener la notificación hasta que se confirme el correo #12950 2023-04-04 13:21:38 -03:00
f ea71aafe58 fix: enviar los correos de devise en el idioma de le usuarie #12952 2023-04-04 11:33:51 -03:00
f 94d30ac12a fixup! feat: cuando se modifica la licencia, considerarla personalizada 2023-04-03 17:50:04 -03:00
f b7a27a87dd feat: cuando se modifica la licencia, considerarla personalizada 2023-04-03 16:58:22 -03:00
f 4b6b422f95 BREAKING CHANGE: clonar el skel en la rama de la plantilla #12760 2023-04-03 16:34:35 -03:00
f 3dacef76f1 fix: esto no funciona 2023-04-03 13:55:21 -03:00
f 191dbbd823 fix: indicar que hay un link 2023-04-03 13:47:59 -03:00
f bd21f3d9b4 fixup! fix: alert en modo oscuro 2023-04-03 13:47:12 -03:00
f ad76fed1b1 fix: alert en modo oscuro 2023-04-03 13:31:32 -03:00
f ec47335f04 fix: es necesario el arbol actual para ignorar cambios en paralelo
cuando estamos guardando un post con archivos subidos y posts
relacionados, al no usar el arbol actual se pisaban los archivos
modificados y el repositorio quedaba en un estado inconsistente.
2023-04-03 12:44:09 -03:00
f 5ae3fe0b35 fix: dar una acción 2023-03-31 20:52:35 -03:00
f f62d7fcc80 fix: esperar a que la primera publicación termine 2023-03-31 20:51:20 -03:00
f 8f19f837cd fix: hacer que devise respete el idioma de la sesión #10478 2023-03-31 20:20:37 -03:00
f 0442aa1e06 fixup! feat: informar el estado del sitio #10492 2023-03-31 19:37:47 -03:00
f c2fafac7f0 feat: informar el estado del sitio #10492 2023-03-31 19:32:36 -03:00
f 0d0c8c8b07 fix: mostrar los diseños en dos columnas 2023-03-31 19:31:22 -03:00
fauno b15ebdf549 Merge branch 'issue-12792' into 'rails'
Issue #12792

See merge request sutty/sutty!134
2023-03-31 22:21:06 +00:00
f 59e97ef685 fix: forzar la compilación de brotli
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-31 18:16:11 -03:00
f 30a70e9308 fix: cambió la ruta 2023-03-31 18:03:34 -03:00
f e8678d6fdf feat: editor 0.1.16 2023-03-31 17:43:27 -03:00
f 8c5535c5c7 fix: ordenar layouts alfabéticamente #5085 2023-03-31 17:39:25 -03:00
f 5bdcaef738 feat: descargar archivos remotos sutty/editor#62 2023-03-31 17:21:50 -03:00
f 465d12a7f9 feat: editor v0.1.15 2023-03-31 17:20:09 -03:00
f 3aaf60489a feat: aceptar otros atributos de listas sutty/editor#85 2023-03-31 14:56:50 -03:00
f 3b94072b09 fix: mantener la numeración de items sutty/editor#85 2023-03-31 14:54:58 -03:00
f 0744e124e3 fixup! fix: instalar las gemas cuando sea necesario #12755 2023-03-31 10:56:09 -03:00
f 059230ad6b fix: poder cambiar de idioma manteniendo los parametros #12886 2023-03-30 19:33:04 -03:00
f aff16fdf77 fix: texto 2023-03-30 16:50:45 -03:00
f 16c3fa2413 fix: ancho máximo 2023-03-30 14:56:22 -03:00
f 661655abb5 fix: hacer el deploy cuando el sitio ya está guardado #12276 2023-03-30 13:51:09 -03:00
f 6e100d8954 Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-159 2023-03-30 13:50:55 -03:00
f 691b87b911 fixup! feat: poder serializar las excepciones 2023-03-30 13:11:37 -03:00
f d3166f2c5a feat: poder serializar las excepciones 2023-03-30 13:07:25 -03:00
f edd88d04b9 feat: pre comprimir con brotli también
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-30 11:29:23 -03:00
f 117b850276 fix: hacer pull antes de push
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-30 10:27:30 -03:00
f be902e33bc fix: demostrar otro sitio #10233 2023-03-29 20:45:36 -03:00
f a7b199941d fixup! feat: anchos y altos máximos y mínimos 2023-03-29 20:39:27 -03:00
f ce26c15a50 fix: mejorar el texto 2023-03-29 20:34:54 -03:00
f 1f921d836f fixup! feat: anchos y altos máximos y mínimos 2023-03-29 20:18:52 -03:00
f 167aaf5549 Revert "fix: mostrar siempre los links de recuperación"
This reverts commit 944668edbe.
2023-03-29 16:43:19 -03:00
f 951a045745 fix: no mostrar un título 2023-03-29 16:43:11 -03:00
f 40dfa65bc2 feat: anchos y altos máximos y mínimos 2023-03-29 16:40:10 -03:00
f 71afdc16ae fix: aumentar la prioridad de las publicaciones 2023-03-29 15:41:11 -03:00
f fff499d1f8 fix: correr todo en la misma cola 2023-03-29 15:40:57 -03:00
f fd56ee4c3e fix: usar perform_later 2023-03-29 15:35:00 -03:00
f d5db27ac95 fix: sin prefijo para las colas 2023-03-29 12:34:57 -03:00
f 6856b60517 fixup! fix: usar siempre el componente 2023-03-29 12:05:55 -03:00
f cfc85e6356 feat: iniciar que en segundo plano 2023-03-28 21:15:55 -03:00
f 39e997d0ca BREAKING CHANGE: deprecar sucker punch en favor de que 2023-03-28 20:21:52 -03:00
f 445bf26257 fix: hacer la caja más legible 2023-03-28 19:21:07 -03:00
f 79f8241dec fix: ser especificxs 2023-03-28 19:18:55 -03:00
f 944668edbe fix: mostrar siempre los links de recuperación
por si se vencen, poder encontrarlos
2023-03-28 19:18:30 -03:00
f 40e68da16a fix: mostrar los errores de devise 2023-03-28 19:18:11 -03:00
f b415b3f3cf fix: especificar dónde se puede pedir reconfirmación 2023-03-28 19:05:32 -03:00
f f3845c755f fix: informar que hay que confirmar la cuenta 2023-03-28 19:03:00 -03:00
f 74a19ad9d9 feat: mostrar los mensajes en todas las vistas #12792 2023-03-28 18:55:48 -03:00
f d48231e725 fix: usar siempre el componente 2023-03-28 18:52:42 -03:00
f 706d829613 feat: componente de mensajes resaltados 2023-03-28 18:52:17 -03:00
f 852f96448f Merge branch 'rails' of 0xacab.org:sutty/sutty into distributed-press 2023-03-27 14:05:48 -03:00
f dab670b895 Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-2123 2023-03-27 13:40:52 -03:00
f 5d40fabe54 feat: ordenar los sitios por actividad #12762 2023-03-27 12:38:31 -03:00
f 6b759c92ce fix: instalar las gemas cuando sea necesario #12755
si se modificó el gemfile queremos volver a instalarlas también
2023-03-27 11:45:23 -03:00
f 2fb5bc24d5 fix: encontrar el blob para este servicio 2023-03-25 15:45:34 -03:00
f 2940b5d3e8 fix: no podemos saber quién subió el archivo todavía 2023-03-25 15:45:34 -03:00
f 2215a00727 feat: commitear el archivo en lfs al subirlo 2023-03-25 15:45:34 -03:00
f 960c8dcca4 feat: implementar un servicio liviano de git-lfs #9361 2023-03-25 15:17:22 -03:00
f d44ca16f81 fix: cambiar la descripción de la licencia también 2023-03-25 13:51:12 -03:00
f c62d0d3a72 fixup! feat: agregar una descripción corta a la licencia 2023-03-25 13:48:30 -03:00
f 42b2549f09 feat: agregar una descripción corta a la licencia
que es lo que usan las plantillas como aviso de licencia
2023-03-25 13:46:30 -03:00
f 3e6288fefe fix: filtrar #12774 2023-03-24 14:36:37 -03:00
f b51eb6856c fix: siempre devolver una relación #12768 2023-03-24 11:50:25 -03:00
f a593ecefdb Merge branch 'preview' into rails 2023-03-23 19:24:24 -03:00
f 9fe528a64b Merge branch 'limpieza-del-editor' into rails 2023-03-23 19:23:54 -03:00
f 55e0466102 Merge branch 'locale' into rails 2023-03-23 19:23:27 -03:00
f 054a42ca20 Merge branch 'cancelar-el-trabajo-si-el-sitio-no-existe' into rails 2023-03-23 19:22:58 -03:00
f 952e03fa34 Merge branch 'non-geo' into rails 2023-03-23 19:22:32 -03:00
f 22abe846f4 Merge branch 'rails' of 0xacab.org:sutty/sutty into bundler 2023-03-23 19:21:34 -03:00
fauno 1fc1b4a9bd Merge branch 'permalinks-estaticos' into 'rails'
no setear un permalink por defecto

Closes #3635

See merge request sutty/sutty!74
2023-03-23 22:20:18 +00:00
fauno 81b3dae740 Merge branch 'resiliencia' into 'rails'
ignorar posts sin layout pero notificar

Closes #3251 and #5828

See merge request sutty/sutty!97
2023-03-23 22:14:53 +00:00
fauno c9eed6c60c Merge branch 'slugify-mode' into 'rails'
Slugify mode

See merge request sutty/sutty!93
2023-03-23 22:13:57 +00:00
fauno 4cc93313f4 Merge branch 'deadlock' into 'rails'
Deadlock

See merge request sutty/sutty!81
2023-03-23 22:12:18 +00:00
f b590396a6b fix: implementar output 2023-03-23 19:11:33 -03:00
f 77304d3de9 Merge branch 'rails' into deadlock 2023-03-23 19:10:37 -03:00
fauno 0075113c23 Merge branch 'informative-deploys' into 'rails'
enviar más información

See merge request sutty/sutty!86
2023-03-23 22:07:11 +00:00
fauno 2c5a93f11b Merge branch 'deploy-reindex' into 'rails'
reindexar los sitios al terminar de compilarlos

Closes #7530, #7529, #7528, #7527, #7512, #7511, #7510, #7509, #7494, #7493, #7492, #7491, #7408, #7407, #7406, #7405, #7397, #7396, #7395, #7394, #7383, #7382, #7381, #7380, #7170, #7169, #7168, #7167, #7154, #7153, #7152, and #7151

See merge request sutty/sutty!104
2023-03-23 22:06:10 +00:00
f 539fc7bded Merge branch 'rails' into deploy-reindex 2023-03-23 19:05:41 -03:00
fauno d106eb96e0 Merge branch 'indexed-posts' into 'rails'
no compartir el uuid del post con su indexación

See merge request sutty/sutty!105
2023-03-23 22:04:25 +00:00
fauno e65b563229 Merge branch 'issue-8342' into 'rails'
feat: implementar campo de tipo password #8342

Closes #8204, #1944, #1943, #1942, #1940, #1939, #1938, and #1515

See merge request sutty/sutty!109
2023-03-23 22:03:50 +00:00
fauno 34d2089951 Merge branch 'issue-8400' into 'rails'
fix: poder mostrar la vista previa sin errores de liquid #8400

Closes #8153, #8263, and #8397

See merge request sutty/sutty!110
2023-03-23 22:03:07 +00:00
fauno a289477e30 Merge branch 'issue-8427' into 'rails'
fix: traducción de algunos locales en uso #8427

See merge request sutty/sutty!111
2023-03-23 22:02:08 +00:00
fauno 6758d7f126 Merge branch 'jekyll-service' into 'rails'
permitir tener sitios duplicados

Closes #6967, #6968, #6970, #6972, #6973, #6974, #6979, #6982, #6966, #6969, #6985, #6990, #6991, #9362, #9364, #9377, #9378, #7611, #7612, #7844, #7845, #8098, #8099, #8674, #8764, #8765, #8888, #9366, #9374, #9375, #9379, #9380, #9376, #9363, #8887, #8690, #8262, #7998, #7807, #7053, and #6984

See merge request sutty/sutty!101
2023-03-23 22:00:05 +00:00
fauno effadafeb8 Merge branch 'issue-9386' into 'rails'
Issue #9386

See merge request sutty/sutty!116
2023-03-23 21:59:05 +00:00
fauno ea774cf097 Merge branch 'issue-9989' into 'rails'
fix: temporalmente deshabilitar el boton #9989

See merge request sutty/sutty!118
2023-03-23 21:57:42 +00:00
fauno 0d4a0e1dc3 Merge branch 'deploy-locales' into 'rails'
vincular a un idioma según el dominio

Closes #4545

See merge request sutty/sutty!76
2023-03-23 21:56:59 +00:00
f f7f16bcaa3 Merge branch 'rails' into deploy-locales 2023-03-23 18:56:34 -03:00
fauno 4aba6379d8 Merge branch 'cleanup' into 'rails'
hacer tareas de limpieza

See merge request sutty/sutty!91
2023-03-23 21:53:31 +00:00
f 180c5ce01a Merge branch 'rails' of 0xacab.org:sutty/sutty into cleanup 2023-03-23 18:53:08 -03:00
fauno cb17c651bc Merge branch 'issue-2466' into 'rails'
Issue #2466

See merge request sutty/sutty!120
2023-03-23 21:51:55 +00:00
fauno 41918bde6a Merge branch 'sites-api' into 'rails'
devolver todos los dominios

See merge request sutty/sutty!80
2023-03-23 21:51:33 +00:00
fauno ab0f8af4ff Merge branch 'issue-10022' into 'rails'
feat: al crear un sitio configurarlo con el idioma de le usuarie #10022

See merge request sutty/sutty!122
2023-03-23 21:50:42 +00:00
fauno cce1b28118 Merge branch 'cambiar-idioma-desde-login' into 'rails'
permitir a les usuaries elegir idioma y registrarse con ese

See merge request sutty/sutty!106
2023-03-23 21:50:07 +00:00
fauno c6e5e6d2b2 Merge branch 'issue-10512' into 'rails'
fix: la tienda se activa luego de crear el sitio #10512

See merge request sutty/sutty!123
2023-03-23 21:49:46 +00:00
f 85bfacb37d Merge branch 'rails' of 0xacab.org:sutty/sutty into distributed-press 2023-03-23 18:49:28 -03:00
f c9fa518b33 fix: el parametro puede venir vacío 2023-03-23 17:53:13 -03:00
f c2fbc06d41 fix: tenemos un lío de singulares y plurales 2023-03-23 17:50:24 -03:00
f df8efe800b fix: no hardcodear roles 2023-03-23 17:41:45 -03:00
f 7a13dffc9b fix: establecer un parámetro por defecto #12754 2023-03-23 17:41:45 -03:00
f d01f4ae5e2 fix: volver a leer el sitio después de guardarlo #12755 2023-03-23 16:53:06 -03:00
f 1bfff4dfdb fix: enviar las invitaciones luego de crear el rol 2023-03-23 16:24:53 -03:00
f 1fa37b20e1 fix: solo invitar una vez 2023-03-23 15:47:06 -03:00
f 732db666c7 fix: usar el último sitio al que todavía no aceptamos invitación 2023-03-23 15:42:20 -03:00
f fce5c0d90b fix: hacer todo en una transacción 2023-03-23 15:38:46 -03:00
f 1ac83140d6 fix: no enviar la invitación hasta último momento 2023-03-23 15:32:54 -03:00
f 98b38e4caa fix: el último ítem es un hash
closes #12747
2023-03-23 15:15:15 -03:00
f 5cda6a440c fix: enviar los argumentos como un hash
closes ##12742

closes ##12740

closes ##12734

closes ##12732

closes ##12725

closes ##12721

closes ##12718

closes ##12715
2023-03-23 14:11:19 -03:00
f 1496a6f04b fix: a veces no se puede deployear nada
closes ##12735

closes ##12733

closes ##12722

closes ##12719

closes ##12716

closes ##10417
2023-03-23 11:59:27 -03:00
f 8fa2991bb1 fix: enviar la invitación luego de crear el rol #12728
de otra forma les usuaries que ya tienen sitios reciben una invitación a
un sitio que no es y les que no tienen sitios no reciben nada porque hay
un error.
2023-03-23 11:44:47 -03:00
f b698a3397c Merge branch 'rails' of 0xacab.org:sutty/sutty into issue-2123 2023-03-23 11:22:11 -03:00
f 0817139032 feat: agregar política de privacidad 2023-03-22 21:12:19 -03:00
f 0263169074 fix: devolver true aunque no haga falta modificar la configuracion 2023-03-22 21:12:19 -03:00
f caa4861d79 fix: poder pasar el slug como parametro
como slug es un atributo privado, hay que asignarlo manualmente
2023-03-22 21:12:19 -03:00
f 136a9e3edb fix: traducir la descripción 2023-03-22 21:12:19 -03:00
f 368001b341 fix: poder encadenar licencias con códigos 2023-03-22 21:12:19 -03:00
f e25b4858a0 fix: no cambiar las licencias si el sitio no las soporta 2023-03-22 21:12:19 -03:00
f 89ef2959e3 feat: usar un slug
sino cuando cambia la licencia queda con la url de la anterior
2023-03-22 21:12:19 -03:00
f 3f3ef00410 fix: solo crear el código de conducta si la plantilla lo soporta
como fallback usamos page
2023-03-22 21:12:19 -03:00
f ddd2bc07ff feat: incorporar los códigos de conducta 2023-03-22 21:12:19 -03:00
f 7b68bc1569 fix: crear las licencias después de crear el título
y los commits también se harían en el idioma de le usuarie
2023-03-22 21:12:18 -03:00
f 0b353466a4 fix: solo cambiar la licencia si existe una #159 2023-03-22 21:12:18 -03:00
f 46c20cae7d feat: no agregar licencia si la plantilla no lo soporta 2023-03-22 21:12:18 -03:00
f abacabff8e fix: agregar licencia con layout 2023-03-22 21:12:18 -03:00
Cat /dev/Nulo 758f9de36d Arreglar scroll al reordenar posts
Utilizaba
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded
que es propietario. Ahora usa scrollIntoView siempre, configurado para que prácticamente siempre se pueda ver el post al reordenar.
2023-03-22 21:12:18 -03:00
f 59606f3263 fix: reducir el alto de la leyenda 2023-03-22 14:38:18 -03:00
f fc14889d0e fix: soporte para urdu 2023-03-22 14:36:17 -03:00
f 6d59d79e2a fix: establecer relación bidireccional #10491 2023-03-22 14:36:17 -03:00
f 034015938b fix: mostrar el idioma si no existe una traducción 2023-03-22 14:14:55 -03:00
f ad1d59d6a4 fix: recuperar el valor 2023-03-22 13:59:08 -03:00
f 88c1ffe4b8 fix: hacer que los locales sean bidireccionales #10491 #12064 2023-03-22 13:59:08 -03:00
Cat /dev/Nulo 823ac94e74 Arreglar scroll al reordenar posts
Utilizaba
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded
que es propietario. Ahora usa scrollIntoView siempre, configurado para que prácticamente siempre se pueda ver el post al reordenar.
2023-03-22 13:59:08 -03:00
f bbb951594b fix: enviar las opciones post limpieza 2023-03-22 09:59:36 -03:00
f 1230dc2e96 fix: solo permitimos un hash de opciones 2023-03-22 09:58:00 -03:00
f 706ff80b18 fix: algo está enviando las opciones como array 2023-03-21 14:05:11 -03:00
f 11e503061c fix: enviar invitación sin link
Usuarie#deliver_invitation además generaba un token cuando no era
necesario y esto es lo que hacía que les usuaries quedaran flotando.
2023-03-20 17:45:08 -03:00
f 362e45b51d fix: efectivamente ignorar mails que ya son usuaries de este sitio 2023-03-20 17:45:08 -03:00
f 92fa2b8932 fix: no llevar registro de quien se conoce con quien
aunque es un poco obvio al mirar la lista de usuaries de un sitio
2023-03-20 17:45:08 -03:00
f 61a23cb3d7 fix: solo enviar invitación si le usuarie no existe 2023-03-20 17:45:08 -03:00
f 7d7fcdc409 fix: recuperar el comportamiento esperado #2123 2023-03-20 17:45:08 -03:00
f d25937f536 fix: no producir type error 2023-03-20 15:33:28 -03:00
f 16ed7db1d7 fix: capturar la excepción #10546 2023-03-20 12:13:51 -03:00
f 5ec698366a fix: capturar standard error 2023-03-20 11:46:21 -03:00
fauno 75c4d3264d Merge branch 'arreglar-scroll' into 'rails'
Arreglar scroll al reordenar posts

See merge request sutty/sutty!96
2023-03-18 22:26:42 +00:00
f 7160cb01df fix: la tienda se activa luego de crear el sitio #10512 2023-03-18 19:22:08 -03:00
f 50f1ce51d9 fix: el locale de los posts es distinto al de le usuarie #10454 2023-03-18 19:14:12 -03:00
f b297800933 fix: volver a fallar si al hacer deploy todavia estan caidos los servicios 2023-03-17 17:44:13 -03:00
f 698b3a0bf6 feat: separar la creación de DP de njalla 2023-03-17 17:39:41 -03:00
f 0c674d6ca1 fix: crear el sitio remoto si no se pudo crear antes 2023-03-17 17:37:48 -03:00
f f2e79a733d fix: no fallar si hay errores remotos
closes #10467

closes #10506

closes #10509
2023-03-17 17:33:52 -03:00
f a2660485b8 fix: poder cambiar el idioma! 2023-03-17 16:03:11 -03:00
f 0910753437 fix: login como botón 2023-03-17 15:53:56 -03:00
f 6887e5319a feat: mantener el idioma de le usuarie en todos los links que envíe devise 2023-03-17 15:52:10 -03:00
f da721ddaaf feat: enviar el idioma en el correo de confirmación 2023-03-17 15:49:26 -03:00
f 5ac72f8b2b feat: soportar varios idiomas 2023-03-17 15:32:56 -03:00
f 2f3a596fa5 feat: cambiar el idioma en toda la sesión 2023-03-17 15:32:46 -03:00
f 13ec35f61b Merge branch 'rails' of 0xacab.org:sutty/sutty into cambiar-idioma-desde-login 2023-03-17 14:59:15 -03:00
f 59bbc04230 fix: actualizar el hash solo cuando se escribir cambios
y devolver el resultado de Site::Writer#save
2023-03-17 14:06:54 -03:00
f 74af751264 feat: al crear un sitio configurarlo con el idioma de le usuarie #10022 2023-03-17 14:06:54 -03:00
f bf45707be4 fix: obtener correctamente los dominios con www #10452 2023-03-16 13:17:39 -03:00
f ebccbc5b46 Merge branch 'rails' of 0xacab.org:sutty/sutty into sites-api 2023-03-16 13:14:21 -03:00
fauno ca989fe8a7 Merge branch 'issue-1849' into 'rails'
feat: leer datos de las plantillas directamente #1849

See merge request sutty/sutty!112
2023-03-16 15:57:51 +00:00
f 2654a5c977 fix: los assets los compila la ci 2023-03-16 12:29:57 -03:00
f ddb4520a86 Merge branch 'rails' of 0xacab.org:sutty/sutty into assets 2023-03-16 12:29:01 -03:00
f a97da5b821 fix: volver a ignorar los secretos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-16 12:22:37 -03:00
f 800386e52c ci: no hacer conflicto con las credenciales de producción
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-16 11:24:38 -03:00
f 4de942a7ca ci: eliminar packs antes de recompilarlos
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-16 10:23:11 -03:00
f b51748ddcb ci: limpiar assets por separado 2023-03-16 10:19:19 -03:00
f c9d7ac437b ci: probar conexión a ssh antes de perder tiempo 2023-03-16 10:19:19 -03:00
f 9773285e9f fix: no duplicar el remote 2023-03-16 10:16:01 -03:00
f 805eb28273 feat: publicar cambios apenas se crea el sitio #2466 2023-03-15 18:23:27 -03:00
f 8b479d1743 refactor: convertir deploy en un servicio 2023-03-15 18:22:20 -03:00
f 08cad58b77 fixup! ci: publicar los assets
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-14 20:29:58 -03:00
fauno 70033d3c17 Merge branch 'issue-9804' into 'rails'
feat: informar la rama actual del repositorio #9804

See merge request sutty/sutty!117
2023-03-14 23:29:02 +00:00
f 723b8e7974 ci: publicar los assets
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-14 20:26:07 -03:00
f 12a85bc585 fix: credentials must be strings 2023-03-14 20:07:12 -03:00
f cacd37348f fix: credenciales de prueba
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-14 19:53:17 -03:00
f 4b575801c5 fix: usar .env 2023-03-14 19:53:17 -03:00
f 77e209ac97 fix: traducir el asunto #9941 2023-03-14 19:23:25 -03:00
f 25e6cd62dd fix: aplicar una master key
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-14 19:20:13 -03:00
f 6d25d71dd1 fix: solo compilar el container cuando cambia 2023-03-14 19:17:16 -03:00
f 0b63ebdd27 chore: yaml 2023-03-14 19:15:26 -03:00
f 1b0c3cb0ac ci: compilar en cambios de javascript tambien
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2023-03-14 19:11:18 -03:00
f bbd19f44ae ci: compilar assets cuando cambian las dependencias 2023-03-14 19:10:59 -03:00
f 51c7c57572 fix: strings #10030 2023-03-14 16:48:44 -03:00
f 222cc8f626 fix: volver a traducir los correos #9941 2023-03-14 16:45:39 -03:00
f 6f363f2c35 fix: params a veces es un array?? 2023-03-14 16:16:46 -03:00
f 5822a9b661 fix: enviar más información con el error
closes #10064

closes #10065

closes #10066

closes #10067

closes #10068

closes #10069

closes #10070

closes #10071

closes #10072

closes #10073

closes #10074

closes #10075

closes #10076

closes #10077

closes #10078

closes #10079

closes #10080

closes #10081

closes #10082

closes #10083

closes #10084

closes #10085

closes #10086

closes #10087

closes #10088

closes #10089

closes #10090

closes #10091

closes #10092

closes #10093

closes #10094

closes #10095

closes #10096

closes #10097

closes #10098

closes #10099

closes #10100

closes #10101

closes #10102

closes #10103

closes #10104

closes #10105

closes #10106

closes #10107

closes #10108

closes #10109

closes #10110

closes #10111

closes #10112

closes #10113

closes #10114

closes #10115

closes #10116

closes #10117

closes #10118

closes #10119

closes #10120

closes #10121

closes #10122

closes #10123

closes #10124

closes #10125

closes #10126

closes #10127

closes #10128

closes #10129

closes #10130

closes #10131

closes #10132

closes #10133

closes #10134

closes #10135

closes #10136

closes #10137

closes #10138

closes #10139

closes #10140

closes #10141

closes #10142

closes #10143

closes #10144

closes #10145

closes #10146

closes #10147

closes #10148

closes #10149

closes #10150

closes #10151

closes #10152

closes #10153

closes #10154

closes #10155

closes #10156

closes #10157

closes #10158

closes #10159

closes #10160

closes #10161

closes #10162

closes #10163

closes #10164

closes #10165

closes #10166

closes #10167

closes #10168

closes #10169

closes #10170

closes #10171

closes #10172

closes #10173

closes #10174

closes #10175

closes #10176

closes #10177

closes #10178

closes #10179

closes #10180

closes #10181

closes #10182

closes #10183

closes #10184

closes #10185

closes #10186

closes #10187

closes #10188

closes #10189

closes #10190

closes #10191

closes #10192

closes #10193

closes #10194

closes #10195

closes #10196

closes #10197

closes #10198

closes #10199

closes #10200

closes #10201

closes #10202

closes #10203

closes #10204

closes #10205

closes #10206

closes #10207

closes #10208

closes #10209

closes #10210

closes #10211

closes #10212

closes #10213

closes #10214

closes #10215

closes #10216

closes #10217

closes #10218

closes #10219

closes #10220

closes #10221

closes #10222

closes #10223

closes #10224

closes #10225

closes #10226

closes #10227

closes #10228

closes #10229

closes #10230

closes #10231

closes #10232

closes #10234

closes #10235

closes #10236

closes #10237

closes #10238

closes #10239

closes #10240

closes #10241

closes #10242

closes #10243

closes #10244
2023-03-14 16:11:04 -03:00
f 07da26b0a4 fixup! fix: retrocompatibilidad 2023-03-14 15:41:28 -03:00
f df48f0cf57 fix: retrocompatibilidad 2023-03-14 15:36:20 -03:00
f b552b0fecd fixup! fixup! fixup! fixup! feat: seccion de log 2023-03-13 20:52:30 -03:00
f d166e669b7 fixup! fixup! fixup! feat: seccion de log 2023-03-13 20:51:28 -03:00
f 5fe0efeccd fixup! fixup! feat: seccion de log 2023-03-13 20:50:14 -03:00
f 3764e14812 fixup! feat: seccion de log 2023-03-13 20:49:00 -03:00
f 347aba6728 feat: seccion de log 2023-03-13 20:47:54 -03:00
f 72f982ee76 fix: no fallar la segunda vez que se reporta el issue 2023-03-13 20:42:40 -03:00
f df3faba784 fix: send sucker punch args 2023-03-13 20:31:59 -03:00
f 8a5ecd98f7 fix: legible data, remove log section 2023-03-13 20:31:16 -03:00
f 6992d16ab0 Merge branch 'issue-10031' into informative-deploys 2023-03-13 20:13:04 -03:00
f 6bac8ed65d fix: agrupar por sitio y enviar el log 2023-03-13 20:11:12 -03:00
f 4604560d51 Merge branch 'issue-10031' into informative-deploys 2023-03-13 20:05:20 -03:00
f a0263ad3fb fix: el log completo hace un título demasiado largo 2023-03-13 20:04:53 -03:00
f 8c5a109610 fix: informar cuando no se puede procesar un issue 2023-03-13 20:04:18 -03:00
f 3a52633ae0 Merge branch 'issue-10031' into informative-deploys 2023-03-13 19:28:07 -03:00
f e0a7232643 fix: notificar las excepciones manualmente
por alguna razón sucker punch dejó de enviarlas!
2023-03-13 19:27:03 -03:00
f efe3474f5f fix: hay deploys sin url 2023-03-13 19:14:36 -03:00
f 87f37ae39e Merge branch 'issue-10031' into informative-deploys 2023-03-13 19:14:30 -03:00
f 1d08b3fdcd fix: llegar hasta el final aunque fallen algunos metodos
al usar ensure en el commit anterior, podemos garantizar que cualquier
excepción en otros deploys no deja la compilación en estado de
compilación permanente, pero no se notifica a les usuaries.
2023-03-13 19:04:55 -03:00
f 955786be0e fix: cancelar la compilación al primer error
Recupera el comportamiento de #1716 #1730 #1735 #1738 #1739 #1740 #1741 #1743 #1744 #1746 #1832 #1952 #2057 #2058 #2059 #2062 #1104 #1124 #1152 #1153 #1154 #1175 #1191 #1230 #1303 #1461 #1478 #1609 #1610 #1667 #504
2023-03-13 18:52:15 -03:00
f 6a7a0dddda fix: no notificar al liberar la tarea 2023-03-13 18:47:53 -03:00
f e62172e37a chore: secar el código
la primera hipótesis sobre #10031 es que las excepciones cancelan la
actualización de la información, como si fueran una transacción, pero
haciendo pruebas manuales no pasa.

con este cambio al menos el código queda más limpio.
2023-03-13 18:47:53 -03:00
f 866b11ff74 fix: poder distinguir entre errores de deploy 2023-03-13 17:29:13 -03:00
f ffce90daf3 wip: no mostrar errores al tener errores de renderización
pero no muestra nada de nada
2023-03-09 15:13:43 -03:00
f a1f09a91e7 Merge branch 'issue-9989' of 0xacab.org:sutty/sutty into issue-9989 2023-03-09 15:13:16 -03:00
f 611a1f0eb0 fix: temporalmente deshabilitar el boton #9989 2023-03-09 15:12:46 -03:00
f d821f14305 fix: temporalmente deshabilitar el boton #9989 2023-03-09 15:08:48 -03:00
f a3c1d7193f fix: requires 2023-02-09 20:11:17 -03:00
f a849eac179 fix: no crear subdominios para dominios personalizados
esto es por retrocompatibilidad para sitios que no usan
DeployAlternativeDomain
2023-02-09 20:08:56 -03:00
f 3f7b2484d0 feat: crear temporalmente los dominios en njalla
el problema es que no podemos delegar `_dnslink.*.sutty.nl` hacia
distributed press, con lo que es necesario crear un subdominio por cada
sitio que lo active.
2023-02-09 20:01:22 -03:00
f e81f188147 fix: no generar links si la url viene vacía 2023-02-08 19:30:05 -03:00
f b091b3212a feat: refactorizar mailer para que use menos recursors
y soporte varias urls
2023-02-08 18:55:05 -03:00
f f15bcf453b Merge branch 'rails' of 0xacab.org:sutty/sutty into informative-deploys 2023-02-08 18:53:39 -03:00
f 7ff284d547 feat: texto para el correo de notificación 2023-02-08 18:52:48 -03:00
f 15e6696bcf feat: un deploy puede tener varias urls 2023-02-08 18:49:37 -03:00
f 89f5ed90eb fix: link a saber más 2023-02-08 17:44:35 -03:00
f ccfd77d956 feat: guardar un log y mostrarlo en output también 2023-02-08 17:08:02 -03:00
f 6683f80aba fix: no fallar si tarda mucho dp 2023-02-08 11:55:07 -03:00
f 9661a34a04 fix: faltaban algunos require 2023-02-08 09:38:36 -03:00
f 464ff4841b feat: textos para el panel 2023-02-07 18:15:25 -03:00
f 8dcc8596e2 feat: informar la rama actual del repositorio #9804 2023-02-07 09:19:38 -03:00
f 75cbed8f6d fix: no eliminar archivos
gem-compiler sabe mejor cuales se pueden eliminar y cuáles no

sutty/gems#3

sutty/gems#1
2023-02-06 16:23:41 -03:00
f a73100a436 fix: pnpm se instala localmente 2023-02-06 16:16:27 -03:00
f 928bc45920 feat: usar pnpm si existe
relacionado con sutty/jekyll/sutty-base-jekyll-theme#53
2023-02-06 16:09:51 -03:00
f de10837ad3 fix: typo 2023-02-03 11:50:09 -03:00
f 28767145a5 feat: habilitar la api pero no el panel
retrocompatibilidad con sitios que llaman a api.sit.io
2023-02-01 17:54:34 -03:00
f 727435569c fix: rehabilitar protección contra dns rebinding
lo habíamos deshabilitado en 2022 sin una explicación real y nos impide
verificar la procedencia de los archivos.
2023-02-01 17:53:13 -03:00
f d095dbcc14 fix: usar HTML5 2023-02-01 17:51:30 -03:00
f 4e4091f6c9 feat: limpieza de estilos
esto permite guardar los nuevos estilos sin permitir otras cosas

sutty/editor!1
2023-02-01 17:13:00 -03:00
f 0781bee40a fix: usar MetadataContent#to_s para procesar los adjuntos 2023-02-01 17:12:27 -03:00
f 04622751ef feat: realiza el paso inverso sutty/editor#59 2023-02-01 17:12:09 -03:00
f 1adfc91a7f feat: convertir urls del panel en urls internas sutty/editor#59 2023-02-01 17:10:47 -03:00
f ecff604c8e fix: eliminar el elemento sin src válido en un solo lugar 2023-02-01 17:09:58 -03:00
f ebf1390bdf fix: actualizar api 2023-01-26 15:41:54 -03:00
f 5611042c58 editor 0.1.14 2023-01-25 13:11:12 -03:00
f 9c5e370d42 feat: mantener data-turbo 2023-01-25 11:49:12 -03:00
f b28d794646 feat: no vamos a expedir tokens efímeros por ahora 2023-01-23 18:39:10 -03:00
f 8006bd0353 fix: permitir modificar el token
estos parches hacian que no se pueda modificar el token
2023-01-20 20:35:39 -03:00
f 932355fa2e feat: crear y publicar el sitio en distributed press v1 2023-01-20 20:34:27 -03:00
f cbf7b58927 fixup! feat: almacenar y renovar tokens de distributed press 2023-01-20 18:28:29 -03:00
f 67c0b29029 feat: almacenar y renovar tokens de distributed press 2023-01-20 18:25:12 -03:00
Maki 5da4c796e0 agrego toggler para distributed press 2023-01-17 18:31:54 -03:00
f 247e069f2b fix: fast_jsonparser 0.6.0 da segfaults #9386 2023-01-12 14:24:21 -03:00
f 2352ce52ec fix: no filtrar la url del panel en sitios proxeados #9386 2023-01-12 13:40:43 -03:00
f 5117ffbce3 fix: siempre devolver la ruta completa
closes #6984

closes #7053

closes #7807

closes #7998

closes #8262

closes #8690

closes #8887

closes #9363

closes #9376
2023-01-11 17:04:22 -03:00
f 53b11cba15 fix: no devolver 'true' si no existe el archivo
closes #9380

closes #9379

closes #9375

closes #9374

closes #9366

closes #8888

closes #8765

closes #8764

closes #8674

closes #8099

closes #8098

closes #7845

closes #7844

closes #7612

closes #7611

closes #9378

closes #9377

closes #9364

closes #9362
2023-01-11 17:03:49 -03:00
f 501091acc5 fix: no eliminar <code> 2023-01-06 12:48:53 -03:00
f e55e981305 fix: no eliminar atributo role
se usan para la accesibilidad de las notas al pie
2023-01-05 13:33:17 -03:00
f aaaa1ad7b2 fix: enviar el período como parámetros del formulario #9359 2023-01-02 17:07:51 -03:00
f f35f4c0f06 fix: cargar jekyll cuando realmente se lo usa 2022-12-30 10:56:00 -03:00
f d896a111b8 fix: no cargar el sitio hasta que no se usen los posts 2022-12-30 10:55:10 -03:00
f 7407e1c06d fix: scrollear al centro vertical 2022-12-29 16:39:45 -03:00
f ba4fca13f4 fix: evitar error de scss 2022-12-29 16:39:34 -03:00
f a265caad97 feat: eliminar archivos que no se usan de las gemas
para liberar espacio
2022-12-29 16:38:17 -03:00
f 4ce0eed173 fix: css del editor 2022-12-29 15:55:36 -03:00
f 33db365597 fix: scrollear las notas al pie al medio 2022-12-29 15:55:08 -03:00
f 3bccc3ad3b fix: editor importable 2022-12-29 15:32:11 -03:00
f 3ec546eb82 fix: dependencias faltantes
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2022-12-29 14:55:30 -03:00
f e260582c26 fix: import 2022-12-29 13:16:37 -03:00
f c9bcf9258c fix: yarn 2022-12-29 12:56:01 -03:00
f 6e16bffd0d Merge branch 'rails' of 0xacab.org:sutty/sutty into usar-sutty-editor 2022-12-29 12:38:33 -03:00
f d71309b309 feat: editor con notas al pie 2022-12-29 12:38:18 -03:00
f 4d4461335a Merge branch 'rails' of 0xacab.org:sutty/sutty into ci
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2022-12-28 16:26:14 -03:00
fauno 9681f15b70 Merge branch 'blazer' into 'rails'
Mostrar estadísticas en el panel de Sutty

Closes #2331, #7530, #7529, #7528, #7527, #7512, #7511, #7510, #7509, #7494, #7493, #7492, #7491, #7408, #7407, #7406, #7405, #7397, #7396, #7395, #7394, #7383, #7382, #7381, #7380, #7170, #7169, #7168, #7167, #7154, #7153, #7152, and #7151

See merge request sutty/sutty!52
2022-12-28 19:25:14 +00:00
fauno cf4c719cdb Merge branch 'deploy-rsync' into 'rails'
hacer deploys remotos

See merge request sutty/sutty!85
2022-12-28 19:23:13 +00:00
f b628badeb5 Merge branch 'rails' of 0xacab.org:sutty/sutty into ci 2022-12-28 15:41:07 -03:00
f e258e6e2d9 fix: asegurarse que las gemas están instaladas 2022-12-27 18:41:36 -03:00
f 47f1a8e530 feat: leer datos de las plantillas directamente #1849
usando el lockfile de cada repositorio, acceder directamente al
directorio de datos usando jekyll-data.
2022-12-27 17:42:00 -03:00
f 072b01e4d9 fix: siempre instalar las gemas localmente 2022-12-27 17:37:47 -03:00
f e6068fa7ec fix: traer gemas del mismo repositorio 2022-12-27 17:36:32 -03:00
f 7e8e47387b feat: eliminar dependencia en plantillas instaladas #1849 2022-12-27 17:35:37 -03:00
f 581e8e10c2 fix: vaciar la imagen al borrarla 2022-11-28 19:31:09 -03:00
f 4fc2ece2d5 fix: permitir borrar la imagen sin vaciar la descripción #8347
sin embargo no estamos pudiendo distinguir entre imagen borrada e imagen
sin subir, con lo que perdimos una verificación
2022-11-28 19:30:20 -03:00
f f393668133 fixup! feat: campos enriquecidos con el nuevo editor 2022-11-28 14:52:25 -03:00
f 48b65c5cb1 feat: campos enriquecidos con el nuevo editor 2022-11-28 13:58:50 -03:00
f d05b93d85e feat: poder modificar la url de distributed press 2022-11-18 15:56:59 -03:00
f d813b250c8 Merge branch 'rails' of 0xacab.org:sutty/sutty into distributed-press 2022-11-18 15:51:50 -03:00
f 5a5d414482 fix: traducción de algunos locales en uso #8427 2022-11-11 19:09:38 -03:00
f b141b09ee4 fix: poder mostrar la vista previa sin errores de liquid
closes #8397

closes #8263

closes #8153
2022-11-09 18:44:27 -03:00
f f582e692ef fix: explicar mejor por qué no es una preview completa #8400 2022-11-09 18:43:55 -03:00
f d8a20be0b6 fix: dar el mismo estilo al editor nuevo 2022-11-09 13:01:12 -03:00
f fd855a1e93 fix: ajustes para el contenido #8395 2022-11-08 20:19:53 -03:00
f b42fa9f736 fix: permitir guardar br sutty/editor#61 2022-11-08 20:19:24 -03:00
f ba39233739 fix: extender clases de bootstrap 2022-11-04 16:58:56 -03:00
f 395e5fa83a feat: distinguir los elementos de una tabla sutty/editor#7 2022-11-04 16:49:37 -03:00
f f6ea00ed30 feat: no sanitizar tablas sutty/editor#7 2022-11-04 16:47:55 -03:00
f 3fd2e1edfc @sutty/editor 1.0.6 2022-11-04 15:40:43 -03:00
fauno 120ff9e114 Merge branch 'borrar-comentario-viejo' into 'rails'
editor: Borrar comentario viejo

See merge request sutty/sutty!95
2022-11-04 17:23:15 +00:00
f 2dc01cef9c fix: actualizar contenedor a alpine 3.14 #8369 2022-11-04 14:13:44 -03:00
f 3d8c9b4031 feat: implementar campo de tipo password #8342 2022-11-01 13:17:03 -03:00
f 6c7ddb082d fix: no guardar el valor en texto plano si estuvo cifrado
cuando un campo está cifrado y no fue modificado, al guardar se guardaba
en texto plano y luego salían errores de decifrado.

closes #1515

closes #1938

closes #1939

closes #1940

closes #1942

closes #1943

closes #1944

closes #8204
2022-11-01 13:08:06 -03:00
f b3a0ae3284 @sutty/editor 0.1.5 2022-10-26 19:13:47 -03:00
f 93dd2e096e @sutty/editor 1.0.4 2022-10-26 18:15:41 -03:00
f 7dd9061f34 fix: no limpiar las clases de css
relacionado con sutty/editor#51

las imágenes sobrepasan el contenedor porque el sanitizador elimina el
atributo class.
2022-10-26 17:42:56 -03:00
f ea392f21ce fix: eliminar x-frame-options de disk controller
relacionado con sutty/editor#59

relacionado con sutty/editor#51

la razón por la que no se pueden incrustar pdfs es que rails agregar
x-frame-options: sameorigin a todas las urls, aunque no es necesario
para los archivos, porque les usuaries no interactuan con ellos para
enviar información de vuelta al panel.
2022-10-26 17:25:58 -03:00
f 94482ef4ee Merge branch 'rails' of 0xacab.org:sutty/sutty into usar-sutty-editor 2022-10-26 17:24:38 -03:00
f fda9047590 Merge branch 'rails' into usar-sutty-editor 2022-10-26 17:24:27 -03:00
f e517ad9f36 fix: @sutty/editor 1.0.3
resuelve errores de usabilidad
2022-10-25 20:13:18 -03:00
f 937e41df9f fix: colocar el menu sobre el editor 2022-10-24 15:16:18 -03:00
f e15191e242 feat: soportar editor prosemirror con ui actual 2022-10-24 14:42:24 -03:00
f f448b4c7ee feat: marcar el editor actual como el antiguo 2022-10-24 14:41:07 -03:00
f 87f638355d permitir atributos de cuidados en links sutty/editor#32 2022-10-22 12:15:06 -03:00
f bed39ab4cf usar @suttyweb/editor 0.1.0 2022-10-21 16:33:40 -03:00
f 8221ae63c8 Revert "usar @suttyweb/editor"
This reverts commit 7e0600779e.
2022-10-21 16:33:10 -03:00
f 5f4b589f4f Revert "Deprecar el editor"
This reverts commit 6467a265d3.
2022-10-21 16:32:09 -03:00
f 6154b36670 Revert "Deprecar el editor incorporado"
This reverts commit c0b5863573.
2022-10-21 16:31:54 -03:00
f 44de522764 soportar distributed press apiv0 #7839 2022-10-05 18:44:23 -03:00
Elihu 3d30f3e1c3 Merge branch 'url-without-trailing-slash' into 'rails'
jekyll no soporta urls con barra al final

See merge request sutty/sutty!94
2022-09-17 14:43:29 +00:00
Elihu 6c8bb30610 Merge branch 'issue-6841' into 'rails'
no fallar si los layouts no tienen traducción #6841

See merge request sutty/sutty!99
2022-09-17 14:17:39 +00:00
f 3595342d3a pry! 2022-09-03 10:51:58 -03:00
f 0afe4b6aba permitir a les usuaries elegir idioma y registrarse con ese 2022-08-27 19:30:52 -03:00
f 2d0090c488 usar el uuid del post para reordenar 2022-08-24 18:00:18 -03:00
fauno b021e93ac9 Merge branch 'issue-7076' into 'rails'
equiparar file con image  #7076

See merge request sutty/sutty!103
2022-08-03 19:52:08 +00:00
f cacb355b62 los deploys pueden no tener destino
closes #7151

closes #7152

closes #7153

closes #7154

closes #7167

closes #7168

closes #7169

closes #7170

closes #7380

closes #7381

closes #7382

closes #7383

closes #7394

closes #7395

closes #7396

closes #7397

closes #7405

closes #7406

closes #7407

closes #7408

closes #7491

closes #7492

closes #7493

closes #7494

closes #7509

closes #7510

closes #7511

closes #7512

closes #7527

closes #7528

closes #7529

closes #7530
2022-08-03 13:24:36 -03:00
f fff679b981 no devolver un destino
closes #7151

closes #7152

closes #7153

closes #7154

closes #7167

closes #7168

closes #7169

closes #7170

closes #7380

closes #7381

closes #7382

closes #7383

closes #7394

closes #7395

closes #7396

closes #7397

closes #7405

closes #7406

closes #7407

closes #7408

closes #7491

closes #7492

closes #7493

closes #7494

closes #7509

closes #7510

closes #7511

closes #7512

closes #7527

closes #7528

closes #7529

closes #7530
2022-08-03 13:23:03 -03:00
f 3e442865ab permitir indexar 2022-08-03 13:11:06 -03:00
f d5f6d3c61b no compartir el uuid del post con su indexación
aunque los uuid son únicos, en el contexto de un sitio los posts son
únicos por cada sitio.  si tenemos sitios duplicados (por ejemplo un
sitio de testing), la indexación funciona pero va moviendo posts de un
panel a otro.

ahora los uuid de cada post se guardan por separado y las indexaciones
tienen sus propios uuids únicos.

por ahora no los estamos usando para nada, pero cuando tengamos
permalinks, los registros van a estar relacionados con sus posts
indexados.
2022-08-03 12:56:39 -03:00
f 64e93506b7 eliminar código que no se usa más 2022-08-03 12:53:50 -03:00
f 70ee313254 tampoco tienen url 2022-07-26 14:50:46 -03:00
f b983353223 log de reindexación 2022-07-26 14:13:54 -03:00
f 0d6a2c020c reindexar los sitios al terminar de compilarlos
para poder soportar modificaciones durante la generación del sitio
2022-07-26 13:49:59 -03:00
f 69712a306e equiparar file con image #7076 2022-07-25 16:01:08 -03:00
f 6c62c20572 subir directamente los archivos a la base de datos
cuando subimos un archivo usando attach en realidad estábamos generando
una copia y dejándola huérfana en el repositorio del sitio.  usando blob
podemos imitar un servicio de subida de archivos sin generar io
innecesario.
2022-07-15 19:32:06 -03:00
f 83384b686a solo copiar el archivo si no existe 2022-07-15 18:22:06 -03:00
f 091ceac788 botón de estadísticas más arriba 2022-07-15 14:17:46 -03:00
f 03d2914ec6 Merge branch 'rails' of 0xacab.org:sutty/sutty into blazer 2022-07-15 14:12:51 -03:00
f 332ae66b8a no juntar estadísticas por mes y año todavía
la forma en que las estamos recopilando es rápida pero no acumulativa,
entonces los números siempre dan mal.
2022-07-15 13:19:08 -03:00
fauno 5458fc6291 Merge branch 'issue-5102' into 'rails'
editor: No reportar error cuando no se selecciona un archivo para subir

Closes #297, #336, #337, #344, #349, #402, #444, #533, #534, #2132, #2147, #2240, #2251, #2254, #2381, #2469, #2926, #2983, #3018, #3130, #3193, #3383, #3425, #3604, #4125, #4127, #4431, #4733, and #5102

See merge request sutty/sutty!102
2022-07-13 21:53:36 +00:00
Cat /dev/Nulo 2a416b4e67 editor: No reportar error cuando no se selecciona un archivo para subir 2022-07-13 21:43:44 +00:00
f 5397ae66a2 informar con mas detalle cuando el archivo no existe
closes #6991

closes #6990

closes #6985

closes #6969

closes #6966
2022-07-13 14:18:39 -03:00
f aab8ed9fed informar cuando el nombre de archivo está vacío 2022-07-13 13:34:45 -03:00
f cd523babad siempre devolver Pathname
closes #6982

closes #6979

closes #6974

closes #6973

closes #6972

closes #6970

closes #6968

closes #6967
2022-07-12 15:58:31 -03:00
f def4402313 permitir cargar archivos con la misma key
podemos tener sitios distintos con la misma llave identificatoria.
ahora permitimos solo una llave por cada sitio distinto.  si subimos un
archivo duplicado en un mismo sitio el error va a seguir siendo el
mismo.
2022-07-12 15:39:42 -03:00
f 0b06bf3541 notificar cuando no se pudo cargar el archivo
no perder información silenciosamente
2022-07-12 15:39:08 -03:00
f 9e531e4995 no cambiar el valor si no se pudo cargar el archivo
esto hace que sutilmente desaparezcan archivos
2022-07-12 15:38:16 -03:00
f f1137c6ed2 error de sintaxis 2022-07-01 15:02:17 -03:00
f e6c03df13f mostrar las estadisticas en el menú 2022-07-01 15:01:57 -03:00
f 655c6b65d5 procesar todas las urls
a veces las urls vienen como arrays, con lo que no hay que procesarlas.
2022-07-01 14:43:30 -03:00
f d18536f587 no generar issues para log 2022-06-29 18:41:51 -03:00
f 24c0161aac no fallar si los layouts no tienen traducción #6841 2022-06-29 18:17:23 -03:00
f a4eef2edc0 notificar correctamente la excepción 2022-06-28 15:07:08 -03:00
f dd34d176ea sincronizar links duros 2022-06-15 13:34:46 -03:00
f 369b0c9937 fixup! comandos correctos 2022-06-11 19:52:38 -03:00
f a0441a858e comandos correctos 2022-06-11 19:51:11 -03:00
f 00f303cf20 procesar las estadísticas automáticamente 2022-06-11 19:42:55 -03:00
f 6f45756e6d mejorar el mensaje de tiempo de compilación 2022-06-11 19:33:21 -03:00
f 4720853019 al recargar la página volver al gráfico 2022-06-11 19:33:02 -03:00
f 844ba75d08 indicar qué significa lo vacío 2022-05-30 15:10:52 -03:00
f 88ecf06f7d Merge branch 'rails' into blazer 2022-05-30 15:07:04 -03:00
f 87c09323dc ignorar posts sin layout pero notificar
closes #5828

closes #3251
2022-05-05 19:37:14 -03:00
Cat /dev/Nulo 6a7511a5e1 Arreglar scroll al reordenar posts
Utilizaba
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded
que es propietario. Ahora usa scrollIntoView siempre, configurado para que prácticamente siempre se pueda ver el post al reordenar.
2022-05-02 18:55:35 +00:00
f 755db601a1 ordenar en la base de datos 2022-05-02 13:41:37 -03:00
f 35d16b1139 fixup! fixup! generar los rollups para los siguientes intervalos 2022-04-30 21:21:58 -03:00
f 8ca5085aae fixup! generar los rollups para los siguientes intervalos 2022-04-30 20:49:03 -03:00
f 62bdfff98c poder ver y filtrar por rangos 2022-04-30 20:42:38 -03:00
f c8ff6de9ae trasladar los parametros a los graficos 2022-04-30 20:42:10 -03:00
f 3f29d87acd las tablas también están filtradas 2022-04-30 20:41:38 -03:00
f 158c224449 generar los rollups para los siguientes intervalos 2022-04-30 20:40:54 -03:00
f 8a3c9a76a7 fixup! fixup! simplificar el código!! 2022-04-30 19:44:02 -03:00
f 6464f35625 fixup! simplificar el código!! 2022-04-30 19:38:32 -03:00
f 26b2d34b4d simplificar el código!!
envía todos los parámetros a la base de datos para acelerar por un
montón la generación de datos
2022-04-30 19:35:14 -03:00
f e8300364d1 pasar todas las uris a la base de datos 2022-04-30 19:11:57 -03:00
f e4009e59dc las tablas con cabeceras sticky usan el color de fondo del theme 2022-04-30 18:42:50 -03:00
f 8244532c5a fixup! ordenar de menor a mayor 2022-04-30 18:30:24 -03:00
f 0969652941 acomodar el valor a la cantidad de nodos
en realidad para estas visitas no tiene mucho sentido y de hecho es en
las que estaríamos perdiendo información, porque nada indica que no
hubo otros países y referencias que quedaron en otros nodos...
2022-04-30 18:22:35 -03:00
f 99e3f093fc ordenar de menor a mayor 2022-04-30 18:20:45 -03:00
f 224e599de2 fixup! mostrar la cantidad de visitas por origen y pais 2022-04-30 18:05:08 -03:00
f e00780c7f0 mostrar la cantidad de visitas por origen y pais 2022-04-30 17:55:53 -03:00
f fb34823ce3 deprecar square_rollup
es muy lento buscar dentro de cada dimensión
2022-04-30 17:51:05 -03:00
f d766ee4eff fixup! agregar la dimensión al agrupar 2022-04-30 16:44:23 -03:00
f 604ee233bd agregar la dimensión al agrupar 2022-04-30 16:38:50 -03:00
f d181c179ff nota 2022-04-30 16:38:32 -03:00
f 756fb8f1cb usar el id del sitio como dimensión 2022-04-30 16:38:16 -03:00
f 92cd2ac052 fixup! fixup! generar estadísticas de uso de infra 2022-04-30 14:48:42 -03:00
f 8d4958af53 fixup! generar estadísticas de uso de infra 2022-04-30 14:44:27 -03:00
f 6bf286077b generar estadísticas de uso de infra 2022-04-30 14:39:31 -03:00
f 001443c1be la última actualización es cuando se cierra el stat 2022-04-30 14:07:34 -03:00
fauno eb1c12e362 Merge branch 'jekyll-service' into 'rails'
Subir imágenes directo a los sitios

Closes #4987, #4986, #4985, #4984, #4983, #4982, #4981, #4980, #4979, #4978, #4977, #4976, #4908, #4907, #4906, #4892, #4891, #4890, #4889, #4888, #4887, #4886, #4885, #4884, #4883, #4882, #4881, #4879, #4877, #4876, #4875, #4836, #4835, #4833, #4794, #4787, #4767, #4759, #4647, #4606, #4603, #4556, #4553, #4265, #4262, #4259, #4256, #4229, #3554, #3551, #3488, #3487, #3486, #3437, #3356, #3353, #3350, #3347, #2922, #2396, #2393, #2373, #2372, #2371, #2370, #2369, #2368, #1842, #1316, #1315, #1768, #1969, #1970, #2295, #2296, #2297, #2702, #2703, #2705, #2706, #2707, #3557, #3558, #3562, #3856, #4946, #5030, #5032, #5033, #5034, #5036, #5038, #5040, #5042, #5045, #5047, #5048, #5050, #5051, #5053, #5054, #5056, #5057, #5058, #5060, #5061, #3550, #3552, #3553, #3555, #4255, #4257, #4258, #4260, #4261, #4263, #4264, #4266, #4766, #4768, #4786, #4788, #4793, and #4795

See merge request sutty/sutty!78
2022-04-30 16:11:57 +00:00
f 2589516b16 fixup! commitear automáticamente los assets 2022-04-30 12:55:51 -03:00
f ef74013fa3 chequear que los assets estén actualizados al actualizar 2022-04-30 12:20:19 -03:00
f 80f135d495 commitear automáticamente los assets 2022-04-30 12:19:51 -03:00
Cat /dev/Nulo 6bbb5b48c0 editor: Borrar comentario viejo
Ahora la blockquote está implementada por https://0xacab.org/sutty/sutty/-/merge_requests/83, está implementada como bloque normal ya que una blockquote puede tener varios blockquotes adentro
2022-04-30 14:56:04 +00:00
f 6699db8380 otra vez el mismo error de hashes acumulados
hice benchmarks, generar hashes nuevos es mas rapido que duplicarlos, y
eliminar las keys que no corresponden es apenas mas rapido pero con mas
posibilidad de bugs
2022-04-30 11:34:21 -03:00
f 1962175cc6 Revert "mostrar demora"
This reverts commit e9d13a7c59.
2022-04-30 10:58:41 -03:00
f e9d13a7c59 mostrar demora 2022-04-30 10:49:32 -03:00
f 80f2df362b precalcular las columnas 2022-04-30 10:24:21 -03:00
f deb3f0f070 usar el último intervalo, no el que acabamos de crear 2022-04-30 10:23:58 -03:00
f ce0d2306f6 fixup! fixup! no se puede renombrar un rollup usando dimensiones exactas 2022-04-30 10:13:49 -03:00
f b36bdc9763 fixup! no se puede renombrar un rollup usando dimensiones exactas 2022-04-30 10:03:14 -03:00
f 121d4f49e2 no se puede renombrar un rollup usando dimensiones exactas
además era un método que hacía dos cosas distintas según un parámetro
2022-04-30 09:56:19 -03:00
f 595a8759a4 usar las uris como fuente de verdad 2022-04-29 20:32:21 -03:00
f 7dad3e9e54 ser más explicitxs 2022-04-29 20:06:07 -03:00
f d56eeb465a comprobar que los idiomas también existan 2022-04-29 18:04:43 -03:00
f 23e2edf259 la validación de directorio pasa por otro lado 2022-04-29 18:01:07 -03:00
f 9998f19087 acumular visitas por país 2022-04-29 17:57:29 -03:00
f cc839affb8 tener en cuenta todos los directorios posibles
por ejemplo DeployLocalizedDomain en la otra rama tiene otras rutas
2022-04-29 17:43:14 -03:00
f 23260791e4 fixup! recolectar información acumulándola 2022-04-29 15:29:27 -03:00
f 957c810aea recolectar información acumulándola 2022-04-29 15:04:42 -03:00
f f4ec30eac7 jekyll no soporta urls con barra al final
y genera un montón de problemas!
2022-04-28 12:06:27 -03:00
f cadb3ad6a6 normalizar unicode en la string 2022-04-28 10:57:28 -03:00
f bfeb513b6b agregar modo de slugificación en el sitio 2022-04-28 10:56:47 -03:00
f eb7d0679bb normalizar strings sin romperlas
en castellano no nos afectó pero en árabe rompe el significado
2022-04-28 10:34:57 -03:00
f 752935afb4 calcular bien la fecha 2022-04-27 13:57:33 -03:00
f 479ca7430f nombre 2022-04-26 18:50:11 -03:00
f 3b19d8f792 actualización diaria 2022-04-26 18:50:00 -03:00
f be6224ddf1 recolectar estadísticas de referers 2022-04-26 16:59:02 -03:00
f 5186892a87 fixup! usar métodos del sitio 2022-04-26 16:57:57 -03:00
f a703eb4096 no fallar si el sitio no existe 2022-04-26 16:57:16 -03:00
f 7e575372cf parametros por defecto 2022-04-26 16:56:45 -03:00
f 0754e29a5a cada sitio tiene su propio control de estadísticas 2022-04-26 16:56:25 -03:00
f 027d24d66a memoizar el sitio 2022-04-26 16:55:54 -03:00
f 3a32422e26 usar métodos del sitio 2022-04-26 16:54:04 -03:00
f 7c7ae2f750 mostrar un período por defecto
todavía no hay interfaz para cambiarlos
2022-04-26 16:53:38 -03:00
f f72d27c308 optimización: usar las dimensiones como índices y no como texto
`Rollup#where_dimensions` no aprovecha los índices.
2022-04-26 16:49:26 -03:00
f fb5cc0aaa7 breadcrumbs 2022-04-26 16:48:25 -03:00
f 298fd5bed1 centralizar la forma en que se obtienen los hostnames
relacionado con !50
2022-04-26 16:46:48 -03:00
f 47a74b5848 fixup! refactorizar rollups recursivos 2022-04-23 20:33:58 -03:00
f c09df3b87b registrar el tiempo que pasó 2022-04-23 20:33:02 -03:00
f aad5c82cb7 refactorizar rollups recursivos 2022-04-23 20:32:20 -03:00
f 6b191d2d91 usar la misma optimización para stats 2022-04-23 19:37:08 -03:00
f d8060728be mantener el día anterior completo en la base de datos 2022-04-23 19:32:55 -03:00
f 7cbc48d45b actualizar todo el intervalo 2022-04-23 19:24:06 -03:00
f f94ece78cf optimizar sql usando indices 2022-04-23 19:06:17 -03:00
f 0c34613cb5 encontrar todos los idiomas 2022-04-23 18:56:34 -03:00
f bfdd90088f permisos 2022-04-23 18:29:18 -03:00
f 3edf45e27f fixup! usar fork por ahora 2022-04-23 18:04:51 -03:00
f 0cd71ad779 eliminar blazer de las rutas por sitio 2022-04-23 17:55:09 -03:00
f 83b9325d0c grabar la duración 2022-04-23 17:50:36 -03:00
f f96c7aff7d volcar y eliminar los logs del día anterior 2022-04-23 16:28:32 -03:00
f cd1263a672 usar fork por ahora 2022-04-23 15:46:24 -03:00
f ef32a6d7f6 schema 2022-04-23 15:30:03 -03:00
f 9b2194ee95 detener la tarea 2022-04-23 15:24:06 -03:00
f 22742cf058 migraciones faltantes 2022-04-23 15:06:55 -03:00
f 30861d240e aplicar la operación! 2022-04-23 15:06:17 -03:00
f ed3f153919 es una tarea periódica 2022-04-23 15:06:00 -03:00
fauno d869b99baa Merge branch 'csp-reports' into 'rails'
no generar errores si se envía el reporte incompleto

Closes #5136

See merge request sutty/sutty!92
2022-04-20 12:43:08 +00:00
f 52f446fcf1 refactorizacion 2022-04-19 10:57:01 -03:00
f 13561a5f71 no generar errores si se envía el reporte incompleto
closes #5136
2022-04-19 10:07:10 -03:00
f f2eea5fbcb no fallar al cerrarse la salida 2022-04-18 17:27:43 -03:00
f 3b616198ea realizar la limpieza mensualmente 2022-04-15 10:57:51 -03:00
f 170cbeb69e poder hacer limpieza desde la terminal 2022-04-15 10:41:53 -03:00
f 9fefc0f554 abl 2022-04-15 10:41:22 -03:00
f 1e0fb95825 correr la recolección de basura de git 2022-04-15 10:40:18 -03:00
f 78c0bdcc39 cada deploy puede ejecutar tareas de limpieza
pero la mayoría no lo va a necesitar
2022-04-15 10:39:44 -03:00
f 30ddcca4a8 enviar cambios 2022-04-14 18:30:34 -03:00
f 1e0642c45b unificar ota de js 2022-04-14 18:28:32 -03:00
f d9e2291f26 usar argumentos 2022-04-13 16:44:52 -03:00
f 244a8de406 ramas que provocan deploys 2022-04-13 12:37:13 -03:00
f d9a5f7ff23 actualizar pandoc 2022-04-13 12:34:42 -03:00
f dd32a5a0c1 woodpecker 2022-04-13 12:31:36 -03:00
f c021cf0e0e actualizar jekyll-images
produce una excepcion
2022-04-11 15:25:07 -03:00
f 02d72f4227 rubocop 2022-04-11 14:57:28 -03:00
f f9e0ad698b reemplazar todos los elementos que traen archivos de public/ 2022-04-11 14:56:58 -03:00
f 30398a8982 incorporar assets en el repositorio
usando lfs.  esto nos permite hacer deploys con `git pull`
2022-04-11 14:18:29 -03:00
f 026b3879e3 resolver la ruta real
para que en el contenedor los sitios y deploys estén en el mismo sistema
de archivos los colocamos en el mismo volumen `data` y los vinculamos a
la raíz del proyecto.

esto es configurable para los sitios pero no para los deploys.

algunas verificaciones de seguridad de jekyll resuelven las rutas reales
(`realpath`) de los archivos y fallan porque convierte en el symlink en
la ruta real.

esto rompe cosas como la previsualización de artículos.

closes #5140

closes #5122

closes #5121

closes #5086

closes #4958
2022-04-11 13:29:42 -03:00
f 106029b48f header 2022-04-07 13:34:12 -03:00
f bb7c50e24b calcular el espacio una sola vez 2022-04-06 20:54:35 -03:00
f ea25d27f24 calcular el tamaño a partir de deploy local 2022-04-06 20:53:45 -03:00
f ef2589a4f1 no es necesario traer el tamaño de los build_stats 2022-04-06 20:51:45 -03:00
f 9024a13490 algunos deploys no generan build_stats 2022-04-06 20:48:14 -03:00
f 35e41b729a el espacio ocupado es el mismo que el local 2022-04-06 20:44:46 -03:00
f 9286670424 mostrar espacio utilizado 2022-04-06 20:42:40 -03:00
f 8c9bd6aa88 por ahora no es configurable 2022-04-06 20:31:49 -03:00
f c47b4f179c fixup! enviar más información 2022-04-06 20:16:31 -03:00
f 87cdba9bec enviar más información 2022-04-06 20:07:14 -03:00
f f51c051af8 mensajes 2022-04-06 19:35:35 -03:00
f aa0c359554 crear un rsync por cada sitio existente 2022-04-06 19:06:11 -03:00
f a0134cc052 ya existe un lugar donde guardar la configuración 2022-04-06 19:05:50 -03:00
f 10d950689b crear rsyncs al crear el sitio 2022-04-06 18:39:52 -03:00
f a5e90257a3 generar un deploy rsync para el sitio con todos los nodos 2022-04-06 18:38:03 -03:00
f 20915443d8 deprecar las flags por ahora 2022-04-06 18:27:58 -03:00
f 5fac827ca0 registrar los cambios 2022-04-06 18:27:15 -03:00
f dcbd1c02ac el método es público 2022-04-06 18:26:41 -03:00
f 8edc9b460a obtener listado de nodos de un lugar central 2022-04-06 18:17:55 -03:00
f c49c63f776 timeout de rsync 2022-04-06 18:11:21 -03:00
f ea198f185b bajar el timeout para no bloquear el deploy 2022-04-06 18:07:45 -03:00
f 6fcdeb52f3 entorno 2022-04-06 17:23:42 -03:00
f f10b65173a fixup! hacer deploys remotos 2022-04-06 17:05:51 -03:00
f accb559f01 hacer deploys remotos 2022-04-06 16:39:56 -03:00
f 6ce0cb2c41 descartar el deploy si el sitio no existe 2022-04-05 16:25:47 -03:00
f 4d6a26d671 normalizar todos los nombres de archivos subidos 2022-04-04 14:32:58 -03:00
f 30bc14d83e normalizar los nombres de archivo enviados por subida directa 2022-04-04 14:27:00 -03:00
f 455070f2ea normalizar todas las strings
convierte la codificación de windows/osx en unicode normalizado.
2022-04-04 13:56:40 -03:00
fauno 9dee10bcb9 Merge branch 'editor-blockquote' into 'rails'
Agregar citas al editor

See merge request sutty/sutty!83
2022-04-02 14:40:00 +00:00
Cat /dev/Nulo b4532e94ca Agregar citas al editor 2022-04-02 14:34:12 +00:00
f ecb823f407 al migrar un archivo reutilizar la key 2022-03-23 11:37:00 -03:00
f c5896a63cf resiliencia
closes #5061

closes #5060

closes #5058

closes #5057

closes #5056

closes #5054

closes #5053

closes #5051

closes #5050

closes #5048

closes #5047

closes #5045

closes #5042

closes #5040

closes #5038

closes #5036

closes #5034

closes #5033

closes #5032

closes #5030

closes #4946

closes #3856

closes #3562

closes #3558

closes #3557

closes #2707

closes #2706

closes #2705

closes #2703

closes #2702

closes #2297

closes #2296

closes #2295

closes #1970

closes #1969

closes #1768
2022-03-22 20:22:39 -03:00
f 263394baef no fallar al serializar Site#everything_of
el problema era que los archivos subidos no se pueden marshalear y
estamos usando MetadataTemplate#values para poder cachearlos.

closes #1315

closes #1316

closes #1842

closes #2368

closes #2369

closes #2370

closes #2371

closes #2372

closes #2373

closes #2393

closes #2396

closes #2922

closes #3347

closes #3350

closes #3353

closes #3356

closes #3437

closes #3486

closes #3487

closes #3488

closes #3551

closes #3554

closes #4229

closes #4256

closes #4259

closes #4262

closes #4265

closes #4553

closes #4556

closes #4603

closes #4606

closes #4647

closes #4759

closes #4767

closes #4787

closes #4794

closes #4833

closes #4835

closes #4836

closes #4875

closes #4876

closes #4877

closes #4879

closes #4881

closes #4882

closes #4883

closes #4884

closes #4885

closes #4886

closes #4887

closes #4888

closes #4889

closes #4890

closes #4891

closes #4892

closes #4906

closes #4907

closes #4908

closes #4976

closes #4977

closes #4978

closes #4979

closes #4980

closes #4981

closes #4982

closes #4983

closes #4984

closes #4985

closes #4986

closes #4987
2022-03-18 15:43:39 -03:00
f 1071eba200 implementar la misma api en todos los deploys 2022-03-16 18:19:04 -03:00
f 3160b30dec eliminar atributo style del editor 2022-03-16 17:49:28 -03:00
f f3c3da81e0 poder ver la salida si lo ejecutamos desde la terminal 2022-03-15 16:03:16 -03:00
f 8e89643bdb leer la salida por separado para no bloquear el programa 2022-03-14 13:40:17 -03:00
f ef00ce4d12 poder ver la salida opcionalmente 2022-03-14 13:39:54 -03:00
f d4d1acc8d9 retrocompatibilidad
los archivos subidos como archivos locales ya estaban copiados al sitio
2022-03-09 19:32:53 -03:00
f d18293bea3 Merge branch 'docker' into rails 2022-03-09 14:20:26 -03:00
f c63ad496d8 ota con el nuevo container 2022-03-09 14:19:50 -03:00
f 6801d5655b mejorar estilo 2022-03-08 21:56:41 -03:00
f 437d5ff230 etiquetas 2022-03-08 21:54:25 -03:00
f d7f9f0c9b1 devolver todos los dominios 2022-03-08 15:10:03 -03:00
f 79974b7104 validar imágenes 2022-03-08 13:21:13 -03:00
f 7de96a4581 usar la ruta absoluta también
en producción usamos links simbólicos entre directorios y sin resolver
la ubicación real de los sitios estábamos generando rutas erróneas.
2022-03-08 13:10:34 -03:00
f a4eade946f Merge branch 'rails' into jekyll-service 2022-03-08 13:05:56 -03:00
f 81cbafef66 validaciones 2022-03-07 20:52:33 -03:00
fauno daa7684fdd Merge branch 'docker' into 'rails'
reutilizar contenedores

See merge request sutty/sutty!79
2022-03-07 22:40:15 +00:00
f 9a68d80675 simplificar
el contenedor solo se encarga de las dependencias, el panel se deployea
aparte.
2022-03-07 19:37:05 -03:00
f 07546bafb2 reutilizar contenedores 2022-03-07 12:49:49 -03:00
f 507e7ced84 Merge branch 'rails' into blazer 2022-03-07 12:27:53 -03:00
f c9edc86be3 copiar una tabla desde producción a desarrollo 2022-03-07 11:48:46 -03:00
f 87c94e9548 mostrar el html 2022-03-07 11:47:37 -03:00
f f7d8a3ecf9 fixup! obtener el nombre de archivo desde la key 2022-03-06 17:07:37 -03:00
f 6c9288b03b deprecar la migración de archivos estáticos
siempre fue super lenta y falible
2022-03-06 16:01:16 -03:00
f 61622a4c41 documentación 2022-03-06 16:00:21 -03:00
f 211fb308e3 asignar archivos subidos desde el editor al sitio 2022-03-06 15:59:57 -03:00
f c13c021fe9 asignar el nombre de archivo en la subida directa 2022-03-06 15:28:25 -03:00
f 85cab49208 subir los archivos desde el editor al sitio 2022-03-06 15:27:53 -03:00
f bfb8e95599 obtener el nombre de archivo desde la key
esto agrega una query pero permite no tener que agregar una ruta falsa
2022-03-06 12:51:06 -03:00
f 10eef47ce8 todos los archivos subidos se asocian al sitio 2022-03-05 20:09:37 -03:00
f 7f6063475b método genérico para instanciar el servicio 2022-03-05 20:09:09 -03:00
f 15e978c877 eran clases 2022-03-05 20:08:55 -03:00
f 69e7df4c31 instanciar JekyllService para cada sitio 2022-03-04 19:26:56 -03:00
f 02b52b23b9 compartir el nombre de archivo con JekyllService 2022-03-04 19:24:04 -03:00
f f3df550494 no permitir subir imágenes que no son para web 2022-03-04 19:21:48 -03:00
f fdbe724f7c asociar el archivo subido al post 2022-03-04 19:21:26 -03:00
f 03d9913f58 obtener el archivo subido 2022-03-04 19:21:03 -03:00
f 37deb36178 conseguir la ruta al archivo 2022-03-04 19:19:40 -03:00
f 63f8b869eb fixup! cargar decorators 2022-03-04 19:17:03 -03:00
f d8fd25a7cb chequear la descripción 2022-03-04 19:16:36 -03:00
f 3d5267451e eliminar código que ya no se usa 2022-03-04 19:15:38 -03:00
f c4139c4b92 eliminar código que no se usa 2022-03-04 19:12:06 -03:00
f 873f2c7bcb informar cuando no se pudo cargar el archivo 2022-03-04 19:11:25 -03:00
f 3de1228c26 implementa un servicio de carga de archivos en jekyll 2022-03-04 19:08:09 -03:00
f 29950e4380 cargar decorators 2022-03-04 19:05:11 -03:00
f 460635e940 ya no hace falta analizar archivos en primer plano 2022-03-04 19:03:02 -03:00
f 38c34f7b4f usar la dirección desde el sitio 2022-03-02 14:01:17 -03:00
f b54a8280a5 soportar más idiomas 2022-03-02 13:56:19 -03:00
f 53ce970bb0 no intentar descargar el mapa 2022-02-11 13:57:53 -03:00
f 05fba76ab8 usar mosaicos en lugar de svg 2022-02-10 19:00:25 -03:00
f 958306ce06 expedir certificados para los dominios localizados 2022-02-10 15:26:20 -03:00
f aa3cbc209e vincular a un idioma según el dominio
closes #4545
2022-02-10 15:18:49 -03:00
f c5c96c8f3c ajustar al contenido 2022-02-01 18:28:27 -03:00
f c68508f89a usar el sistema de coordenadas simplificado 2022-02-01 18:21:32 -03:00
f cf5341eec4 usar el tamaño del svg 2022-02-01 18:20:19 -03:00
f 417559399a traer archivos subidos localmente 2022-02-01 17:52:40 -03:00
f c77fb50366 obtener el overlay antes que nada 2022-02-01 17:38:29 -03:00
f a664c2dcd3 mapa no geografico 2022-02-01 17:11:00 -03:00
f e9c338a8b9 no setear un permalink por defecto
es algo que quisiéramos retomar pero la implementación actual depende de
los mecanismos internos de jekyll, que son problemáticos porque espera
que se seteen algunos valores antes de poder usarlo.  de lo contrario el
permalink termina siendo /, haciendo conflicto con la portada del sitio.

hasta que lo podamos resolver, lo dejamos vacío.

closes #3635
2021-12-27 11:25:24 -03:00
f d70ce8efdb no instalar las gemas de desarrollo 2021-12-24 10:19:18 -03:00
f 8fc7051588 limpiar gemas al terminar de instalar 2021-12-24 10:09:20 -03:00
f 36cf199548 devolver una string 2021-12-23 22:47:15 -03:00
f 4e461e7af6 usar una caché común para yarn 2021-12-09 10:42:03 -03:00
f 380d80ded4 solo instalar paquetes de producción
closes #3892
2021-12-06 14:55:46 -03:00
f d3ed9bff7b Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-11-30 14:20:04 -03:00
fauno 6c9dad7b23 Merge branch 'editor-click-para-subir' into 'rails'
Permitir clickear en el párrafo de ejemplo para subir multimedia

Closes #3439

See merge request sutty/sutty!71
2021-11-30 17:06:20 +00:00
Cat /dev/Nulo f2a0654ebc Permitir clickear en el párrafo de ejemplo para subir multimedia 2021-11-30 16:45:19 +00:00
fauno 7b9323d69b Merge branch 'hainish-env-file' into 'rails'
Makefile: setear ENV_FILE en hain

See merge request sutty/sutty!68
2021-11-30 15:16:20 +00:00
f edcb7c9554 Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-11-30 09:33:35 -03:00
f 1fa97854a6 actualizar mobility para recuperar performance 2021-11-29 11:30:55 -03:00
f d85f21c3ca actualización de cuidados 2021-11-25 09:42:58 -03:00
f da5f7e959e Merge branch 'rails' into actualizacion-de-cuidados 2021-11-24 21:02:11 -03:00
Maki e9a9ec0364 Merge branch 'shorter-description' into 'rails'
permitir descripciones mas cortas

See merge request sutty/sutty!70
2021-11-08 10:27:33 +00:00
f 6dcbe97ac6 permalinks relativos 2021-11-04 10:58:49 -03:00
f 66ec526937 permitir descripciones mas cortas 2021-11-04 10:42:57 -03:00
fauno 385d943a2c Merge branch 'arreglar-editor-oscuro' into 'rails'
Editor: forzar modo claro

Closes #2135

See merge request sutty/sutty!69
2021-10-30 13:22:25 +00:00
Cat /dev/Nulo 21f650fc57 Editor: forzar modo claro
Esto hace que sea legible y más usable cuando el modo oscuro está
activado. https://0xacab.org/sutty/sutty/-/issues/2135

Idealmente, me gustaría tener modo oscuro real en el editor.
2021-10-28 16:15:33 -03:00
Cat /dev/Nulo 2844ca9f5f .env.example: setear RAILS_ENV=development 2021-10-28 16:06:31 -03:00
Cat /dev/Nulo 09f5583d31 Makefile: setear ENV_FILE en hain
Requiere de https://0xacab.org/sutty/haini.sh/-/merge_requests/33. Pasa
RAILS_GROUPS y otras variables.
2021-10-28 15:32:13 -03:00
Maki cebee29ac4 Merge branch 'permalinks-estaticos' into 'rails'
guardar y mostrar la url actual en el campo permalink

See merge request sutty/sutty!60
2021-10-28 16:22:53 +00:00
Maki f0613aef25 Merge branch 'rollups' into 'rails'
Estadísticas

Closes #3228

See merge request sutty/sutty!61
2021-10-28 16:22:02 +00:00
fauno 58bb42e532 Merge branch 'reorder-with-locale' into 'rails'
enviar el idioma al reordenar!

See merge request sutty/sutty!67
2021-10-27 19:35:20 +00:00
f 25fe41bfa2 enviar el idioma al reordenar!
los tests envían el idioma pero no el panel
2021-10-27 10:12:28 -03:00
fauno ad27a938f9 Merge branch 'assets' into 'rails'
no instalar las gemas de assets en producción

See merge request sutty/sutty!64
2021-10-26 19:24:02 +00:00
f 7a780188e4 asegurarse que siempre buscamos assets 2021-10-26 16:19:42 -03:00
f c84462c4a8 recolectar estadísticas usando menos recursos 2021-10-26 11:33:15 -03:00
f ab004fae70 decodificar las urls para poder buscarlas en el log 2021-10-22 18:21:47 -03:00
f 449829ff09 Merge branch 'rails' into rollups 2021-10-22 18:02:34 -03:00
Maki 05edb296d0 Merge branch 'change-licencias' into 'rails'
ignorar los cambios de licencia en idiomas no soportados

See merge request sutty/sutty!65
2021-10-22 20:55:58 +00:00
f 21bf478af7 actualizacion de cuidados 2021-10-22 17:36:00 -03:00
f 443950819f Merge branch 'rails' into actualizacion-de-cuidados 2021-10-22 17:34:15 -03:00
f 84e543ac07 ignorar los cambios de licencia en idiomas no soportados 2021-10-22 17:13:26 -03:00
f 8bebe155f4 no hace falta subir los parches dos veces 2021-10-22 17:06:34 -03:00
f 570761fab5 actualizar contenedor con una versión específica de bundler 2021-10-21 20:55:40 -03:00
f 084bf8547f ya no es necesario hacer limpieza en docker 2021-10-21 20:54:50 -03:00
f fd784919df rails ya corre yarn antes de compilar 2021-10-21 20:54:12 -03:00
f 7227ecfe2a solo instalar las gemas de assets en desarrollo 2021-10-21 20:53:25 -03:00
f 4456deff9c usar la traducción del idioma que viene del sitio 2021-10-21 15:02:07 -03:00
f 5d40907199 Merge branch 'rails' into rollups 2021-10-21 14:46:57 -03:00
f 9c4a0a86f3 deshabilitar el paginado temporalmente
no permite mover posts entre paginas!
2021-10-21 14:40:55 -03:00
f 69ef571bdb garantizar que sea una hash de simbolos 2021-10-21 14:25:05 -03:00
f 883182ffe2 rutas más específicas 2021-10-21 13:45:34 -03:00
f e3d2213afc especificar el idioma de un post nuevo 2021-10-21 13:44:34 -03:00
f 3335d0d9eb usar una guard como sugiere rubocop 2021-10-21 13:25:05 -03:00
f 6349fd7b40 los url helpers necesitan hashes o params
y params.to_h devuelve un hashwithindifferentaccess, lo que rompia las
urls con locale
2021-10-21 13:23:35 -03:00
f 08e0a0ca9d traducir correctamente 2021-10-21 10:49:02 -03:00
f d67d43ff1e hacer más claro el código 2021-10-21 10:48:34 -03:00
f 090b630525 la lógica estaba invertida y los valores nunca llegaban al archivo 2021-10-21 10:47:32 -03:00
f 7e16962041 no fallar si no hay stat
closes #3228
2021-10-20 18:48:30 -03:00
f 07e5baa378 Merge branch 'rails' into rollups 2021-10-20 16:29:45 -03:00
f ba7d0c2e00 Merge branch 'paginacion' into rails 2021-10-20 16:29:25 -03:00
f b7c2061f80 Merge branch 'rails' into rollups 2021-10-20 13:32:13 -03:00
f 8d38d0d2ae recolección de estadísticas con mejor performance 2021-10-20 13:14:19 -03:00
f 9cf7c62861 procesar uris a demanda 2021-10-20 13:08:21 -03:00
f 849ee4491c instalar las librerías en producción 2021-10-20 12:58:51 -03:00
f 1497113f73 usar menos intervalos
las horas y semanas generan demasiados rollups
2021-10-20 12:58:19 -03:00
f cc3535097e todavía no empezar la recolección automática 2021-10-20 12:57:11 -03:00
f 245973b519 no fallar si todavía no hay stats 2021-10-20 12:56:37 -03:00
f d06edc2f62 usar rollups desde git para poder hacer un rollup recursivo 2021-10-20 12:52:31 -03:00
f aa86ead112 ruboyuta 2021-10-09 18:29:53 -03:00
f 356db85465 empezar a recolectar estadísticas cuando se inicia el panel 2021-10-09 18:28:38 -03:00
f ec775847b9 sugerir algunas URLs 2021-10-09 18:27:42 -03:00
f 810f71e9c1 contar por qué mostramos los recursos usados 2021-10-09 18:25:43 -03:00
f fd2e2509d0 sin comillas 2021-10-09 17:29:09 -03:00
f 5dad13bc3c más espacio entre los gráficos 2021-10-09 17:28:56 -03:00
f 7ab2ec5933 no fallar si el intervalo está vacío 2021-10-09 17:28:26 -03:00
f 6c485e5e18 obtener estadísticas de cualquier link 2021-10-09 17:27:45 -03:00
f 5ca8e3c923 usar guards 2021-10-09 15:52:18 -03:00
f f36ea9629d centralizar valores 2021-10-09 15:50:38 -03:00
f c927a56bef ejecutar una vez por hora exacto 2021-10-09 15:47:42 -03:00
f 11568e6ce8 no distinguir entre todas las uris
para poder buscar descargas de archivos binarios después
2021-10-09 15:36:14 -03:00
f e35cbe79eb recolectar visitas a páginas 2021-10-09 14:46:58 -03:00
f 306d1ed983 recolectar estadísticas una vez por hora 2021-10-09 14:45:34 -03:00
f 0342455955 encontrar páginas y distinguir si fueron cyborgs o no 2021-10-08 18:42:34 -03:00
f 51c2fdf6d6 fixup! fixup! mostrar gráficos de recursos utilizados 2021-10-08 18:41:07 -03:00
f 86f1ac4504 fixup! mostrar gráficos de recursos utilizados 2021-10-08 18:40:52 -03:00
f 833213ec80 agregar opciones a cada recurso 2021-10-08 18:40:16 -03:00
f 224ea1ebc5 mostrar gráficos de recursos utilizados 2021-10-08 18:39:55 -03:00
f 8e9401036c cachear los resultados hasta la próxima actualización 2021-10-08 18:38:02 -03:00
f ef0055db05 agrupar por año 2021-10-08 18:36:31 -03:00
f d2b1220df6 informar cuando no hay datos 2021-10-08 18:35:40 -03:00
f 38090d7de7 resaltar el intervalo seleccionado 2021-10-08 18:34:16 -03:00
f cfb2d7a61d todas las peticiones necesitan une usuarie 2021-10-08 18:33:31 -03:00
f a2e4e0ab89 informar hace cuánto se actualizaron los datos 2021-10-08 18:32:35 -03:00
f df2b66afe8 llevar el registro de las recolecciones de estadísticas 2021-10-08 18:21:09 -03:00
f a7ae7f8e8d ver cantidad de visitas 2021-10-08 16:31:02 -03:00
f 930f88903e instalar chartkick para generar gráficos 2021-10-07 15:24:21 -03:00
f 56cb11dc49 Merge branch 'predefined-value' into rails 2021-10-05 09:49:19 -03:00
Maki 42896a5f33 Merge branch 'uniqueness' into 'rails'
Agregar índices únicos que pensábamos que teníamos

See merge request sutty/sutty!59
2021-10-04 17:53:29 +00:00
Maki f8b1752c04 cambio texto cerrar sesion #2896 2021-10-04 14:49:14 -03:00
f 662b5eeec4 guardar y mostrar la url actual en el campo permalink 2021-10-04 14:48:19 -03:00
f 5c2e5fd62e Agregar índices únicos que pensábamos que teníamos
`unique: true` es un parámetro de `add_index` no de `add_column`.
2021-09-26 19:29:03 -03:00
f 0dece732aa Al buscar eliminar la paginación 2021-09-15 21:03:28 -03:00
f f90c92dc26 Poder navegar páginas en la lista de artículos 2021-09-15 21:03:07 -03:00
f 8e1f5c5558 Paginación 2021-09-15 21:02:09 -03:00
f 859b8518c0 Mostrar el tipo de artículo 2021-09-15 21:00:48 -03:00
f 5a324ae71f No cortar las columnas 2021-09-15 21:00:10 -03:00
f c601845a27 Garantizar que todas las lecturas se hacen dentro del directorio del sitio
fixes ##2667

fixes ##2655

fixes ##2640

fixes #2675

fixes #2653

fixes #2635

fixes #2624

fixes #2626

fixes #2627

fixes #2629

fixes #2634

fixes #2636

fixes #2637

fixes #2641

fixes #2642

fixes #2643

fixes #2644

fixes #2645

fixes #2646

fixes #2648

fixes #2649

fixes #2650

fixes #2651

fixes #2654

fixes #2657

fixes #2672

fixes #2676

fixes #2677

fixes #2678

fixes #2681

fixes #2682

fixes #2687

fixes #2688

fixes #2689

fixes #2691

fixes #2692

fixes #2693
2021-09-15 19:54:27 -03:00
f ed213cda9f Actualización de cuidados 2021-09-11 20:17:35 -03:00
f a4ca89a36b @suttyweb/editor@0.0.8 2021-09-11 20:07:51 -03:00
f 47096f20b7 Traducción de valores vacíos 2021-09-11 19:43:27 -03:00
f a242ceee68 Siempre guardar el valor de los campos booleanos 2021-09-11 17:26:44 -03:00
f 9b8c09cb00 Soportar campos númericos con decimales 2021-09-11 17:06:27 -03:00
f 1623ab73de Soportar un campo con una lista de valores predefinidos y elegir uno 2021-09-11 17:00:28 -03:00
f 4e4b5888a3 Peticiones completas 2021-09-03 15:55:30 -03:00
f 016da28529 Inflexiones para Rollup 2021-09-03 15:53:45 -03:00
f 604c16bfb8 Agregar created_at a access_logs para poder agrupar por fecha 2021-09-03 15:28:45 -03:00
f 094a8092de Agregar rollups 2021-09-03 15:25:41 -03:00
f be549c5cd5 ruby 2.7.4 2021-08-28 13:02:12 -03:00
f 9ccc1be898 actualización de cuidados 2021-08-28 12:56:04 -03:00
Maki c1a9aaa037 Merge branch 'only-urls-allowed' into 'rails'
Solo permitir URLs web al sanitizar

Closes #2382

See merge request sutty/sutty!54
2021-08-16 15:36:30 +00:00
f 0bd8a2243e Solo permitir URLs web al sanitizar
fixes #2382
2021-08-11 10:25:05 -03:00
f c0b5863573 Deprecar el editor incorporado 2021-08-10 18:38:33 -03:00
f 6467a265d3 Deprecar el editor 2021-08-10 18:36:55 -03:00
Maki 752569c8a7 Merge branch 'hotfix-yarn-lock' into 'rails'
Soportar sitios sin yarn.lock

See merge request sutty/sutty!53
2021-08-09 14:39:30 +00:00
f 9f84c14a69 Soportar sitios sin yarn.lock
Como el chequeo devuelve nil, un sitio sin yarn.lock nunca se
compilaría.
2021-08-07 15:55:00 -03:00
f 5885dd7e96 fixup! No enviar URLs en los chequeos. 2021-08-06 17:47:27 -03:00
f 249b115af8 No enviar URLs en los chequeos.
Necesita más trabajo hacer esto y no tenemos un uso inmediato para
chequeos específicos de sitios.

fixes #2331
2021-08-04 20:16:56 -03:00
f 71436d3be4 Usar el sistema de autorización de Sutty
Y eliminar código sin utilizar.
2021-08-04 12:17:49 -03:00
f 71ff9e5e7b Traducir columnas o mostrarlas como títulos
Los nombres más comunas de columnas se pueden agregar al archivo de
traducción, si la traducción no existe se convierte a un título.

```ruby
"total_horas".titleize => "Total Horas"
```
2021-08-03 10:24:18 -03:00
f e87fad33ea La tabla se puede scrollear y mantiene los títulos 2021-08-03 10:16:26 -03:00
f 489cbb414c Ya no usamos un hash de queries 2021-08-03 10:15:48 -03:00
f 6f08ca6c36 A veces se pasa el parámetro en set_queries 2021-08-03 10:10:30 -03:00
f 44450da520 Les usuaries solo pueden ver sus propias consultas. 2021-08-02 18:41:09 -03:00
f af67c39dc4 Agregar el nombre del sitio en la miga de pan 2021-08-02 18:37:15 -03:00
f 841279f6cf fixup! Agregar los helpers de Devise también 2021-08-02 18:31:17 -03:00
f 75e6b7a801 Agregar los helpers de Devise también
Para que tengamos `current_usuarie` dentro de las vistas de Blazer.
2021-08-02 18:25:42 -03:00
f 85ad518d8d Correr Blazer sincrónicamente
Deshabilitamos la funcionalidad asincrónica de Blazer porque ejecuta
unos malabares extraños con JS, que filtran la consulta hacia el código.
La idea es ejecutar consultas más livianas, con lo que por ahora no lo
necesitamos.  Podríamos recuperar esto usando ActionCable luego.

Además, reimplementa la lógica de generación de gráficos en el
controlador, para simplificar la vista.
2021-08-02 18:01:34 -03:00
f 49e5603687 Por cuidados, modificar Blazer pero no poder crear consultas 2021-08-02 17:58:46 -03:00
f ddc459130a Acceder a la lista de consultas disponibles con la identidad de Sutty 2021-08-02 17:54:27 -03:00
f 7511afbf88 Les usuaries tienen consultas 2021-08-02 17:51:35 -03:00
f 3a2ce1d47d Configurar Blazer para mostrar estadísticas 2021-08-02 17:51:24 -03:00
fauno 312df05a84 Merge branch 'readme' into 'rails'
Mejorar el entorno de desarrollo

Closes #732 and #1190

See merge request sutty/sutty!47
2021-08-02 17:18:04 +00:00
Nulo 4c84389b35 Apply 3 suggestion(s) to 1 file(s) 2021-08-02 16:17:30 +00:00
fauno 35ca1ee91c Merge branch 'timeout-deploys' into 'rails'
Cancelar la tarea pendiente si tomó mas de 10 minutos

See merge request sutty/sutty!51
2021-08-01 05:15:07 +00:00
fauno d42bab9f1c Merge branch 'actualizacion-de-cuidados' into 'rails'
actualización de cuidados

See merge request sutty/sutty!43
2021-08-01 05:14:08 +00:00
f d456feac8e Cancelar la tarea pendiente si tomó mas de 10 minutos
Si la tarea se reintentó durante 10 minutos, lo más probable es que haya
quedado trabada en algún lado.  Este cambio permite volver a compilar
sitios al cambiar el estado a espera y cancelarse a sí misma.
2021-07-29 14:46:29 -03:00
Nulo 6448a881ac Merge branch 'request-uri' into 'rails'
agregar request_uri a los logs

See merge request sutty/sutty!49
2021-07-22 22:18:30 +00:00
f d474b819ad agregar request_uri a los logs sutty/containers/nginx!1 2021-07-22 16:19:25 -03:00
f 8f88023d52 El espacio es importante 2021-07-22 16:16:10 -03:00
f 5c36de818f Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-07-13 17:24:46 -03:00
f c9de4f7198 si estamos actualizando desde origin/rails hay que ignorar el directorio 2021-07-13 17:24:09 -03:00
f 68bd68a2ee actualización de cuidados, resuelve un cve en addressable 2021-07-13 17:22:05 -03:00
f b71eea505c Merge branch 'rails' into actualizacion-de-cuidados 2021-07-13 17:20:44 -03:00
Maki e3aba348a2 Merge branch 'hotfix-metadata-belongs-to' into 'rails'
Devolver el tipo de dato correcto

See merge request sutty/sutty!48
2021-07-13 16:41:21 +00:00
f cf67dbb0c3 Devolver el tipo de dato correcto
Como MetadataBelongsTo desciende de MetadataArray, al cambiar métodos de
MetadataArray tenemos efectos secundarios.

Esto es un hotfix, la solución correcta sería reimplementar
MetadataBelongsTo para que deje de ser un Array.
2021-07-12 16:52:44 -03:00
f 2ceeeff86c Mejorar el entorno de desarrollo
fixes #1190

fixes #732
2021-07-10 20:13:03 -03:00
f 6ad2980caf Merge remote-tracking branch 'origin/traduccion' into rails 2021-07-10 19:00:01 -03:00
f ffa2c80bf1 @suttyweb/editor@0.0.7 2021-06-28 14:29:37 -03:00
f 06a9b78eee usar @suttyweb/editor@0.0.6 2021-06-28 14:29:03 -03:00
void a64f554f0e usar @suttyweb/editor@0.0.4
subida de archivos :)
2021-06-28 14:29:03 -03:00
void 7e0600779e usar @suttyweb/editor 2021-06-28 14:29:03 -03:00
Maki f19bfe1539 una linea 2021-06-28 10:18:20 -03:00
f 69577e6495 sutty-liquid 0.7.3 no falla con algunas fechas 2021-06-26 20:35:19 -03:00
f fd9350cd10 permitir autocompletar tests en make 2021-06-26 20:34:53 -03:00
f 66d1846cea la fecha cambió si se acaba de inicializar el post 2021-06-26 20:34:33 -03:00
f 06e958710f no guardar valores nulos 2021-06-26 20:34:13 -03:00
f 411728648a Merge branch 'search-engine' into rails 2021-06-26 20:33:45 -03:00
void 3fd31e645c Merge branch 'fix-markdown-attribute' into 'rails'
arreglar el atributo `markdown`

Closes #2102

See merge request sutty/sutty!46
2021-06-19 15:07:45 +00:00
void c7b7d660e1 arreglar el atributo markdown
es igual a markdown_content, pero como estaba antes causaba #2102 por
que le faltaba .markdown-editor.

fixes #2102
2021-06-19 14:59:37 +00:00
void 5fd718a185 Merge branch 'tmp-hainish-certs' into 'rails'
usar certificados de haini.sh para dev

See merge request sutty/sutty!45
2021-06-18 23:06:22 +00:00
void a4716a0ad1 usar certificados de haini.sh para dev
en vez de sutty.local, ver https://0xacab.org/sutty/haini.sh/-/merge_requests/18
2021-06-18 22:47:42 +00:00
Maki 972ebca033 Merge branch 'sutty-liquid' into 'rails'
actualizar sutty-liquid

Closes #2092 and #2100

See merge request sutty/sutty!44
2021-06-16 22:18:27 +00:00
f bd3b117282 aplicar parches en el servidor 2021-06-16 12:08:21 -03:00
f 96a16379bd correr yarn en hain 2021-06-16 12:08:05 -03:00
f c3a8b2401c estandarizar la forma de obtener el valor de los documentos
teníamos dos métodos que hacían lo mismo y generaban conflictos al
obtener el valor por defecto de los arrays cuando no eran arrays.
2021-06-16 11:35:37 -03:00
f 78a3cae077 solo indexar los valores actuales
sin este cambio los artículos se indexaban por todas las categorías
posibles!
2021-06-16 09:13:40 -03:00
f 810c5e32da convertir valores en arrays por retrocompatibilidad
esto permite indexar sitios antiguos y cargar artículos sin generar
errores.
2021-06-16 09:11:13 -03:00
f 7b5b24ab2b actualizar sutty-liquid
las versiones anteriores no verifican correctamente la fecha en el
filtro `date_local` y fallan en fechas incorrectas, especialmente en la
vista previa de los artículos.

fixes #2100
fixes #2092
2021-06-15 20:40:18 -03:00
f 92a292c42b no fallar el container si vendor no existe 2021-06-15 19:04:00 -03:00
f 7f7129de3f Merge branch 'menos-reportes' into rails 2021-06-15 18:15:07 -03:00
f a2669e0aa4 actualización de cuidados 2021-06-15 17:07:52 -03:00
fauno ba8b80fca0 Merge branch 'ssh-git' into 'rails'
poder traer actualizaciones desde repositorios remotos

Closes #1837

See merge request sutty/sutty!36
2021-06-08 17:52:41 +00:00
fauno e014ab166a poder traer actualizaciones desde repositorios remotos 2021-06-08 17:52:41 +00:00
fauno 171ebc2388 Merge branch 'postgresql' into 'rails'
usar postgresql en desarrollo

See merge request sutty/sutty!42
2021-06-08 17:51:50 +00:00
f 57e86f3cfb usar postgresql en desarrollo 2021-06-08 14:36:48 -03:00
fauno 2b14010b1e Merge branch 'preview' into 'rails'
cargar los layouts para poder acceder a la versión preliminar

Closes #2006

See merge request sutty/sutty!41
2021-06-07 17:21:21 +00:00
f 9ea199876d cargar los layouts para poder acceder a la versión preliminar
cuando separamos la lectura de datos de jekyll había faltado leer los
layouts para poder aplicarlos a la version preliminar.  con este cambio
solo se leen cuando se los va a usar.

fixes #2006
2021-06-07 13:37:18 -03:00
Maki 39ffe9e926 edit_posts recuperado #1823 2021-06-03 16:09:26 -03:00
f 7191baff4a reindexar después de mergear 2021-05-31 13:23:40 -03:00
f c6bcf95f34 si la notificación produce una excepción, capturarla por correo 2021-05-31 12:19:52 -03:00
f 4540ea73ad variables de entorno nuevas 2021-05-31 12:18:06 -03:00
f 5468a11885 reportar el issue una sola vez y luego actualizarlo 2021-05-31 12:08:19 -03:00
f fc7c2f31dd enviar reportes a gitlab usando la api en lugar del correo 2021-05-29 17:42:45 -03:00
Maki 595ee27417 Merge branch 'decryption-error' into 'rails'
a veces el decifrado falla porque el valor todavía no estaba cifrado

Closes #1813, #1811, #1810, #1809, #1807, #1805, #1804, #1803, #1802, #1800, #1799, #1785, #1780, #1779, #1728, #1725, #1724, #1723, #1721, #1719, #1718, #1717, #1714, #1713, #1712, #1710, #1709, #1708, #1706, and #1704

See merge request sutty/sutty!37
2021-05-24 15:17:37 +00:00
f 160558470b a veces el decifrado falla porque el valor todavía no estaba cifrado
buscamos un espacio para saber si se trata de una oración o un mensaje
que realmente no se pudo decifrar.

fixes #1704
fixes #1706
fixes #1708
fixes #1709
fixes #1710
fixes #1712
fixes #1713
fixes #1714
fixes #1717
fixes #1718
fixes #1719
fixes #1721
fixes #1723
fixes #1724
fixes #1725
fixes #1728
fixes #1779
fixes #1780
fixes #1785
fixes #1799
fixes #1800
fixes #1802
fixes #1803
fixes #1804
fixes #1805
fixes #1807
fixes #1809
fixes #1810
fixes #1811
fixes #1813
2021-05-24 10:49:35 -03:00
f 691f064a24 actualización de cuidados 2021-05-20 20:32:53 -03:00
fauno 7c12a03c36 Merge branch 'staging-process' into 'rails'
trabajar con un entorno de pruebas que es igual a producción

See merge request sutty/sutty!35
2021-05-20 15:46:47 +00:00
f e4754b342b trabajar con un entorno de pruebas que es igual a producción
al correr `make ota build save` se genera un entorno de staging en
panel.staging.sutty.nl con los datos de los sitios y una copia de la base
de datos.

no copiamos los sitios porque les usuaries van a entrar a hacer pruebas
en staging y esperar encontrar los cambios luego en producción.  además
usaría mucho almacenamiento hacer copias.

al correr `make env=production ota build save` se realiza el mismo
proceso para producción.

los assets se alojan por fuera para que podamos actualizarlos sin tocar
el contenedor y separar los de production de los de staging.

estos cambios van en línea con ansible-sutty-deploy.
2021-05-19 17:55:55 -03:00
Maki d3edefd5f0 Merge branch 'no-romperse-con-sitios-faltantes' into 'rails'
si los archivos del sitio no existen, saltearlo

See merge request sutty/sutty!33
2021-05-18 18:20:05 +00:00
Maki 918dd4cb10 Merge branch 'validar-has-many' into 'rails'
validar de más has_many

See merge request sutty/sutty!34
2021-05-18 18:17:44 +00:00
f 4609ab21b2 separar las categorías con barras 2021-05-18 11:22:09 -03:00
f 2612f44965 validar de más has_many
esta validación de has_many no permite guardar el post si no coinciden
la cantidad de valores con los posts asociados, lo que funciona en casos
muy ideales y no deja que se pueda guardar el post desde el formulario.

el formulario envía un valor vacío para poder indicar que se quieren
borrar todos los artículos por limitaciones de http, pero también suma
un ítem vacío a la lista, con lo que la cantidad de posts encontrados
siempre es 1 menor.

de la misma forma, si la relación está rota porque uno de los posts
asociados ya no existe, no permite guardar sin dar mayor feedback.  así
que por ahora dejamos que se puedan guardar.
2021-05-17 17:56:56 -03:00
f 7f75f5cd8a si los archivos del sitio no existen, saltearlo
lo correcto sería mostrar un error.  esto nos ayuda a tener pocos sitios
en staging en lugar de todos y que se puedan mostrar en el panel.
2021-05-17 17:54:21 -03:00
f 0a23fe1edd lo que se indexa son los valores actuales, no todos los valores posibles 2021-05-17 17:27:01 -03:00
f 553b4f15f7 mostrar si es borrador sin acudir al sitio 2021-05-17 15:58:37 -03:00
f dab44aa1cf Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-05-17 15:51:47 -03:00
f 43b85a6e9b poder cambiar la base de datos de producción 2021-05-17 15:51:20 -03:00
f df425bab5a poder indexar los sitios!
me había olvidado de este archivo
2021-05-17 15:33:46 -03:00
f 7b15a32de0 Merge branch 'rails' into search-engine 2021-05-17 13:38:59 -03:00
Maki 7257e02cbd vendor vacío 2021-05-17 13:31:04 -03:00
f c3d7dc317c Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-05-17 13:15:21 -03:00
f a112233e2a soportar make bundle 2021-05-17 13:14:57 -03:00
Maki 36f256beca Merge branch 'vali-date' into 'rails'
validar la fecha

Closes #1572 and #1573

See merge request sutty/sutty!31
2021-05-17 15:58:59 +00:00
f e19713f5df usar Post#new? que ya sabe cuándo el documento no existe aun 2021-05-17 12:43:23 -03:00
Maki 4a9ecd41de Merge branch 'belongs-to' into 'rails'
Testear relaciones entre artículos

See merge request sutty/sutty!32
2021-05-17 15:15:17 +00:00
f 64b59bfc4d si el post ya tiene fecha, no cambiarla 2021-05-14 17:41:44 -03:00
f 189b94e074 aplicar caché a los parámetros de búsqueda también 2021-05-14 17:19:03 -03:00
f 219a9985f5 testear el buscador 2021-05-14 16:59:47 -03:00
f 7413f6e2aa Merge branch 'rails' into search-engine 2021-05-14 12:53:35 -03:00
fauno 9c288b896c Merge branch 'build-once-at-a-time' into 'rails'
compilar el sitio de a uno por vez

See merge request sutty/sutty!27
2021-05-14 15:02:51 +00:00
f 3dacdf82bf testear que lo que diga sutty termine en jekyll
agregué el método `Jekyll::Document#reset` para que no queden datos de
la versión anterior, porque jekyll mergea la información.

además, para evitar bugs en las plantillas, se mantienen los arrays
vacíos en el front matter para que se puedan seguir usando métodos de
arrays, como each y sort.
2021-05-14 11:15:32 -03:00
f fc6e7da5d6 testear relación has_and_belongs_to_many
un artículo puede pertenecer y tener muchos artículos (una relación
poliamorosa de muchos a muchos)

también utilizamos asignación para aprovechar `value=`.
2021-05-13 19:50:41 -03:00
f 817d5650f8 testear la relación has_many
un artículo puede tener varios artículos, es la inversa de belongs_to

también eliminamos la memoización
2021-05-13 19:48:41 -03:00
f bda56e3c10 eliminar memoización en las búsquedas 2021-05-13 19:47:24 -03:00
f 38c5cdef81 testear la relación belongs_to
belongs_to indica que un artículo pertenece a otro, la relación inversa
es un has_many.

en este caso nos fuimos dando cuenta que las memoizaciones nos juegan en
contra, así que las vamos eliminando del código cuando no hacen falta.

utilizamos `value = value.filtrado` para aprovechar
`MetadataTemplate#value=` que guarda el valor anterior en
`MetadataTemplate#value_was` y nos permite comparar entre el valor
anterior y el actual.
2021-05-13 19:44:21 -03:00
f 42923c4e04 sitios de testeo 2021-05-13 19:42:12 -03:00
f f5834b5c1b en lugar de asumir un valor, informar el error 2021-05-13 12:52:49 -03:00
f 8a5e965e61 validar la fecha
una fecha en el futuro como 20213-01-01 es válida para ruby, pero jekyll
valida las fechas con cuatro digitos nada mas (issue pendiente :P), así
que tomaba el archivo con fecha en el futurísimo como un archivo sin
fecha.

fixes #1573
fixes #1572
2021-05-13 11:44:09 -03:00
f 5d24834234 los sitios pueden ser más grandes que 2GB
fixes #1552
fixes #1553
fixes #1554
fixes #1555
2021-05-11 18:16:34 -03:00
f c1d6316462 los posts solo tienen lang
fixes #1551
fixes #1550
fixes #1549
fixes #1548
2021-05-11 17:59:30 -03:00
f 404436e294 algunas categorias son de texto
fixes #1537
fixes #1538
fixes #1539
fixes #1541
2021-05-11 15:27:54 -03:00
fauno a421a79840 Merge branch 'publicar' into 'rails'
botón crear cuenta

See merge request sutty/sutty!29
2021-05-10 18:29:38 +00:00
f ea12caef9b actualizar el recursero para ingles 2021-05-10 15:28:53 -03:00
f e935fb5433 Merge branch 'locale-fixes' into rails 2021-05-10 15:28:26 -03:00
f 9e935a2c49 poder ver las categorias que son articulos 2021-05-10 15:28:04 -03:00
f 65a049c027 traducciones faltantes 2021-05-10 15:18:24 -03:00
f 9d91323f49 redirigir a la lista con idioma 2021-05-10 15:18:04 -03:00
f cf01fb700c siempre empezar por el idioma por defecto 2021-05-10 14:49:18 -03:00
f 84e77c1232 si el idioma actual no existe en el sitio mostrar el idioma por defecto 2021-05-10 14:49:01 -03:00
f 9faecbc289 centralizar la detección del idioma 2021-05-10 14:48:48 -03:00
Maki f417d45a6b botón crear cuenta 2021-05-10 14:37:41 -03:00
f e0eeaf7fc6 tomar en cuenta el idioma actual al cachear
para que al cambiar de idioma no se vean partes en el anterior
2021-05-10 14:27:47 -03:00
fauno 1e2b2d9de3 Merge branch 'breadcrumbs' into 'rails'
Breadcrumbs

See merge request sutty/sutty!26
2021-05-10 17:06:15 +00:00
fauno d74448b81d Merge branch 'traduccion' into 'rails'
Traduccion

See merge request sutty/sutty!28
2021-05-10 17:04:03 +00:00
f 8d7e4d2b64 solo poner en cola una sola vez
el cambio anterior no permitía que se encolen varias compilaciones y la
versión actual pone el sitio en cola mientras se está compilando.

con este cambio el sitio se puede encolar varias veces pero el estado se
cambia una sola vez, para no abrirle la puerta a un loop infinito de
compilaciones.

lo correcto sería generar un modelo de cola con su propio estado (y
probablemente a partir de cuál commit se está compilando).
2021-05-10 13:55:36 -03:00
f 39eb584a97 no compilar varias veces desde el compilador
esto evita que se espamee el botón de publicar
2021-05-10 13:14:02 -03:00
f 10580d2b4f compilar el sitio de a uno por vez
estamos deshabilitando el botón en el panel, pero gracias a la caché (o
si le usuarie tiene el botón ya abierto y habilitado) es posible correr
dos o más tareas de compilación a la vez, lo que produce errores.  por
ejemplo, que una compilación falle porque quiere comprimir archivos que
ya no están.

con este cambio, si un sitio está compilando, la tarea se aplaza un
minuto.  si hay muchas tareas, eventualmente se harán todas pero no se
pisan entre sí.

quizás lo correcto sería hacerlo cuando se lanza la compilación también.
2021-05-10 10:56:08 -03:00
f f3fcf11da3 acomodar la sección de usuaries al resto del sitio 2021-05-09 13:12:22 -03:00
f c2b150df12 migas responsivas 2021-05-09 13:12:06 -03:00
f 1a4d1b13f9 traducciones 2021-05-09 13:11:50 -03:00
f a9da4b3f2c ya que estaba, un poco de refactorización para no escribir tantas @
memoizamos site y post cuando podemos
2021-05-09 13:11:15 -03:00
f 8fe343ae45 hay migas que van dentro de sus vistas
porque modificar el controlador de devise solo para agregar la miga de
pan es demasiado trabajo
2021-05-09 13:10:00 -03:00
f 88051425ae agregar migas de pan comunes y en cada accióñ
las migas que van dentro de cada acción son strings vacías porque no las
estamos vinculando a nada, así que nos ahorramos el proceso.
2021-05-09 13:08:18 -03:00
f 0a5908d02d eliminar las migas de pan casero 2021-05-09 13:02:09 -03:00
f cb8032d9e1 usar loaf para configurar las breadcrumbs 2021-05-09 12:59:33 -03:00
f 35518ba48a no hacen falta los parametros al crear un artículo nuevo 2021-05-09 12:52:26 -03:00
f 98df0ceb3a los datos privados no se indexan 2021-05-09 12:25:16 -03:00
Maki de92cc117a deselect all en en.yml 2021-05-08 17:19:13 -03:00
Maki f2981a6a45 Merge branch 'lectura-de-jekyll' into 'rails'
optimizar la lectura de datos desde jekyll

See merge request sutty/sutty!25
2021-05-08 20:05:34 +00:00
fauno a0caa5ca95 Merge branch 'backtrace' into 'rails'
arreglar y testear el procesamiento de errores de js

See merge request sutty/sutty!19
2021-05-08 17:44:00 +00:00
fauno eafe5fa96c Merge branch 'validar-sitio-antes-de-guardar-la-imagen' into 'rails'
validar el sitio antes de subir una imagen

Closes #1192, #1193, #1194, #1195, #1196, and #1197

See merge request sutty/sutty!17
2021-05-08 17:42:41 +00:00
fauno dffae5a49f Merge branch 'renovar-cache' into 'rails'
renovar la caché de formularios

See merge request sutty/sutty!12
2021-05-08 17:40:46 +00:00
fauno de2db01e9f Merge branch 'sin-markdown' into 'rails'
deprecar la guia de markdown

See merge request sutty/sutty!5
2021-05-08 17:38:22 +00:00
fauno ceb5523ccd Merge branch 'traduccion' into 'rails'
Ajustes traducción de archivos de db/seeds

See merge request sutty/sutty!24
2021-05-08 17:37:58 +00:00
Maki 478730e882 Ajustes traducción de archivos de db/seeds 2021-05-08 17:37:57 +00:00
f 6396841b2c evitar confusiones entre diccionario y locale
el diccionario es lo que usa internamente pg para indexar, el locale es
el idioma que asignamos en sutty.
2021-05-07 19:25:09 -03:00
f edff238a36 optimizar la lectura de datos desde jekyll
durante el proceso de compilación de jekyll se cargan todos los datos en
memoria, buscando e interpretando todos los archivos del sitio.  en el
caso de sutty, solo queremos leer alguna información por vez.

trabajando en el buscador me dí cuenta que aunque el panel cargue los
posts desde la base de datos, sutty seguía leyendo la información
completa del sitio, porque respetaba el proceso de lectura de jekyll.

con este cambio podemos leer los _data/ por separado de los _posts/ con
lo que la carga del sitio es mucho más rápida.
2021-05-07 19:02:15 -03:00
f d2ae406023 eliminar del índice al eliminar el artículo 2021-05-07 18:06:49 -03:00
f 13b6b7a452 cambiar la leyenda del botón en el filtro
no cambia el resaltado porque la definición de la clase .btn hace
conflicto, para arreglar eso hay que verificar todo el panel.
2021-05-07 17:54:45 -03:00
f f9a2d12803 mostrar el texto buscado en el buscador
para poder editarlo si hace falta
2021-05-07 17:46:49 -03:00
f e1055cc912 necesitamos el locale para poder marcar el idioma actual 2021-05-07 17:45:07 -03:00
f 754e8fbbcc mostrar cuáles son los filtros actuales y poder removerlos
además, crear una sección de notas al pie con definiciones disponibles
para lectores de pantalla.  (no quiere decir que sean completas, `title`
solo funciona con usuaries de mouse)
2021-05-07 17:32:54 -03:00
f 051e40f64b el formulario de busqueda tiene que incorporar los filtros
para poder volverlos a enviar.  me había olvidado de convertirlos en
campos ocultos.
2021-05-07 17:31:50 -03:00
f 418ffb8463 cambiar btn-sm para que tenga el tamaño de badge 2021-05-07 17:31:13 -03:00
f 6df7f09c26 darle estilo de botón a los filtros
como eran badges con links no tenían sombra en el foco ni color al
pasarles por encima.
2021-05-07 17:11:08 -03:00
f 2d3f5b21ae al eliminar los saltos de línea se quedaban pegadas algunas palabras 2021-05-07 16:21:59 -03:00
f 4f2e602822 también buscar por palabras similares 2021-05-07 16:21:44 -03:00
f ad871baca6 implementar el buscador en el panel
ahora el índice de artículos incorporar buscador de texto libre.

además todos los filtros de búsqueda se mantienen entre búsquedas,
entonces al filtrar por tipo de artículo y término, se aplican ambos y
al cambiar el tipo se mantiene la búsqueda de texto.
2021-05-07 16:17:25 -03:00
Maki 47aaf8a5fa designs.yml ajuste 2021-05-07 15:57:19 -03:00
Maki e305c8c958 licencias.yml 2021-05-07 15:52:27 -03:00
Maki 83bf42c2a0 designs.yml 2021-05-07 15:52:11 -03:00
f 34a05e860d elimina el espacio vacío del contenido 2021-05-06 19:47:43 -03:00
f fd7ab8d7ef actualizar el índice cuando se agrega o modifica un post
además, activa callbacks de activerecord de forma que Post se va
pareciendo cada vez más a un modelo de rails :D
2021-05-06 19:46:36 -03:00
f d61d1cad56 respetar el orden de los artículos
siempre ordenamos primero por número de orden y fecha de creación,
siempre decrecientes.  esto permite que les usuaries prioricen contenido
usando las herramientas de reordenamiento.

pg_search no soporta esto, siempre ordena por cuánto corresponde el
resultado con la búsqueda, así que lo emparchamos para que respete el
orden que necesitamos.

el reporte de error relacionado es este:
https://github.com/Casecommons/pg_search/issues/467
2021-05-06 19:07:11 -03:00
f f9dca42f95 Merge branch 'rails' into search-engine 2021-05-06 18:11:55 -03:00
f 91cc5fe465 variable de entorno de testeo para los tests 2021-05-06 18:11:10 -03:00
f 6b84720401 si los artículos son nuevos no tienen llave para cachearlos 2021-05-06 18:10:31 -03:00
f 28e927d0af Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-05-06 17:58:14 -03:00
f 9b255a23e0 ajustes en el makefile 2021-05-06 17:57:56 -03:00
f dcc47ad258 poder trabajar con git+ssh en el contenedor
y aplicar parches
2021-05-06 17:55:03 -03:00
f 5880c47676 rubocop 2021-05-06 17:54:49 -03:00
f 0d81653cfa Merge branch 'rails' into search-engine 2021-05-06 17:39:51 -03:00
Maki 4bc39af3d8 Merge branch 'traduccion' into 'rails'
correcciones en.yml

See merge request sutty/sutty!23
2021-05-06 20:38:13 +00:00
Maki 5441fe5503 saque comillas en md 2021-05-06 17:37:25 -03:00
f a27a0ca7d8 Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-05-06 17:30:43 -03:00
f 20d2cf6840 no fallar si no tiene un diseño asignado 2021-05-06 17:29:29 -03:00
Maki 2efb416136 correcciones en.yml 2021-05-06 17:29:24 -03:00
Maki 18a0513397 idiomas 2021-05-06 16:03:23 -03:00
Maki bd3be549b4 texto mis sitios 2021-05-06 15:43:54 -03:00
f f37ed785e3 correr rake y rails dentro de hainish
```bash
make rails args="g migration CreateTable"
make rake args="routes"
```
2021-05-06 15:19:34 -03:00
f a149c870e2 las categorías se guardan en indexed posts
algunas categorías son otros artículos relacionados, con este método
garantizamos que sólo se guardan los títulos.
2021-05-06 13:00:05 -03:00
f 86ae7fb8f8 los posts pueden ser indexados
`IndexedPost` es una representación indexada por PG de `Post`.  ambos
están relacionados por el UUID de `Post`, de forma que se puede traer el
artículo completo (por ejemplo al previsualizar o editar).

cada artículo está indexado según su idioma.  para eso convertimos el
locale en el equivalente en el diccionario de PG.

`Site#index_posts` es un método para indexar todos los artículos en
masa.

`Post#to_index` genera el `IndexedPost` correspondiente

`IndexedPost.search(:es, 'hola')` busca "hola" en todos los artículos
utilizando el diccionario de castellano.  esto no quiere decir que
busque en todos los artículos en castellano.  por ahora para eso hay que
hacer algo como:

```ruby
site = Site.find 1
site.indexed_posts.where(locale: :english).search(:en, 'hello')
```

para encontrar todos los artículos en inglés del sitio con id 1
2021-05-06 12:52:30 -03:00
f ceaadeb7bf crear la tabla de indexación de posts
los posts se siguen guardando en el sitio jekyll, lo que guardamos en la
base de datos es una representación indexable que tiene los datos
mínimos de los posts para buscarlos por distintos parámetros.

esto nos permite cargar la lista de artículos y filtrarla de distintas
formas sin cargar todo jekyll en memoria, lo que reduciría el consumo de
recursos y aceleraría el panel.  ya tenemos caché así que el problema
estaba mitigado, pero igual es un avance.

ya que migramos la base de datos a postgresql, aparecieron todas las
tablas y campos en el schema.rb, que es lo que usa rails para configurar
una base de datos desde cero.
2021-05-06 12:45:33 -03:00
f 26d186721d algunos metadatos son indexables
solo los de texto que no se refieran a otros artículos por ahora
2021-05-06 12:33:28 -03:00
f 655e07cd40 configuración de las bases de datos
ahora el testeo y desarrollo también se hace en postgresql.  nos queda
pendiente que cada quien pueda usar la base de datos que quiera y que si
nos posible indexar documentos, que sea opcional.
2021-05-06 12:29:48 -03:00
f cc2b4a2971 dependencias del buscador
pg_search: habilita búsquedas en postgresql
hairtrigger: permite crear acciones automáticas en postgresql
2021-05-06 12:26:36 -03:00
fauno 8924e6aee8 Merge branch 'editor-usar-css-para-text-align' into 'rails'
setear style en los divs de alineación

See merge request sutty/sutty!21
2021-04-29 14:23:00 +00:00
void f798b5781e setear style en los divs de alineación
arregla el estilo en sitios que no tienen css para los [data-align]
2021-04-29 14:13:31 +00:00
fauno b0d78dfade Merge branch 'editor-mark-text-color' into 'rails'
permitir cambiar el color del texto en <mark>

Closes #1160

See merge request sutty/sutty!20
2021-04-28 19:20:40 +00:00
void 57f885360f permitir cambiar el color del texto en <mark>
fixes #1160
2021-04-28 18:54:55 +00:00
void 525a6fc680 style: correr prettier sobre el editor 2021-04-28 18:48:50 +00:00
void df38e12e3c fallar si no existe panel.sutty
fixes #1279

antes fallaba silenciosamente y rompía airbrake que en consecuencia
rompía el resto del javacript
2021-04-28 18:00:56 +00:00
Maki fdabd16663 Merge branch 'default-locale' into 'rails'
no fallar si el idioma de le usuarie no es el del sitio

Closes #1163, #1164, and #1168

See merge request sutty/sutty!15
2021-04-27 21:51:55 +00:00
f 2448ed20e6 alpine 3.13.5 2021-04-27 11:53:39 -03:00
f f46637e6ff schema.rb
las tablas que no se pudieron exportar son porque sqlite no soporta el
tipo de campo uuid
2021-04-27 11:53:03 -03:00
f 11c4713839 entorno por defecto 2021-04-27 11:52:35 -03:00
f f2683c3a5a hotfixes via make
en realidad deberíamos hacer esto vía git pero hay que hacer algunos
cambios en el dockerfile para eso
2021-04-27 11:52:02 -03:00
f c2c179c8e7 schema.rb 2021-04-27 11:33:16 -03:00
f 0bd6d13335 testear archivos individuales o todo 2021-04-27 11:31:57 -03:00
f c8f1118640 testear el procesamiento de errores de js 2021-04-27 11:27:17 -03:00
f 22f61dc31f eliminar los espacios en el lugar correcto
esto hacía que no se puedan enviar los correos de excepciones porque
producían una excepción a su vez.
2021-04-27 11:25:37 -03:00
void 3b0cddc9df Merge branch 'hain' into 'rails'
usar hain como entorno de trabajo reproducible

See merge request sutty/sutty!16
2021-04-26 16:04:55 +00:00
fauno 7d2288ae48 usar hain como entorno de trabajo reproducible 2021-04-26 16:04:55 +00:00
f 2fbbb212ad validar el sitio antes de subir una imagen
si `Site` no es válido (por ejemplo la `description` es muy corta), no se
pueden guardar los archivos estáticos asociados, porque
`ActiveStorage::Attached` solo se copia al disco cuando se guardan a
través de `Site#static_files`.

el error que se producía es que `MetadataFile` no puede vincular el
archivo porque todavía no fue copiado al disco.

este cambio have que `MetadataFile` no valide cuando `Site` no valida.

queda un error pendiente en `Site::StaticFileMigration` con una
situación similar.  para eso necesitamos identificar el momento en que
el archivo se "sube" al disco, es decir se copia el `IO` al directorio,
a través de `ActiveStorage::Service::DiskService#upload`.

fixes #1197
fixes #1196
fixes #1195
fixes #1194
fixes #1193
fixes #1192
2021-04-24 20:04:38 -03:00
f b71c6a5fa4 no fallar si el idioma de le usuarie no es el del sitio
si tenemos el panel en inglés pero gestionamos un sitio en castellano,
teníamos un error porque sutty siempre quiere cargar el sitio en el
idioma de le usuarie.

con este cambio si el sitio no tiene el idioma del panel, usamos el
idioma por defecto del sitio.

fixes #1168
fixes #1164
fixes #1163
2021-04-22 20:26:42 -03:00
f 9ae9450875 vista previa 2021-04-22 13:19:47 -03:00
f 70e64e6e97 usar el editor en otros campos
como reemplazo del campo `markdown` que coloca texto con markdown en el
front matter.
2021-04-22 13:09:49 -03:00
f c9531af77b rails ya soportaba deshabilitar durante el envío 2021-04-21 15:26:27 -03:00
f 9cf59d7137 Merge branch 'submit-once' into rails 2021-04-21 14:16:34 -03:00
f f733716ff9 Merge branch 'backtrace-origin' into rails 2021-04-21 10:27:26 -03:00
f 4b6e43b63d mostrar solo el origen del error 2021-04-21 10:24:16 -03:00
f 56725f3bd7 Merge branch 'writable' into rails 2021-04-21 10:19:57 -03:00
f 78a830a0e7 eliminar las traducciones también 2021-04-21 10:18:01 -03:00
f 1e60b5f447 Merge branch 'no-masters' into rails 2021-04-21 10:16:31 -03:00
f 522da5bdb3 Merge branch 'editorial-fix' into rails 2021-04-21 10:13:07 -03:00
f 8ded0e47b7 Merge branch 'notify' into rails 2021-04-21 10:09:45 -03:00
f fce3e7c8b3 Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-04-20 11:29:13 -03:00
f 0e96cd9d2a actualización de cuidados 2021-04-19 18:03:27 -03:00
f 81a565cd0f renovar la caché de formularios
usando la fecha de modificación del post, esto nos permite renovar la
caché haciendo `touch _es/*.markdown` en el repositorio.
2021-04-18 19:00:21 -03:00
f a960f93075 no usar espacio extra en los asuntos 2021-04-17 15:33:41 -03:00
f 2a70d6a8db no permitir modificaciones en los artículos marcados como solo lectura
antes permitiamos la modificación en memoria pero no al salvar, lo que
producía un bug porque el valor se seteaba pero no se aplicaban
conversiones al guardarlo.  los numeros, por ejemplo se guardaban como
strings.

XXX: no aplicar conversiones al guardar sino al setear.
2021-04-16 14:11:28 -03:00
f c9e0ce9c38 agregar el origen del error en el asunto 2021-04-16 12:10:32 -03:00
f f60fbd70f4 deshabilitar el botón de publicación una vez que se lo toca 2021-04-16 11:10:59 -03:00
f af3d59d34a asegurarse que solo podamos encolar el sitio una vez 2021-04-16 11:10:59 -03:00
void 9c2ad4f858 Merge branch 'void/editor' into 'rails'
desactivar alt input si es placeholder

Closes #970

See merge request sutty/sutty!3
2021-04-16 13:53:29 +00:00
f 86ae34a6b3 desde que se actualizó editorial-autogestiva-jekyll-theme este test fallaba
porque cambió la cantidad de layouts que tiene
2021-04-16 10:37:53 -03:00
f 6e9b09e19b deprecar un atributo que nunca usamos 2021-04-16 10:36:38 -03:00
f 8fc054a735 documentación
closes #1094
closes #1093
closes #1089
closes #1054
2021-04-16 10:36:18 -03:00
f d3174c6e3f arreglar un test 2021-04-16 10:29:17 -03:00
f 70f5d4f001 no asumir que la rama principal se llama master
la estábamos hardcodeando, este cambio permite descubrir el nombre de la
rama actual.

el efecto secundario es que podemos abrir ramas manualmente en el
repositorio (desde terminal) y sutty va a respetar eso (no sé por qué lo
haríamos, pero está la posibilidad).
2021-04-16 10:27:37 -03:00
f 21eea41583 deprecar la referencia de markdown
es una supervivencia de cuando se escribia md a mano
2021-04-15 18:33:37 -03:00
f 1d6cf11d52 encontrar la api independientemente del dominio que la aloje 2021-04-15 11:34:42 -03:00
f 73d1a7dcd8 recuperar las variables de spree 2021-04-14 18:22:17 -03:00
f 1a435ba204 Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-04-14 16:31:11 -03:00
void d2a158570e typescript: solo compilar app/ 2021-04-14 19:30:31 +00:00
f 17a0e78bfd actualización de cuidados 2021-04-14 13:37:56 -03:00
f f3ed882ca4 registrar si falló la compilación. no colgar la io. 2021-04-14 13:09:03 -03:00
f 1d8eda67a9 un tipo de campo que no hace nada 2021-04-13 15:52:34 -03:00
f 6712393393 deploys sin notificar 2021-04-11 16:45:26 -03:00
f 6e9b333cd5 permitir guardar artículos con campos de solo lectura 2021-04-11 16:43:59 -03:00
void c1204c1163 desactivar alt input si es placeholder
fixes #970
2021-04-10 22:20:13 +00:00
f b9f7dc4826 typo 2021-04-10 13:17:24 -03:00
f b60dff4df4 renderizar la tabla como texto plano 2021-04-07 17:47:58 -03:00
f 1d8e04dbb1 alpine 3.13.4 2021-04-07 17:46:59 -03:00
f ee881e22ab no ofrecer la renderización de layouts ignorados 2021-04-07 17:46:37 -03:00
f 77904dc473 deprecar sprockets y ganar sourcemaps 2021-04-07 17:45:27 -03:00
f 71be841dfc Merge branch 'void/editor' into rails 2021-04-07 17:21:38 -03:00
void ff532c7658 arreglar imports en typescript 2021-04-07 20:18:36 +00:00
f 76522676ca instalar las gemas por separado
estábamos compartiendo las gemas en un solo directorio para ahorrar
espacio, pero bundler decidió no instalar o reutilizar las gemas
binarias de sutty sino compilarlas.  esto no pasa instalando las gemas
de cada sitio por separado y no tenemos tiempo de debuguear esto por
ahora.  es algo que apareció en bundler post 2.1.4 porque hasta ahora
todo funcionaba bien.

TODO: encontrar el problema o instalar bundler 2.1.4
2021-04-07 16:12:08 -03:00
f b22699a079 soporte para ipv6
con esto los otros nodos pueden hacer proxy reverso de la instancia de
sutty en el nodo delegado
2021-04-03 13:59:29 -03:00
f 3d3934ac43 algunos campos solo se escriben una vez, como los precios en la tienda 2021-03-31 15:04:04 -03:00
f 67f145cb3f indicar cuándo se vacía un select 2021-03-30 17:39:48 -03:00
f 602e8cc9cf generar un link posta 2021-03-30 13:00:05 -03:00
f 072662cab8 siempre mandar un array en data-keys
closes #887
closes #886
closes #885
closes #884
closes #877
closes #876
closes #871
closes #867
closes #865
2021-03-27 17:18:09 -03:00
void f25e93ad4b editor: chore: estilo 2021-03-27 18:45:46 +00:00
void b11346074a editor: desrepetir código
esto me huele a que podría introducir bugs pero espero que no.
2021-03-27 18:44:24 +00:00
f 0c491f88e1 actualización de cuidados 2021-03-27 11:25:15 -03:00
f 46c5760a2b preparando para soportar ssh 2021-03-27 11:15:17 -03:00
f 2f0e3ee20e mostrar el tipo de articulo bien 2021-03-27 10:38:37 -03:00
void 3b9237d870 fix: editor: guardar <sub> y <sup> 2021-03-26 15:57:47 +00:00
void 2d8507369b editor: mantener text nodes solo cuando tienen texto 2021-03-26 15:57:07 +00:00
void 117fa84cc4 editor: WIP: <small> 2021-03-26 15:56:37 +00:00
f 102cd0abd3 cerrar la sesión del todo 2021-03-26 12:45:43 -03:00
f 2e7c1d23f4 guardar el atributo name #331 2021-03-26 10:27:50 -03:00
f 17ba7db651 los articulos no se relacionan consigo mismos :( 2021-03-25 19:56:50 -03:00
f 5140a34f55 mostrar el tipo de artículo en las relaciones 2021-03-25 19:50:40 -03:00
f e3727eb6b2 no permitir artículos duplicados 2021-03-25 19:17:34 -03:00
f 365146ed59 Merge branch 'void/editor' into rails 2021-03-23 11:43:49 -03:00
f 3fdbd01b78 usar tabs acá 2021-03-23 11:37:14 -03:00
f 85efaf988a un array vacío por defecto
closes #774
2021-03-23 11:35:49 -03:00
void 891bb4db3f llamar a onClick al crear nodos
si hay un onClick cuando se apreta el botón para crear el nodo, se
llama. esto hace que las cosas con barras auxiliares aparezcan cuando se
crean sin tener que apretar manualmente.
2021-03-22 20:54:26 +00:00
f 43430ca730 mejor soporte de errores 2021-03-22 16:47:01 -03:00
f 5f87540de7 solo descargar los sourcemaps remotos a través de conexiones seguras 2021-03-22 16:25:18 -03:00
f f356793908 agrupar errores 2021-03-20 13:49:53 -03:00
f 496d30807f recuperar el código fuente 2021-03-20 13:43:31 -03:00
f 8cf5d92dae permitir cors para nombres de dominio completos también
en realidad necesitamos una forma de consultar a la base de datos por
todas las versiones de dominios de un sitio, de una forma barata que no
nos obligue a instanciar el sitio y todos sus deploy.
2021-03-20 13:10:47 -03:00
f 65af7da0fb enviar los reportes 2021-03-19 20:50:11 -03:00
f 39fc094790 tabla correcta y más información 2021-03-19 19:54:56 -03:00
f 5977aa37af mejorar notificación de errores 2021-03-19 19:41:03 -03:00
f a25ddb004a cerrar la sesión en lugar de dar un error
closes #290
closes #261
closes #232
closes #237
closes #238
closes #239
2021-03-13 20:43:03 -03:00
f f73e6ecb6f no mezclar markdown con html 2021-03-03 09:46:02 -03:00
f c006ed7f29 garantizar que todos los locales son simbolos 2021-03-03 09:43:15 -03:00
f 3bcdc5a00f autenticar la subida de archivos
activestorage permite subida de archivos sin autenticación!
2021-02-28 11:00:48 -03:00
f 56b4884b32 Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-02-27 10:00:06 -03:00
void 79197956f2 fix(editor): arreglar problema con el coso de imágenes 2021-02-26 17:55:32 +00:00
f fb7ad9ae1a Revert "editor: mover imagenes a un figure aparte si no lo están"
This reverts commit dfc9d6a2a4.
2021-02-26 11:23:11 -03:00
f 269db4cd09 un wip de ota (over the air updates) 2021-02-26 10:22:30 -03:00
f 9cb3c084ee olvidar el artículo al guardar 2021-02-26 10:21:53 -03:00
f de5c1864c3 Merge branch 'void/editor' into rails 2021-02-25 19:47:51 -03:00
void dfc9d6a2a4 editor: mover imagenes a un figure aparte si no lo están 2021-02-25 22:29:14 +00:00
void b8e9e4799a editor: borrar archivos viejos 2021-02-25 21:06:11 +00:00
f 7175af05d7 permitir atributos de multimedia 2021-02-25 18:01:56 -03:00
f cb5890e00e cargar html que ya existía 2021-02-25 18:00:43 -03:00
f ba2d714348 typo 2021-02-25 17:53:08 -03:00
f e3faa3b37b en los artículos nuevos no hay contenido
closes #341
closes #340
closes #339
closes #338
2021-02-25 12:02:03 -03:00
f dce75d6d6c no vincular si el archivo ya existe #213
por ejemplo git lfs rompe los links duros
2021-02-24 17:40:27 -03:00
f 0ee6d5a2ab inspeccionar metadatos 2021-02-24 17:37:13 -03:00
f 537ee4cb58 webpack-dev-server 2021-02-24 17:29:14 -03:00
f c9eacc0995 ruby ~> 2.7 2021-02-24 17:29:14 -03:00
f 9a8839dd93 validar direcciones de correo
closes #291
2021-02-24 17:29:09 -03:00
f 75cb667d1c no convertir las comillas 2021-02-24 17:04:32 -03:00
f 17a248260f soportar contenido en markdown 2021-02-24 16:57:20 -03:00
f 070ef62806 las imagenes requeridas solo se pueden reemplazar 2021-02-24 16:31:57 -03:00
f 1b6599dd40 refactorizacion 2021-02-24 13:05:51 -03:00
f 3a38cae0bc no ejecutar validaciones al guardar un archivo 2021-02-24 13:04:46 -03:00
f 1ae226bb3a arreglos a la subida de archivos 2021-02-23 19:16:58 -03:00
f c050d861bf generar imágenes a demanda
relacionado con #213
closes #309
closes #310
closes #311
closes #312
closes #313
2021-02-23 19:00:38 -03:00
f 2a395dcc48 sugerir un sku 2021-02-22 18:22:21 -03:00
f 7d9acab840 mantener el atributo id para las notas al pie 2021-02-22 17:06:55 -03:00
f 5dd2108b2d dependencias de babel para compilar assets
por alguna razón la primera vez no recompiló los assets y subimos el
contenedor sin js, luego empezó a fallar y así fuimos instalando
dependencias.

al parecer webpack y @rails/webpacker generan conflictos entre sí.
2021-02-22 12:29:07 -03:00
f a1b2f852e2 botones con iconos y otros arreglos 2021-02-19 17:57:19 -03:00
f ab86019286 emprolijar barra de herramientas 2021-02-19 14:31:38 -03:00
f 0b86702bdb Merge branch 'rails' into void/editor 2021-02-19 14:07:11 -03:00
f f4a130b97e agregar extensión para concurrencia más veloz
andá a saber cómo vamos a medir esto :P
2021-02-19 14:05:49 -03:00
void 7cf35a98c4 editor: i18n en la template 2021-02-18 21:43:47 +00:00
void 8212c323ca editor: fallar cuando se intenta subir sin archivo 2021-02-18 21:42:53 +00:00
void d5592fffb4 WIP: multimedia 2021-02-18 21:29:48 +00:00
f b38db8f988 tests de reordenamiento 2021-02-17 18:51:41 -03:00
f 737416488b garantizar que PostRelation siempre usa la misma colección/idioma 2021-02-17 18:46:00 -03:00
f 6edd9e67a2 simplificar MetadataSlug 2021-02-17 18:44:28 -03:00
f 0c6b85c030 preparar MetadataFactory para poder llamar métodos estáticos 2021-02-17 18:41:42 -03:00
f aa66e2cc9b obtener el valor correo para value_was 2021-02-17 18:40:07 -03:00
f 1a2d7931e9 optimizar posts
* eliminar dependencia en OpenStruct
* los metadata se instancian a medida que se usan
* la lista de atributos se envió a Layout
2021-02-17 18:39:21 -03:00
f d3890a6117 saltearse archivos ya migrados 2021-02-16 18:08:42 -03:00
void 704616b18e editor: hacer que el color de mark se pueda cambiar 2021-02-14 00:07:38 +00:00
void 1759d0f680 editor: arreglar bug raro de scss hardcodeando variable 2021-02-13 23:51:10 +00:00
void 4dfba17941 editor: fixes y links 2021-02-13 01:15:27 +00:00
void a45d3c898f editor: mejorar estilos y agregar borde a todo 2021-02-13 00:01:53 +00:00
void e60dcf70fe WIP: propiedades 2021-02-12 23:04:01 +00:00
void 0602c6ccb8 editor: hacer que sea posible poner parentBlocks y reestructurar 2021-02-12 22:18:48 +00:00
void c9d0fb87a4 actualizar dependencias de yarn y agregar un coso
que detecta dependencias ciruclares en el javascript
2021-02-12 22:17:58 +00:00
void 570752edec borrar <script> y <style> 2021-02-12 21:01:22 +00:00
void 792047d4c8 WIP: arreglar espacios al final de la linea y <i>/<b> 2021-02-12 20:33:23 +00:00
void 6489680c57 WIP: arreglar marcado de cosas entre varios elementos 2021-02-12 19:10:55 +00:00
void 52f9fe5b22 WIP: revamp del editor
"reescribir" en typescript y simplificar cosas.. esto es una prueba por
ahora
2021-02-12 15:57:23 +00:00
f 16b92e846d belongs_to => has_many
closes #266
closes #267
2021-02-12 11:26:00 -03:00
f 9c448f1173 crear los subdominios para ipv6 2021-02-11 19:33:18 -03:00
f c71bec2182 typo + rubocop 2021-02-11 18:41:52 -03:00
f 863fd684b4 asegurarse que siempre se compilan los assets 2021-02-11 18:08:55 -03:00
f 522494de5a validar relaciones correctamente 2021-02-11 17:57:12 -03:00
f 17d0ab6df3 validar fechas en navegadores que no las soportan
closes 168
2021-02-11 17:49:49 -03:00
f 2fb79ffa15 arreglos menores 2021-02-11 16:45:03 -03:00
f c5cd07a82e revisión de habtm 2021-02-11 16:44:36 -03:00
f bbdbfc4ee1 renovar relaciones 2021-02-11 16:17:45 -03:00
f c2f5c22fc2 revisión de has many 2021-02-11 16:16:25 -03:00
f 5fdc170db0 mostrar el valor de la relación y actualizarla bidireccionalmente
closes #226
2021-02-11 15:27:44 -03:00
f 69159e6749 aunque el archivo sea obligatorio la descripcion no lo es 2021-02-11 12:13:53 -03:00
f 419749b912 poder vaciar arrays closes #219 2021-02-11 12:13:18 -03:00
f 360b999dcb la opción required tiene más prioridad que la definición closes #217 2021-02-11 11:49:15 -03:00
f 12756e3d6a actualización de cuidados 2021-02-11 11:30:59 -03:00
f 3b015e0c22 excepciones con contexto
closes #255
closes #256
closes #257
closes #258
closes #259
2021-02-11 11:26:17 -03:00
f 77e71f6a66 asegurarse que la protección csfr se realiza primero #239 #238 #237 #232 2021-02-10 19:32:48 -03:00
void 9d855ee8ba WIP: simplificar subida de multimedia 2021-02-10 21:28:36 +00:00
void c0084d5d1f makefile: agregar serve-js 2021-02-10 16:21:19 +00:00
void 9da4e7492c actualizar puma por que rompe el SSL en dev 2021-02-10 16:18:32 +00:00
void 42dcf06d27 webpacker: arreglar webpack-dev-server 2021-02-10 16:17:37 +00:00
f 69f1687962 capturar el evento de envío del formulario closes #231 2021-02-04 14:03:53 -03:00
f 6467f6b09c alpine 3.13 2021-02-04 13:00:53 -03:00
f ceadb318b4 actualización de cuidados 2021-02-02 19:39:38 -03:00
f a61f2a39ad ruby 2.7.2 2021-02-02 19:32:17 -03:00
f 9e4e2f4d6a autoconfigurar airbrake 2021-02-02 18:52:54 -03:00
f 143e392ab5 Merge branch 'editor' into rails 2021-02-02 17:36:21 -03:00
void 8f4566f06c editor: elegir el elemento correcto al seleccionar 2021-02-02 20:30:19 +00:00
void cd091d2e30 editor: arreglar otra vez la selección en un documento vacio 2021-02-02 20:13:50 +00:00
void db0a32a930 Merge branch 'editor-en-webpack' into editor 2021-02-02 20:00:32 +00:00
void e87991af48 editor: tagName no es un setter! 2021-02-02 19:48:47 +00:00
f 013b7e5ed7 Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-02-02 16:39:27 -03:00
f 73ee9e4d15 WIP: editor en webpack
mover el editor a webpack para tener mejores stacktraces

algunas funciones que se usan en types.js se definían en editor.js

conversión a arrow functions para tener consistencia en la sintaxis

cleanContent() falla diciendo que tagName no es un setter
2021-02-02 16:38:36 -03:00
void 8ae8ffeb2b editor: arreglar selección cuando no hay nada en el editor
esto se rompió en 8887932bee
2021-02-02 19:34:58 +00:00
f 86bee68b8a Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-02-02 14:59:24 -03:00
void 0c844a5c94 editor: borrar código usando createObjectURL
está deprecado por Chrome y de todas formas hay cosas que no funcionaban
por el content policy. hay algunos lugares en los que se podría arreglar
(con MediaStream) pero IMO no tiene sentido
2021-02-02 17:44:10 +00:00
void 8887932bee editor: no se por que falla esto
pero es medio chota la forma en que lo hace así que no me sorprende.
igualmente esto no debería pasar.
2021-02-02 17:20:54 +00:00
void 812f5aab2a editor: getRangeAt puede fallar 2021-02-02 17:20:32 +00:00
void 9514ff7e24 editor: arreglar bug de los espacios 2021-02-02 17:00:42 +00:00
f 9c12449dae aviso de deprecación de rails 6 2021-01-25 16:47:19 -03:00
f 61423f03a6 pasar valores de airbrake como variables de entorno
y asegurarse que siempre respondamos con una llave aunque no se guarde
2021-01-25 16:08:29 -03:00
f 996c70f298 guardar la fecha de modificación en el archivo
last_modified_at es utilizada por jekyll-feed y otros plugins, aunque
nos hubiera gustado updated_at
2021-01-25 15:29:14 -03:00
f c5faba9a6b al aceptar una invitación aceptar la invitación al sitio también 2021-01-11 13:22:11 -03:00
f a77be964fa aclarar la invitación a la tienda 2021-01-11 13:13:41 -03:00
f adf579d3a1 cuando las invitaciones vencen les usuaries no se pueden volver a loguear 2021-01-11 12:20:48 -03:00
void 70ed3476e4 Merge branch 'rails' of 0xacab.org:sutty/sutty into rails 2021-01-09 19:22:34 +00:00
void 3535ea057f editor: arreglar el aviso de word
al pegar, ahora si se muestra un aviso de word, y se arregló el css
para que no tape el texto del editor.
2021-01-09 19:20:59 +00:00
void 805780730d editor: arreglar marks con propiedades con otras marks adentro 2021-01-09 19:20:29 +00:00
void 9cdcaf3cb3 editor: arreglar inconsistencia entre navegadores que hace que chrome sea inutilizable
amo que los navegadores funcionen de formas completamente distintas!
Object.values(element.style) da las propiedades seteadas explicitamente
con style="" en firefox, pero en chrome da TODAS las propiedades
posibles, generando un bug y un problema gigante de performance (ya que
esta funcion corre cada vez que pasa cualquier cosa en el editor).
2021-01-09 19:18:35 +00:00
f 66875efa73 entorno de trabajo 2021-01-09 14:25:41 -03:00
f 3a3b39a2ac compilar todas las gemas binarias 2021-01-05 12:01:19 -03:00
f 475cb970bc actualización de cuidados 2021-01-05 12:00:32 -03:00
f 61d18f37b4 implementar safe_yaml con parche de performance #177 2020-12-30 13:48:24 -03:00
f ac013b5d6e agregar el repositorio git para poder hacer pull 2020-12-29 15:10:50 -03:00
f e2d4ef6c9e ya aceptaron nuestro parche en prometheus_exporter 2020-12-29 15:10:35 -03:00
f 49bbc97db6 archivos faltantes durante la actualización de rails 🙈 2020-12-29 14:41:25 -03:00
f 02b05efcb9 actualizar a jekyll 4.2 2020-12-29 14:40:51 -03:00
f 8b984eafe6 si el artículo es nuevo usar el layout como cache_key closes #224 2020-12-28 17:55:39 -03:00
f 8fa21aa315 quitar el filtro 2020-12-24 16:25:45 -03:00
f c338cb87de guardar fechas 2020-12-24 16:13:29 -03:00
f 3f19e79366 actualización a rails 6.1 2020-12-24 15:02:03 -03:00
f f7828127d8 enviar la dirección de origen con el formulario de contacto 2020-12-24 12:50:33 -03:00
f 5900e63b07 filtrar por tipo de artículo 2020-12-24 12:36:38 -03:00
f 9225ae7ce8 seleccionar artículos con el estilo de sutty 2020-12-24 12:35:58 -03:00
f 42d22458a0 eliminar comillas del layout 2020-12-14 12:20:39 -03:00
f b113432032 si el rol no es temporal la usuaria ya aceptó la invitación 2020-12-09 10:46:00 -03:00
f d83b32d4fd faltaba el selector de clase 2020-12-09 10:09:46 -03:00
f 1006f6b4c5 typo al aceptar invitación 2020-12-09 10:05:00 -03:00
f dc12ee27f9 el preflight va a impedir que se envíe 2020-12-08 20:40:03 -03:00
f 077a43ed65 Revert "cors simplificado"
This reverts commit 2a97fa8174.
2020-12-08 20:37:26 -03:00
f 2a97fa8174 cors simplificado 2020-12-08 20:22:26 -03:00
f dd89451e55 cors 2020-12-08 20:21:42 -03:00
f 20f5acacb8 hacer una sola consulta
friendly_id primero busca por nombre y despues por id
2020-12-08 19:36:09 -03:00
f 893d79f7fd un poco más robusto 2020-12-08 18:51:41 -03:00
f 695f12ad0f primer bug encontrado gracias a nuestro airbrake :B 2020-12-08 09:53:14 -03:00
f 47a6222363 simplificar compilación de assets 2020-12-07 15:43:09 -03:00
f baa7d58715 enviar más información 2020-12-07 15:27:24 -03:00
f e53a560af0 solo descargar archivos del sitio, faltaba la migración 2020-12-07 13:36:09 -03:00
f 0ce42f17b5 ignorar todos los entornos de configuración 2020-12-07 13:23:07 -03:00
f 9e35867ed5 ruboyuta 2020-12-07 13:22:29 -03:00
f 8d36b5734e no fallar si la configuración no existe 2020-12-07 13:22:15 -03:00
f 42c7e7006a mini airbrake para poder hacer seguimiento de js 2020-12-07 13:21:46 -03:00
f cc6efb095b no fallar si no hay cuerpo en la vista previa 2020-12-02 10:16:56 -03:00
f 1fb53168e2 los artículos filtrados también tienen un sitio 2020-11-27 20:54:29 -03:00
f 227e48681e algunos layouts pueden estar escondidos 2020-11-27 20:53:14 -03:00
f 1ac4e02bf9 recordar la relación inversa 2020-11-27 20:51:56 -03:00
f 2f6aeaf63f la nueva yuta 2020-11-27 19:32:33 -03:00
f ac82d609d4 permitir cambiar la base de los formularios 2020-11-27 19:32:16 -03:00
f e28a14e8b0 poder gestionar usuaries desde el sitio mismo 2020-11-26 15:47:41 -03:00
f ac58a56882 poder enviar varias invitaciones por vez 2020-11-26 15:47:05 -03:00
698 changed files with 24103 additions and 7947 deletions

View file

@ -1,10 +1,5 @@
# Excluir todo
*
# Solo agregar lo que usamos en COPY
!./.git/
!./rubygems-platform-musl.patch
!./Gemfile
!./Gemfile.lock
!./config/credentials.yml.enc
!./public/assets-production/
!./public/packs-production/
# !./archivo
!./monit.conf

11
.editorconfig Normal file
View file

@ -0,0 +1,11 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 2
[Makefile]
indent_style = tab

43
.env Normal file
View file

@ -0,0 +1,43 @@
NODE_OPTIONS=--openssl-legacy-provider
# pwgen -1 32
RAILS_MASTER_KEY=11111111111111111111111111111111
RAILS_GROUPS=assets
DELEGATE=panel.sutty.nl
DATABASE_URL=postgres://suttier@postgresql.sutty.local/sutty
RAILS_ENV=development
IMAP_SERVER=
DEFAULT_FROM=
EXCEPTION_TO=
SKEL_SUTTY=https://0xacab.org/sutty/skel.sutty.nl
# XXX: Si cambiás esta variable, tenés que editar config/webpacker.yml también :(
SUTTY=sutty.local
SUTTY_WITH_PORT=sutty.local:3000
REDIS_SERVER=
REDIS_CLIENT=
# API authentication
HTTP_BASIC_USER=
HTTP_BASIC_PASSWORD=
# Blazer
BLAZER_DATABASE_URL=
BLAZER_SLACK_WEBHOOK_URL=
BLAZER_USERNAME=
BLAZER_PASSWORD=
# Guardar los formularios enviados como LogEntries
# @see Api::V1::ProtectedController
DEBUG_FORMS=
# Duración de la Cookie de invitade
# @see Api::V1::ProtectedController
COOKIE_DURATION=30
# Dominio de la tienda
TIENDA=tienda.sutty.local
# Obtener esto con Site.find_by_name('panel').airbrake_api_key
PANEL_URL=https://panel.sutty.nl
AIRBRAKE_SITE_ID=1
AIRBRAKE_API_KEY=
GITLAB_URI=https://0xacab.org
GITLAB_PROJECT=
GITLAB_TOKEN=
PGVER=15
PGPID=/run/postgresql.pid
PANEL_ACTOR_MENTION=@sutty@sutty.nl
PANEL_ACTOR_SITE_ID=1

1
.env.development Normal file
View file

@ -0,0 +1 @@
HAINISH=../haini.sh/haini.sh

View file

@ -1,24 +0,0 @@
RAILS_ENV=
IMAP_SERVER=
DEFAULT_FROM=
SKEL_SUTTY=https://0xacab.org/sutty/skel.sutty.nl
SUTTY=sutty.local
SUTTY_WITH_PORT=sutty.local:3000
REDIS_SERVER=
REDIS_CLIENT=
# API authentication
HTTP_BASIC_USER=
HTTP_BASIC_PASSWORD=
# Blazer
BLAZER_DATABASE_URL=
BLAZER_SLACK_WEBHOOK_URL=
BLAZER_USERNAME=
BLAZER_PASSWORD=
# Guardar los formularios enviados como LogEntries
# @see Api::V1::ProtectedController
DEBUG_FORMS=
# Duración de la Cookie de invitade
# @see Api::V1::ProtectedController
COOKIE_DURATION=30
# Dominio de la tienda
TIENDA=tienda.sutty.local

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
public/assets/** filter=lfs diff=lfs merge=lfs -text
public/packs/** filter=lfs diff=lfs merge=lfs -text

13
.gitignore vendored
View file

@ -28,18 +28,13 @@
/data/*
/_storage/*
.env
.env.*
# Ignore master key for decrypting credentials and more.
/config/master.key
/config/credentials.yml.enc
/public/packs
/public/packs-test
/public/assets
/public/assets-production
/public/packs
/public/packs-production
/node_modules
/yarn-error.log
yarn-debug.log*
@ -49,9 +44,11 @@ yarn-debug.log*
*.key
*.crt
/public/packs
/public/packs-test
/node_modules
/yarn-error.log
yarn-debug.log*
.yarn-integrity
/.task
/.yardoc
/public/doc/

124
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,124 @@
.apk-add: &apk-add
- "apk add go-task diffutils gitlab_ci_log_section"
.disable-hainish: &disable-hainish
- "rm -f .env.development"
.cache-ruby: &cache-ruby
- paths:
- "vendor/ruby"
- ".bundle"
key:
files:
- "Gemfile.lock"
.cache-node: &cache-node
- paths:
- "node_modules"
key:
files:
- "yarn.lock"
.cache-task: &cache-task
- paths:
- ".task"
image: "registry.0xacab.org/sutty/sutty:3.17.3-3.1.4-rails"
variables:
RAILS_ENV: "production"
LC_ALL: "C.UTF-8"
HAINISH: ""
cache:
push:
stage: "deploy"
only:
- "rails"
except:
- "schedules"
before_script:
- "git config --global user.email \"${GIT_USER_EMAIL:-$GITLAB_USER_EMAIL}\""
- "git config --global user.name \"${GIT_USER_NAME:-$GITLAB_USER_NAME}\""
- "git remote set-url --push origin \"https://GITLAB_CI_PUSH_TOKEN:${GITLAB_CI_PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git\""
script:
- "git commit --allow-empty -m \"ci: test [skip ci]\""
- "git push -o ci.skip origin HEAD:${CI_COMMIT_BRANCH}"
assets:
stage: "deploy"
only:
- "rails"
- "production.panel.sutty.nl"
- "panel.sutty.nl"
except:
- "schedules"
cache:
- *cache-ruby
- *cache-node
- *cache-task
before_script:
- *apk-add
- "gitlab_ci_log_section --name git --header=\"Configuring git\""
- "git config --global user.email \"${GIT_USER_EMAIL:-$GITLAB_USER_EMAIL}\""
- "git config --global user.name \"${GIT_USER_NAME:-$GITLAB_USER_NAME}\""
- "git remote set-url --push origin \"https://GITLAB_CI_PUSH_TOKEN:${GITLAB_CI_PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git\""
- "gitlab_ci_log_section --name git --end"
- "gitlab_ci_log_section --name apk --header=\"Installing dependencies\""
- "apk add brotli"
- *disable-hainish
- "gitlab_ci_log_section --name apk --end"
script:
- "gitlab_ci_log_section --name assets --header=\"Building\""
- "go-task assets"
after_script:
- "git add public && git commit -m \"ci: assets [skip ci]\""
- "git push -o ci.skip origin HEAD:${CI_COMMIT_BRANCH}"
gem-audit:
stage: "test"
only:
- "schedules"
cache:
- *cache-ruby
before_script:
- *apk-add
- *disable-hainish
script:
- "go-task gem-audit"
node-audit:
stage: "test"
only:
- "schedules"
cache:
- *cache-node
before_script:
- *apk-add
- *disable-hainish
script:
- "apk add go-task"
- "go-task node-audit"
brakeman:
stage: "test"
cache:
- *cache-ruby
rules:
- if: "$CI_PIPELINE_SOURCE == 'merge_request_event'"
before_script:
- *apk-add
- *disable-hainish
script:
- "go-task bundle -- exec brakeman"
rubocop:
stage: "test"
cache:
- *cache-ruby
rules:
- if: "$CI_PIPELINE_SOURCE == 'merge_request_event'"
before_script:
- *apk-add
- *disable-hainish
script:
- "go-task rubocop"
haml:
stage: "test"
cache:
- *cache-ruby
rules:
- if: "$CI_PIPELINE_SOURCE == 'merge_request_event'"
before_script:
- *apk-add
- *disable-hainish
script:
- "go-task haml-lint"

9
.profile Normal file
View file

@ -0,0 +1,9 @@
Color_Off='\e[0m'
BPurple='\e[1;35m'
BBlue='\e[1;34m'
is_git() {
git rev-parse --abbrev-ref HEAD 2>/dev/null
}
PS1="\[${BPurple}\]\$(is_git) \[${BBlue}\]\W\[${Color_Off}\] >_ "

View file

@ -1,5 +1,6 @@
AllCops:
TargetRubyVersion: '2.7'
NewCops: enable
Style/AsciiComments:
Enabled: false

View file

@ -1 +0,0 @@
2.7.1

33
.woodpecker.yml Normal file
View file

@ -0,0 +1,33 @@
pipeline:
publish:
image: "docker.io/woodpeckerci/plugin-docker-buildx"
settings:
registry: "gitea.nulo.in"
username: "sutty"
repo: "gitea.nulo.in/sutty/panel"
tags:
- "${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH}-${CI_COMMIT_BRANCH}"
- "latest"
build_args:
- "RUBY_VERSION=${RUBY_VERSION}"
- "RUBY_PATCH=${RUBY_PATCH}"
- "ALPINE_VERSION=${ALPINE_VERSION}"
- "BASE_IMAGE=gitea.nulo.in/sutty/rails"
purge: false
secrets:
- "DOCKER_PASSWORD"
when:
branch:
- "rails"
- "17.3.alpine.panel.sutty.nl"
event: "push"
path:
include:
- "Dockerfile"
- ".dockerignore"
- ".woodpecker.yml"
matrix:
include:
- ALPINE_VERSION: "3.17.3"
RUBY_VERSION: "3.1"
RUBY_PATCH: "4"

View file

@ -1,130 +1,30 @@
# Este Dockerfile está armado pensando en una compilación lanzada desde
# el mismo repositorio de trabajo. Cuando tengamos CI/CD algunas cosas
# como el tarball van a tener que cambiar porque ya vamos a haber hecho
# un clone/pull limpio.
FROM alpine:3.12 AS build
MAINTAINER "f <f@sutty.nl>"
ARG RAILS_MASTER_KEY
# Un entorno base
ENV SECRET_KEY_BASE solo_es_necesaria_para_correr_rake
ARG RUBY_VERSION=3.1
ARG RUBY_PATCH=4
ARG ALPINE_VERSION=3.17.3
ARG BASE_IMAGE=registry.nulo.in/sutty/rails
FROM ${BASE_IMAGE}:${ALPINE_VERSION}-${RUBY_VERSION}.${RUBY_PATCH}
ARG PANDOC_VERSION=2.18
ENV RAILS_ENV production
ENV RAILS_MASTER_KEY=$RAILS_MASTER_KEY
RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-bundler ruby-json ruby-bigdecimal ruby-rake
RUN apk add --no-cache postgresql-libs git yarn brotli libssh2 python3
RUN test "2.7.1" = `ruby -e 'puts RUBY_VERSION'`
# https://github.com/rubygems/rubygems/issues/2918
# https://gitlab.alpinelinux.org/alpine/aports/issues/10808
RUN apk add --no-cache patch
COPY ./rubygems-platform-musl.patch /tmp/
RUN cd /usr/lib/ruby/2.7.0 && patch -Np 0 -i /tmp/rubygems-platform-musl.patch
# Agregar el usuario
RUN addgroup -g 82 -S www-data
RUN adduser -s /bin/sh -G www-data -h /home/app -D app
RUN install -dm750 -o app -g www-data /home/app/sutty
RUN gem install --no-document bundler
# Empezamos con la usuaria app
USER app
# Vamos a trabajar dentro de este directorio
WORKDIR /home/app/sutty
# Copiamos solo el Gemfile para poder instalar las gemas necesarias
COPY --chown=app:www-data ./Gemfile .
COPY --chown=app:www-data ./Gemfile.lock .
RUN bundle config set no-cache 'true'
RUN bundle install --path=./vendor --without='test development'
# Vaciar la caché
RUN rm vendor/ruby/2.7.0/cache/*.gem
# Copiar el repositorio git
COPY --chown=app:www-data ./.git/ ./.git/
# Hacer un clon limpio del repositorio en lugar de copiar todos los
# archivos
RUN cd .. && git clone sutty checkout
WORKDIR /home/app/checkout
# Traer las gemas:
RUN mv ../sutty/vendor ./vendor
RUN mv ../sutty/.bundle ./.bundle
# Instalar secretos
COPY --chown=app:root ./config/credentials.yml.enc ./config/
# Traer los assets pre-compilados
COPY --chown=app:www-data ./public/assets-production ./public/assets
COPY --chown=app:www-data ./public/packs-production ./public/packs
# Eliminar la necesidad de un runtime JS en producción, porque los
# assets ya están pre-compilados.
RUN sed -re "/(sassc|uglifier|bootstrap|coffee-rails)/d" -i Gemfile
RUN bundle clean
RUN rm -rf ./node_modules ./tmp/cache ./.git ./test ./doc
# Eliminar archivos innecesarios
USER root
RUN apk add --no-cache findutils
RUN find /home/app/checkout/vendor/ruby/2.7.0 -maxdepth 3 -type d -name test -o -name spec -o -name rubocop | xargs -r rm -rf
RUN cd /home/app/checkout/vendor/ruby/2.7.0/gems/prometheus_exporter-0.5.3 && patch -Np 0 -i /home/app/checkout/prom.patch
# Contenedor final
FROM sutty/monit:latest
ENV RAILS_ENV production
# Pandoc
RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/repositories
# Instalar las dependencias, separamos la librería de base de datos para
# poder reutilizar este primer paso desde otros contenedores
RUN apk add --no-cache libxslt libxml2 tzdata ruby ruby-bundler ruby-json ruby-bigdecimal ruby-rake ruby-irb
RUN apk add --no-cache postgresql-libs libssh2 file rsync git jpegoptim vips
RUN apk add --no-cache ffmpeg imagemagick pandoc tectonic oxipng jemalloc
RUN apk add --no-cache git-lfs
# Chequear que la versión de ruby sea la correcta
RUN test "2.7.1" = `ruby -e 'puts RUBY_VERSION'`
# https://github.com/rubygems/rubygems/issues/2918
# https://gitlab.alpinelinux.org/alpine/aports/issues/10808
COPY ./rubygems-platform-musl.patch /tmp/
RUN apk add --no-cache patch && cd /usr/lib/ruby/2.7.0 && patch -Np 0 -i /tmp/rubygems-platform-musl.patch && apk del patch
#
# Necesitamos yarn para que Jekyll pueda generar los sitios
# XXX: Eliminarlo cuando extraigamos la generación de sitios del proceso
# principal
RUN apk add --no-cache yarn
# Instalar foreman para poder correr los servicios
RUN gem install --no-document --no-user-install bundler foreman
RUN apk add --no-cache libxslt libxml2 postgresql-libs libssh2 \
rsync git jpegoptim vips tectonic oxipng git-lfs openssh-client \
yarn daemonize ruby-webrick postgresql-client dateutils file
# Agregar el grupo del servidor web y la usuaria
RUN addgroup -g 82 -S www-data
RUN adduser -s /bin/sh -G www-data -h /srv/http -D app
RUN gem install --no-document --no-user-install foreman
RUN wget https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/pandoc-${PANDOC_VERSION}-linux-amd64.tar.gz -O - | tar --strip-components 1 -xvzf - pandoc-${PANDOC_VERSION}/bin/pandoc && mv /bin/pandoc /usr/bin/pandoc
RUN apk add npm && npm install -g pnpm@~7 && apk del npm
# Convertirse en app para instalar
USER app
COPY --from=build --chown=app:www-data /home/app/checkout /srv/http
RUN rm -rf /srv/http/_sites /srv/http/_deploy
RUN ln -s data/_storage /srv/http/_storage
RUN ln -s data/_sites /srv/http/_sites
RUN ln -s data/_deploy /srv/http/_deploy
RUN ln -s data/_public /srv/http/_public
RUN ln -s data/_private /srv/http/_private
COPY ./monit.conf /etc/monit.d/sutty.conf
# Volver a root para cerrar la compilación
USER root
# Sincronizar los assets a un directorio compartido
RUN install -m 755 /srv/http/sync_assets.sh /usr/local/bin/sync_assets
# Instalar la configuración de monit
RUN install -m 640 -o root -g root /srv/http/monit.conf /etc/monit.d/sutty.conf
RUN apk add --no-cache daemonize ruby-webrick
RUN install -m 755 /srv/http/entrypoint.sh /usr/local/bin/sutty
RUN apk add npm && npm install -g pnpm && apk del npm
# Mantener estos directorios!
VOLUME "/srv/http/data"
VOLUME "/srv"
# El puerto de puma
EXPOSE 3000
EXPOSE 9394

116
Gemfile
View file

@ -1,35 +1,26 @@
# frozen_string_literal: true
# TODO: Podríamos usar solo gems.sutty.nl pero por alguna razón bundler
# prefiere x86_64-linux-musl antes que x86_64-linux y ya perdimos mucho
# tiempo buscando soporte para musl
if ENV['RAILS_ENV'] == 'production'
source 'https://gems.sutty.nl'
else
source 'https://rubygems.org'
end
source ENV.fetch('GEMS_SOURCE', 'https://17.3.alpine.gems.sutty.nl')
git_source(:github) do |repo_name|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?('/')
"https://github.com/#{repo_name}.git"
end
# Cambiar en Dockerfile también
ruby '2.7.1'
gem 'dotenv-rails', require: 'dotenv/rails-now'
ruby "~> #{ENV.fetch('RUBY_VERSION', '3.1')}"
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 6'
gem 'rails', '~> 6.1.0'
# Use Puma as the app server
gem 'puma'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
# Use SCSS for stylesheets
gem 'sassc-rails'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
gem 'bootstrap', '~> 4'
# Solo incluir las gemas cuando estemos en desarrollo o compilando los
# assets. No es necesario instalarlas en producción.
#
# XXX: Supuestamente Rails ya soporta RAILS_GROUPS, pero Bundler no.
if ENV['RAILS_GROUPS']&.split(',')&.include? 'assets'
gem 'sassc-rails'
gem 'uglifier', '>= 1.3.0'
gem 'bootstrap', '~> 4'
end
gem 'nokogiri'
gem 'rgl'
# Turbolinks makes navigating your web application faster. Read more:
# https://github.com/turbolinks/turbolinks
@ -39,12 +30,17 @@ gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.5'
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
gem 'safely_block', '~> 0.3.0'
gem 'blazer'
gem 'chartkick'
gem 'commonmarker'
gem 'devise'
gem 'devise-i18n'
gem 'devise_invitable'
gem 'email_address'
gem 'redis-client'
gem 'hiredis-client'
gem 'distributed-press-api-client', '~> 0.4.1'
gem 'email_address', git: 'https://github.com/fauno/email_address', branch: 'i18n'
gem 'exception_notification'
gem 'fast_blank'
gem 'friendly_id'
@ -53,31 +49,47 @@ gem 'hiredis'
gem 'image_processing'
gem 'icalendar'
gem 'inline_svg'
gem 'jekyll', git: 'https://0xacab.org/sutty/jekyll/jekyll.git',
branch: 'master'
gem 'jekyll-data', require: 'jekyll-data',
git: 'https://0xacab.org/sutty/jekyll/jekyll-data.git'
gem 'jekyll-commonmark'
gem 'httparty'
gem 'safe_yaml', require: false
gem 'jekyll', '~> 4.2.0'
gem 'jekyll-commonmark', '~> 1.4.0'
gem 'jekyll-images'
gem 'jekyll-include-cache'
gem 'sutty-liquid'
gem 'sutty-liquid', '>= 0.7.3'
gem 'loaf'
gem 'lockbox'
gem 'mini_magick'
gem 'mobility'
gem 'pg'
gem 'pundit'
gem 'rails-i18n'
gem 'rails_warden'
gem 'redis', require: %w[redis redis/connection/hiredis]
gem 'redis', '~> 4.0', require: %w[redis redis/connection/hiredis]
gem 'redis-rails'
gem 'rollups', git: 'https://github.com/fauno/rollup.git', branch: 'update'
gem 'rubyzip'
gem 'rugged'
gem 'sucker_punch'
gem 'ruby-brs'
gem 'rugged', '1.5.0.1'
gem 'git_clone_url'
gem 'concurrent-ruby-ext'
gem 'que'
gem 'symbol-fstring', require: 'fstring/all'
gem 'terminal-table'
gem 'validates_hostname'
gem 'webpacker'
gem 'yaml_db', git: 'https://0xacab.org/sutty/yaml_db.git'
gem 'kaminari'
gem 'device_detector'
gem 'dry-schema'
gem 'rubanok'
gem 'after_commit_everywhere', '~> 1.0'
gem 'aasm'
gem 'que-web'
# database
gem 'hairtrigger'
gem 'pg'
gem 'pg_search'
# performance
gem 'flamegraph'
@ -86,17 +98,16 @@ gem 'rack-mini-profiler'
gem 'stackprof'
gem 'prometheus_exporter'
group :themes do
gem 'adhesiones-jekyll-theme', require: false
gem 'editorial-autogestiva-jekyll-theme', require: false
gem 'minima', require: false
gem 'sutty-minima', require: false
gem 'radios-comunitarias-jekyll-theme', require: false
gem 'share-to-fediverse-jekyll-theme', require: false
gem 'sutty-donaciones-jekyll-theme', require: false
gem 'sutty-jekyll-theme', require: false
gem 'recursero-jekyll-theme', require: false
end
# debug
gem 'fast_jsonparser', '~> 0.5.0'
gem 'down'
gem 'sourcemap'
gem 'rack-cors'
# ssh
gem 'net-ssh'
gem 'ed25519'
gem 'bcrypt_pbkdf'
group :production do
gem 'lograge'
@ -104,22 +115,25 @@ end
group :development, :test do
gem 'derailed_benchmarks'
gem 'dotenv-rails'
gem 'pry'
# Adds support for Capybara system testing and selenium driver
gem 'capybara', '~> 2.13'
gem 'selenium-webdriver'
gem 'selenium-webdriver', '~> 4.8.0'
gem 'sqlite3'
end
group :development do
gem 'yard'
gem 'brakeman'
gem 'bundler-audit'
gem 'haml-lint', require: false
gem 'letter_opener'
gem 'listen', '>= 3.0.5', '< 3.2'
gem 'listen'
gem 'rubocop-rails'
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
gem 'web-console', '>= 3.3.0'
gem 'spring-watcher-listen'
gem 'web-console'
end
group :test do

File diff suppressed because it is too large Load diff

View file

@ -1,88 +0,0 @@
# Incluir las variables de entorno
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
root_dir := $(patsubst %/,%,$(dir $(mkfile_path)))
include $(root_dir)/.env
delegate := athshe
assets := package.json yarn.lock $(shell find app/assets/ app/javascript/ -type f)
alpine_version := 3.12
public/assets-production/: $(assets)
RAILS_ENV=production bundle exec rake assets:precompile assets:clean
rsync --delete-after -a public/assets/ $@
public/packs-production/: public/packs/
rsync -a --delete-after $< $@
assets: public/assets-production/ public/packs-production/
serve:
bundle exec rails s -b "ssl://0.0.0.0:3000?key=../sutty.local/domain/sutty.local.key&cert=../sutty.local/domain/sutty.local.crt"
# Limpiar los archivos de testeo
clean:
rm -rf _sites/test-* _deploy/test-*
# Generar la imagen Docker
build: assets
time docker build --build-arg="RAILS_MASTER_KEY=`cat config/master.key`" -t sutty/sutty .
docker tag sutty/sutty:latest sutty:keep
save:
time docker save sutty/sutty:latest | ssh root@$(delegate).sutty.nl docker load
date +%F | xargs git tag -f
load:
ssh root@sutty.nl sh -c "gunzip -c sutty.latest.gz | docker load"
# Crear el directorio donde se almacenan las gemas binarias
../gems/:
mkdir -p $@
gem_dir := $(shell readlink -f ../gems)
ifeq ($(MAKECMDGOALS),build-gems)
gems := $(shell bundle show --paths | xargs -I {} sh -c 'test -f {}/ext/*/extconf.rb && basename {}')
gems += $(shell bundle show --paths | xargs -I {} sh -c 'test -f {}/ext/extconf.rb && basename {}')
gems := $(patsubst %,$(gem_dir)/cache/%.gem,$(gems))
gems_musl := $(patsubst $(gem_dir)/cache/%.gem,$(gem_dir)/$(alpine_version)/%-x86_64-linux-musl.gem,$(gems))
endif
$(gem_dir)/%-x86_64-linux-musl.gem:
@docker run \
-v $(gem_dir):/srv/gems \
-v `readlink -f ~/.ccache`:/home/builder/.ccache \
-e HTTP_BASIC_USER=$(HTTP_BASIC_USER) \
-e HTTP_BASIC_PASSWORD=$(HTTP_BASIC_PASSWORD) \
-e GEM=`echo $(notdir $*) | sed -re "s/-[^-]+$$//"` \
-e VERSION=`echo $(notdir $*) | sed -re "s/.*-([^-]+)$$/\1/"` \
-e JOBS=2 \
--rm -it \
sutty/gem-compiler:latest || echo "No se pudo compilar $*"
# Compilar todas las gemas binarias y subirlas a gems.sutty.nl para que
# al crear el contenedor no tengamos que compilarlas cada vez
build-gems: $(gems_musl)
cached_gems = $(wildcard $(gem_dir)/cache/*.gem)
rebuild_gems = $(patsubst $(gem_dir)/cache/%.gem,$(gem_dir)/$(alpine_version)/%-x86_64-linux-musl.gem,$(cached_gems))
rebuild-gems: $(rebuild_gems)
dirs := $(patsubst %,root/%,data sites deploy public)
$(dirs):
mkdir -p $@
test-container: $(dirs)
docker run -v $(PWD)/root/data:/srv/http/data \
-v $(PWD)/root/sites:/srv/http/_sites \
-v $(PWD)/root/deploy:/srv/http/_deploy \
-v $(PWD)/root/public:/srv/http/_public \
-v $(PWD)/config/credentials.yml.enc:/srv/http/config/credentials.yml.enc \
-e RAILS_MASTER_KEY=`cat config/master.key` \
-e RAILS_ENV=production \
-it \
--rm \
--name=sutty \
sutty/sutty /bin/sh

View file

@ -5,3 +5,9 @@ blazer_1h: bundle exec rake blazer:run_checks SCHEDULE="1 hour"
blazer_1d: bundle exec rake blazer:run_checks SCHEDULE="1 day"
blazer: bundle exec rake blazer:send_failing_checks
prometheus: bundle exec prometheus_exporter -b 0.0.0.0 --prefix "sutty_"
distributed_press_tokens_renew: bundle exec rake distributed_press:tokens:renew
cleanup: bundle exec rake cleanup:everything
emergency_cleanup: bundle exec rake cleanup:everything BEFORE=7
stats: bundle exec rake stats:process_all
que: daemonize -c /srv/ -p /srv/tmp/que.pid -u rails /usr/local/bin/syslogize bundle exec que
fediblock: bundle exec rails activity_pub:fediblocks

View file

@ -15,6 +15,35 @@ Este repositorio es la plataforma _Ruby on Rails_ para alojar el
Para más información visita el [sitio de Sutty](https://sutty.nl/).
### Desarrollar
Para facilitar la gestión de dependencias y entorno de desarrollo,
instala [haini.sh](https://0xacab.org/sutty/haini.sh)
Todas las tareas se gestionan con `go-task`. [Instrucciones de
instalación (en inglés)](https://taskfile.dev/installation/)
```bash
go-task
```
### Variables de entorno
Las variables de entorno por defecto se encuentran en el archivo `.env`.
Para modificar las opciones, crear o modificar el archivo `.env.local`
con valores distintos.
### Documentación
Para navegar la documentación del código usando YARD:
```bash
go-task doc serve
```
Y luego navegar a <https://panel.sutty.local:3000/doc/>
## English
Sutty is a platform for hosting safer, faster and more resilient
@ -25,3 +54,32 @@ This repository is the Ruby on Rails platform that hosts the
self-managed [panel](https://panel.sutty.nl/).
For more information, visit [Sutty's website](https://sutty.nl/en/).
### Development
To facilitate dependencies and dev environment, install
[haini.sh](https://0xacab.org/sutty/haini.sh)
Every task is run via `go-task`. [Installation
instructions](https://taskfile.dev/installation/).
```bash
go-task
```
### Environment variables
Default env vars are store on `.env`. For local options, copy them to
`.env.local`.
### Documentation
To browse documentation using YARD:
```bash
go-task doc serve
```
And then open <https://panel.sutty.local:3000/doc/>

197
Taskfile.yaml Normal file
View file

@ -0,0 +1,197 @@
---
version: "3"
vars:
CURRENT_BRANCH:
sh: "git rev-parse --abbrev-ref HEAD"
shopt:
- "globstar"
dotenv:
- ".env.development"
- ".env"
- ".env.local"
- ".env.development.local"
tasks:
credentials:
desc: "Generate credentials file"
cmds:
- "cp --no-clobber config/credentials.yml.enc.ci config/credentials.yml.enc"
sources:
- "config/credentials.yml.enc.ci"
generates:
- "config/credentials.yml.enc"
gems:
desc: "Install gems"
deps:
- "credentials"
cmds:
- "{{.HAINISH}} bundle config set --local path './vendor'"
- "{{.HAINISH}} bundle install"
sources:
- "Gemfile"
generates:
- "Gemfile.lock"
status:
- "test -d vendor/ruby"
clean:
desc: "Clean"
cmds:
- "rm -rf _sites/test-* _deploy/test-* log/*.log tmp/cache tmp/letter_opener tmp/miniprofiler tmp/storage"
node-modules:
desc: "Install Node modules"
cmds:
- "{{.HAINISH}} yarn"
sources:
- "package.json"
- "yarn.lock"
status:
- "test -d node_modules"
assets:
desc: "Generate assets"
deps:
- "node-modules"
- "gems"
cmds:
- "git lfs fetch"
- "git lfs checkout"
- task: "rails"
vars:
CLI_ARGS: "webpacker:clobber RAILS_ENV=production"
- task: "rails"
vars:
CLI_ARGS: "assets:precompile RAILS_ENV=production"
- task: "rails"
vars:
CLI_ARGS: "assets:clean RAILS_ENV=production"
sources:
- "package.json"
- "yarn.lock"
- "app/assets/**/*"
- "app/javascript/**/*"
generates:
- "public/packs/manifest.json"
hosts:
desc: "Local DNS resolution for hostnames"
interactive: true
cmds:
- "echo -e \"127.0.0.1 panel.{{.SUTTY}} api.{{.SUTTY}} postgresql.{{.SUTTY}}\" | sudo tee -a /etc/hosts"
- "echo -e \"::1 panel.{{.SUTTY}} api.{{.SUTTY}} postgresql.{{.SUTTY}}\" | sudo tee -a /etc/hosts"
status:
- "grep -q \" panel.{{.SUTTY}} \" /etc/hosts"
database-init:
desc: "Database install"
cmds:
- "{{.HAINISH}} /usr/bin/initdb --locale en_US.utf8 -E UTF8 -D /var/lib/postgresql/{{.PGVER}}/data"
- "echo \"host all all samenet trust\" >> ../hain/var/lib/postgresql/{{.PGVER}}/data/pg_hba.conf"
- "echo \"listen_addresses = '*'\" >> ../hain/var/lib/postgresql/{{.PGVER}}/data/postgresql.conf"
- "echo \"external_pid_file = '{{.PGPID}}'\" >> ../hain/var/lib/postgresql/{{.PGVER}}/data/postgresql.conf"
- "install -dm755 ../hain/run/postgresql"
status:
- "test -d ../hain/var/lib/postgresql/{{.PGVER}}/data"
- "test -f ../hain/var/lib/postgresql/{{.PGVER}}/data/postgresql.conf"
database:
desc: "Database"
deps:
- "database-init"
cmds:
- "{{.HAINISH}} daemonize -c /var/lib/postgresql/{{.PGVER}}/data /usr/bin/postgres -D /var/lib/postgresql/{{.PGVER}}/data"
status:
- "test -f ../hain{{.PGPID}}"
- "pgrep -F ../hain{{.PGPID}}"
prepare:
desc: "Create database or run pending migrations"
deps:
- "database"
cmds:
- task: "rails"
vars:
CLI_ARGS: "db:prepare"
serve:
desc: "Run Rails development server"
deps:
- "prepare"
- "gems"
cmds:
- ": == Development server running at https://panel.{{.SUTTY_WITH_PORT}} =="
- task: "rails"
vars:
CLI_ARGS: "server"
status:
- "test -f tmp/pids/server.pid"
- "pgrep -F tmp/pids/server.pid"
yarn:
desc: "Yarn. Call with: go-task yarn -- arguments"
deps:
- "node-modules"
cmds:
- "{{.HAINISH}} yarn {{.CLI_ARGS}}"
- defer:
task: "notify"
bundle:
desc: "Bundle. Call with: go-task bundle -- arguments"
interactive: true
deps:
- "gems"
cmds:
- "{{.HAINISH}} bundle {{.CLI_ARGS}}"
- defer:
task: "notify"
rails:
desc: "Rails. Call with: go-task rails -- arguments"
cmds:
- task: "bundle"
vars:
CLI_ARGS: "exec rails {{.CLI_ARGS}}"
console:
desc: "Rails console"
interactive: true
cmds:
- task: "rails"
vars:
CLI_ARGS: "console"
doc:
desc: "Build documentation"
deps:
- "gems"
cmds:
- task: "bundle"
vars:
CLI_ARGS: "exec yardoc -o public/doc app lib config db"
gem-audit:
desc: "Audit Gem dependencies"
deps:
- "gems"
- "bundler-audit"
cmds:
- task: "bundle"
vars:
CLI_ARGS: "audit --update"
node-audit:
desc: "Audit Node dependencies"
deps:
- "node-modules"
cmds:
- task: "yarn"
vars:
CLI_ARGS: "audit"
notify:
internal: true
cmds:
- "echo -e \"\a\""
bundler-audit:
internal: true
cmds:
- "{{.HAINISH}} gem install bundler-audit"
status:
- "test -f ../hain/usr/bin/bundler-audit"
rubocop:
desc: "Ruby linting"
deps:
- "gems"
cmds:
- "./bin/modified_files | ./bin/with_extension rb | xargs -r {{.HAINISH}} bundle exec rubocop {{.CLI_ARGS}}"
haml-lint:
desc: "HAML linting"
deps:
- "gems"
cmds:
- "./bin/modified_files | ./bin/with_extension haml | xargs -r {{.HAINISH}} bundle exec haml-lint {{.CLI_ARGS}}"

Binary file not shown.

View file

@ -1,422 +0,0 @@
function setAuxiliaryToolbar (editorEl, toolbarName) {
const toolbarEl = editorEl.querySelector(`*[data-editor-auxiliary-toolbar]`)
for (const otherEl of toolbarEl.childNodes) {
if (otherEl.nodeType !== Node.ELEMENT_NODE) continue
otherEl.classList.remove("editor-auxiliary-tool-active")
}
if (toolbarName) {
const auxEl = editorEl.querySelector(`*[data-editor-auxiliary="${toolbarName}"]`)
auxEl.classList.add("editor-auxiliary-tool-active")
}
}
const marks = {
bold: {
selector: "strong",
createFn: () => document.createElement("STRONG"),
},
italic: {
selector: "em",
createFn: () => document.createElement("EM"),
},
deleted: {
selector: "del",
createFn: () => document.createElement("DEL"),
},
underline: {
selector: "u",
createFn: () => document.createElement("U"),
},
sub: {
selector: "sub",
createFn: () => document.createElement("SUB"),
},
sup: {
selector: "sup",
createFn: () => document.createElement("SUP"),
},
mark: {
selector: "mark",
createFn: () => document.createElement("MARK"),
},
a: {
selector: "a",
createFn: () => document.createElement("A"),
}
}
const tagNameSetFn = tagName => el => {
const newEl = document.createElement(tagName)
moveChildren(el, newEl, null)
el.parentNode.insertBefore(newEl, el)
el.parentNode.removeChild(el)
window.getSelection().collapse(newEl, 0)
}
const blocks = {
p: {
noButton: true,
selector: "P",
setFn: tagNameSetFn("P"),
},
h1: {
selector: "H1",
setFn: tagNameSetFn("H1"),
},
h2: {
selector: "H2",
setFn: tagNameSetFn("H2"),
},
h3: {
selector: "H3",
setFn: tagNameSetFn("H3"),
},
h4: {
selector: "H4",
setFn: tagNameSetFn("H4"),
},
h5: {
selector: "H5",
setFn: tagNameSetFn("H5"),
},
h6: {
selector: "H6",
setFn: tagNameSetFn("H6"),
},
ul: {
selector: "UL",
setFn: tagNameSetFn("UL"),
},
ol: {
selector: "OL",
setFn: tagNameSetFn("OL"),
},
img: {
selector: "IMG",
createFn: editorEl => {
const el = document.createElement("IMG")
el.src = "/placeholder.png"
el.alt = ""
return el
},
},
figure: {
selector: "FIGURE",
noButton: true
},
figcaption: {
selector: "FIGCAPTION",
noButton: true,
},
audio: {
selector: "AUDIO",
createFn: editorEl => {
const el = document.createElement("FIGURE")
el.appendChild(document.createElement("AUDIO"))
el.appendChild(document.createElement("FIGCAPTION"))
el.children[0].controls = true
el.children[1].innerText = "Toca el borde para subir un archivo de audio"
return el
},
},
video: {
selector: "VIDEO",
createFn: editorEl => {
const el = document.createElement("VIDEO")
el.poster = "/placeholder.png"
// Para poder seleccionar el video tenemos que sacarle los
// controles, pero queremos poder verlos para reproducir el video.
// Al hacer click le damos los controles y al salir se los sacamos
// para poder hacer click de vuelta
el.addEventListener('click', event => event.target.controls = true)
el.addEventListener('focusout', event => event.target.controls = false)
return el
},
},
// PDF
pdf: {
selector: "IFRAME",
createFn: editorEl => {
const el = document.createElement("FIGURE")
el.appendChild(document.createElement("IFRAME"))
el.appendChild(document.createElement("FIGCAPTION"))
el.children[1].innerText = "Toca el borde para subir un archivo PDF"
return el
},
},
}
const divWithStyleCreateFn = styleFn => () => {
const el = document.createElement("DIV")
styleFn(el)
return el
}
const parentBlocks = {
left: {
selector: "div[data-align=left]",
createFn: divWithStyleCreateFn(el => el.dataset.align = "left"),
},
center: {
selector: "div[data-align=center]",
createFn: divWithStyleCreateFn(el => el.dataset.align = "center"),
},
right: {
selector: "div[data-align=right]",
createFn: divWithStyleCreateFn(el => el.dataset.align = "right"),
},
}
// https://stackoverflow.com/a/3627747
// TODO: cambiar por una solución más copada
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
const getSelected = contentEl => contentEl.querySelector(".selected")
const typesWithProperties = {
a: {
selector: marks.a.selector,
updateInput (el, editorEl) {
setAuxiliaryToolbar(editorEl, "a")
const markAInputEl = editorEl.querySelector(`*[data-prop="a-href"]`)
markAInputEl.disabled = false
markAInputEl.value = el.href
},
disableInput (editorEl) {
const markAInputEl = editorEl.querySelector(`*[data-prop="a-href"]`)
markAInputEl.disabled = true
markAInputEl.value = ""
},
setupInput (editorEl, contentEl) {
const markAInputEl = editorEl.querySelector(`*[data-prop="a-href"]`)
markAInputEl.addEventListener("change", event => {
const markEl = contentEl.querySelector(marks.a.selector + ".selected")
if (markEl) markEl.href = markAInputEl.value
}, false)
}
},
mark: {
selector: marks.mark.selector,
updateInput (el, editorEl) {
setAuxiliaryToolbar(editorEl, "mark")
const markColorInputEl = editorEl.querySelector(`*[data-prop="mark-color"]`)
markColorInputEl.disabled = false
markColorInputEl.value = el.style.backgroundColor ? rgb2hex(el.style.backgroundColor) : "#f206f9"
},
disableInput (editorEl) {
const markColorInputEl = editorEl.querySelector(`*[data-prop="mark-color"]`)
markColorInputEl.disabled = true
markColorInputEl.value = "#000000"
},
setupInput (editorEl, contentEl) {
const markColorInputEl = editorEl.querySelector(`*[data-prop="mark-color"]`)
markColorInputEl.addEventListener("change", event => {
const markEl = contentEl.querySelector(marks.mark.selector + ".selected")
if (markEl) markEl.style.backgroundColor = markColorInputEl.value
}, false)
},
},
img: {
selector: blocks.img.selector,
updateInput (el, editorEl) {
setAuxiliaryToolbar(editorEl, "img")
const imgFileEl = editorEl.querySelector(`*[data-prop="img-file"]`)
imgFileEl.disabled = false
// XXX: No se puede cambiar el texto, ¡esto puede ser confuso!
const imgAltEl = editorEl.querySelector(`*[data-prop="img-alt"]`)
imgAltEl.disabled = false
imgAltEl.value = el.alt
},
disableInput (editorEl) {
const imgFileEl = editorEl.querySelector(`*[data-prop="img-file"]`)
imgFileEl.disabled = true
const imgAltEl = editorEl.querySelector(`*[data-prop="img-alt"]`)
imgAltEl.disabled = true
imgAltEl.value = ""
},
setupInput (editorEl, contentEl) {
const imgFileEl = editorEl.querySelector(`*[data-prop="img-file"]`)
imgFileEl.addEventListener("input", event => {
const imgEl = contentEl.querySelector("img.selected")
if (!imgEl) return
const file = imgFileEl.files[0]
imgEl.src = URL.createObjectURL(file)
imgEl.dataset.editorLoading = true
uploadFile(file)
.then(url => {
imgEl.src = url
delete imgEl.dataset.editorError
})
.catch(err => {
// TODO: mostrar error
console.error(err)
imgEl.dataset.editorError = true
})
.finally(() => {
delete imgEl.dataset.editorLoading
})
}, false)
const imgAltEl = editorEl.querySelector(`*[data-prop="img-alt"]`)
imgAltEl.addEventListener("input", event => {
const imgEl = contentEl.querySelector("img.selected")
if (imgEl) imgEl.alt = imgAltEl.value
}, false)
},
},
figure: {
selector: blocks.figure.selector,
actualInput (el) {
// TODO: Cuando tengamos otros iframes hay que seleccionarlos de
// otra forma.
const tag = el.children[0].tagName.toLowerCase()
return typesWithProperties[(tag === 'iframe' ? 'pdf' : tag)]
},
updateInput (el, editorEl) {
typesWithProperties.figure.actualInput(el).updateInput(el.children[0], editorEl)
},
disableInput (editorEl) {},
setupInput (editorEl, contentEl) {},
},
audio: {
selector: blocks.audio.selector,
updateInput (el, editorEl) {
setAuxiliaryToolbar(editorEl, "audio")
const audioFileEl = editorEl.querySelector(`*[data-prop="audio-file"]`)
audioFileEl.disabled = false
// XXX: No se puede cambiar el texto, ¡esto puede ser confuso!
},
disableInput (editorEl) {
const audioFileEl = editorEl.querySelector(`*[data-prop="audio-file"]`)
audioFileEl.disabled = true
},
setupInput (editorEl, contentEl) {
const audioFileEl = editorEl.querySelector(`*[data-prop="audio-file"]`)
audioFileEl.addEventListener("input", event => {
const figureEl = getSelected(contentEl)
if (!figureEl) return
const file = audioFileEl.files[0]
const audioEl = figureEl.querySelector('audio')
audioEl.src = URL.createObjectURL(file)
audioEl.dataset.editorLoading = true
uploadFile(file)
.then(url => {
audioEl.src = url
delete audioEl.dataset.editorError
})
.catch(err => {
// TODO: mostrar error
console.error(err)
audioEl.dataset.editorError = true
})
.finally(() => {
delete audioEl.dataset.editorLoading
})
}, false)
},
},
video: {
selector: blocks.video.selector,
updateInput (el, editorEl) {
setAuxiliaryToolbar(editorEl, "video")
const videoFileEl = editorEl.querySelector(`*[data-prop="video-file"]`)
videoFileEl.disabled = false
// XXX: No se puede cambiar el texto, ¡esto puede ser confuso!
},
disableInput (editorEl) {
const videoFileEl = editorEl.querySelector(`*[data-prop="video-file"]`)
videoFileEl.disabled = true
},
setupInput (editorEl, contentEl) {
const videoFileEl = editorEl.querySelector(`*[data-prop="video-file"]`)
videoFileEl.addEventListener("input", event => {
const videoEl = getSelected(contentEl)
if (!videoEl) return
const file = videoFileEl.files[0]
videoEl.poster = ""
videoEl.src = URL.createObjectURL(file)
videoEl.dataset.editorLoading = true
uploadFile(file)
.then(url => {
videoEl.src = url
delete videoEl.dataset.editorError
})
.catch(err => {
// TODO: mostrar error
console.error(err)
videoEl.dataset.editorError = true
})
.finally(() => {
delete videoEl.dataset.editorLoading
})
}, false)
},
},
pdf: {
selector: blocks.pdf.selector,
updateInput (el, editorEl) {
setAuxiliaryToolbar(editorEl, "pdf")
const pdfFileEl = editorEl.querySelector(`*[data-prop="pdf-file"]`)
pdfFileEl.disabled = false
// XXX: No se puede cambiar el texto, ¡esto puede ser confuso!
},
disableInput (editorEl) {
const pdfFileEl = editorEl.querySelector(`*[data-prop="pdf-file"]`)
pdfFileEl.disabled = true
},
setupInput (editorEl, contentEl) {
const pdfFileEl = editorEl.querySelector(`*[data-prop="pdf-file"]`)
pdfFileEl.addEventListener("input", event => {
const figureEl = getSelected(contentEl)
if (!figureEl) return
const file = pdfFileEl.files[0]
const pdfEl = figureEl.children[0]
pdfEl.src = URL.createObjectURL(file)
pdfEl.dataset.editorLoading = true
uploadFile(file)
.then(url => {
pdfEl.src = url
delete pdfEl.dataset.editorError
})
.catch(err => {
// TODO: mostrar error
console.error(err)
pdfEl.dataset.editorError = true
})
.finally(() => {
delete pdfEl.dataset.editorLoading
})
}, false)
},
},
}

View file

@ -1,551 +0,0 @@
const origin = location.origin
/*
* Guarda una copia local de los cambios para poder recuperarlos
* después.
*
* Usamos la URL completa sin anchors.
*/
const storageKey = (editorEl) => editorEl.querySelector('[data-target="storage-key"]').value
const forgetContent = (storedKey) => window.localStorage.removeItem(storedKey)
const storeContent = (editorEl, contentEl) => {
if (contentEl.innerText.trim().length === 0) return
window.localStorage.setItem(storageKey(editorEl), contentEl.innerHTML)
}
const restoreContent = (editorEl, contentEl) => {
const content = window.localStorage.getItem(storageKey(editorEl))
if (!content) return
if (content.trim().length === 0) return
contentEl.innerHTML = content
}
function uploadFile (file) {
return new Promise((resolve, reject) => {
const upload = new ActiveStorage.DirectUpload(
file,
origin + '/rails/active_storage/direct_uploads',
)
upload.create((error, blob) => {
if (error) {
reject(error)
} else {
const url = `${origin}/rails/active_storage/blobs/${blob.signed_id}/${blob.filename}`
resolve(url)
}
})
})
}
function moveChildren (from, to, toRef) {
while (from.firstChild) to.insertBefore(from.firstChild, toRef);
}
function isDirectChild (node, supposedChild) {
for (const child of node.childNodes) {
if (child == supposedChild) return true
}
}
function isChildSelection (sel, el) {
return (
(el.contains(sel.anchorNode) || el.contains(sel.focusNode))
&& !(sel.anchorNode == el || sel.focusNode == el)
)
}
function getElementParent (node) {
let parentEl = node
while (parentEl.nodeType != Node.ELEMENT_NODE) parentEl = parentEl.parentElement
return parentEl
}
function splitNode (node, range) {
const [left, right] = [
{ range: document.createRange(), node: node.cloneNode(false) },
{ range: document.createRange(), node: node.cloneNode(false) },
]
left.range.setStartBefore(node.firstChild)
left.range.setEnd(range.startContainer, range.startOffset)
left.range.surroundContents(left.node)
right.range.setStart(range.endContainer, range.endOffset)
right.range.setEndAfter(node.lastChild)
right.range.surroundContents(right.node)
//left.node.appendChild(left.range.extractContents())
//left.range.insertNode(left.node)
//right.node.appendChild(right.range.extractContents())
//right.range.insertNode(right.node)
moveChildren(node, node.parentNode, node)
node.parentNode.removeChild(node)
return [left, right]
}
/* Configura un botón que hace una acción inline (ej: negrita).
* Parametros:
* * button: el botón
* * mark: un objeto que representa el tipo de acción (ver types.js)
* * contentEl: el elemento de contenido del editor.
*/
function setupMarkButton (button, mark, contentEl) {
button.addEventListener("click", event => {
event.preventDefault()
const sel = window.getSelection()
if (!isChildSelection(sel, contentEl)) return
let parentEl = getElementParent(sel.anchorNode)
//if (sel.anchorNode == parentEl) parentEl = parentEl.firstChild
const range = sel.getRangeAt(0)
if (parentEl.matches(mark.selector)) {
const [left, right] = splitNode(parentEl, range)
right.range.insertNode(range.extractContents())
const selectionRange = document.createRange()
selectionRange.setStartAfter(left.node)
selectionRange.setEndBefore(right.node)
sel.removeAllRanges()
sel.addRange(selectionRange)
} else {
for (const child of parentEl.childNodes) {
if (
(child instanceof Element)
&& child.matches(mark.selector)
&& sel.containsNode(child)
) {
moveChildren(child, parentEl, child)
parentEl.removeChild(child)
// TODO: agregar a selección
return
}
}
const tagEl = mark.createFn()
try {
range.surroundContents(tagEl)
} catch (error) {
// TODO: mostrar error
return console.error("No puedo marcar cosas a través de distintos bloques!")
}
for (const child of tagEl.childNodes) {
if (child instanceof Element && child.matches(mark.selector)) {
moveChildren(child, tagEl, child)
tagEl.removeChild(child)
}
}
range.insertNode(tagEl)
range.selectNode(tagEl)
}
})
}
/* Igual que `setupMarkButton` pero para bloques. */
function setupBlockButton (button, block, contentEl, editorEl) {
button.addEventListener("click", event => {
event.preventDefault()
const sel = window.getSelection()
// TODO: mostrar error
if (
!contentEl.contains(sel.anchorNode)
|| !contentEl.contains(sel.focusNode)
|| sel.anchorNode == contentEl
|| sel.focusNode == contentEl
) return
const range = sel.getRangeAt(0)
let parentEl = sel.anchorNode
while (!isDirectChild(contentEl, parentEl)) parentEl = parentEl.parentElement
if (block.setFn) {
if (parentEl.matches(block.selector)) {
tagNameSetFn("P")(parentEl)
} else {
block.setFn(parentEl)
}
} else if (block.createFn) {
const newEl = block.createFn(editorEl)
parentEl.parentElement.insertBefore(newEl, parentEl.nextSibling)
newEl.click()
}
})
}
/* Igual que `setupBlockButton` pero para bloques parientes. */
function setupParentBlockButton (button, parentBlock, contentEl) {
button.addEventListener("click", event => {
event.preventDefault()
const sel = window.getSelection()
if (
!contentEl.contains(sel.anchorNode)
|| !contentEl.contains(sel.focusNode)
|| sel.anchorNode == contentEl
|| sel.focusNode == contentEl
) return
const range = sel.getRangeAt(0)
let parentEl = sel.anchorNode
while (!isDirectChild(contentEl, parentEl)) parentEl = parentEl.parentElement
if (parentEl.matches(parentBlock.selector)) {
moveChildren(parentEl, parentEl.parentElement, parentEl)
parentEl.parentElement.removeChild(parentEl)
} else if (elementIsParentBlock(parentEl)) {
const el = parentBlock.createFn()
moveChildren(parentEl, el, null)
parentEl.parentElement.insertBefore(el, parentEl)
parentEl.parentElement.removeChild(parentEl)
} else {
const el = parentBlock.createFn()
parentEl.parentElement.insertBefore(el, parentEl)
el.appendChild(parentEl)
}
})
}
const elementIsTypes = types => element => {
for (const type of Object.values(types)) {
if (element.matches(type.selector)) return true
}
return false
}
const elementIsBlock = elementIsTypes(blocks)
const elementIsParentBlock = elementIsTypes(parentBlocks)
function hasContent (element) {
if (element.firstElementChild) return true
for (const child of element.childNodes) {
if (child.nodeType === Node.TEXT_NODE && child.data.length > 0) return true
else if (child.hasChildNodes() && hasContent(child)) return true
}
// TODO: verificar que los elementos tiene contenido
if (element.tagName === "IMG"
|| element.tagName === "AUDIO"
|| element.tagName === "VIDEO"
|| element.tagName === "IFRAME") return true
return false
}
/* Limpia el elemento de contenido del editor
* Por ahora:
* * Cambia el tag de los bloques no reconocidos (ver `elementIsBlock`)
* * Hace lo que hace cleanNode
*/
function cleanContent (contentEl) {
const sel = window.getSelection()
cleanNode(contentEl, contentEl)
for (const child of contentEl.childNodes) {
if (child.tagName) {
if (elementIsParentBlock(child)) {
cleanContent(child)
} else if (!elementIsBlock(child)) {
child.tagName = "P"
}
} else if (child.nodeType === Node.TEXT_NODE) {
const wasSelected = sel.getRangeAt(0).intersectsNode(child)
const el = document.createElement("p")
el.appendChild(child)
contentEl.insertBefore(el, child.nextSibling)
if (wasSelected) sel.collapse(el, child.data.length)
}
}
}
/* Arregla cosas en el elemento de contendo del editor
* Por ahora:
* * Crea un p y inserta la selección si no hay elementos
* * Wrappea el contenido de un UL o OL en un LI si no lo está
*/
function fixContent (contentEl) {
for (const child of contentEl.childNodes) {
if (child.tagName) {
if (elementIsParentBlock(child)) {
fixContent(child)
} else if (child.tagName === "UL" || child.tagName === "OL") {
let notItems = []
for (const item of child.childNodes) {
if (item.tagName !== "LI") notItems.push(item)
}
if (notItems.length) {
const item = document.createElement("li")
item.append(...notItems)
child.appendChild(item)
}
}
}
}
}
/* Recursivamente "limpia" los nodos a partir del llamado.
* Por ahora:
* * Junta nodos de texto que están al lado
* * Junta nodos de la misma "mark" que están al lado
* * Borra elementos sin contenido (ver `hasContent`) y no están seleccionados
* * Borra inline styles no autorizados
* * Borra propiedades de IMG no autorizadas
* * Borra <FONT> y <STYLE>
*/
function cleanNode (node, contentEl) {
for (const child of node.childNodes) {
if (child.nodeType === Node.TEXT_NODE) {
if (child.nextSibling && child.nextSibling.nodeType === Node.TEXT_NODE) {
// Juntar nodos
child.data += child.nextSibling.data
child.parentNode.removeChild(child.nextSibling)
}
} else if (child.nodeType === Node.ELEMENT_NODE) {
if (!hasContent(child) && !window.getSelection().getRangeAt(0).intersectsNode(child))
child.parentNode.removeChild(child)
for (const mark of Object.values(marks)) {
if (
child.matches(mark.selector)
&& child.nextSibling
&& (child.nextSibling instanceof Element)
&& child.nextSibling.matches(mark.selector)
) {
moveChildren(child.nextSibling, child, null)
child.nextSibling.parentNode.removeChild(child.nextSibling)
}
}
if (child.tagName === "LI") {
let parentEl = child
while (
parentEl
&& !(parentEl.nodeType == Node.ELEMENT_NODE && elementIsBlock(parentEl))
&& contentEl.contains(parentEl)
)
parentEl = parentEl.parentElement
if (
parentEl
&& contentEl.contains(parentEl)
&& parentEl.tagName !== "UL"
&& parentEl.tagName !== "OL"
)
moveChildren(child, parentEl, child.nextSibling)
} else if (child.tagName === "IMG") {
if (child.getAttribute("width")) child.removeAttribute("width")
if (child.getAttribute("height")) child.removeAttribute("height")
if (child.getAttribute("vspace")) child.removeAttribute("vspace")
if (child.getAttribute("hspace")) child.removeAttribute("hspace")
if (child.align.length) child.removeAttribute("align")
if (child.name.length) child.removeAttribute("name")
if (!child.src.length) child.src = "/placeholder.png"
} else if (child.tagName === "FONT") {
moveChildren(child, child.parentElement, child.nextSiling)
child.parentElement.removeChild(child)
return
} else if (child.tagName === "STYLE") {
return child.parentElement.removeChild(child)
} else if (child.tagName === "B") {
const el = document.createElement("STRONG")
moveChildren(child, el)
child.parentElement.insertBefore(el, child)
child.parentElement.removeChild(child)
} else if (child.tagName === "I") {
const el = document.createElement("EM")
moveChildren(child, el)
child.parentElement.insertBefore(el, child)
child.parentElement.removeChild(child)
}
for (const style of Object.values(child.style)) {
const value = child.style[style]
switch (style) {
case 'background-color':
if (child.tagName === "MARK") break
default:
child.style[style] = ""
}
}
}
cleanNode(child, contentEl)
}
}
/* Generar el clickListener para este editor.
*/
function generateClickListener (editorEl, contentEl) {
/* El event listener para los typesWithProperties.
*/
return function clickListener (event) {
// Borrar todas las selecciones
for (const el of contentEl.querySelectorAll(".selected")) {
el.classList.remove("selected")
}
setAuxiliaryToolbar(editorEl)
let selectedType
let selectedEl
for (const [name, type] of Object.entries(typesWithProperties)) {
type.disableInput(editorEl)
let el = event.target
while (el && !el.matches(type.selector)) el = el.parentElement
if (el && contentEl.contains(el)) {
selectedType = type
selectedEl = el
}
}
if (selectedType) {
event.preventDefault()
selectedType.updateInput(selectedEl, editorEl)
event.target.classList.add("selected")
return false
}
}
}
function setupEditor (editorEl) {
// XXX: ¡Esto afecta a todo el documento! ¿Quizás usar un iframe para el editor?
document.execCommand('defaultParagraphSeparator', false, 'p')
const contentEl = editorEl.querySelector(".editor-content")
contentEl.addEventListener("keydown", event => {
if (event.keyCode === 32) { // Espacio
event.preventDefault()
const sel = window.getSelection()
const range = sel.getRangeAt(0)
range.insertNode(document.createTextNode("\xa0"))
cleanContent(contentEl)
range.collapse()
}
})
contentEl.addEventListener("paste", event => {
contentEl.querySelector("editor-aviso-word").style.display = "block"
})
document.addEventListener("selectionchange", event => {
cleanContent(contentEl)
})
const clickListener = generateClickListener(editorEl, contentEl)
contentEl.addEventListener("click", clickListener, true)
const htmlEl = editorEl.querySelector("textarea")
const observer = new MutationObserver((mutationList, observer) => {
cleanContent(contentEl)
fixContent(contentEl)
storeContent(editorEl, contentEl)
htmlEl.value = contentEl.innerHTML
})
observer.observe(contentEl, {
childList: true,
attributes: true,
subtree: true,
characterData: true,
})
const editorBtn = id => editorEl.querySelector(`*[data-button="${id}"]`)
// XXX: Por qué está duplicada de types.js esta función?
const tagNameSetFn = tagName => el => {
const newEl = document.createElement(tagName)
moveChildren(el, newEl, null)
el.parentNode.insertBefore(newEl, el)
el.parentNode.removeChild(el)
window.getSelection().collapse(newEl, 0)
}
// == SETUP BUTTONS ==
for (const [name, mark] of Object.entries(marks)) {
setupMarkButton(editorBtn(name), mark, contentEl)
}
for (const [name, block] of Object.entries(blocks)) {
if (block.noButton) continue
setupBlockButton(editorBtn(name), block, contentEl, editorEl)
}
for (const [name, parentBlock] of Object.entries(parentBlocks)) {
if (parentBlock.noButton) continue
setupParentBlockButton(editorBtn(name), parentBlock, contentEl)
}
for (const [name, type] of Object.entries(typesWithProperties)) {
type.setupInput(editorEl, contentEl)
}
document.addEventListener(editorBtn("mark"), () => setAuxiliaryToolbar(editorEl, "mark"))
document.addEventListener(editorBtn("img"), () => setAuxiliaryToolbar(editorEl, "img"))
document.addEventListener(editorBtn("audio"), () => setAuxiliaryToolbar(editorEl, "audio"))
document.addEventListener(editorBtn("video"), () => setAuxiliaryToolbar(editorEl, "video"))
document.addEventListener(editorBtn("pdf"), () => setAuxiliaryToolbar(editorEl, "pdf"))
document.addEventListener(editorBtn("a"), () => setAuxiliaryToolbar(editorEl, "a"))
for (const video of document.querySelectorAll('.editor .editor-content video')) {
video.addEventListener('click', event => event.target.controls = true)
video.addEventListener('focusout', event => event.target.controls = false)
video.controls = false
}
cleanContent(contentEl)
fixContent(contentEl)
// Recuperar el contenido si hay algo guardado, si tuviéramos un campo
// de última edición podríamos saber si el artículo fue editado
// después o la versión local es la última.
//
// TODO: Preguntar si se lo quiere recuperar.
restoreContent(editorEl, contentEl)
htmlEl.value = contentEl.innerHTML
}
// TODO: por ahora confiamos, quizás queremos filtrar estilos?
function stringifyAllowedStyle (element) {
return element.style.cssText
}
document.addEventListener("turbolinks:load", () => {
for (const editorEl of document.querySelectorAll(".editor")) {
if (!editorEl.querySelector('.editor-toolbar')) continue
setupEditor(editorEl)
}
const flash = document.querySelector('.js-flash[data-target="editor"]')
if (!flash) return
switch (flash.dataset.action) {
case 'forget-content':
if (!flash.dataset.keys) break
try { JSON.parse(flash.dataset.keys).forEach(forgetContent) } catch(e) { undefined }
break
default:
}
})

View file

@ -1,5 +0,0 @@
//= require rails-ujs
//= require turbolinks
//= require input-tag/input-tag.js
//= require input-map/input-map.js
//= require_tree .

View file

@ -1,11 +0,0 @@
document.addEventListener('turbolinks:load', () => {
document.querySelectorAll('input[type=file]').forEach(file => {
if (!file.dataset.preview) return
file.addEventListener('change', event => {
if (file.files.length === 0) return
document.querySelector('#' + file.dataset.preview).src = window.URL.createObjectURL(file.files[0])
})
})
})

View file

@ -1,3 +0,0 @@
document.addEventListener('turbolinks:load', () => {
document.querySelectorAll('a[href^="#"]').forEach(a => a.data.turbolinks = false)
})

View file

@ -13,16 +13,41 @@ $colors: (
// Redefinir variables de Bootstrap
$primary: $magenta;
$secondary: $black;
$jumbotron-bg: transparent;
$enable-rounded: false;
$form-feedback-valid-color: $cyan;
$form-feedback-valid-color: $black;
$form-feedback-invalid-color: $magenta;
$form-feedback-icon-valid-color: $black;
$component-active-bg: $magenta;
$spacers: (
2-plus: 0.75rem
);
$sizes: (
"70ch": 70ch,
);
@import "bootstrap";
@import "editor";
@each $color, $rgb in $theme-colors {
.#{$color} {
color: var(--#{$color});
&:focus {
color: var(--#{$color});
}
::-moz-selection,
::selection {
background: var(--#{$color});
color: white;
}
}
}
.editor {
.editor-content {
figure {
@ -43,6 +68,25 @@ $component-active-bg: $magenta;
--background: #{$black};
--color: #{$cyan};
}
.btn-secondary {
background-color: $white;
color: $black;
border: none;
&:hover {
color: $black;
background-color: $cyan;
}
&:active {
background-color: $cyan;
}
&:focus {
box-shadow: 0 0 0 0.2rem $cyan;
}
}
}
// TODO: Encontrar la forma de generar esto desde los locales de Rails
@ -121,6 +165,7 @@ ol.breadcrumb {
color: var(--foreground);
}
.table tr.sticky-top,
.form-control,
.custom-file-label {
background-color: var(--background);
@ -148,6 +193,12 @@ ol.breadcrumb {
transition: all 3s;
}
fieldset {
legend {
font-size: 1rem;
}
}
.mapable,
.taggable {
.input-map,
@ -174,7 +225,7 @@ ol.breadcrumb {
&[type=button] {
@extend .btn;
@extend .btn-info;
@extend .btn-secondary;
@extend .m-0;
}
}
@ -188,10 +239,6 @@ svg {
}
.btn {
background-color: var(--foreground);
color: var(--background);
border: none;
border-radius: 0;
margin-right: 0.3rem;
margin-bottom: 0.3rem;
@ -209,6 +256,10 @@ svg {
}
}
.btn-sm {
@extend .badge
}
.black-bg {
color: $white;
background-color: $black;
@ -223,7 +274,7 @@ svg {
color: $magenta;
}
.btn {
.btn-secondary {
background-color: $white;
color: $black;
border: none;
@ -354,8 +405,18 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1);
.text-column-#{$size} {
column-count: $size;
}
.line-clamp-#{$size} {
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: $size;
-webkit-box-orient: vertical;
}
}
.word-break-all { word-break: break-all !important; }
.hyphens { hyphens: auto; }
/*
* Modificadores de Bootstrap que no tienen versión responsive.
*/
@ -378,6 +439,8 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1);
.text-#{$grid-breakpoint}-right { text-align: right !important; }
.text-#{$grid-breakpoint}-center { text-align: center !important; }
.word-break-#{$grid-breakpoint}-all { word-break: break-all !important; }
// posición
@each $position in $positions {
.position-#{$grid-breakpoint}-#{$position} { position: $position !important; }
@ -387,6 +450,8 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1);
@each $prop, $abbrev in (width: w, height: h) {
@each $size, $length in $sizes {
.#{$abbrev}-#{$grid-breakpoint}-#{$size} { #{$prop}: $length !important; }
.min-#{$abbrev}-#{$grid-breakpoint}-#{$size} { min-#{$prop}: $length !important; }
.max-#{$abbrev}-#{$grid-breakpoint}-#{$size} { max-#{$prop}: $length !important; }
}
}
@ -488,3 +553,71 @@ $bezier: cubic-bezier(0.75, 0, 0.25, 1);
}
}
}
@import "new_editor";
.new-editor {
.editor {
table {
@extend .table;
@extend .table-responsive;
}
}
}
.content {
p { min-height: $font-size-base * $line-height-base; }
h1 { min-height: $h1-font-size * $headings-line-height; }
h2 { min-height: $h2-font-size * $headings-line-height; }
h3 { min-height: $h3-font-size * $headings-line-height; }
h4 { min-height: $h4-font-size * $headings-line-height; }
h5 { min-height: $h5-font-size * $headings-line-height; }
h6 { min-height: $h6-font-size * $headings-line-height; }
iframe { border: 0; }
audio { width: 100%; }
img,
video,
iframe {
@extend .img-fluid;
height: auto;
}
& > * {
margin-bottom: 1rem;
&:last-child {
margin-bottom: 0;
}
}
}
// details styles
.details {
& > summary {
list-style: none;
cursor: pointer;
.hide-when-open {
display: inline;
}
.show-when-open {
display: none;
}
}
&[open] {
& > summary {
.hide-when-open {
display: none;
}
.show-when-open {
display: inline;
}
}
}
}

View file

@ -0,0 +1,34 @@
$black: black;
$white: white;
$cyan: #13fefe;
:root {
--foreground: #{$white};
--background: #{$black};
--color: #{$cyan};
}
.btn {
background-color: $white;
}
.btn-secondary {
background-color: $white;
color: $black;
border: none;
&:hover {
color: $black;
background-color: $cyan;
}
&:active {
background-color: $cyan;
}
&:focus {
box-shadow: 0 0 0 0.2rem $cyan;
}
}

View file

@ -1,7 +1,14 @@
.editor {
.old.editor {
box-sizing: border-box;
*, *::before, *::after { box-sizing: inherit; }
// Arreglo temporal para que las cosas sean legibles en modo oscuro
--foreground: black;
--background: white;
--color: #f206f9;
background: var(--background);
color: var(--foreground);
h1, h2, h3, h4, h5, h6, p, li {
min-height: 1.5rem;
}
@ -11,8 +18,6 @@
padding: 0;
}
.selected { outline: #f206f9 solid medium; }
iframe {
border: 0;
min-height: 480px;
@ -35,7 +40,10 @@
background: white;
}
.editor-aviso-word { display: none; }
.editor-aviso-word {
display: none;
position: initial; /* evitar que tape el texto */
}
.editor-primary-toolbar, .editor-auxiliary-toolbar {
display: block;
@ -47,7 +55,7 @@
& > * {
display: none;
}
.editor-auxiliary-tool-active {
[data-editor-auxiliary-active] {
display: block;
}
}
@ -57,9 +65,21 @@
div[data-align="center"] { text-align: center; }
div[data-align="right"] { text-align: right; }
.editor-content {
min-height: 480px;
}
.editor-content {
min-height: 480px;
p, h1, h2, h3, h4, h5, h6, ul, li, blockquote, figcaption { outline: #ccc solid thin; }
blockquote {
border-left: #555 solid .25em;
padding: .75em;
}
strong, em, del, u, sub, sup, small { background: #0002; }
a { background: #13fefe50; }
[data-editor-selected] { outline: #f206f9 solid thick; }
p[data-multimedia-inner] {
// Ignorar clicks en el párrafo placeholder
pointer-events: none;
}
}
*[data-editor-loading] {
opacity: 0.5;

View file

@ -0,0 +1,22 @@
.new-editor {
.editor {
.menubar {
z-index: 1;
label.btn {
margin-bottom: 0.3rem !important;
}
.btn-group {
.btn {
margin-right: 0;
}
}
}
.ProseMirror,
& > ol li {
margin-bottom: 1rem;
}
}
}

View file

@ -0,0 +1,30 @@
# frozen_string_literal: true
module ActiveStorage
# Modifica la creación de un blob antes de subir el archivo para que
# incluya el JekyllService adecuado.
module DirectUploadsControllerDecorator
extend ActiveSupport::Concern
included do
def create
blob = ActiveStorage::Blob.create_before_direct_upload!(service_name: session[:service_name], **blob_args)
render json: direct_upload_json(blob)
end
private
# Normalizar los caracteres unicode en los nombres de archivos
# para que puedan propagarse correctamente a través de todo el
# stack.
def blob_args
params.require(:blob).permit(:filename, :byte_size, :checksum, :content_type,
metadata: {}).to_h.symbolize_keys.tap do |ba|
ba[:filename] = ba[:filename].unicode_normalize.sub(/\A_+/, '')
end
end
end
end
end
ActiveStorage::DirectUploadsController.include ActiveStorage::DirectUploadsControllerDecorator

View file

@ -0,0 +1,73 @@
# frozen_string_literal: true
module ActiveStorage
# Modificar {DiskController} para poder asociar el blob a un sitio
module DiskControllerDecorator
extend ActiveSupport::Concern
included do
alias_method :original_show, :show
# Permitir incrustar archivos subidos (especialmente PDFs) desde
# otros sitios.
def show
original_show.tap do |s|
response.headers.delete 'X-Frame-Options'
end
end
rescue_from ActiveRecord::RecordNotFound, with: :page_not_found
# Asociar el archivo subido al sitio correspondiente. Cada sitio
# tiene su propio servicio de subida de archivos.
def update
if (token = decode_verified_token)
if acceptable_content?(token)
blob = ActiveStorage::Blob.find_by_key! token[:key]
site = Site.find_by_name token[:service_name]
if remote_file?(token)
begin
url = request.body.read
body = Down.download(url, max_size: 111.megabytes)
checksum = Digest::MD5.file(body.path).base64digest
blob.metadata[:url] = url
blob.update_columns checksum: checksum, byte_size: body.size, metadata: blob.metadata
rescue StandardError => e
ExceptionNotifier.notify_exception(e, data: { key: token[:key], url: url, site: site.name })
head :content_too_large
end
else
body = request.body
checksum = token[:checksum]
end
named_disk_service(token[:service_name]).upload token[:key], body, checksum: checksum
site.static_files.attach(blob)
else
head :unprocessable_entity
end
else
head :not_found
end
rescue ActiveStorage::IntegrityError
head :unprocessable_entity
end
private
def remote_file?(token)
token[:content_type] == 'sutty/download-from-url'
end
def page_not_found(exception)
head :not_found
ExceptionNotifier.notify_exception(exception, data: {params: params.to_hash})
end
end
end
end
ActiveStorage::DiskController.include ActiveStorage::DiskControllerDecorator

View file

@ -0,0 +1,74 @@
# frozen_string_literal: true
# Gestiona acciones de moderación
class ActivityPubsController < ApplicationController
include ModerationConcern
ActivityPub.events.each do |event|
define_method(event) do
authorize activity_pub
if event == :report
remote_flag_params(activity_pub).tap do |p|
activity_pub.remote_flag_id = p[:remote_flag_attributes][:id]
activity_pub.update(p)
end
end
message =
if activity_pub.public_send(:"may_#{event}?") && activity_pub.public_send(:"#{event}!")
:success
else
:error
end
flash[message] = I18n.t("activity_pubs.#{event}.#{message}")
redirect_to_moderation_queue!
end
end
def action_on_several
redirect_to_moderation_queue!
activity_pubs = site.activity_pubs.where(id: params[:activity_pub])
return if activity_pubs.count.zero?
authorize activity_pubs
action = params[:activity_pub_action].to_sym
method = :"#{action}_all!"
may = :"may_#{action}?"
return unless ActivityPub.events.include? action
# Crear una sola remote flag por autore
ActivityPub.transaction do
if action == :report
message = remote_flag_params(activity_pubs.first).dig(:remote_flag_attributes, :message)
activity_pubs.distinct.pluck(:actor_id).each do |actor_id|
remote_flag = ActivityPub::RemoteFlag.find_or_initialize_by(actor_id: actor_id, site_id: site.id)
remote_flag.message = message
# Lo estamos actualizando, con lo que lo vamos a volver a enviar
remote_flag.requeue if remote_flag.persisted?
remote_flag.save
# XXX: Idealmente todas las ActivityPub que enviamos pueden
# cambiar de estado, pero chequeamos de todas formas.
remote_flag.activity_pubs << (activity_pubs.where(actor_id: actor_id).to_a.select { |a| a.public_send(may) })
end
end
message = activity_pubs.public_send(method) ? :success : :error
flash[message] = I18n.t("activity_pubs.action_on_several.#{message}")
end
end
private
def activity_pub
@activity_pub ||= site.activity_pubs.find(params[:activity_pub_id])
end
end

View file

@ -0,0 +1,85 @@
# frozen_string_literal: true
# Gestiona la cola de moderación de actores
class ActorModerationsController < ApplicationController
include ModerationConcern
include ModerationFiltersConcern
before_action :authenticate_usuarie!
breadcrumb -> { current_usuarie.email }, :edit_usuarie_registration_path
breadcrumb 'sites.index', :sites_path, match: :exact
ActorModeration.events.each do |actor_event|
define_method(actor_event) do
authorize actor_moderation
# Crea una RemoteFlag si se envían los parámetros adecuados
if actor_event == :report
remote_flag_params(actor_moderation).tap do |p|
actor_moderation.remote_flag_id = p[:remote_flag_attributes][:id]
actor_moderation.update(p)
end
end
message =
if actor_moderation.public_send(:"may_#{actor_event}?") && actor_moderation.public_send(:"#{actor_event}!")
:success
else
:error
end
flash[message] = I18n.t("actor_moderations.#{actor_event}.#{message}")
redirect_to_moderation_queue!
end
end
# Ver el perfil remoto
def show
breadcrumb site.title, site_posts_path(site)
breadcrumb I18n.t('moderation_queue.index.title'), site_moderation_queue_path(site)
@remote_profile = actor_moderation.actor.content
@moderation_queue = rubanok_process(site.activity_pubs.where(actor_id: actor_moderation.actor_id),
with: ActivityPubProcessor)
breadcrumb @remote_profile['name'] || actor_moderation.actor.mention || actor_moderation.actor.uri, ''
end
def action_on_several
redirect_to_moderation_queue!
actor_moderations = site.actor_moderations.where(id: params[:actor_moderation])
return if actor_moderations.count.zero?
authorize actor_moderations
action = params[:actor_moderation_action].to_sym
method = :"#{action}_all!"
may = :"may_#{action}?"
return unless ActorModeration.events.include? action
ActorModeration.transaction do
if action == :report
actor_moderations.find_each do |actor_moderation|
next unless actor_moderation.public_send(may)
actor_moderation.update(actor_moderation_params(actor_moderation))
end
end
message = actor_moderations.public_send(method) ? :success : :error
flash[message] = I18n.t("actor_moderations.action_on_several.#{message}")
end
end
private
def actor_moderation
@actor_moderation ||= site.actor_moderations.find(params[:actor_moderation_id] || params[:id])
end
end

View file

@ -0,0 +1,27 @@
# frozen_string_literal: true
module Api
module V1
module ActivityPub
# Devuelve los reportes remotos hechos
#
# @todo Verificar la firma. Por ahora no es necesario porque no es
# posible obtener remotamente todos los reportes y se identifican por
# UUIDv4.
class RemoteFlagsController < BaseController
skip_forgery_protection
def show
render json: (remote_flag&.content || {}), content_type: 'application/activity+json'
end
private
# @return [ActivityPub::RemoteFlag,nil]
def remote_flag
@remote_flag ||= ::ActivityPub::RemoteFlag.find(params[:id])
end
end
end
end
end

View file

@ -18,9 +18,10 @@ module Api
# Si todo salió bien, enviar los correos y redirigir al sitio.
# El sitio nos dice a dónde tenemos que ir.
ContactJob.perform_async site.id,
ContactJob.perform_later site,
params[:form],
contact_params.to_h.symbolize_keys
contact_params.to_h.symbolize_keys,
params[:redirect]
redirect_to params[:redirect] || origin.to_s
end

View file

@ -6,19 +6,22 @@ module Api
class CspReportsController < BaseController
skip_forgery_protection
# No queremos indicar que algo salió mal
rescue_from ActionController::ParameterMissing, with: :csp_report_created
# Crea un reporte de CSP intercambiando los guiones medios por
# bajos
#
# TODO: Aplicar rate_limit
def create
csp = CspReport.new(csp_report_params.to_h.map do |k, v|
[k.tr('-', '_'), v]
end.to_h)
csp = CspReport.new(csp_report_params.to_h.transform_keys do |k|
k.tr('-', '_')
end)
csp.id = SecureRandom.uuid
csp.save
render json: {}, status: :created
csp_report_created
end
private
@ -39,6 +42,10 @@ module Api
:'column-number',
:'source-file')
end
def csp_report_created
render json: {}, status: :created
end
end
end
end

View file

@ -0,0 +1,76 @@
# frozen_string_literal: true
module Api
module V1
# Recibe notificaciones desde Airbrake
class NoticesController < BaseController
skip_before_action :verify_authenticity_token
# Generar un stacktrace en segundo plano y enviarlo por correo
# solo si la API key es verificable. Del otro lado siempre
# respondemos con lo mismo.
def create
if (site&.airbrake_valid? airbrake_token) && !detected_device.bot?
BacktraceJob.perform_later site: site,
params: airbrake_params.to_h
end
render status: 201, json: { id: 1, url: '' }
end
private
# XXX: Por alguna razón Airbrake envía los datos con Content-Type:
# text/plain.
def airbrake_params
@airbrake_params ||=
params.merge!(FastJsonparser.parse(request.raw_post) || {})
.permit(
{
errors: [
:type,
:message,
{ backtrace: %i[file line column function] }
]
},
{
context: [
:url,
:language,
:severity,
:userAgent,
:windowError,
:rootDirectory,
{
history: [
:date,
:type,
:severity,
:target,
:method,
:duration,
:statusCode,
{ arguments: [] }
]
}
]
}
)
end
def site
@site ||= Site.find(params[:site_id])
rescue ActiveRecord::RecordNotFound
end
def airbrake_token
@airbrake_token ||= params[:key]
end
# @return [DeviceDetector]
def detected_device
@detected_device ||= DeviceDetector.new(request.headers['User-Agent'], request.headers)
end
end
end
end

View file

@ -9,44 +9,26 @@ module Api
# Lista de nombres de dominios a emitir certificados
def index
render json: sites_names + alternative_names + api_names
end
# Sitios con hidden service de Tor
#
# @return [Array] lista de nombres de sitios sin onion aun
def hidden_services
render json: DeployHiddenService.where(values: nil).includes(:site).pluck(:name)
end
# Tor va a enviar el onion junto con el nombre del sitio y tenemos
# que guardarlo en su deploy_hidden_service.
#
# @params [String] name
# @params [String] onion
def add_onion
site = Site.find_by(name: params[:name])
if site
usuarie = GitAuthor.new email: 'tor@' + Site.domain, name: 'Tor'
service = SiteService.new site: site, usuarie: usuarie,
params: params
service.add_onion
end
head :ok
render json: alternative_names + api_names + www_names
end
private
# Nombres de los sitios
def sites_names
Site.all.order(:name).pluck(:name)
def canonicalize(name)
name.end_with?('.') ? name[0..-2] : "#{name}.#{Site.domain}"
end
def subdomain?(name)
name.end_with? ".#{Site.domain}"
end
# Dominios alternativos
def alternative_names
DeployAlternativeDomain.all.map(&:hostname)
(DeployAlternativeDomain.all.map(&:hostname) + DeployLocalizedDomain.all.map(&:hostname)).map do |name|
canonicalize name
end.reject do |name|
subdomain? name
end
end
# Obtener todos los sitios con API habilitada, es decir formulario
@ -56,7 +38,18 @@ module Api
def api_names
Site.where(contact: true)
.or(Site.where(colaboracion_anonima: true))
.select("'api.' || name as name").map(&:name)
.select("'api.' || name as name").map(&:name).map do |name|
canonicalize name
end.reject do |name|
subdomain? name
end
end
# Todos los dominios con WWW habilitado
def www_names
Site.where(id: DeployWww.all.pluck(:site_id)).select("'www.' || name as name").map(&:name).map do |name|
canonicalize name
end
end
end
end

View file

@ -0,0 +1,79 @@
# frozen_string_literal: true
module Api
module V1
module Webhooks
module Concerns
# Helpers para webhooks
module WebhookConcern
extend ActiveSupport::Concern
included do
skip_before_action :verify_authenticity_token
# Responde con forbidden si falla la validación del token
rescue_from ActiveRecord::RecordNotFound, with: :platforms_answer
rescue_from ActiveRecord::RecordInvalid, with: :platforms_answer
private
# Valida el token que envía la plataforma en el webhook
#
# @return [String]
def token
@token ||=
begin
header = request.headers
token = header['X-Social-Inbox'].presence
token ||= header['X-Gitlab-Token'].presence
token ||= token_from_signature(header['X-Gitea-Signature'].presence)
token ||= token_from_signature(header['X-Hub-Signature-256'].presence, 'sha256=')
token
ensure
raise ActiveRecord::RecordNotFound, 'Proveedor no soportado' if token.blank?
end
end
# Valida token a partir de firma
#
# @param signature [String,nil]
# @param prepend [String]
# @return [String, nil]
def token_from_signature(signature, prepend = '')
return if signature.nil?
payload = request.raw_post
site.roles.where(temporal: false, rol: 'usuarie').pluck(:token).find do |token|
new_signature = prepend + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), token, payload)
ActiveSupport::SecurityUtils.secure_compare(new_signature, signature.to_s)
end
end
# Encuentra el sitio a partir de la URL
#
# @return [Site]
def site
@site ||= Site.find_by_name!(params[:site_id])
end
# Encuentra le usuarie
#
# @return [Site]
def usuarie
@usuarie ||= site.roles.find_by!(temporal: false, rol: 'usuarie', token: token).usuarie
end
# Respuesta de error a plataformas
def platforms_answer(exception)
ExceptionNotifier.notify_exception(exception, data: { headers: request.headers.to_h })
head :forbidden
end
end
end
end
end
end
end

View file

@ -0,0 +1,25 @@
# frozen_string_literal: true
module Api
module V1
module Webhooks
# Recibe webhooks y lanza un PullJob
class PullController < BaseController
include Api::V1::Webhooks::Concerns::WebhookConcern
# Trae los cambios a partir de un post de Webhooks:
# (Gitlab, Github, Gitea, etc)
#
# @return [nil]
def pull
message = I18n.with_locale(site.default_locale) do
I18n.t('webhooks.pull.message')
end
GitPullJob.perform_later(site, usuarie, message)
head :ok
end
end
end
end
end

View file

@ -0,0 +1,59 @@
# frozen_string_literal: true
module Api
module V1
module Webhooks
# Recibe webhooks de la Social Inbox
#
# @see {https://www.w3.org/TR/activitypub/}
class SocialInboxController < BaseController
include Api::V1::Webhooks::Concerns::WebhookConcern
# Validar que el token sea correcto
before_action :usuarie
# Cuando una actividad ingresa en la cola de moderación, la
# recibimos por acá
#
# Vamos a recibir Create, Update, Delete, Follow, Undo,
# Announce, Like y obtener el objeto dentro de cada una para
# guardar un estado asociado al sitio.
#
# El objeto del estado puede ser un objeto o une actore,
# dependiendo de la actividad.
def moderationqueued
process! :paused
head :accepted
end
# Cuando la Social Inbox acepta una actividad, la recibimos
# igual y la guardamos por si cambiamos de idea.
def onapproved
process! :approved
head :accepted
end
# Cuando la Social Inbox rechaza una actividad, la recibimos
# igual y la guardamos por si cambiamos de idea.
def onrejected
process! :rejected
head :accepted
end
private
# Envía la actividad para procesamiento por separado.
#
# @param initial_state [Symbol]
def process!(initial_state)
::ActivityPub::ProcessJob
.set(wait: ApplicationJob.random_wait)
.perform_later(site: site, body: request.raw_post, initial_state: initial_state)
end
end
end
end
end

View file

@ -3,18 +3,18 @@
# Forma de ingreso a Sutty
class ApplicationController < ActionController::Base
include ExceptionHandler
include Pundit::Authorization
protect_from_forgery with: :exception
protect_from_forgery with: :null_session, prepend: true
before_action :prepare_exception_notifier
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :notify_unconfirmed_email, unless: :devise_controller?
around_action :set_locale
rescue_from ActionController::RoutingError, with: :page_not_found
rescue_from ActionController::ParameterMissing, with: :page_not_found
after_action :store_location!
before_action do
Rack::MiniProfiler.authorize_request if current_usuarie&.email&.ends_with?('@' + ENV.fetch('SUTTY', 'sutty.nl'))
Rack::MiniProfiler.authorize_request if current_usuarie&.email&.ends_with?("@#{ENV.fetch('SUTTY', 'sutty.nl')}")
end
# No tenemos índice de sutty, vamos directamente a ver el listado de
@ -23,10 +23,17 @@ class ApplicationController < ActionController::Base
redirect_to sites_path
end
def markdown; end
private
def notify_unconfirmed_email
return unless current_usuarie
return if current_usuarie.confirmed?
I18n.with_locale(current_usuarie.lang) do
flash[:notice] ||= I18n.t('devise.registrations.signed_up')
end
end
def uuid?(string)
/[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}/ =~ string
end
@ -35,32 +42,79 @@ class ApplicationController < ActionController::Base
def find_site
id = params[:site_id] || params[:id]
unless (site = current_usuarie.sites.find_by_name(id))
unless (site = current_usuarie&.sites&.find_by_name(id))
raise SiteNotFound
end
site
end
# Devuelve el idioma actual y si no lo encuentra obtiene uno por
# defecto.
#
# Esto se refiere al idioma de la interfaz, no de los artículos.
#
# @return [String,Symbol]
def current_locale
locale = params[:change_locale_to]
session[:locale] = params[:change_locale_to] if locale.present? && I18n.locale_available?(locale)
session[:locale] || current_usuarie&.lang || I18n.locale
end
# El idioma es el preferido por le usuarie, pero no necesariamente se
# corresponde con el idioma de los artículos, porque puede querer
# traducirlos.
def set_locale(&action)
I18n.with_locale(current_usuarie&.lang || I18n.default_locale, &action)
I18n.with_locale(current_locale, &action)
end
# Muestra una página 404
def page_not_found
render 'application/page_not_found', status: :not_found
# Necesario para poder acceder a Blazer. Solo les usuaries de este
# sitio pueden acceder al panel.
def require_usuarie
site = find_site
authorize SiteBlazer.new(site)
# Necesario para los breadcrumbs.
ActionView::Base.include Loaf::ViewExtensions unless ActionView::Base.included_modules.include? Loaf::ViewExtensions
breadcrumb current_usuarie.email, main_app.edit_usuarie_registration_path
breadcrumb 'sites.index', main_app.sites_path, match: :exact
breadcrumb site.title, main_app.site_path(site), match: :exact
breadcrumb 'stats.index', root_path, match: :exact
end
def site
@site ||= find_site
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: Usuarie::CONSENT_FIELDS)
devise_parameter_sanitizer.permit(:account_update, keys: %i[lang])
end
def prepare_exception_notifier
request.env['exception_notifier.exception_data'] = { usuarie: current_usuarie }
end
# Olvidar el idioma elegido antes de iniciar la sesión y reenviar a
# los sitios en el idioma de le usuarie.
def after_sign_in_path_for(resource)
session[:locale] = nil
super
end
# Guardar la ubicación para que devise redirija a donde íbamos, a
# menos que estemos recibiendo información o intentando ingresar.
def store_location!
return if request.xhr?
return unless request.request_method_symbol == :GET
return if devise_controller? && !is_a?(Devise::RegistrationsController) && params[:action] != 'edit'
session[:usuarie_return_to] = request.fullpath
end
end

View file

@ -0,0 +1,46 @@
# frozen_string_literal: true
# La lista de estados de compilación, por ahora solo mostramos el último
# estado.
class BuildStatsController < ApplicationController
include ActionView::Helpers::NumberHelper
include ActionView::Helpers::DateHelper
before_action :authenticate_usuarie!
breadcrumb -> { current_usuarie.email }, :edit_usuarie_registration_path
breadcrumb 'sites.index', :sites_path, match: :exact
breadcrumb -> { site.title }, -> { site_posts_path(site, locale: locale) }, match: :exact
def index
authorize SiteBuildStat.new(site)
breadcrumb I18n.t('build_stats.index.title'), ''
@headers = %w[type url seconds size].map do |header|
t("deploy_mailer.deployed.th.#{header}")
end
@table = site.deployment_list.map do |deploy|
type = deploy.class.name.underscore
urls = deploy.urls.map do |url|
URI.parse(url)
rescue URI::Error
nil
end.compact
urls = [nil] if urls.empty?
build_stat = deploy.build_stats.where(status: true).last
seconds = build_stat&.seconds || 0
{
title: t("deploy_mailer.deployed.#{type}.title"),
urls: urls,
seconds: {
human: distance_of_time_in_words(seconds),
machine: "PT#{seconds}S"
},
size: number_to_human_size(build_stat&.bytes || 0, precision: 2)
}
end
end
end

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
module ActiveStorage
module AuthenticatedDirectUploadsController
extend ActiveSupport::Concern
included do
before_action :authenticate_usuarie!
end
end
end

View file

@ -0,0 +1,194 @@
# frozen_string_literal: true
# Modificaciones para Blazer
module BlazerDecorator
# No poder obtener información de la base de datos.
module DisableDatabaseInfo
extend ActiveSupport::Concern
included do
def docs; end
def tables; end
def schema; end
end
end
# Deshabilitar edición de consultas y chequeos.
module DisableEdits
extend ActiveSupport::Concern
included do
def create; end
def update; end
def destroy; end
def run; end
def refresh; end
def cancel; end
end
end
# Blazer hace un gran esfuerzo para ejecutar consultas de forma
# asincrónica pero termina enviándolas por JS.
module RunSync
extend ActiveSupport::Concern
included do
alias_method :original_show, :show
include Blazer::BaseHelper
def show
original_show
options = { user: blazer_user, query: @query, run_id: SecureRandom.uuid, async: false }
@data_source = Blazer.data_sources[@query.data_source]
@result = Blazer::RunStatement.new.perform(@data_source, @statement, options)
chart_data
end
private
# Solo mostrar las consultas de le usuarie
def set_queries(_ = nil)
@queries = (@current_usuarie || current_usuarie).blazer_queries
end
# blazer-2.4.2/app/views/blazer/queries/run.html.erb
def chart_type
case @result.chart_type
when /\Aline(2)?\z/
chart_options.merge! min: nil
when /\Abar(2)?\z/
chart_options.merge! library: { tooltips: { intersect: false, axis: 'x' } }
when 'pie'
chart_options
when 'scatter'
chart_options.merge! library: { tooltips: { intersect: false } }, xtitle: @result.columns[0],
ytitle: @result.columns[1]
when nil
else
if @result.column_types.size == 2
chart_options.merge! library: { tooltips: { intersect: false, axis: 'x' } }
else
chart_options.merge! library: { tooltips: { intersect: false } }
end
end
@result.chart_type
end
def chart_data
@chart_data ||=
case chart_type
when 'line'
@result.columns[1..-1].each_with_index.map do |k, i|
{
name: blazer_series_name(k),
data: @result.rows.map do |r|
[r[0], r[i + 1]]
end,
library: series_library[i]
}
end
when 'line2'
@result.rows.group_by do |r|
v = r[1]
(@result.boom[@result.columns[1]] || {})[v.to_s] || v
end.each_with_index.map do |(name, v), i|
{
name: blazer_series_name(name),
data: v.map do |v2|
[v2[0], v2[2]]
end,
library: series_library[i]
}
end
when 'pie'
@result.rows.map do |r|
[(@result.boom[@result.columns[0]] || {})[r[0].to_s] || r[0], r[1]]
end
when 'bar'
(@result.rows.first.size - 1).times.map do |i|
name = @result.columns[i + 1]
{
name: blazer_series_name(name),
data: @result.rows.first(20).map do |r|
[(@result.boom[@result.columns[0]] || {})[r[0].to_s] || r[0], r[i + 1]]
end
}
end
when 'bar2'
first_20 = @result.rows.group_by { |r| r[0] }.values.first(20).flatten(1)
labels = first_20.map { |r| r[0] }.uniq
series = first_20.map { |r| r[1] }.uniq
labels.each do |l|
series.each do |s|
first_20 << [l, s, 0] unless first_20.find { |r| r[0] == l && r[1] == s }
end
end
first_20.group_by do |r|
v = r[1]
(@result.boom[@result.columns[1]] || {})[v.to_s] || v
end.each_with_index.map do |(name, v), _i|
{
name: blazer_series_name(name),
data: v.sort_by do |r2|
labels.index(r2[0])
end.map do |v2|
v3 = v2[0]
[(@result.boom[@result.columns[0]] || {})[v3.to_s] || v3, v2[2]]
end
}
end
when 'scatter'
@result.rows
end
end
def target_index
@target_index ||= @result.columns.index do |k|
k.downcase == 'target'
end
end
def series_library
@series_library ||= {}.tap do |sl|
if target_index
color = '#109618'
sl[target_index - 1] = {
pointStyle: 'line',
hitRadius: 5,
borderColor: color,
pointBackgroundColor: color,
backgroundColor: color,
pointHoverBackgroundColor: color
}
end
end
end
def chart_options
@chart_options ||= { id: SecureRandom.hex }
end
end
end
end
classes = [Blazer::QueriesController, Blazer::ChecksController, Blazer::DashboardsController]
modules = [BlazerDecorator::DisableDatabaseInfo, BlazerDecorator::DisableEdits]
classes.each do |klass|
modules.each do |modul|
klass.include modul unless klass.included_modules.include? modul
end
end
Blazer::QueriesController.include BlazerDecorator::RunSync

View file

@ -12,13 +12,31 @@ module ExceptionHandler
rescue_from PageNotFound, with: :page_not_found
rescue_from ActionController::RoutingError, with: :page_not_found
rescue_from Pundit::NilPolicyError, with: :page_not_found
rescue_from Pundit::NilPolicyError, with: :page_not_found
rescue_from ActionController::RoutingError, with: :page_not_found
rescue_from ActionController::ParameterMissing, with: :page_not_found
end
def site_not_found
reset_response!
flash[:error] = I18n.t('errors.site_not_found')
redirect_to sites_path
end
def page_not_found
send_file Rails.root.join('public', '404.html')
reset_response!
render 'application/page_not_found', status: :not_found
end
private
def reset_response!
self.response_body = nil
@_response_body = nil
headers.delete('Location')
end
end

View file

@ -0,0 +1,36 @@
# frozen_string_literal: true
module ModerationConcern
extend ActiveSupport::Concern
included do
private
def redirect_to_moderation_queue!
redirect_back fallback_location: site_moderation_queue_path(**(session[:moderation_queue_filters] || {}))
end
# @return [String]
def panel_actor_mention
@panel_actor_mention ||= ENV.fetch('PANEL_ACTOR_MENTION', '@sutty@sutty.nl')
end
def remote_flag_params(model)
remote_flag = ActivityPub::RemoteFlag.find_by(actor_id: model.actor_id)
{ remote_flag_attributes: { id: remote_flag&.id, message: ''.dup } }.tap do |p|
p[:remote_flag_attributes][:site_id] = model.site_id
p[:remote_flag_attributes][:actor_id] = model.actor_id
I18n.available_locales.each do |locale|
p[:remote_flag_attributes][:message].tap do |m|
m << I18n.t(locale)
m << ': '
m << I18n.t('remote_flags.report_message', locale: locale, panel_actor_mention: panel_actor_mention)
m << '\n\n'
end
end
end
end
end
end

View file

@ -0,0 +1,15 @@
# frozen_string_literal: true
module ModerationFiltersConcern
extend ActiveSupport::Concern
included do
before_action :store_filters_in_session!, only: %i[index show]
private
def store_filters_in_session!
session[:moderation_queue_filters] = params.permit(:instance_state, :actor_state, :activity_pub_state)
end
end
end

View file

@ -0,0 +1,11 @@
# frozen_string_literal: true
class EnvController < ActionController::Base
skip_before_action :verify_authenticity_token
def index
@site = Site.find_by_name('panel') || Site.first
stale? @site if @site
end
end

View file

@ -0,0 +1,49 @@
# frozen_string_literal: true
# Estado de las listas de bloqueo en cada sitio
class FediblockStatesController < ApplicationController
# Realiza cambios en las listas de bloqueo
def action_on_several
# Encontrar todas y deshabilitar las que no se enviaron
site.fediblock_states.all.find_each do |fediblock_state|
if fediblock_states_ids.include? fediblock_state.id
fediblock_state.enable! if fediblock_state.may_enable?
elsif fediblock_state.may_disable?
fediblock_state.disable!
end
flash[:success] = I18n.t('fediblock_states.action_on_several.success')
rescue Exception => e
ExceptionNotifier.notify_exception(e, data: { site: site.name })
flash.delete(:success)
flash[:error] = I18n.t('fediblock_states.action_on_several.error')
end
# Bloquear otras instancias
if custom_blocklist.present?
if ActivityPub::InstanceModerationJob.perform_now(site: site, hostnames: custom_blocklist)
flash[:success] = I18n.t('fediblock_states.action_on_several.custom_blocklist_success')
else
flash[:error] = I18n.t('fediblock_states.action_on_several.custom_blocklist_error')
end
end
redirect_to site_moderation_queue_path
end
private
def fediblock_states_ids
params[:fediblock_states_ids] || []
end
# La lista de hostnames
def custom_blocklist
@custom_blocklist ||= fediblocks_states_params[:custom_blocklist].split("\n").map(&:strip).select(&:present?)
end
def fediblocks_states_params
@fediblocks_states_params ||= params.permit(:custom_blocklist, fediblock_states_ids: [])
end
end

View file

@ -0,0 +1,51 @@
# frozen_string_literal: true
# Actualiza la relación entre un sitio y una instancia
class InstanceModerationsController < ApplicationController
include ModerationConcern
InstanceModeration.events.each do |event|
define_method(event) do
authorize instance_moderation
message =
if instance_moderation.public_send(:"may_#{event}?") && instance_moderation.public_send(:"#{event}!")
:success
else
:error
end
flash[message] = I18n.t("instance_moderations.#{event}.#{message}")
redirect_to_moderation_queue!
end
end
def action_on_several
redirect_to_moderation_queue!
instance_moderations = site.instance_moderations.where(id: params[:instance_moderation])
return if instance_moderations.count.zero?
authorize instance_moderations
action = params[:instance_moderation_action].to_sym
method = :"#{action}_all!"
return unless InstanceModeration.events.include? action
InstanceModeration.transaction do
message = instance_moderations.public_send(method) ? :success : :error
flash[:message] = I18n.t("instance_moderations.action_on_several.#{message}")
end
end
private
# @return [InstanceModeration]
def instance_moderation
@instance_moderation ||= site.instance_moderations.find(params[:instance_moderation_id])
end
end

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
# Cola de moderación de ActivityPub
class ModerationQueueController < ApplicationController
include ModerationFiltersConcern
before_action :authenticate_usuarie!
breadcrumb -> { current_usuarie.email }, :edit_usuarie_registration_path
breadcrumb 'sites.index', :sites_path, match: :exact
# Cola de moderación viendo todo el sitio
def index
authorize ModerationQueue.new(site)
breadcrumb site.title, site_posts_path(site)
breadcrumb I18n.t('moderation_queue.index.title'), ''
site.moderation_checked!
# @todo cambiar el estado por query
@activity_pubs = site.activity_pubs
@instance_moderations = rubanok_process(site.instance_moderations, with: InstanceModerationProcessor)
@actor_moderations = rubanok_process(site.actor_moderations, with: ActorModerationProcessor)
@moderation_queue = rubanok_process(site.activity_pubs, with: ActivityPubProcessor)
end
end

View file

@ -2,85 +2,73 @@
# Controlador para artículos
class PostsController < ApplicationController
include Pundit
rescue_from Pundit::NilPolicyError, with: :page_not_found
before_action :authenticate_usuarie!
before_action :service_for_direct_upload, only: %i[new edit]
# TODO: Traer los comunes desde ApplicationController
breadcrumb -> { current_usuarie.email }, :edit_usuarie_registration_path
breadcrumb 'sites.index', :sites_path, match: :exact
breadcrumb -> { site.title }, -> { site_posts_path(site, locale: locale) }, match: :exact
# Las URLs siempre llevan el idioma actual o el de le usuarie
def default_url_options
{ locale: params[:locale] || current_usuarie&.lang || I18n.locale }
{ locale: locale }
end
def index
authorize Post
@site = find_site
@category = params.dig(:category)
@layout = params.dig(:layout)
@locale = locale
# XXX: Cada vez que cambiamos un Post tocamos el sitio con lo que es
# más simple saber si hubo cambios.
if @category || @layout || stale?(@site)
@posts = @site.posts(lang: locale)
@posts = @posts.where(categories: @category) if @category
@posts = @posts.where(layout: @layout) if @layout
@posts = PostPolicy::Scope.new(current_usuarie, @posts).resolve
return unless stale?([current_usuarie, site, filter_params])
@category_name = if uuid?(@category)
@site.posts(lang: locale).find(@category, uuid: true)&.title&.value
else
@category
end
# Todos los artículos de este sitio para el idioma actual
@posts = site.indexed_posts.where(locale: locale)
@posts = @posts.page(filter_params.delete(:page)) if site.pagination
# De este tipo
@posts = @posts.where(layout: filter_params[:layout]) if filter_params[:layout]
# Que estén dentro de la categoría
@posts = @posts.in_category(filter_params[:category]) if filter_params[:category]
# Aplicar los parámetros de búsqueda
@posts = @posts.search(locale, filter_params[:q]) if filter_params[:q].present?
# A los que este usuarie tiene acceso
@posts = PostPolicy::Scope.new(current_usuarie, @posts).resolve
# Filtrar los posts que les invitades no pueden ver
@usuarie = @site.usuarie? current_usuarie
# Filtrar los posts que les invitades no pueden ver
@usuarie = site.usuarie? current_usuarie
# Orden descendiente por número y luego por fecha
@posts.sort_by!(:order, :date).reverse!
end
@site_stat = SiteStat.new(site)
end
def show
@site = find_site
@post = @site.posts(lang: locale).find params[:id]
authorize @post
@locale = locale
fresh_when @post
authorize post
breadcrumb post.title.value, ''
fresh_when post
end
# Genera una previsualización del artículo.
#
# TODO: No todos los artículos tienen previsualización!
def preview
@site = find_site
@post = @site.posts(lang: locale).find params[:post_id]
authorize post
authorize @post
render html: @post.render
render html: post.render
end
def new
authorize Post
@site = find_site
@post = @site.posts.build(lang: locale, layout: params[:layout])
@locale = locale
@post = site.posts(lang: locale).build(layout: params[:layout])
breadcrumb I18n.t('loaf.breadcrumbs.posts.new', layout: @post.layout.humanized_name.downcase), ''
end
def create
authorize Post
@site = find_site
service = PostService.new(site: @site,
service = PostService.new(site: site,
usuarie: current_usuarie,
params: params)
@post = service.create
if @post.persisted?
@site.touch
site.touch
forget_content
redirect_to site_post_path(@site, @post)
@ -90,30 +78,24 @@ class PostsController < ApplicationController
end
def edit
@site = find_site
@post = @site.posts(lang: locale).find params[:id]
authorize @post
@locale = locale
authorize post
breadcrumb post.title.value, site_post_path(site, post, locale: locale), match: :exact
breadcrumb 'posts.edit', ''
end
def update
@site = find_site
@post = @site.posts(lang: locale).find params[:id]
authorize post
authorize @post
service = PostService.new(site: @site,
post: @post,
service = PostService.new(site: site,
post: post,
usuarie: current_usuarie,
params: params)
if service.update.persisted?
@site.touch
site.touch
forget_content
redirect_to site_post_path(@site, @post)
redirect_to site_post_path(site, post)
else
render 'posts/edit'
end
@ -121,34 +103,30 @@ class PostsController < ApplicationController
# Eliminar artículos
def destroy
@site = find_site
@post = @site.posts(lang: locale).find params[:id]
authorize post
authorize @post
service = PostService.new(site: @site,
post: @post,
service = PostService.new(site: site,
post: post,
usuarie: current_usuarie,
params: params)
# TODO: Notificar si se pudo o no
service.destroy
@site.touch
redirect_to site_posts_path(@site)
site.touch
redirect_to site_posts_path(site, locale: post.lang.value)
end
# Reordenar los artículos
def reorder
@site = find_site
authorize @site
authorize site
service = PostService.new(site: @site,
service = PostService.new(site: site,
usuarie: current_usuarie,
params: params)
service.reorder
@site.touch
redirect_to site_posts_path(@site)
site.touch
redirect_to site_posts_path(site, locale: site.default_locale)
end
# Devuelve el idioma solicitado a través de un parámetro, validando
@ -159,14 +137,35 @@ class PostsController < ApplicationController
# solicite a le usuarie crear el nuevo idioma y que esto lo agregue al
# _config.yml del sitio en lugar de mezclar idiomas.
def locale
@site&.locales&.find(-> { I18n.locale.to_s }) do |l|
l == params[:locale]
@locale ||= site&.locales&.find(-> { site&.default_locale }) do |l|
l.to_s == params[:locale]
end
end
# Instruye al editor a olvidarse el contenido del artículo. Usar
# cuando hayamos guardado la información correctamente.
def forget_content
flash[:js] = { target: 'editor', action: 'forget-content', keys: params[:storage_keys].to_json }
flash[:js] = { target: 'editor', action: 'forget-content', keys: (params[:storage_keys] || []).to_json }
end
private
# Los parámetros de filtros que vamos a mantener en todas las URLs,
# solo los que no estén vacíos.
#
# @return [Hash]
def filter_params
@filter_params ||= params.permit(:q, :category, :layout, :page).to_hash.select do |_, v|
v.present?
end.transform_keys(&:to_sym)
end
def post
@post ||= site.posts(lang: locale).find(params[:post_id] || params[:id])
end
# Recuerda el nombre del servicio de subida de archivos
def service_for_direct_upload
session[:service_name] = site.name.to_sym
end
end

View file

@ -6,8 +6,6 @@ class PrivateController < ApplicationController
# XXX: Permite ejecutar JS
skip_forgery_protection
include Pundit
# Enviar el archivo si existe, agregar una / al final siempre para no
# romper las direcciones relativas.
def show

View file

@ -2,32 +2,45 @@
# Controlador de sitios
class SitesController < ApplicationController
include Pundit
rescue_from Pundit::NilPolicyError, with: :page_not_found
before_action :authenticate_usuarie!
breadcrumb -> { current_usuarie.email }, :edit_usuarie_registration_path
breadcrumb 'sites.index', :sites_path, match: :exact
# Ver un listado de sitios
def index
authorize Site
@sites = current_usuarie.sites.order(:title)
@sites = current_usuarie.sites.order(updated_at: :desc)
fresh_when @sites
end
# Genera la caja del estado para HTMX
def status
authorize site
render('sites/status', layout: false) if stale? site
end
def button
authorize site
render('sites/build', layout: false)
end
# No tenemos propiedades de un sitio aún, así que vamos al listado de
# artículos
def show
authorize site
redirect_to site_posts_path(site)
redirect_to site_posts_path(site, locale: site.default_locale)
end
def new
breadcrumb 'sites.new', :new_site_path
@site = Site.new
authorize @site
@site.deploys.build type: 'DeployLocal'
end
def create
@ -35,7 +48,7 @@ class SitesController < ApplicationController
params: site_params)
if (@site = service.create).persisted?
redirect_to site_posts_path(@site)
redirect_to site_posts_path(@site, locale: @site.default_locale)
else
render 'new'
end
@ -43,6 +56,10 @@ class SitesController < ApplicationController
def edit
authorize site
breadcrumb site.title, site_posts_path(site, locale: site.default_locale), match: :exact
breadcrumb 'sites.edit', site_path(site)
SiteService.new(site: site).build_deploys
end
@ -53,7 +70,8 @@ class SitesController < ApplicationController
usuarie: current_usuarie)
if service.update.valid?
redirect_to site_posts_path(site)
flash[:notice] = I18n.t('sites.update.post')
redirect_to site_posts_path(site, locale: site.default_locale)
else
render 'edit'
end
@ -62,10 +80,9 @@ class SitesController < ApplicationController
def enqueue
authorize site
# XXX: Convertir en una máquina de estados?
DeployJob.perform_async site.id if site.enqueue!
SiteService.new(site: site).deploy
redirect_to site_posts_path(site)
redirect_to site_posts_path(site, locale: site.default_locale)
end
def reorder_posts
@ -85,7 +102,7 @@ class SitesController < ApplicationController
flash[:danger] = I18n.t('errors.posts.reorder')
end
redirect_to site_posts_path(site)
redirect_to site_posts_path(site, locale: site.default_locale)
end
def fetch
@ -97,7 +114,7 @@ class SitesController < ApplicationController
def merge
authorize site
if site.repository.merge(current_usuarie)
if SiteService.new(site: site, usuarie: current_usuarie).merge
flash[:success] = I18n.t('sites.fetch.merge.success')
else
flash[:error] = I18n.t('sites.fetch.merge.error')
@ -106,27 +123,6 @@ class SitesController < ApplicationController
redirect_to sites_path
end
# Obtiene y streamea archivos estáticos desde el repositorio mismo,
# pero sólo los públicos (es decir los archivos subidos desde Sutty).
def static_file
authorize site
file = params.require(:file) + '.' + params.require(:format)
raise ActionController::RoutingError.new(nil, nil) unless file.start_with? 'public/'
path = site.relative_path file
raise ActionController::RoutingError.new(nil, nil) unless File.exist? path
# TODO: Hacer esto usa recursos, pero menos que generar el sitio
# cada vez. Para poder usar X-Accel tendríamos que montar los
# repositorios en el servidor web, cosa que no queremos, o hacer
# links simbólicos desde todos los public, o usar un servidor web
# local que soporte sendfile mejor que Rails (nghttpd?)
send_file path
end
private
def site

View file

@ -3,16 +3,223 @@
# Estadísticas del sitio
class StatsController < ApplicationController
include Pundit
include ActionView::Helpers::DateHelper
before_action :authenticate_usuarie!
before_action :authorize_stats
breadcrumb -> { current_usuarie.email }, :edit_usuarie_registration_path
breadcrumb 'sites.index', :sites_path, match: :exact
breadcrumb -> { site.title }, -> { site_posts_path(site, locale: locale) }, match: :exact
EXTRA_OPTIONS = {
builds: {},
space_used: { bytes: true },
build_time: {}
}.freeze
# XXX: Permitir a Chart.js inyectar su propio CSS
content_security_policy only: :index do |policy|
policy.style_src :self, :unsafe_inline
policy.script_src :self, :unsafe_inline
end
# Parámetros por defecto
#
# @return [Hash]
def default_url_options
{ interval: 'day', period_start: Date.today.beginning_of_year, period_end: Date.today }
end
def index
@site = find_site
authorize SiteStat.new(@site)
breadcrumb I18n.t('stats.index.title'), ''
# Solo queremos el promedio de tiempo de compilación, no de
# instalación de dependencias.
stats = @site.build_stats.jekyll
@build_avg = stats.average(:seconds).to_f.round(2)
@build_max = stats.maximum(:seconds).to_f.round(2)
params.with_defaults! default_url_options
@chart_params = {
interval: interval,
period_start: params[:period_start],
period_end: params[:period_end]
}
hostnames
last_stat
chart_options
normalized_urls
expires_in = Time.now.try(:"end_of_#{Stat.default_interval}") - Time.now
@columns = {}
Stat::COLUMNS.each do |column|
@columns[column] =
Rails.cache.fetch("stats/#{column}/#{site.id}", expires_in: expires_in) do
rollup_scope.where(interval: interval, name: "host|#{column}")
.where_dimensions(host: hostnames)
.group("dimensions->>'#{column}'")
.order('sum(value) desc')
.sum(:value)
.transform_values(&:to_i)
.transform_values do |v|
v * nodes
end
end
end
end
# Genera un gráfico de visitas por dominio asociado a este sitio
def host
return unless stale? [last_stat, hostnames, interval, period]
stats = rollup_scope.where_dimensions(host: hostnames).multi_series('host', interval: interval).tap do |series|
series.each do |serie|
serie[:name] = serie.dig(:dimensions, 'host')
serie[:data].transform_values! do |value|
value * nodes
end
end
end
render json: stats
end
def resources
return unless stale? [last_stat, interval, resource, period]
options = { interval: interval, dimensions: { site_id: site.id } }
render json: rollup_scope.series(resource, **options)
end
def uris
return unless stale? [last_stat, hostnames, interval, normalized_urls, period]
options = { host: hostnames, uri: normalized_paths }
# XXX: where_dimensions es más corto pero no aprovecha los índices
# de Rollup
stats = rollup_scope.where_dimensions(**options).multi_series('host|uri', interval: interval).tap do |series|
series.each do |serie|
serie[:name] = serie[:dimensions].slice('host', 'uri').values.join.sub('/index.html', '/')
serie[:data].transform_values! do |value|
value * nodes
end
end
end
render json: stats
end
private
def rollup_scope
Rollup.where(time: period)
end
def last_stat
@last_stat ||= site.stats.last
end
def authorize_stats
authorize SiteStat.new(site)
end
# TODO: Eliminar cuando mergeemos referer-origin
def hostnames
@hostnames ||= site.hostnames
end
# Normalizar las URLs
#
# @return [Array]
def normalized_urls
@normalized_urls ||=
begin
urls = params[:urls].is_a?(Array) ? params[:urls] : params[:urls]&.split("\n")
urls = urls&.map(&:strip)&.select(&:present?)&.select do |uri|
uri.start_with? 'https://'
end
urls ||= [site.url]
urls.map do |u|
# XXX: Eliminar al deployear
# @see {https://0xacab.org/sutty/containers/nginx/-/merge_requests/1}
next u unless u.end_with? '/'
"#{u}index.html"
end.uniq
end
end
def normalized_paths
@normalized_paths ||= normalized_urls.map do |u|
"/#{u.split('/', 4).last}"
end.map do |u|
URI.decode_www_form_component u
end
end
# Opciones por defecto para los gráficos.
#
# La invitación a volver dentro de X tiempo es para dar un estimado de
# cuándo habrá información disponible, porque Rollup genera intervalos
# completos (¿aunque dice que no?)
#
# La diferencia se calcula sumando el intervalo a la hora de última
# toma de estadísticas y restando el tiempo que pasó desde ese
# momento.
def chart_options
time = (last_stat&.created_at || Time.now) + 1.try(interval)
please_return_at = { please_return_at: distance_of_time_in_words(Time.now, time) }
@chart_options ||= {
locale: I18n.locale,
empty: I18n.t('stats.index.empty', **please_return_at),
loading: I18n.t('stats.index.loading'),
html: %(<div id="%{id}" class="d-flex align-items-center justify-content-center" style="height: %{height}; width: %{width};">%{loading}</div>)
}
end
# Obtiene y valida los intervalos
#
# @return [Symbol]
def interval
@interval ||= begin
i = params[:interval]&.to_sym
Stat::INTERVALS.include?(i) ? i : Stat::INTERVALS.first
end
end
# @return [Symbol]
def resource
@resource ||= begin
r = params[:resource].to_sym
Stat::RESOURCES.include?(r) ? r : Stat::RESOURCES.first
end
end
# Obtiene la cantidad de nodos de Sutty, para poder calcular la
# cantidad de visitas.
#
# Como repartimos las visitas por nodo rotando las IPs en el
# nameserver y los resolvedores de DNS eligen un nameserver
# aleatoriamente, la cantidad de visitas se reparte
# equitativamente.
#
# XXX: Remover cuando podamos centralizar los AccessLog
#
# @return [Integer]
def nodes
@nodes ||= ENV.fetch('NODES', 1).to_i
end
def period
@period ||= begin
p = params.permit(:period_start, :period_end)
p[:period_start]..p[:period_end]
end
end
def site
@site ||= find_site
end
end

View file

@ -7,12 +7,18 @@ class UsuariesController < ApplicationController
include Pundit
before_action :authenticate_usuarie!
# TODO: Traer los comunes desde ApplicationController
breadcrumb -> { current_usuarie.email }, :edit_usuarie_registration_path
breadcrumb 'sites.index', :sites_path, match: :exact
breadcrumb -> { site.title }, -> { site_posts_path(site, locale: locale) }, match: :exact
# Mostrar todes les usuaries e invitades de un sitio
def index
@site = find_site
site_usuarie = SiteUsuarie.new(@site, current_usuarie)
site_usuarie = SiteUsuarie.new(site, current_usuarie)
authorize site_usuarie
breadcrumb 'usuaries.index', ''
@policy = policy(site_usuarie)
end
@ -41,7 +47,7 @@ class UsuariesController < ApplicationController
@usuarie = Usuarie.find(params[:usuarie_id])
if @site.usuaries.count > 1
@usuarie.rol_for_site(@site).update_attribute :rol, 'invitade'
@usuarie.rol_for_site(@site).update_attribute :rol, Rol::INVITADE
else
flash[:warning] = I18n.t('usuaries.index.demote.denied')
end
@ -55,7 +61,7 @@ class UsuariesController < ApplicationController
authorize SiteUsuarie.new(@site, current_usuarie)
@usuarie = Usuarie.find(params[:usuarie_id])
@usuarie.rol_for_site(@site).update_attribute :rol, 'usuarie'
@usuarie.rol_for_site(@site).update_attribute :rol, Rol::USUARIE
redirect_to site_usuaries_path
end
@ -66,6 +72,8 @@ class UsuariesController < ApplicationController
site_usuarie = SiteUsuarie.new(@site, current_usuarie)
authorize site_usuarie
params[:invite_as] = invite_as
@policy = policy(site_usuarie)
end
@ -75,27 +83,33 @@ class UsuariesController < ApplicationController
authorize SiteUsuarie.new(@site, current_usuarie)
# Enviar la invitación si es necesario y agregar al sitio
invitaciones.each do |invitacion|
# Si la cuenta no existe, envía una invitación por correo, sino,
# no se envía nada
#
# TODO: Enviar invitación igual! Podemos no usar el Mailer de
# DeviseInvitations y usar uno propio que contenga texto y se
# envíe de todas formas.
usuarie = Usuarie.invite! email: invitacion.address,
skip_invitation: true
invitaciones.each do |address|
next if Usuarie.where(id: @site.roles.pluck(:usuarie_id)).find_by_email(address)
# No invitar al sitio si ya estaba en la lista!
#
# XXX: En este caso no estamos enviando ninguna invitación
next if usuarie.sites.exists? @site.id
Usuarie.transaction do
usuarie = Usuarie.find_by_email(address)
usuarie ||= Usuarie.invite!({ email: address, skip_invitation: true }).tap do |u|
u.send :generate_invitation_token!
end
@site.roles << Rol.create(usuarie: usuarie, site: @site,
temporal: true, rol: invited_as)
role = @site.roles.create(usuarie: usuarie, temporal: true, rol: invited_as)
# Invitamos después de crear el rol para que el correo de
# invitación pueda recibir el sitio.
usuarie.deliver_invitation
# XXX: La invitación tiene que ser enviada luego de crear el rol
if role.persisted?
# Si es una cuenta manual que no está confirmada aun,
# aprovechar para reconfirmarla.
if !usuarie.confirmed? && !usuarie.created_by_invite?
usuarie.confirmation_token = nil
usuarie.send :generate_confirmation_token!
end
usuarie.deliver_invitation
else
raise ArgumentError, role.errors.full_messages
end
rescue ArgumentError => e
ExceptionNotifier.notify_exception(e, data: { site: @site.name, address: address })
end
end
redirect_to site_usuaries_path(@site)
@ -104,16 +118,21 @@ class UsuariesController < ApplicationController
# Aceptar la invitación
def accept_invitation
@site = find_site
rol = current_usuarie.rol_for_site(@site)
# Le usuarie ya aceptó la invitación
if site.usuarie?(current_usuarie) || site.invitade?(current_usuarie)
unless rol&.temporal
redirect_to sites_path
return
end
authorize SiteUsuarie.new(@site, current_usuarie)
@site.touch if current_usuarie.rol_for_site(@site).update_attribute :temporal, false
Rol.transaction do
rol.update(temporal: false) &&
current_usuarie.update(invitation_token: nil) &&
@site.touch
end
redirect_to sites_path
end
@ -131,26 +150,32 @@ class UsuariesController < ApplicationController
private
# Traer todas las invitaciones que al menos tengan usuarie y dominio
#
# @return [Array]
def invitaciones
# XXX: Podríamos usar EmailAddress pero hace chequeos más lentos
i = params[:invitaciones].split("\n").map do |m|
params[:invitaciones]&.tr("\r", '')&.split("\n")&.map do |m|
Mail::Address.new m
rescue Mail::Field::IncompleteParseError
nil
end.compact
i.select do |m|
rescue Mail::Field::IncompleteParseError
nil
end.compact.select do |m|
m.local && m.domain
end
end.map(&:address)
end
# El tipo de invitación que tenemos que enviar, si alguien mandó
# cualquier cosa, usamos el privilegio menor.
#
# @return [String]
def invited_as
if Rol::ROLES.include?(params[:invited_as])
params[:invited_as]
else
'invitade'
end
Rol.role?(params[:invited_as]) ? params[:invited_as] : Rol::INVITADE
end
def invite_as
Rol.role?(params[:invite_as]&.singularize) ? params[:invite_as] : Rol::INVITADE.pluralize
end
def site
@site ||= find_site
end
end

View file

@ -13,7 +13,7 @@ module ApplicationHelper
root = names.shift
names.each do |n|
root += '[' + n.to_s + ']'
root += "[#{n}]"
end
[root, name]
@ -22,7 +22,7 @@ module ApplicationHelper
def plain_field_name_for(*names)
root, name = field_name_for(*names)
root + '[' + name.to_s + ']'
"#{root}[#{name}]"
end
def distance_of_time_in_words_if_more_than_a_minute(seconds)
@ -33,10 +33,24 @@ module ApplicationHelper
end
end
# Devuelve todas las etiquetas HTML que queremos mantener
def all_html_tags
%w[h1 h2 h3 h4 h5 h6 p a ul ol li table tr td th tbody thead
tfoot em strong sup blockquote cite pre section article]
# Sanitizador que elimina todo
#
# @param html [String]
# @return [String]
def text_plain(html)
sanitize(html, tags: [], attributes: [])
end
# Sanitizador con etiquetas y atributos por defecto
#
# @param html [String]
# @param options [Hash]
# @return [String]
def sanitize(html, options = {})
options[:tags] ||= Sutty::ALLOWED_TAGS
options[:attributes] ||= Sutty::ALLOWED_ATTRIBUTES
super(html, options)
end
# Genera HTML y limpia etiquetas innecesarias
@ -73,11 +87,12 @@ module ApplicationHelper
# Opciones por defecto para el campo de un formulario
def field_options(attribute, metadata, **extra)
required = metadata.required || extra[:required]
required = extra.key?(:required) ? extra[:required] : metadata.required
{
class: "form-control #{invalid(metadata.post, attribute)} #{extra[:class]}",
required: required,
disabled: metadata.disabled?,
autofocus: (metadata.post.attributes.first == attribute),
aria: {
describedby: id_for_help(attribute),
@ -92,10 +107,11 @@ module ApplicationHelper
end
# Busca la traducción de una etiqueta en los metadatos de un post
def post_label_t(*attribute, post:)
label = post_t(*attribute, post: post, type: :label)
def post_label_t(*attribute, post:, **extra)
required = extra.key?(:required) ? extra[:required] : post[attribute.first].required
label += I18n.t('posts.attributes.required.label') if post.send(attribute.first).required
label = post_t(*attribute, post: post, type: :label)
label += I18n.t('posts.attributes.required.label') if required
label
end
@ -116,16 +132,11 @@ module ApplicationHelper
"#{attribute.join('-')}-datalist"
end
def local_channel
"sutty-#{I18n.locale}"
end
private
def post_t(*attribute, post:, type:)
post.layout.metadata.dig(*attribute, type.to_s, I18n.locale.to_s) ||
post.layout.metadata.dig(*attribute,
type.to_s, I18n.default_locale.to_s) ||
post.layout.metadata.dig(*attribute, type.to_s, I18n.default_locale.to_s) ||
I18n.t("posts.attributes.#{attribute.join('.')}.#{type}")
end
end

View file

@ -0,0 +1,15 @@
# frozen_string_literal: true
module ModerationQueueHelper
def filter_states(**args)
params.permit(:instance_state, :actor_state, :activity_pub_state).merge(**args)
end
def active?(states, state_name, state)
if params[state_name].present?
params[state_name] == state.to_s
else
states.first == state
end
end
end

View file

@ -0,0 +1,17 @@
import { Controller } from "stimulus";
export default class extends Controller {
static targets = [];
connect() {
const state = window.sessionStorage.getItem(this.element.id);
if (state === "open") {
this.element.setAttribute("open", true);
}
}
store(event = undefined) {
window.sessionStorage.setItem(this.element.id, event.newState);
}
}

View file

@ -0,0 +1,106 @@
import { Controller } from "stimulus";
// https://getbootstrap.com/docs/4.6/components/dropdowns/#single-button
export default class extends Controller {
static targets = ["dropdown", "button", "item"];
// Al iniciar el controlador
connect() {
// Llevar la cuenta del item con foco
this.data.set("item", -1);
// Gestionar las teclas
this.keydownEvent = this.keydown.bind(this);
this.element.addEventListener("keydown", this.keydownEvent);
// Gestionar el foco
this.focusinEvent = this.focusin.bind(this);
}
// Al eliminar el controlador (al pasar a otra página)
disconnect() {
// Eliminar la gestión de teclas
this.element.removeEventListener("keydown", this.keydownEvent);
// Eliminar la gestión del foco
document.removeEventListener("focusin", this.focusinEvent);
}
// Mostrar u ocultar
toggle(event) {
(this.buttonTarget.ariaExpanded === "false") ? this.show() : this.hide();
}
// Mostrar
show() {
this.buttonTarget.ariaExpanded = "true";
this.element.classList.add("show");
this.dropdownTarget.classList.add("show");
// Activar la gestión del foco
document.addEventListener("focusin", this.focusinEvent);
}
// Ocultar
hide() {
this.buttonTarget.ariaExpanded = "false";
this.element.classList.remove("show");
this.dropdownTarget.classList.remove("show");
// Volver al inicio el foco de items
this.data.set("item", -1);
// Desactivar la gestión del foco
document.removeEventListener("focusin", this.focusinEvent);
}
// Gestionar el foco
focusin(event) {
const item = this.itemTargets.find(x => x === event.target);
// Si el foco se coloca sobre elementos del controlador, no hacer
// nada
if (event.target === this.buttonTarget || item) {
// Si es un item, el comportamiento de las flechas verticales y el
// Tab tiene que ser igual
if (item) this.data.set("item", this.itemTargets.indexOf(item));
return;
}
// De lo contrario, ocultar
this.hide();
}
// Gestionar las teclas
keydown(event) {
const initial = parseInt(this.data.get("item"));
let item = initial;
switch (event.keyCode) {
case 27:
// Esc cierra el menú y devuelve el foco
this.hide();
this.buttonTarget.focus();
break;
case 38:
// Moverse hacia arriba con tope en el primer item
if (item > -1) item--;
break;
case 40:
// Moverse hacia abajo con tope en el último ítem, si el
// dropdown estaba cerrado, abrirlo.
if (item === -1) this.show();
if (item <= this.itemTargets.length) item++;
break;
}
// Si cambió la posición del ítem, darle foco y actualizar el
// contador.
if (initial !== item) {
this.itemTargets[item]?.focus();
this.data.set("item", item);
}
}
}

View file

@ -0,0 +1,19 @@
import { Controller } from 'stimulus'
import bsCustomFileInput from "bs-custom-file-input";
document.addEventListener("turbolinks:load", () => {
bsCustomFileInput.init();
});
export default class extends Controller {
static targets = ["preview", "input"];
connect() {
}
update(event = undefined) {
if (!this.hasPreviewTarget) return;
this.previewTarget.src = window.URL.createObjectURL(this.inputTarget.files[0])
}
}

View file

@ -0,0 +1,81 @@
import { Controller } from 'stimulus'
require("leaflet/dist/leaflet.css")
import L from 'leaflet'
delete L.Icon.Default.prototype._getIconUrl
L.Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png'),
})
export default class extends Controller {
static targets = [ 'lat', 'lng', 'map', 'overlay' ]
async connect () {
this.marker()
this.latTarget.addEventListener('change', event => this.marker())
this.lngTarget.addEventListener('change', event => this.marker())
window.addEventListener('resize', event => this.map.invalidateSize())
this.map.on('click', event => {
this.latTarget.value = event.latlng.lat
this.lngTarget.value = event.latlng.lng
this.latTarget.dispatchEvent(new Event('change'))
})
}
marker () {
if (this._marker) this.map.removeLayer(this._marker)
this._marker = L.marker(this.coords).addTo(this.map)
return this._marker
}
get lat () {
const lat = parseFloat(this.latTarget.value)
return isNaN(lat) ? 0 : lat
}
get lng () {
const lng = parseFloat(this.lngTarget.value)
return isNaN(lng) ? 0 : lng
}
get coords () {
return [this.lat, this.lng]
}
get bounds () {
return [
[0, 0],
[
this.svgOverlay.viewBox.baseVal.height,
this.svgOverlay.viewBox.baseVal.width,
]
];
}
get map () {
if (!this._map) {
this._map = L.map(this.mapTarget, {
minZoom: 0,
maxZoom: 5
}).setView(this.coords, 0);
this._layer = L.tileLayer(`${this.element.dataset.site}public/map/{z}/{y}/{x}.png`, {
minNativeZoom: 0,
maxNativeZoom: 5,
noWrap: true
}).addTo(this._map);
}
return this._map
}
}

View file

@ -103,7 +103,7 @@ export default class extends Controller {
this.reorder()
// Mantenemos el primero a la vista
rows[0].row.scrollIntoViewIfNeeded()
rows[0].row.scrollIntoView({ block: "center" });
}
counter () {
@ -142,7 +142,7 @@ export default class extends Controller {
this.reorder()
// Mantenemos el primero a la vista
rows[0].row.scrollIntoViewIfNeeded()
rows[0].row.scrollIntoView({ block: "center" });
}
bottom (event) {
@ -163,7 +163,7 @@ export default class extends Controller {
this.reorder()
// Mantenemos el primero a la vista
rows[0].row.scrollIntoViewIfNeeded()
rows[0].row.scrollIntoView({ block: "center" });
}
/*

View file

@ -0,0 +1,11 @@
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["toggle", "input"];
toggle(event = undefined) {
this.inputTargets.forEach(input => {
input.checked = this.toggleTarget.checked;
});
}
}

View file

@ -0,0 +1,339 @@
import { storeContent, restoreContent, forgetContent } from "editor/storage";
import {
isDirectChild,
moveChildren,
safeGetSelection,
safeGetRangeAt,
setAuxiliaryToolbar,
parentBlockNames,
clearSelected,
} from "editor/utils";
import { types, getValidChildren, getType } from "editor/types";
import { setupButtons as setupMarksButtons } from "editor/types/marks";
import { setupButtons as setupBlocksButtons } from "editor/types/blocks";
import { setupButtons as setupParentBlocksButtons } from "editor/types/parentBlocks";
import { setupAuxiliaryToolbar as setupLinkAuxiliaryToolbar } from "editor/types/link";
import {
setupAuxiliaryToolbar as setupMultimediaAuxiliaryToolbar,
setupButtons as setupMultimediaButtons,
} from "editor/types/multimedia";
import { setupAuxiliaryToolbar as setupMarkAuxiliaryToolbar } from "editor/types/mark";
// Esta funcion corrije errores que pueden haber como:
// * que un nodo que no tiene 'text' permitido no tenga children (se les
// inserta un allowedChildren[0])
// * TODO: que haya una imágen sin <figure> o que no esté como bloque (se ponen
// después del bloque en el que están como bloque de por si)
// * convierte <i> y <b> en <em> y <strong>
// Lo hace para que siga la estructura del documento y que no se borren por
// cleanContent luego.
function fixContent(editor: Editor, node: Element = editor.contentEl): void {
if (node.tagName === "SCRIPT" || node.tagName === "STYLE") {
node.parentElement?.removeChild(node);
return;
}
if (node.tagName === "I") {
const el = document.createElement("em");
moveChildren(node, el, null);
node.parentElement?.replaceChild(el, node);
node = el;
}
if (node.tagName === "B") {
const el = document.createElement("strong");
moveChildren(node, el, null);
node.parentElement?.replaceChild(el, node);
node = el;
}
if (node instanceof HTMLImageElement) {
node.dataset.multimediaInner = "";
const figureEl = types.multimedia.create(editor);
let targetEl = node.parentElement;
if (!targetEl) throw new Error("No encontré lx objetivo");
while (true) {
const type = getType(targetEl);
if (!type) throw new Error("lx objetivo tiene tipo");
if (type.type.allowedChildren.includes("multimedia")) break;
if (!targetEl.parentElement) throw new Error("No encontré lx objetivo");
targetEl = targetEl.parentElement;
}
let parentEl = [...targetEl.childNodes].find((el) => el.contains(node));
if (!parentEl) throw new Error("no encontré lx pariente");
targetEl.insertBefore(figureEl, parentEl);
const innerEl = figureEl.querySelector("[data-multimedia-inner]");
if (!innerEl) throw new Error("Raro.");
figureEl.replaceChild(node, innerEl);
node = figureEl;
}
const _type = getType(node);
if (!_type) return;
const { typeName, type } = _type;
if (type.allowedChildren !== "ignore-children") {
const sel = safeGetSelection(editor);
const range = sel && safeGetRangeAt(sel);
if (getValidChildren(node, type).length == 0) {
if (typeof type.handleEmpty !== "string") {
const el = type.handleEmpty.create(editor);
// mover cosas que pueden haber
// por ejemplo: cuando convertís a un <ul>, queda texto fuera del li que
// creamos acá
moveChildren(node, el, null);
node.appendChild(el);
if (range?.intersectsNode(node)) sel?.collapse(el);
}
}
for (const child of node.childNodes) {
if (!(child instanceof Element)) continue;
fixContent(editor, child);
}
}
}
// Esta funcion hace que los elementos del editor sigan la estructura.
// TODO: nos falta borrar atributos (style, y básicamente cualquier otra cosa)
// Edge cases:
// * no borramos los <br> por que se requieren para que los navegadores
// funcionen bien al escribir. no se deberían mostrar de todas maneras
function cleanContent(editor: Editor, node: Element = editor.contentEl): void {
const _type = getType(node);
if (!_type) {
node.parentElement?.removeChild(node);
return;
}
const { type } = _type;
if (type.allowedChildren !== "ignore-children") {
for (const child of node.childNodes) {
if (
child.nodeType === Node.TEXT_NODE &&
!type.allowedChildren.includes("text")
) {
node.removeChild(child);
continue;
}
if (!(child instanceof Element)) continue;
const childType = getType(child);
if (childType?.typeName === "br") continue;
if (!childType || !type.allowedChildren.includes(childType.typeName)) {
// XXX: esto extrae las cosas de adentro para que no sea destructivo
moveChildren(child, node, child);
node.removeChild(child);
return;
}
cleanContent(editor, child);
}
// solo contar children válido para ese nodo
const validChildrenLength = getValidChildren(node, type).length;
const sel = safeGetSelection(editor);
const range = sel && safeGetRangeAt(sel);
if (
type.handleEmpty === "remove" &&
validChildrenLength == 0
//&& (!range || !range.intersectsNode(node))
) {
node.parentNode?.removeChild(node);
return;
}
}
}
function routine(editor: Editor): void {
try {
fixContent(editor);
cleanContent(editor);
storeContent(editor);
editor.htmlEl.value = editor.contentEl.innerHTML;
} catch (error) {
console.error("Hubo un problema corriendo la rutina", editor, error);
}
}
export interface Editor {
editorEl: HTMLElement;
toolbarEl: HTMLElement;
toolbar: {
auxiliary: {
mark: {
parentEl: HTMLElement;
colorEl: HTMLInputElement;
textColorEl: HTMLInputElement;
};
multimedia: {
parentEl: HTMLElement;
fileEl: HTMLInputElement;
uploadEl: HTMLButtonElement;
altEl: HTMLInputElement;
removeEl: HTMLButtonElement;
};
link: {
parentEl: HTMLElement;
urlEl: HTMLInputElement;
};
};
};
contentEl: HTMLElement;
wordAlertEl: HTMLElement;
htmlEl: HTMLTextAreaElement;
}
function getSel<T extends Element>(parentEl: HTMLElement, selector: string): T {
const el = parentEl.querySelector<T>(selector);
if (!el) throw new Error(`No pude encontrar un componente \`${selector}\``);
return el;
}
function setupEditor(editorEl: HTMLElement): void {
// XXX: ¡Esto afecta a todo el documento! ¿Quizás usar un iframe para el editor?
document.execCommand("defaultParagraphSeparator", false, "p");
const editor: Editor = {
editorEl,
toolbarEl: getSel(editorEl, ".editor-toolbar"),
toolbar: {
auxiliary: {
mark: {
parentEl: getSel(editorEl, "[data-editor-auxiliary=mark]"),
colorEl: getSel(
editorEl,
"[data-editor-auxiliary=mark] [name=mark-color]"
),
textColorEl: getSel(
editorEl,
"[data-editor-auxiliary=mark] [name=mark-text-color]"
),
},
multimedia: {
parentEl: getSel(editorEl, "[data-editor-auxiliary=multimedia]"),
fileEl: getSel(
editorEl,
"[data-editor-auxiliary=multimedia] [name=multimedia-file]"
),
uploadEl: getSel(
editorEl,
"[data-editor-auxiliary=multimedia] [name=multimedia-file-upload]"
),
altEl: getSel(
editorEl,
"[data-editor-auxiliary=multimedia] [name=multimedia-alt]"
),
removeEl: getSel(
editorEl,
"[data-editor-auxiliary=multimedia] [name=multimedia-remove]"
),
},
link: {
parentEl: getSel(editorEl, "[data-editor-auxiliary=link]"),
urlEl: getSel(
editorEl,
"[data-editor-auxiliary=link] [name=link-url]"
),
},
},
},
contentEl: getSel(editorEl, ".editor-content"),
wordAlertEl: getSel(editorEl, ".editor-aviso-word"),
htmlEl: getSel(editorEl, "textarea"),
};
console.debug("iniciando editor", editor);
// Recuperar el contenido si hay algo guardado, si tuviéramos un campo
// de última edición podríamos saber si el artículo fue editado
// después o la versión local es la última.
//
// TODO: Preguntar si se lo quiere recuperar.
restoreContent(editor);
// Word alert
editor.contentEl.addEventListener("paste", () => {
editor.wordAlertEl.style.display = "block";
});
// Setup routine listeners
const observer = new MutationObserver(() => routine(editor));
observer.observe(editor.contentEl, {
childList: true,
attributes: true,
subtree: true,
characterData: true,
});
document.addEventListener("selectionchange", () => routine(editor));
// Capture onClick
editor.contentEl.addEventListener(
"click",
(event) => {
const target = event.target! as Element;
const type = getType(target);
if (!type || !type.type.onClick) {
setAuxiliaryToolbar(editor, null);
clearSelected(editor);
return true;
}
type.type.onClick(editor, target);
return false;
},
true
);
// Clean seleted
const selectedEl = editor.contentEl.querySelector("[data-editor-selected]");
if (selectedEl) delete (selectedEl as HTMLElement).dataset.editorSelected;
// Setup botones
setupMarksButtons(editor);
setupBlocksButtons(editor);
setupParentBlocksButtons(editor);
setupMultimediaButtons(editor);
setupLinkAuxiliaryToolbar(editor);
setupMultimediaAuxiliaryToolbar(editor);
setupMarkAuxiliaryToolbar(editor);
// Finally...
routine(editor);
}
document.addEventListener("turbolinks:load", () => {
const flash = document.querySelector<HTMLElement>(".js-flash");
if (flash) {
const keys = JSON.parse(flash.dataset.keys || "[]");
switch (flash.dataset.target) {
case "editor":
switch (flash.dataset.action) {
case "forget-content":
keys.forEach(forgetContent);
}
}
}
for (const editorEl of document.querySelectorAll<HTMLElement>(
".editor[data-editor]"
)) {
try {
setupEditor(editorEl);
} catch (error) {
// TODO: mostrar error
console.error("no se pudo iniciar el editor, error completo", error);
}
}
});

View file

@ -0,0 +1,38 @@
import { Editor } from "editor/editor";
/*
* Guarda una copia local de los cambios para poder recuperarlos
* después.
*
* Usamos la URL completa sin anchors.
*/
function getStorageKey(editor: Editor): string {
const keyEl = editor.editorEl.querySelector<HTMLInputElement>(
'[data-target="storage-key"]'
);
if (!keyEl)
throw new Error("No encuentro la llave para guardar los artículos");
return keyEl.value;
}
export function forgetContent(storedKey: string): void {
window.localStorage.removeItem(storedKey);
}
export function storeContent(editor: Editor): void {
if (editor.contentEl.innerText.trim().length === 0) return;
window.localStorage.setItem(
getStorageKey(editor),
editor.contentEl.innerHTML
);
}
export function restoreContent(editor: Editor): void {
const content = window.localStorage.getItem(getStorageKey(editor));
if (!content) return;
if (content.trim().length === 0) return;
editor.contentEl.innerHTML = content;
}

View file

@ -0,0 +1,140 @@
import { Editor } from "editor/editor";
import { marks } from "editor/types/marks";
import { blocks, li, EditorBlock } from "editor/types/blocks";
import { parentBlocks } from "editor/types/parentBlocks";
import { multimedia } from "editor/types/multimedia";
import {
blockNames,
parentBlockNames,
safeGetRangeAt,
safeGetSelection,
} from "editor/utils";
export interface EditorNode {
selector: string;
// la string es el nombre en la gran lista de types O 'text'
// XXX: esto es un hack para no poner EditorNode dentro de EditorNode,
// quizás podemos hacer que esto sea una función que retorna bool
allowedChildren: string[] | "ignore-children";
// * si es 'do-nothing', no hace nada si está vacío (esto es para cuando
// permitís 'text' entonces se puede tipear adentro, ej: párrafo vacío)
// * si es 'remove', sacamos el coso si está vacío.
// ej: strong: { handleNothing: 'remove' }
// * si es un block, insertamos el bloque y movemos la selección ahí
// ej: ul: { handleNothing: li }
handleEmpty: "do-nothing" | "remove" | EditorBlock;
// esta función puede ser llamada para cosas que no necesariamente sea la
// creación del nodo con el botón; por ejemplo, al intentar recuperar
// el formato. esto es importante por que, por ejemplo, no deberíamos
// cambiar la selección acá.
create: (editor: Editor) => HTMLElement;
onClick?: (editor: Editor, target: Element) => void;
}
export const types: { [propName: string]: EditorNode } = {
...marks,
...blocks,
li,
...parentBlocks,
contentEl: {
selector: ".editor-content",
allowedChildren: [...blockNames, ...parentBlockNames, "multimedia"],
handleEmpty: blocks.paragraph,
create: () => {
throw new Error("se intentó crear contentEl");
},
},
br: {
selector: "br",
allowedChildren: [],
handleEmpty: "do-nothing",
create: () => {
throw new Error("se intentó crear br");
},
},
multimedia,
};
export function getType(
node: Element
): { typeName: string; type: EditorNode } | null {
for (let [typeName, type] of Object.entries(types)) {
if (node.matches(type.selector)) {
return { typeName, type };
}
}
return null;
}
// encuentra el primer pariente que pueda tener al type, y retorna un array
// donde
// array[0] = elemento que matchea el type
// array[array.len - 1] = primer elemento seleccionado
export function getValidParentInSelection(args: {
editor: Editor;
type: string;
}): Element[] {
const sel = safeGetSelection(args.editor);
if (!sel) throw new Error("No se donde insertar esto");
const range = safeGetRangeAt(sel);
if (!range) throw new Error("No se donde insertar esto");
let list: Element[] = [];
if (!sel.anchorNode) {
throw new Error("No se donde insertar esto");
} else if (sel.anchorNode instanceof Element) {
list = [sel.anchorNode];
} else if (sel.anchorNode.parentElement) {
list = [sel.anchorNode.parentElement];
} else {
throw new Error("No se donde insertar esto");
}
while (true) {
const el = list[0];
if (!args.editor.contentEl.contains(el) && el != args.editor.contentEl)
throw new Error("No se donde insertar esto");
const type = getType(el);
if (type) {
//if (type.typeName === 'contentEl') break
//if (parentBlockNames.includes(type.typeName)) break
if (
type.type.allowedChildren instanceof Array &&
type.type.allowedChildren.includes(args.type)
)
break;
}
if (el.parentElement) {
list = [el.parentElement, ...list];
} else {
throw new Error("No se donde insertar esto");
}
}
return list;
}
export function getValidChildren(node: Element, type: EditorNode): Node[] {
if (type.allowedChildren === "ignore-children")
throw new Error(
"se llamó a getValidChildren con un type que no lo permite!"
);
return [...node.childNodes].filter((n) => {
// si permite texto y esto es un texto, es válido
if (n.nodeType === Node.TEXT_NODE)
return type.allowedChildren.includes("text") && n.textContent?.length;
// si no es un elemento, no es válido
if (!(n instanceof Element)) return false;
const t = getType(n);
if (!t) return false;
return type.allowedChildren.includes(t.typeName);
});
}

View file

@ -0,0 +1,82 @@
import { Editor } from "editor/editor";
import {
safeGetSelection,
safeGetRangeAt,
moveChildren,
markNames,
blockNames,
parentBlockNames,
} from "editor/utils";
import { EditorNode, getType, getValidParentInSelection } from "editor/types";
export interface EditorBlock extends EditorNode {}
function makeBlock(tag: string): EditorBlock {
return {
selector: tag,
allowedChildren: [...markNames, "text"],
handleEmpty: "do-nothing",
create: () => document.createElement(tag),
};
}
export const li: EditorBlock = makeBlock("li");
const paragraph: EditorBlock = makeBlock("p");
// XXX: si agregás algo acá, agregalo a blockNames
// (y probablemente le quieras hacer un botón en app/views/posts/attributes/_content.haml)
export const blocks: { [propName: string]: EditorBlock } = {
paragraph,
h1: makeBlock("h1"),
h2: makeBlock("h2"),
h3: makeBlock("h3"),
h4: makeBlock("h4"),
h5: makeBlock("h5"),
h6: makeBlock("h6"),
unordered_list: {
...makeBlock("ul"),
allowedChildren: ["li"],
handleEmpty: li,
},
ordered_list: {
...makeBlock("ol"),
allowedChildren: ["li"],
handleEmpty: li,
},
blockquote: {
...makeBlock("blockquote"),
allowedChildren: blockNames,
handleEmpty: paragraph,
},
};
export function setupButtons(editor: Editor): void {
for (const [name, type] of Object.entries(blocks)) {
const buttonEl = editor.toolbarEl.querySelector(
`[data-editor-button="block-${name}"]`
);
if (!buttonEl) continue;
buttonEl.addEventListener("click", (event) => {
event.preventDefault();
const list = getValidParentInSelection({ editor, type: name });
// No borrar cosas como multimedia
if (blockNames.indexOf(getType(list[1])!.typeName) === -1) {
return;
}
let replacementType = list[1].matches(type.selector)
? blocks.paragraph
: type;
const el = replacementType.create(editor);
replacementType.onClick && replacementType.onClick(editor, el);
moveChildren(list[1], el, null);
list[0].replaceChild(el, list[1]);
window.getSelection()?.collapse(el);
return false;
});
}
}

View file

@ -0,0 +1,37 @@
import { Editor } from "editor/editor";
import { EditorNode } from "editor/types";
import { markNames, setAuxiliaryToolbar, clearSelected } from "editor/utils";
function select(editor: Editor, el: HTMLAnchorElement): void {
clearSelected(editor);
el.dataset.editorSelected = "";
editor.toolbar.auxiliary.link.urlEl.value = el.href;
setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.link.parentEl);
}
export const link: EditorNode = {
selector: "a",
allowedChildren: [...markNames.filter((n) => n !== "link"), "text"],
handleEmpty: "remove",
create: () => document.createElement("a"),
onClick(editor, el) {
if (!(el instanceof HTMLAnchorElement)) throw new Error("oh no");
select(editor, el);
},
};
export function setupAuxiliaryToolbar(editor: Editor): void {
editor.toolbar.auxiliary.link.urlEl.addEventListener("input", (event) => {
const url = editor.toolbar.auxiliary.link.urlEl.value;
const selectedEl = editor.contentEl.querySelector<HTMLAnchorElement>(
"a[data-editor-selected]"
);
if (!selectedEl)
throw new Error("No pude encontrar el link para setear el enlace");
selectedEl.href = url;
});
editor.toolbar.auxiliary.link.urlEl.addEventListener("keydown", (event) => {
if (event.keyCode == 13) event.preventDefault();
});
}

View file

@ -0,0 +1,66 @@
import { Editor } from "editor/editor";
import { EditorNode } from "editor/types";
import { markNames, setAuxiliaryToolbar, clearSelected } from "editor/utils";
const hex = (x: string) => ("0" + parseInt(x).toString(16)).slice(-2);
// https://stackoverflow.com/a/3627747
// TODO: cambiar por una solución más copada
function rgbToHex(rgb: string): string {
const matches = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
if (!matches) throw new Error("no pude parsear el rgb()");
return "#" + hex(matches[1]) + hex(matches[2]) + hex(matches[3]);
}
function select(editor: Editor, el: HTMLElement): void {
clearSelected(editor);
el.dataset.editorSelected = "";
editor.toolbar.auxiliary.mark.colorEl.value = el.style.backgroundColor
? rgbToHex(el.style.backgroundColor)
: "#f206f9";
editor.toolbar.auxiliary.mark.textColorEl.value = el.style.color
? rgbToHex(el.style.color)
: "#000000";
setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.mark.parentEl);
}
export const mark: EditorNode = {
selector: "mark",
allowedChildren: [...markNames.filter((n) => n !== "mark"), "text"],
handleEmpty: "remove",
create: () => document.createElement("mark"),
onClick(editor, el) {
if (!(el instanceof HTMLElement)) throw new Error("oh no");
select(editor, el);
},
};
export function setupAuxiliaryToolbar(editor: Editor): void {
editor.toolbar.auxiliary.mark.colorEl.addEventListener("input", (event) => {
const color = editor.toolbar.auxiliary.mark.colorEl.value;
const selectedEl = editor.contentEl.querySelector<HTMLElement>(
"mark[data-editor-selected]"
);
if (!selectedEl)
throw new Error("No pude encontrar el mark para setear el color");
selectedEl.style.backgroundColor = color;
});
editor.toolbar.auxiliary.mark.textColorEl.addEventListener(
"input",
(event) => {
const color = editor.toolbar.auxiliary.mark.textColorEl.value;
const selectedEl = editor.contentEl.querySelector<HTMLElement>(
"mark[data-editor-selected]"
);
if (!selectedEl)
throw new Error(
"No pude encontrar el mark para setear el color del text"
);
selectedEl.style.color = color;
}
);
editor.toolbar.auxiliary.mark.colorEl.addEventListener("keydown", (event) => {
if (event.keyCode == 13) event.preventDefault();
});
}

View file

@ -0,0 +1,102 @@
import { Editor } from "editor/editor";
import { EditorNode } from "editor/types";
import {
safeGetSelection,
safeGetRangeAt,
moveChildren,
markNames,
} from "editor/utils";
import { link } from "editor/types/link";
import { mark } from "editor/types/mark";
function makeMark(name: string, tag: string): EditorNode {
return {
selector: tag,
allowedChildren: [...markNames.filter((n) => n !== name), "text"],
handleEmpty: "remove",
create: () => document.createElement(tag),
};
}
// XXX: si agregás algo acá, agregalo a markNames
export const marks: { [propName: string]: EditorNode } = {
bold: makeMark("bold", "strong"),
italic: makeMark("italic", "em"),
deleted: makeMark("deleted", "del"),
underline: makeMark("underline", "u"),
sub: makeMark("sub", "sub"),
super: makeMark("super", "sup"),
mark,
link,
small: makeMark("small", "small"),
};
function recursiveFilterSelection(
node: Element,
selection: Selection,
selector: string
): Element[] {
let output: Element[] = [];
for (const child of [...node.children]) {
if (child.matches(selector) && selection.containsNode(child))
output.push(child);
output = [
...output,
...recursiveFilterSelection(child, selection, selector),
];
}
return output;
}
export function setupButtons(editor: Editor): void {
for (const [name, type] of Object.entries(marks)) {
const buttonEl = editor.toolbarEl.querySelector(
`[data-editor-button="mark-${name}"]`
);
if (!buttonEl) continue;
buttonEl.addEventListener("click", (event) => {
event.preventDefault();
const sel = safeGetSelection(editor);
if (!sel) return;
const range = safeGetRangeAt(sel);
if (!range) return;
let parentEl = range.commonAncestorContainer;
while (!(parentEl instanceof Element)) {
if (!parentEl.parentElement) return;
parentEl = parentEl.parentElement;
}
const existingMarks = recursiveFilterSelection(
parentEl,
sel,
type.selector
);
console.debug("marks encontradas:", existingMarks);
if (existingMarks.length > 0) {
const mark = existingMarks[0];
if (!mark.parentElement) throw new Error(":/");
moveChildren(mark, mark.parentElement, mark);
mark.parentElement.removeChild(mark);
} else {
if (range.commonAncestorContainer === editor.contentEl)
// TODO: mostrar error
return console.error(
"No puedo marcar cosas a través de distintos bloques!"
);
const tagEl = type.create(editor);
type.onClick && type.onClick(editor, tagEl);
tagEl.appendChild(range.extractContents());
range.insertNode(tagEl);
range.selectNode(tagEl);
}
return false;
});
}
}

View file

@ -0,0 +1,232 @@
import * as ActiveStorage from "@rails/activestorage";
import { Editor } from "editor/editor";
import { EditorNode, getValidParentInSelection } from "editor/types";
import {
safeGetSelection,
safeGetRangeAt,
markNames,
parentBlockNames,
setAuxiliaryToolbar,
clearSelected,
} from "editor/utils";
function uploadFile(file: File): Promise<string> {
return new Promise((resolve, reject) => {
const upload = new ActiveStorage.DirectUpload(
file,
origin + "/rails/active_storage/direct_uploads"
);
upload.create((error: any, blob: any) => {
if (error) {
reject(error);
} else {
const url = `${origin}/rails/active_storage/blobs/${blob.signed_id}/${blob.filename}`;
resolve(url);
}
});
});
}
function getAlt(multimediaInnerEl: HTMLElement): string | null {
switch (multimediaInnerEl.tagName) {
case "VIDEO":
case "AUDIO":
return multimediaInnerEl.getAttribute("aria-label");
case "IMG":
return (multimediaInnerEl as HTMLImageElement).alt;
case "IFRAME":
return multimediaInnerEl.title;
default:
throw new Error("no pude conseguir el alt");
}
}
function setAlt(multimediaInnerEl: HTMLElement, value: string): void {
switch (multimediaInnerEl.tagName) {
case "VIDEO":
case "AUDIO":
multimediaInnerEl.setAttribute("aria-label", value);
break;
case "IMG":
(multimediaInnerEl as HTMLImageElement).alt = value;
break;
case "IFRAME":
multimediaInnerEl.title = value;
break;
default:
throw new Error("no pude setear el alt");
}
}
function select(editor: Editor, el: HTMLElement): void {
clearSelected(editor);
el.dataset.editorSelected = "";
const innerEl = el.querySelector<HTMLElement>("[data-multimedia-inner]");
if (!innerEl) throw new Error("No hay multimedia válida");
if (innerEl.tagName === "P") {
editor.toolbar.auxiliary.multimedia.altEl.value = "";
editor.toolbar.auxiliary.multimedia.altEl.disabled = true;
} else {
editor.toolbar.auxiliary.multimedia.altEl.value = getAlt(innerEl) || "";
editor.toolbar.auxiliary.multimedia.altEl.disabled = false;
}
setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.multimedia.parentEl);
}
export const multimedia: EditorNode = {
selector: "figure[data-multimedia]",
allowedChildren: "ignore-children",
handleEmpty: "remove",
create: () => {
const figureEl = document.createElement("figure");
figureEl.dataset.multimedia = "";
figureEl.contentEditable = "false";
const placeholderEl = document.createElement("p");
placeholderEl.dataset.multimediaInner = "";
// TODO i18n
placeholderEl.append("¡Clickeame para subir un archivo!");
figureEl.appendChild(placeholderEl);
const descriptionEl = document.createElement("figcaption");
descriptionEl.contentEditable = "true";
// TODO i18n
descriptionEl.append("Escribí acá la descripción del archivo.");
figureEl.appendChild(descriptionEl);
return figureEl;
},
onClick(editor, el) {
if (!(el instanceof HTMLElement)) throw new Error("oh no");
select(editor, el);
},
};
function createElementWithFile(url: string, type: string): HTMLElement {
if (type.match(/^image\/.+$/)) {
const el = document.createElement("img");
el.dataset.multimediaInner = "";
el.src = url;
return el;
} else if (type.match(/^video\/.+$/)) {
const el = document.createElement("video");
el.controls = true;
el.dataset.multimediaInner = "";
el.src = url;
return el;
} else if (type.match(/^audio\/.+$/)) {
const el = document.createElement("audio");
el.controls = true;
el.dataset.multimediaInner = "";
el.src = url;
return el;
} else if (type.match(/^application\/pdf$/)) {
const el = document.createElement("iframe");
el.dataset.multimediaInner = "";
el.src = url;
return el;
} else {
// TODO: chequear si el archivo es válido antes de subir
throw new Error("Tipo de archivo no reconocido");
}
}
export function setupAuxiliaryToolbar(editor: Editor): void {
editor.toolbar.auxiliary.multimedia.uploadEl.addEventListener(
"click",
(event) => {
const files = editor.toolbar.auxiliary.multimedia.fileEl.files;
if (!files || !files.length) {
console.info("no hay archivos para subir");
return;
}
const file = files[0];
const selectedEl = editor.contentEl.querySelector<HTMLElement>(
"figure[data-editor-selected]"
);
if (!selectedEl)
throw new Error("No pude encontrar el elemento para setear el archivo");
selectedEl.dataset.editorLoading = "";
uploadFile(file)
.then((url) => {
const innerEl = selectedEl.querySelector("[data-multimedia-inner]");
if (!innerEl) throw new Error("No hay multimedia a reemplazar");
const el = createElementWithFile(url, file.type);
setAlt(el, editor.toolbar.auxiliary.multimedia.altEl.value);
selectedEl.replaceChild(el, innerEl);
select(editor, selectedEl);
delete selectedEl.dataset.editorError;
})
.catch((err) => {
console.error(err);
// TODO: mostrar error
selectedEl.dataset.editorError = "";
})
.finally(() => {
delete selectedEl.dataset.editorLoading;
});
}
);
editor.toolbar.auxiliary.multimedia.removeEl.addEventListener(
"click",
(event) => {
const selectedEl = editor.contentEl.querySelector<HTMLElement>(
"figure[data-editor-selected]"
);
if (!selectedEl)
throw new Error("No pude encontrar el elemento para borrar");
selectedEl.parentElement?.removeChild(selectedEl);
setAuxiliaryToolbar(editor, null);
}
);
editor.toolbar.auxiliary.multimedia.altEl.addEventListener(
"input",
(event) => {
const selectedEl = editor.contentEl.querySelector<HTMLAnchorElement>(
"figure[data-editor-selected]"
);
if (!selectedEl)
throw new Error("No pude encontrar el multimedia para setear el alt");
const innerEl = selectedEl.querySelector<HTMLElement>(
"[data-multimedia-inner]"
);
if (!innerEl) throw new Error("No hay multimedia a para setear el alt");
setAlt(innerEl, editor.toolbar.auxiliary.multimedia.altEl.value);
}
);
editor.toolbar.auxiliary.multimedia.altEl.addEventListener(
"keydown",
(event) => {
if (event.keyCode == 13) event.preventDefault();
}
);
}
export function setupButtons(editor: Editor): void {
const buttonEl = editor.toolbarEl.querySelector(
'[data-editor-button="multimedia"]'
);
if (!buttonEl) throw new Error("No encontre el botón de multimedia");
buttonEl.addEventListener("click", (event) => {
event.preventDefault();
const list = getValidParentInSelection({ editor, type: "multimedia" });
const el = multimedia.create(editor);
list[0].insertBefore(el, list[1].nextElementSibling);
select(editor, el);
return false;
});
}

View file

@ -0,0 +1,77 @@
import { Editor } from "editor/editor";
import {
safeGetSelection,
safeGetRangeAt,
moveChildren,
blockNames,
parentBlockNames,
} from "editor/utils";
import { EditorNode, getType, getValidParentInSelection } from "editor/types";
function makeParentBlock(
tag: string,
create: EditorNode["create"]
): EditorNode {
return {
selector: tag,
allowedChildren: [...blockNames, "multimedia"],
handleEmpty: "remove",
create,
};
}
// XXX: si agregás algo acá, probablemente le quieras hacer un botón
// en app/views/posts/attributes/_content.haml
export const parentBlocks: { [propName: string]: EditorNode } = {
left: makeParentBlock("div[data-align=left]", () => {
const el = document.createElement("div");
el.dataset.align = "left";
el.style.textAlign = "left";
return el;
}),
center: makeParentBlock("div[data-align=center]", () => {
const el = document.createElement("div");
el.dataset.align = "center";
el.style.textAlign = "center";
return el;
}),
right: makeParentBlock("div[data-align=right]", () => {
const el = document.createElement("div");
el.dataset.align = "right";
el.style.textAlign = "right";
return el;
}),
};
export function setupButtons(editor: Editor): void {
for (const [name, type] of Object.entries(parentBlocks)) {
const buttonEl = editor.toolbarEl.querySelector(
`[data-editor-button="parentBlock-${name}"]`
);
if (!buttonEl) continue;
buttonEl.addEventListener("click", (event) => {
event.preventDefault();
// TODO: Esto solo mueve el bloque en el que está el final de la selección
// (anchorNode). quizás lo podemos hacer al revés (iterar desde contentEl
// para encontrar los bloques que están seleccionados y moverlos/cambiarles
// el parentBlock)
const list = getValidParentInSelection({ editor, type: name });
const replacementEl = type.create(editor);
if (list[0] == editor.contentEl) {
// no está en un parentBlock
editor.contentEl.insertBefore(replacementEl, list[1]);
replacementEl.appendChild(list[1]);
} else {
// está en un parentBlock
moveChildren(list[0], replacementEl, null);
editor.contentEl.replaceChild(replacementEl, list[0]);
}
window.getSelection()?.collapse(replacementEl);
return false;
});
}
}

View file

@ -0,0 +1,102 @@
import { Editor } from "editor/editor";
export const blockNames = [
"paragraph",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"unordered_list",
"ordered_list",
"blockquote",
];
export const markNames = [
"bold",
"italic",
"deleted",
"underline",
"sub",
"super",
"mark",
"link",
"small",
];
export const parentBlockNames = ["left", "center", "right"];
export function moveChildren(from: Element, to: Element, toRef: Node | null) {
while (from.firstChild) to.insertBefore(from.firstChild, toRef);
}
export function isDirectChild(node: Node, supposedChild: Node): boolean {
for (const child of node.childNodes) {
if (child == supposedChild) return true;
}
return false;
}
export function safeGetSelection(editor: Editor): Selection | null {
const sel = window.getSelection();
if (!sel) return null;
// XXX: no damos la selección si esta fuera o _es_ el contentEl, ¿quizás
// deberíamos mostrar un error?
if (
!editor.contentEl.contains(sel.anchorNode) ||
!editor.contentEl.contains(sel.focusNode) ||
sel.anchorNode == editor.contentEl ||
sel.focusNode == editor.contentEl
)
return null;
return sel;
}
export function safeGetRangeAt(selection: Selection, num = 0): Range | null {
try {
return selection.getRangeAt(num);
} catch (error) {
return null;
}
}
interface SplitNode {
range: Range;
node: Node;
}
export function splitNode(node: Element, range: Range): [SplitNode, SplitNode] {
const [left, right] = [
{ range: document.createRange(), node: node.cloneNode(false) },
{ range: document.createRange(), node: node.cloneNode(false) },
];
if (node.firstChild) left.range.setStartBefore(node.firstChild);
left.range.setEnd(range.startContainer, range.startOffset);
left.range.surroundContents(left.node);
right.range.setStart(range.endContainer, range.endOffset);
if (node.lastChild) right.range.setEndAfter(node.lastChild);
right.range.surroundContents(right.node);
if (!node.parentElement)
throw new Error("No pude separar los nodos por que no tiene parentNode");
moveChildren(node, node.parentElement, node);
node.parentElement.removeChild(node);
return [left, right];
}
export function setAuxiliaryToolbar(
editor: Editor,
bar: HTMLElement | null
): void {
for (const { parentEl } of Object.values(editor.toolbar.auxiliary)) {
delete parentEl.dataset.editorAuxiliaryActive;
}
if (bar) bar.dataset.editorAuxiliaryActive = "active";
}
export function clearSelected(editor: Editor): void {
const selectedEl = editor.contentEl.querySelector("[data-editor-selected]");
if (selectedEl) delete (selectedEl as HTMLElement).dataset.editorSelected;
}

View file

@ -0,0 +1,7 @@
// Cancela las peticiones pendientes de htmx para todos los elementos al
// cambiar de página.
document.addEventListener("turbolinks:click", () => {
for (const hx of document.querySelectorAll("[hx-get]")) {
window.htmx.trigger(hx, "htmx:abort");
}
});

View file

@ -0,0 +1,9 @@
import './external_links'
import './input-date'
import './input-tag'
import './prosemirror'
import './timezone'
import './turbolinks-anchors'
import './validation'
import './new_editor'
import './htmx_abort'

View file

@ -0,0 +1,11 @@
// Validar fechas en navegadores que no soportan date, como
// Webkit/Safari
document.addEventListener('turbolinks:load', () => {
document.querySelectorAll('input[type="date"]').forEach(date => {
if (date.type === 'date') return
date.addEventListener('change', event => {
date.setCustomValidity(date.validity.patternMismatch ? date.dataset.patternMismatch : '')
})
})
})

View file

@ -1,3 +1,6 @@
import InputTag from 'input-tag/input-tag'
import InputMap from 'input-map/input-map'
document.addEventListener('turbolinks:load', () => {
document.querySelectorAll('.taggable').forEach(target => {
target.innerHTML = ''

View file

@ -0,0 +1,14 @@
import SuttyEditor from "@suttyweb/editor";
import "@suttyweb/editor/dist/style.css";
document.addEventListener("turbolinks:load", () => {
document.querySelectorAll(".new-editor").forEach((editorContainer) => {
new SuttyEditor({
target: editorContainer,
props: {
textareaEl: editorContainer.querySelector("textarea"),
},
});
});
});

View file

@ -0,0 +1,29 @@
import {EditorState} from "prosemirror-state"
import {EditorView} from "prosemirror-view"
import {schema, defaultMarkdownParser, defaultMarkdownSerializer} from "prosemirror-markdown"
import {exampleSetup} from "prosemirror-example-setup"
import "prosemirror-gapcursor/style/gapcursor.css"
import "prosemirror-menu/style/menu.css"
import "prosemirror-view/style/prosemirror.css"
import "prosemirror-example-setup/style/style.css"
document.addEventListener('turbolinks:load', () => {
document.querySelectorAll('.markdown-content').forEach(mdc => {
let textArea = mdc.querySelector(".content"),
editor = mdc.querySelector(".markdown-editor");
let view = new EditorView(editor, {
state: EditorState.create({
doc: defaultMarkdownParser.parse(textArea.value),
plugins: exampleSetup({schema})
})
})
// Guardar los cambios al enviar el formulario y cada 10 segundos
textArea.form.addEventListener('submit', e => textArea.value = defaultMarkdownSerializer.serialize(view.state.doc));
setInterval(() => textArea.value = defaultMarkdownSerializer.serialize(view.state.doc), 10 * 1000);
// Ocultar el area
textArea.style.display = 'none'
})
})

View file

@ -0,0 +1,51 @@
// Lista de equivalencias entre Date#getTimezoneOffset de JS y
// MetadataEvent
const timeZoneOffsets = {
'720': '-12:00',
'660': '-11:00',
'600': '-10:00',
'570': '-09:30',
'540': '-09:00',
'480': '-08:00',
'420': '-07:00',
'360': '-06:00',
'300': '-05:00',
'240': '-04:00',
'210': '-03:30',
'180': '-03:00',
'120': '-02:00',
'60': '-01:00',
'0': '00:00',
'-60': '+01:00',
'-120': '+02:00',
'-180': '+03:00',
'-210': '+03:30',
'-240': '+04:00',
'-270': '+04:30',
'-300': '+05:00',
'-330': '+05:30',
'-345': '+05:45',
'-360': '+06:00',
'-390': '+06:30',
'-420': '+07:00',
'-480': '+08:00',
'-525': '+08:45',
'-540': '+09:00',
'-570': '+09:30',
'-600': '+10:00',
'-630': '+10:30',
'-660': '+11:00',
'-720': '+12:00',
'-765': '+12:45',
'-780': '+13:00',
'-840': '+14:00'
};
// Obtiene el huso horario local
const timeZoneOffset = timeZoneOffsets[(new Date).getTimezoneOffset().toString()];
document.addEventListener('turbolinks:load', () => {
// Aplicar el huso horario descubierto en los campos de evento solo
// cuando estamos creando un artículo.
document.querySelectorAll('.new .event .zone select').forEach(zone => zone.value = timeZoneOffset);
})

View file

@ -0,0 +1,3 @@
document.addEventListener('turbolinks:load', () => {
document.querySelectorAll('a[href^="#"]').forEach(a => a.dataset.turbolinks = false)
})

View file

@ -1,11 +1,10 @@
document.addEventListener('turbolinks:load', () => {
// Al enviar el formulario del artículo, aplicar la validación
// localmente y actualizar los comentarios para lectores de pantalla.
document.querySelectorAll('.submit-post').forEach(submit => {
submit.addEventListener('click', event => {
const form = submit.closest('form')
const invalid_help = form.querySelectorAll('.invalid_help')
const sending_help = form.querySelectorAll('.sending_help')
document.querySelectorAll('form').forEach(form => {
form.addEventListener('submit', event => {
const invalid_help = form.querySelectorAll('.invalid-help')
const sending_help = form.querySelectorAll('.sending-help')
invalid_help.forEach(i => i.classList.add('d-none'))
sending_help.forEach(i => i.classList.add('d-none'))

View file

@ -1,101 +1,44 @@
/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
import { Notifier } from '@airbrake/browser'
// Uncomment to copy all static images under ../images to the output folder and reference
// 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)
try {
window.airbrake = new Notifier({
projectId: window.env.AIRBRAKE_PROJECT_ID,
projectKey: window.env.AIRBRAKE_PROJECT_KEY,
host: window.env.PANEL_URL
});
const ignoredErrors = ["htmx:afterRequest", "htmx:sendAbort"];
console.originalError = console.error;
console.error = (...e) => {
const msg = e.join(" ");
if (!ignoredErrors.some(x => msg.includes(x))) {
window.airbrake.notify(e.join(" "));
}
return console.originalError(...e);
};
} catch(e) {
console.error(e);
}
import 'core-js/stable'
import 'regenerator-runtime/runtime'
import 'controllers'
import 'editor/editor'
import 'fork-awesome/scss/fork-awesome.scss'
import 'etc'
import {EditorState} from "prosemirror-state"
import {EditorView} from "prosemirror-view"
import {schema, defaultMarkdownParser, defaultMarkdownSerializer} from "prosemirror-markdown"
import {exampleSetup} from "prosemirror-example-setup"
import Rails from '@rails/ujs'
import Turbolinks from 'turbolinks'
import * as ActiveStorage from '@rails/activestorage'
import 'chartkick/chart.js'
import "prosemirror-gapcursor/style/gapcursor.css"
import "prosemirror-menu/style/menu.css"
import "prosemirror-view/style/prosemirror.css"
import "prosemirror-example-setup/style/style.css"
Rails.start()
Turbolinks.start()
ActiveStorage.start()
// Lista de equivalencias entre Date#getTimezoneOffset de JS y
// MetadataEvent
const timeZoneOffsets = {
'720': '-12:00',
'660': '-11:00',
'600': '-10:00',
'570': '-09:30',
'540': '-09:00',
'480': '-08:00',
'420': '-07:00',
'360': '-06:00',
'300': '-05:00',
'240': '-04:00',
'210': '-03:30',
'180': '-03:00',
'120': '-02:00',
'60': '-01:00',
'0': '00:00',
'-60': '+01:00',
'-120': '+02:00',
'-180': '+03:00',
'-210': '+03:30',
'-240': '+04:00',
'-270': '+04:30',
'-300': '+05:00',
'-330': '+05:30',
'-345': '+05:45',
'-360': '+06:00',
'-390': '+06:30',
'-420': '+07:00',
'-480': '+08:00',
'-525': '+08:45',
'-540': '+09:00',
'-570': '+09:30',
'-600': '+10:00',
'-630': '+10:30',
'-660': '+11:00',
'-720': '+12:00',
'-765': '+12:45',
'-780': '+13:00',
'-840': '+14:00'
};
// Obtiene el huso horario local
const timeZoneOffset = timeZoneOffsets[(new Date).getTimezoneOffset().toString()];
document.addEventListener('turbolinks:load', () => {
// Aplicar el huso horario descubierto en los campos de evento solo
// cuando estamos creando un artículo.
document.querySelectorAll('.new .event .zone select').forEach(zone => zone.value = timeZoneOffset);
document.querySelectorAll('.markdown-content').forEach(mdc => {
let textArea = mdc.querySelector(".content"),
editor = mdc.querySelector(".markdown-editor");
let view = new EditorView(editor, {
state: EditorState.create({
doc: defaultMarkdownParser.parse(textArea.value),
plugins: exampleSetup({schema})
})
})
// Guardar los cambios al enviar el formulario y cada 10 segundos
textArea.form.addEventListener('submit', e => textArea.value = defaultMarkdownSerializer.serialize(view.state.doc));
setInterval(() => textArea.value = defaultMarkdownSerializer.serialize(view.state.doc), 10 * 1000);
// Ocultar el area
textArea.style.display = 'none'
})
})
window.htmx = require('htmx.org/dist/htmx.js')

View file

@ -0,0 +1,25 @@
# frozen_string_literal: true
class ActivityPub
# Se encarga de mantener las listas de bloqueo actualizadas. Luego de
# actualizar el listado de instancias, bloquea las instancias en cada
# sitio que tenga el fediblock habilitado.
class FediblockFetchJob < ApplicationJob
self.priority = 50
def perform
ActivityPub::Fediblock.find_each do |fediblock|
fediblock.process!
hostnames_added = fediblock.hostnames - fediblock.hostnames_was
# No hacer nada si no cambió con respecto a la versión anterior
next if hostnames_added.empty?
ActivityPub::FediblockUpdatedJob.perform_later(fediblock: fediblock, hostnames: hostnames_added)
rescue ActivityPub::Fediblock::FediblockDownloadError => e
ExceptionNotifier.notify_exception(e, data: { fediblock: fediblock.title })
end
end
end
end

View file

@ -0,0 +1,29 @@
# frozen_string_literal: true
# Se encarga de mantener sincronizadas las listas de instancias
# de los fediblocks con los sitios que las tengan activadas.
#
# También va a asociar las listas con todos los sitios que tengan la
# Social Inbox habilitada.
class ActivityPub
class FediblockUpdatedJob < ApplicationJob
self.priority = 50
# @param :fediblock [ActivityPub::Fediblock]
# @param :hostnames [Array<String>]
def perform(fediblock:, hostnames:)
instances = ActivityPub::Instance.where(hostname: hostnames)
# Todos los sitios con la Social Inbox habilitada
Site.where(id: DeploySocialDistributedPress.pluck(:site_id)).find_each do |site|
# Crea el estado si no existía
fediblock_state = site.fediblock_states.find_or_create_by(fediblock: fediblock)
# No hace nada con los deshabilitados
next unless fediblock_state.enabled?
ActivityPub::InstanceModerationJob.perform_later(site: site, hostnames: hostnames)
end
end
end
end

View file

@ -0,0 +1,65 @@
# frozen_string_literal: true
# Obtiene o actualiza el contenido de un objeto, usando las credenciales
# del sitio.
#
# XXX: Esto usa las credenciales del sitio para volver el objeto
# disponible para todo el CMS. Asumimos que el objeto devuelto es el
# mismo para todo el mundo y las credenciales solo son para
# autenticación.
class ActivityPub
class FetchJob < ApplicationJob
self.priority = 50
attr_reader :object, :response
# Notificar errores de JSON con el contenido, tomar los errores de
# validación y conexión como errores temporales y notificar todo lo
# demás sin reintentar.
#
# @param error [Exception]
# @return [Bool]
discard_on(FastJsonparser::ParseError) do |error|
ExceptionNotifier.notify_exception(error, data: { site: site.name, object: object.uri, body: response.body })
end
retry_on ActiveRecord::RecordInvalid
retry_on SocketError, wait: ApplicationJob.random_wait
retry_on SystemCallError, wait: ApplicationJob.random_wait
retry_on Net::OpenTimeout, wait: ApplicationJob.random_wait
retry_on OpenSSL::OpenSSLError, wait: ApplicationJob.random_wait
def perform(site:, object_id:)
ActivityPub::Object.transaction do
@site = site
@object = ::ActivityPub::Object.find(object_id)
return if object.blank?
return if object.activity_pubs.where(aasm_state: 'removed').count.positive?
@response = site.social_inbox.dereferencer.get(uri: object.uri)
# @todo Fallar cuando la respuesta no funcione?
# @todo Eliminar en 410 Gone
return unless response.success?
# Ignorar si ya la caché fue revalidada y ya teníamos el
# contenido
return if response.hit? && object.content.present?
current_type = object.type
content = FastJsonparser.parse(response.body)
# Modificar atómicamente
::ActivityPub::Object.lock.find(object_id).update!(content: content,
type: ActivityPub::Object.type_from(content).name)
object = ::ActivityPub::Object.find(object_id)
# Actualiza la mención
object.actor&.save! if object.actor_type?
# Arreglar las relaciones con actividades también
ActivityPub.where(object_id: object.id).update_all(object_type: object.type, updated_at: Time.now)
end
end
end
end

View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
class ActivityPub
class InboxJob < ApplicationJob
self.priority = 10
# @param :site [Site]
# @param :activity [String]
# @param :action [Symbol]
def perform(site:, activity:, action:)
response = site.social_inbox.inbox.public_send(action, id: activity)
raise response.body unless response.success?
end
end
end

View file

@ -0,0 +1,38 @@
# frozen_string_literal: true
class ActivityPub
# Obtiene o actualiza los datos de una instancia. Usamos un cliente
# de ActivityPub porque la instancia podría estar en federación
# limitada.
class InstanceFetchJob < ApplicationJob
self.priority = 100
def perform(site:, instance:)
%w[/api/v2/instance /api/v1/instance].each do |api|
uri = SocialInbox.generate_uri(instance.hostname) do |u|
u.path = api
end
response = site.social_inbox.dereferencer.get(uri: uri)
next unless response.success?
# @todo Validate schema
next unless response.parsed_response.is_a?(DistributedPress::V1::Social::ReferencedObject)
instance.update(content: response.parsed_response.object)
break
rescue BRS::BaseError,
Errno::ECONNREFUSED,
HTTParty::Error,
JSON::JSONError,
Net::OpenTimeout,
OpenSSL::OpenSSLError,
SocketError,
Errno::ENETUNREACH => e
ExceptionNotifier.notify_exception(e, data: { instance: uri })
break
end
end
end
end

View file

@ -0,0 +1,38 @@
# frozen_string_literal: true
class ActivityPub
# Bloquea varias instancias de una sola vez
class InstanceModerationJob < ApplicationJob
# @param :site [Site]
# @param :hostnames [Array<String>]
# @param :perform_remotely [Bool]
def perform(site:, hostnames:, perform_remotely: true)
# Crear las instancias que no existan todavía
hostnames.each do |hostname|
ActivityPub::Instance.lock.find_or_create_by(hostname: hostname)
end
instances = ActivityPub::Instance.where(hostname: hostnames)
Site.transaction do
# Crea todas las moderaciones de instancia con un estado por
# defecto si no existen
instances.find_each do |instance|
# Esto bloquea cada una individualmente en la Social Inbox,
# idealmente son pocas instancias las que aparecen.
site.instance_moderations.lock.find_or_create_by(instance: instance)
end
scope = site.instance_moderations.where(instance_id: instances.ids)
if perform_remotely
scope.block_all!
else
scope.block_all_without_callbacks!
end
ActivityPub::SyncListsJob.perform_later(site: site)
end
end
end
end

View file

@ -0,0 +1,145 @@
# frozen_string_literal: true
class ActivityPub
# Procesar las actividades a medida que llegan
class ProcessJob < ApplicationJob
attr_reader :body
retry_on ActiveRecord::RecordInvalid
# Procesa la actividad en segundo plano
#
# @param :body [String]
# @param :initial_state [Symbol,String]
def perform(site:, body:, initial_state: :paused)
@site = site
@body = body
ActiveRecord::Base.connection_pool.with_connection do
::ActivityPub.transaction do
# Crea todos los registros necesarios y actualiza el estado
actor.present?
instance.present?
object.present?
activity_pub.present?
activity_pub.update(aasm_state: initial_state)
activity.update_activity_pub_state!
end
end
end
private
# Si el objeto ya viene incorporado en la actividad o lo tenemos
# que traer remotamente.
#
# @return [Bool]
def object_embedded?
@object_embedded ||= original_activity[:object].is_a?(Hash)
end
# Encuentra la URI del objeto o falla si no la encuentra.
#
# @return [String]
def object_uri
@object_uri ||= ::ActivityPub.uri_from_object(original_activity[:object])
ensure
raise ActiveRecord::RecordNotFound, 'object id missing' if @object_uri.blank?
end
# Atajo a la instancia
#
# @return [ActivityPub::Instance]
def instance
actor.instance
end
# Genera un objeto a partir de la actividad. Si el objeto ya
# existe, actualiza su contenido. Si el objeto no viene
# incorporado, obtenemos el contenido más tarde.
#
# @return [ActivityPub::Object]
def object
@object ||= ::ActivityPub::Object.lock.find_or_initialize_by(uri: object_uri).tap do |o|
o.lock! if o.persisted?
o.content = original_object if object_embedded?
o.save!
# XXX: el objeto necesita ser guardado antes de poder
# procesarlo. No usamos GlobalID porque el tipo de objeto
# cambia y produce un error de deserialización.
::ActivityPub::FetchJob.perform_later(site: site, object_id: o.id) unless object_embedded?
end
end
# Genera el seguimiento del estado del objeto con respecto al
# sitio.
#
# @return [ActivityPub]
def activity_pub
@activity_pub ||= site.activity_pubs.lock.find_or_create_by!(site: site, actor: actor, instance: instance,
object_id: object.id, object_type: object.type)
end
# Crea la actividad y la vincula con el estado
#
# @return [ActivityPub::Activity]
def activity
@activity ||=
::ActivityPub::Activity
.type_from(original_activity)
.lock
.find_or_initialize_by(uri: original_activity[:id], activity_pub: activity_pub, actor: actor).tap do |a|
a.lock! if a.persisted?
a.content = original_activity.dup
a.content[:object] = object.uri
a.save!
end
end
# Actor, si no hay instancia, la crea en el momento, junto con
# su estado de moderación.
#
# @return [Actor]
def actor
@actor ||= ::ActivityPub::Actor.lock.find_or_initialize_by(uri: original_activity[:actor]).tap do |a|
a.lock! if a.persisted?
unless a.instance
a.instance = ::ActivityPub::Instance.lock.find_or_create_by(hostname: URI.parse(a.uri).hostname)
::ActivityPub::InstanceFetchJob.perform_later(site: site, instance: a.instance)
end
site.instance_moderations.lock.find_or_create_by(instance: a.instance)
a.save!
site.actor_moderations.lock.find_or_create_by(actor: a)
::ActivityPub::FetchJob.perform_later(site: site, object_id: a.object.id)
end
end
# @return [Hash,String]
def original_object
@original_object ||= original_activity[:object].dup.tap do |o|
o[:@context] = original_activity[:@context].dup
end
end
# Descubre la actividad recibida, generando un error si la
# actividad no está dirigida a nosotres.
#
# @todo Validar formato con Dry::Schema
# @return [Hash]
def original_activity
@original_activity ||= FastJsonparser.parse(body).tap do |activity|
raise '@context missing' unless activity[:@context].present?
raise 'id missing' unless activity[:id].present?
raise 'object missing' unless activity[:object].present?
end
end
end
end

View file

@ -0,0 +1,37 @@
# frozen_string_literal: true
# Envía un reporte directamente a la instancia remota
#
# @todo El panel debería ser su propia instancia y firmar sus propios
# mensajes.
# @todo Como la Social Inbox no soporta enviar actividades
# a destinataries que no sean seguidores, enviamos el reporte
# directamente a la instancia.
# @see {https://github.com/hyphacoop/social.distributed.press/issues/14}
class ActivityPub
class RemoteFlagJob < ApplicationJob
self.priority = 30
def perform(remote_flag:)
return unless remote_flag.may_queue?
inbox = remote_flag.actor&.content&.[]('inbox')
raise 'Inbox is missing for actor' if inbox.blank?
remote_flag.queue!
uri = URI.parse(inbox)
client = remote_flag.main_site.social_inbox.client_for(uri.origin)
response = client.post(endpoint: uri.path, body: remote_flag.content)
raise 'No se pudo enviar el reporte' unless response.success?
remote_flag.report!
rescue Exception => e
ExceptionNotifier.notify_exception(e, data: { remote_flag: remote_flag.id, response: response.parsed_response })
remote_flag.resend!
raise
end
end
end

View file

@ -0,0 +1,72 @@
# frozen_string_literal: true
class ActivityPub
# Sincroniza las listas de bloqueo y permitidas con el estado actual
# de la base de datos.
class SyncListsJob < ApplicationJob
# Siempre correr al final
self.priority = 100
attr_reader :logs
# Ejecuta todas las requests y consolida los posibles errores.
#
# @param site [Site]
def run(site:)
@logs = {}
instance_scope = site.instance_moderations.joins(:instance)
actor_scope = site.actor_moderations.joins(:actor)
blocklist = wildcardize(instance_scope.blocked.pluck(:hostname)) + actor_scope.blocked.distinct.pluck(:mention).compact + actor_scope.reported.distinct.pluck(:mention).compact
allowlist = wildcardize(instance_scope.allowed.pluck(:hostname)) + actor_scope.allowed.distinct.pluck(:mention).compact
pauselist = wildcardize(instance_scope.paused.pluck(:hostname)) + actor_scope.paused.distinct.pluck(:mention).compact
if blocklist.present?
Rails.logger.info "Bloqueando: #{blocklist.join(', ')}"
process(:blocked) { site.social_inbox.allowlist.delete(list: blocklist) }
process(:blocked) { site.social_inbox.blocklist.post(list: blocklist) }
end
if allowlist.present?
Rails.logger.info "Permitiendo: #{allowlist.join(', ')}"
process(:allowed) { site.social_inbox.blocklist.delete(list: allowlist) }
process(:allowed) { site.social_inbox.allowlist.post(list: allowlist) }
end
if pauselist.present?
Rails.logger.info "Pausando: #{pauselist.join(', ')}"
process(:paused) { site.social_inbox.blocklist.delete(list: pauselist) }
process(:paused) { site.social_inbox.allowlist.delete(list: pauselist) }
end
# Si alguna falló, reintentar
raise if logs.present?
rescue Exception => e
ExceptionNotifier.notify_exception(e,
data: { site: site.name, logs: logs, blocklist: blocklist,
allowlist: allowlist, pauselist: pauselist })
raise
end
private
def process(stage)
response = yield
return if response.success?
logs[stage] ||= []
logs[stage] << { body: response.body, code: response.code }
end
# @params hostnames [Array<String>]
# @return [Array<String>]
def wildcardize(hostnames)
hostnames.map do |hostname|
"@*@#{hostname}"
end
end
end
end

View file

@ -2,11 +2,23 @@
# Base para trabajos
class ApplicationJob < ActiveJob::Base
include SuckerPunch::Job
include Que::ActiveJob::JobExtensions
private
# Esperar una cantidad random de segundos primos, para que no se
# superpongan tareas
#
# @return [Array<Integer>]
RANDOM_WAIT = [3, 5, 7, 11, 13].freeze
def site
@site ||= Site.find @params[:site_id]
# @return [ActiveSupport::Duration]
def self.random_wait
RANDOM_WAIT.sample.seconds
end
attr_reader :site
# Si falla por cualquier cosa informar y descartar
discard_on(Exception) do |job, error|
ExceptionNotifier.notify_exception(error, data: { job: job })
end
end

104
app/jobs/backtrace_job.rb Normal file
View file

@ -0,0 +1,104 @@
# frozen_string_literal: true
# Procesa los errores de JavaScript
class BacktraceJob < ApplicationJob
class BacktraceException < RuntimeError; end
EMPTY_SOURCEMAP = { 'mappings' => '' }.freeze
attr_reader :params
def perform(site:, params:)
@site = site
@params = params
unless sources.empty?
params['errors'].each do |error|
error['backtrace'].each do |backtrace|
offset = SourceMap::Offset.new(backtrace['line'], backtrace['column'])
mapping = sourcemap.bsearch(offset)
next unless mapping
data = data(backtrace['file'])
backtrace['file'] = mapping.source
backtrace['line'] = mapping.original.line
backtrace['column'] = mapping.original.column
# Encuentra el código fuente del error
source = data.dig('sourcesContent', data['sources']&.index(backtrace['file']))&.split("\n")
# XXX: Elimina la sangría aunque cambie las columnas porque
# eso lo vamos a ver en el archivo fuente directo.
backtrace['function'] = source[backtrace['line'] - 1].strip if source.present?
end
end
end
begin
raise BacktraceException, "#{origin}: #{message}"
rescue BacktraceException => e
ExceptionNotifier.notify_exception(e, data: { site: site.name, params: params, javascript_backtrace: true })
end
end
private
# Obtiene todos los archivos del backtrace solo si los puede descargar
# desde fuentes seguras.
#
# XXX: Idealmente no trabajamos con recursos externos, pero en este
# momento no podemos saber todas las URLs de un sitio y quizás nunca
# lo sabremos :B
def sources
@sources ||= params['errors'].map do |x|
x['backtrace']
end.flatten.map do |x|
x['file'].split('@').last
end.uniq.grep(%r{\Ahttps://})
end
# Descarga y devuelve los datos de un archivo
#
# @param [String] La URL del map
# @return [Hash]
def data(map)
return EMPTY_SOURCEMAP unless map.start_with? 'https://'
map += '.map' unless map.end_with? '.map'
@data ||= {}
# TODO: Soportar ETags para la descarga, probablemente pasar a
# Faraday con caché para esto.
@data[map] ||= FastJsonparser.parse(Rails.cache.fetch(map, expires_in: 12.hours) do
Down.open(map).read
end, symbolize_keys: false)
rescue Down::Error, FastJsonparser::Error
EMPTY_SOURCEMAP
end
# Asume que todos los sourcemaps comparten la misma URL, lo
# correcto sería buscarlo en sourceMappingURL al final de cada
# archivo.
#
# Descarga los archivos y obtiene el backtrace original.
#
# @return [SourceMap::Map]
def sourcemap
@sourcemap ||= sources.map do |map|
SourceMap::Map.from_hash data(map)
end.reduce(&:+)
end
# @return [String]
def origin
URI.parse(params.dig('context', 'url')).host
rescue URI::Error
params.dig('context', 'url')
end
# @return [String,Nil]
def message
@message ||= params['errors']&.first&.dig('message')
end
end

8
app/jobs/cleanup_job.rb Normal file
View file

@ -0,0 +1,8 @@
# frozen_string_literal: true
# Realiza tareas de limpieza en segundo plano
class CleanupJob < ApplicationJob
def perform(before = nil)
CleanupService.new(before: before).cleanup_everything!
end
end

View file

@ -0,0 +1,60 @@
# frozen_string_literal: true
# Implementa rollups recursivos
module RecursiveRollup
extend ActiveSupport::Concern
included do
private
# Genera un rollup recursivo en base al período anterior y aplica una
# operación.
#
# @param :name [String]
# @param :interval_previous [String]
# @param :interval [String]
# @param :operation [Symbol]
# @param :dimensions [Hash]
# @param :beginning [Time]
# @return [Rollup]
def recursive_rollup(name:, interval_previous:, interval:, dimensions:, beginning:, operation: :sum)
Rollup.where(name: name, interval: interval_previous, dimensions: dimensions)
.where('time >= ?', beginning.try(:"beginning_of_#{interval}"))
.group(*dimensions_to_jsonb_query(dimensions))
.rollup(name, interval: interval, update: true) do |rollup|
rollup.try(operation, :value)
end
end
# Reducir las estadísticas calculadas aplicando un rollup sobre el
# intervalo más amplio.
#
# @param :name [String]
# @param :operation [Symbol]
# @param :dimensions [Hash]
# @return [nil]
def reduce_rollup(name:, dimensions:, operation: :sum)
Stat::INTERVALS.reduce do |previous, current|
recursive_rollup(name: name,
interval_previous: previous,
interval: current,
dimensions: dimensions,
beginning: beginning_of_interval,
operation: operation)
# Devolver el intervalo actual
current
end
nil
end
# @param :dimensions [Hash]
# @return [Array]
def dimensions_to_jsonb_query(dimensions)
dimensions.keys.map do |key|
"dimensions->'#{key}'"
end
end
end
end

View file

@ -5,13 +5,11 @@ class ContactJob < ApplicationJob
# @param [Integer]
# @param [String]
# @param [Hash]
def perform(site_id, form_name, form)
# Retrocompabilidad al actualizar a 2.7.1
# @see ApplicationJob#site
@params = { site_id: site_id }
def perform(site, form_name, form, origin = nil)
@site = site
# Sanitizar los valores
form.keys.each do |key|
form.each_key do |key|
form[key] = ActionController::Base.helpers.sanitize form[key]
end
@ -23,8 +21,9 @@ class ContactJob < ApplicationJob
usuaries.each_slice(10) do |u|
ContactMailer.with(form_name: form_name,
form: form,
site_id: site_id,
usuaries_emails: u)
site: site,
usuaries_emails: u,
origin: origin)
.notify_usuaries.deliver_now
end
end

Some files were not shown because too many files have changed in this diff Show more