alchemy-chimera 1.0.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## 1.1.0 (2022-07-23)
2
+
3
+ * Upgrade `alchemy-acl` and `alchemy-form`
4
+
5
+ ## 1.0.5 (2022-07-06)
6
+
7
+ * Fix page title containing 'undefined'
8
+ * Update styles
9
+ * Add support for "private" document fields
10
+
11
+ ## 1.0.4 (2022-05-31)
12
+
13
+ * Add delete page
14
+
1
15
  ## 1.0.3 (2022-03-16)
2
16
 
3
17
  * Make table filtering case insensitive
@@ -48,11 +48,21 @@ body {
48
48
  border-radius: 2px;
49
49
  font-weight: 500;
50
50
  cursor: pointer;
51
+ padding: 0.4rem 0.7rem;
52
+
53
+ display: inline-flex;
54
+ align-items: center;
55
+ justify-content: center;
56
+ gap: 0.2rem;
51
57
 
52
58
  &:hover {
53
59
  background-color: var(--button-bg-hover-color);
54
60
  //filter: brightness(1.05);
55
61
  }
62
+
63
+ al-ico {
64
+ margin-right: 4px;
65
+ }
56
66
  }
57
67
 
58
68
  .primary {
@@ -127,7 +137,7 @@ body {
127
137
 
128
138
  .chimera-content {
129
139
  background-color: var(--main-bg-color);
130
- flex: 1 0;
140
+ flex: 10 0;
131
141
  display: flex;
132
142
  flex-flow: column;
133
143
 
@@ -163,6 +173,8 @@ body {
163
173
  .chimera-main {
164
174
  flex: 1;
165
175
  padding: 0.5rem;
176
+ display: flex;
177
+ flex-flow: column;
166
178
 
167
179
  &[data-he-template="chimera/widgets"] {
168
180
  h1 {
@@ -254,198 +266,247 @@ alchemy-widgets-navigation {
254
266
  opacity: 0;
255
267
  }
256
268
 
257
- alchemy-table .aft-column-filters input {
258
- @extend .chimera-input-field;
259
- width: 100%;
260
- }
269
+ .chimera-wrapper {
261
270
 
262
- alchemy-form {
263
- .error-area:not(:empty) {
264
- @extend .error, .alert-box;
265
- margin-top: 0;
271
+ alchemy-table .aft-column-filters input {
272
+ @extend .chimera-input-field;
273
+ width: 100%;
274
+ }
275
+
276
+ alchemy-form {
277
+ .error-area:not(:empty) {
278
+ @extend .error, .alert-box;
279
+ margin-top: 0;
280
+ }
266
281
  }
267
- }
268
282
 
269
- alchemy-field {
270
- border: 1px solid var(--color-box-border);
271
- background-color: white;
272
- border-radius: 4px;
273
-
274
- // In case something goes wrong:
275
- min-height: 1rem;
276
-
277
- alchemy-label {
278
- padding-left: 1rem;
279
- line-height: 3rem;
280
- font-size: 16px;
281
- font-weight: 500;
282
- color: var(--color-title);
283
- border-bottom: 1px solid var(--color-box-border);
283
+ alchemy-field {
284
+ .wrapped-inline {
285
+ > .field {
286
+ padding: 0 !important;
287
+ }
288
+ }
284
289
  }
285
290
 
286
- alchemy-field-translatable {
287
- .prefix-buttons {
288
- width: 100%;
291
+ alchemy-field[mode="inline"] {
292
+ border: none;
293
+ }
294
+
295
+ alchemy-field:not([mode="inline"]) {
296
+ border: 1px solid var(--color-box-border);
297
+ background-color: white;
298
+ border-radius: 4px;
299
+
300
+ // In case something goes wrong:
301
+ min-height: 1rem;
302
+
303
+ alchemy-label {
304
+ padding-left: 1rem;
305
+ line-height: 3rem;
306
+ font-size: 16px;
307
+ font-weight: 500;
308
+ color: var(--color-title);
289
309
  border-bottom: 1px solid var(--color-box-border);
310
+ }
311
+
312
+ alchemy-field-translatable {
313
+ .prefix-buttons {
314
+ width: 100%;
315
+ border-bottom: 1px solid var(--color-box-border);
316
+ display: flex;
317
+
318
+ button {
319
+ flex: 10;
320
+ font-size: 16px;
321
+ font-weight: 500;
322
+ color: var(--button-text-color);
323
+ letter-spacing: 0px;
324
+ background: transparent;
325
+ border: none;
326
+ cursor: pointer;
327
+
328
+ height: 3rem;
329
+ display: flex;
330
+ flex-flow: column;
331
+ justify-content: center;
332
+ align-items: center;
333
+
334
+ &.active {
335
+ box-shadow: inset 0 -2px var(--color-active);
336
+ }
337
+
338
+ &:hover {
339
+ background-color: var(--button-bg-hover-color);
340
+ }
341
+ }
342
+ }
343
+ }
344
+
345
+ .field {
290
346
  display: flex;
347
+ padding: 1rem;
348
+ flex: 10;
291
349
 
292
- button {
293
- flex: 1;
294
- font-size: 16px;
295
- font-weight: 500;
296
- color: var(--button-text-color);
297
- letter-spacing: 0px;
298
- background: transparent;
299
- border: none;
300
- cursor: pointer;
350
+ > * {
351
+ flex: 10;
352
+ }
353
+
354
+ > alchemy-widget {
355
+ border: 1px solid var(--color-input-border);
356
+ padding: 0 12px;
357
+ }
358
+ }
301
359
 
360
+ .field {
361
+ input[type="text"],
362
+ input[type="number"],
363
+ input[type="color"],
364
+ input[type="datetime-local"],
365
+ input[type="password"] {
366
+ @extend .chimera-input-field;
302
367
  height: 3rem;
303
- display: flex;
304
- flex-flow: column;
305
- justify-content: center;
306
- align-items: center;
368
+ }
307
369
 
308
- &.active {
309
- box-shadow: inset 0 -2px var(--color-active);
310
- }
370
+ textarea {
371
+ @extend .chimera-input-field;
372
+ min-height: 5rem;
373
+ padding: 1rem;
374
+ }
311
375
 
312
- &:hover {
313
- background-color: var(--button-bg-hover-color);
314
- }
376
+ input[type="color"] {
377
+ background-color: transparent;
378
+ border: none;
379
+ padding: 0;
315
380
  }
316
381
  }
317
382
  }
318
383
 
319
- .field {
320
- display: flex;
321
- padding: 1rem;
322
- flex: 1;
323
-
324
- > * {
325
- flex: 1;
384
+ alchemy-field-array {
385
+ .add-entry {
386
+ @extend .btn;
387
+ margin: 1rem 0 0 1rem;
326
388
  }
327
389
 
328
- > alchemy-widget {
329
- border: 1px solid var(--color-input-border);
330
- padding: 0 12px;
390
+ button.remove {
391
+ @extend .btn;
392
+ @extend .danger;
393
+ min-width: 6rem;
394
+ margin: 0 1rem 1rem 0;
331
395
  }
332
- }
333
396
 
334
- .field {
335
- input[type="text"],
336
- input[type="number"],
337
- input[type="color"],
338
- input[type="datetime-local"],
339
- input[type="password"] {
340
- @extend .chimera-input-field;
341
- height: 3rem;
397
+ .entries {
398
+ margin-top: 0.5rem;
342
399
  }
343
400
 
344
- textarea {
345
- @extend .chimera-input-field;
346
- min-height: 5rem;
347
- padding: 1rem;
401
+ alchemy-field-array-entry:not(:last-of-type) {
402
+ //border-bottom: 1px solid gray;
403
+ position: relative;
404
+
405
+ &::after {
406
+ display: block;
407
+ content: " ";
408
+ background-color: lightgray;
409
+ position: absolute;
410
+ bottom: 0;
411
+ height: 1px;
412
+ left: 50%;
413
+ transform: translateX(-50%);
414
+ width: 80%;
415
+ }
348
416
  }
349
417
 
350
- input[type="color"] {
351
- background-color: transparent;
352
- border: none;
353
- padding: 0;
418
+ alchemy-field-array-entry:not(:first-of-type) {
419
+ margin-top: 1rem;
354
420
  }
355
421
  }
356
- }
357
422
 
358
- alchemy-field-array {
359
- .add-entry {
360
- @extend .btn;
361
- margin: 1rem 0 0 1rem;
362
- }
423
+ .chimera-editor-widgets {
363
424
 
364
- button.remove {
365
- @extend .btn;
366
- @extend .danger;
367
- min-width: 6rem;
368
- margin: 0 1rem 1rem 0;
369
- }
425
+ alchemy-widgets-column.toc-col {
426
+ flex: 2 2;
427
+ }
370
428
 
371
- .entries {
372
- margin-top: 0.5rem;
429
+ table-of-contents[elements-selector="alchemy-field"] {
430
+ align-self: start;
431
+ top: 2rem;
432
+ position: sticky;
433
+
434
+ ol {
435
+ list-style: none;
436
+ margin: 0 0 0 2rem;
437
+ padding: 0;
438
+
439
+ li {
440
+ a {
441
+ display: block;
442
+ line-height: 2rem;
443
+ border-bottom: 1px solid #aaa;
444
+ text-decoration: none;
445
+ opacity: 0.5;
446
+ color: #0070e4;
447
+ }
448
+ }
449
+
450
+ li a.visible {
451
+ opacity: 1;
452
+ }
453
+ }
454
+ }
373
455
  }
374
456
 
375
- alchemy-field-array-entry:not(:last-of-type) {
376
- //border-bottom: 1px solid gray;
377
- position: relative;
378
-
379
- &::after {
380
- display: block;
381
- content: " ";
382
- background-color: lightgray;
383
- position: absolute;
384
- bottom: 0;
385
- height: 1px;
386
- left: 50%;
387
- transform: translateX(-50%);
388
- width: 80%;
457
+ alchemy-field-schema {
458
+ alchemy-field {
459
+ border: none;
460
+ margin-bottom: 1rem;
389
461
  }
390
462
  }
391
463
 
392
- alchemy-field-array-entry:not(:first-of-type) {
393
- margin-top: 1rem;
464
+ .aft-actions {
465
+ a {
466
+ color: var(--button-text-color);
467
+ background-color: var(--button-bg-color);
468
+ padding: 0.5rem;
469
+ border-radius: 6px;
470
+ margin: 0.2rem;
471
+ display: inline-block;
472
+
473
+ &:hover {
474
+ background-color: var(--button-bg-hover-color);
475
+ }
476
+ }
394
477
  }
395
- }
396
478
 
397
- .chimera-editor-widgets {
479
+ .chimera-confirm-page {
480
+ flex: 1;
481
+ justify-content: center;
482
+ display: flex;
483
+ align-items: center;
484
+ flex-flow: column;
485
+ flex-direction: column;
398
486
 
399
- alchemy-widgets-column.toc-col {
400
- flex: 1 1;
487
+ .action-buttons {
488
+ display: flex;
489
+ gap: 1rem;
490
+ }
401
491
  }
402
492
 
403
- table-of-contents[elements-selector="alchemy-field"] {
404
- align-self: start;
405
- top: 2rem;
406
- position: sticky;
407
-
408
- ol {
409
- list-style: none;
410
- margin: 0 0 0 2rem;
411
- padding: 0;
412
-
413
- li {
414
- a {
415
- display: block;
416
- line-height: 2rem;
417
- border-bottom: 1px solid #aaa;
418
- text-decoration: none;
419
- opacity: 0.5;
420
- color: #0070e4;
421
- }
422
- }
423
-
424
- li a.visible {
425
- opacity: 1;
426
- }
493
+ al-file {
494
+ button {
495
+ @extend .btn;
427
496
  }
428
497
  }
429
- }
430
498
 
431
- alchemy-field-schema {
432
- alchemy-field {
433
- border: none;
434
- margin-bottom: 1rem;
435
- }
436
- }
499
+ alchemy-password-input {
500
+ label:first-of-type {
501
+ margin-bottom: 0;
502
+ }
503
+
504
+ .repeat-input-label {
505
+ margin-top: 1rem;
506
+ }
437
507
 
438
- .aft-actions {
439
- a {
440
- color: var(--button-text-color);
441
- background-color: var(--button-bg-color);
442
- padding: 0.5rem;
443
- border-radius: 6px;
444
- margin: 0.2rem;
445
- display: inline-block;
446
-
447
- &:hover {
448
- background-color: var(--button-bg-hover-color);
508
+ .inputbox {
509
+ background: initial;
449
510
  }
450
511
  }
451
512
  }
package/bootstrap.js CHANGED
@@ -1,4 +1,5 @@
1
1
  alchemy.requirePlugin('widget');
2
+ alchemy.requirePlugin('form');
2
3
 
3
4
  // Define the default options
4
5
  let options = {
package/config/routes.js CHANGED
@@ -2,6 +2,8 @@
2
2
  // By default this will be /chimera
3
3
  let chimera_section = Router.section('chimera', '/' + alchemy.plugins.chimera.base_path);
4
4
 
5
+ chimera_section.requirePermission('chimera');
6
+
5
7
  // Link to the dashboard
6
8
  chimera_section.add({
7
9
  title : __('chimera', 'Dashboard'),
@@ -35,6 +37,14 @@ chimera_section.add({
35
37
  breadcrumb : 'chimera.editor.{model}.edit.{pk}'
36
38
  });
37
39
 
40
+ // Editor trash action
41
+ chimera_section.add({
42
+ name : 'Chimera.Editor#trash',
43
+ methods : ['get', 'post'],
44
+ paths : '/editor/{model}/trash/{pk}',
45
+ breadcrumb : 'chimera.editor.{model}.trash.{pk}'
46
+ });
47
+
38
48
  // Editor data action
39
49
  chimera_section.add({
40
50
  name : 'Chimera.Editor#records',
@@ -12,7 +12,7 @@ const Editor = Function.inherits('Alchemy.Controller.Chimera', 'Editor');
12
12
  *
13
13
  * @author Jelle De Loecker <jelle@elevenways.be>
14
14
  * @since 1.0.1
15
- * @version 1.0.1
15
+ * @version 1.0.5
16
16
  *
17
17
  * @param {String} title
18
18
  */
@@ -27,6 +27,8 @@ Editor.setMethod(function setTitle(title) {
27
27
  if (title && window_title) {
28
28
  window_title += ' | ';
29
29
  }
30
+ } else {
31
+ window_title = '';
30
32
  }
31
33
 
32
34
  if (title) {
@@ -123,7 +125,7 @@ Editor.setAction(async function add(conduit, model_name) {
123
125
  *
124
126
  * @author Jelle De Loecker <jelle@elevenways.be>
125
127
  * @since 0.1.0
126
- * @version 1.0.2
128
+ * @version 1.0.5
127
129
  *
128
130
  * @param {Conduit} conduit
129
131
  * @param {String} model_name
@@ -138,6 +140,8 @@ Editor.setAction(async function edit(conduit, model_name, pk_val) {
138
140
  let record = await model.findByPk(pk_val);
139
141
  let message_type = conduit.param('message');
140
142
 
143
+ record.keepPrivateFields();
144
+
141
145
  let context_variables = {
142
146
  record,
143
147
  };
@@ -178,12 +182,52 @@ Editor.setAction(async function edit(conduit, model_name, pk_val) {
178
182
  this.render('chimera/widgets');
179
183
  });
180
184
 
185
+ /**
186
+ * The trash action
187
+ *
188
+ * @author Jelle De Loecker <jelle@elevenways.be>
189
+ * @since 1.0.4
190
+ * @version 1.0.4
191
+ *
192
+ * @param {Conduit} conduit
193
+ * @param {String} model_name
194
+ * @param {String} pk_val
195
+ */
196
+ Editor.setAction(async function trash(conduit, model_name, pk_val) {
197
+
198
+ let model = this.getModel(model_name);
199
+
200
+ model.translateItems = false;
201
+
202
+ let record = await model.findByPk(pk_val);
203
+
204
+ if (!record) {
205
+ return conduit.notFound();
206
+ }
207
+
208
+ let index_url = alchemy.routeUrl('Chimera.Editor#index', {
209
+ model : model_name
210
+ });
211
+
212
+ if (conduit.method == 'post') {
213
+ await record.remove();
214
+ conduit.redirect(index_url);
215
+ return;
216
+ }
217
+
218
+ let referer = conduit.headers.referer || index_url;
219
+
220
+ this.set('back_url', referer);
221
+ this.set('record', record);
222
+ this.render('chimera/editor/trash');
223
+ });
224
+
181
225
  /**
182
226
  * The records API action
183
227
  *
184
228
  * @author Jelle De Loecker <jelle@elevenways.be>
185
229
  * @since 1.0.0
186
- * @version 1.0.3
230
+ * @version 1.1.0
187
231
  *
188
232
  * @param {Conduit} conduit
189
233
  * @param {String} model_name
@@ -238,18 +282,34 @@ Editor.setAction(async function records(conduit, model_name) {
238
282
  result = [],
239
283
  record,
240
284
  main;
285
+
286
+ records.keepPrivateFields();
241
287
 
242
288
  for (record of records) {
243
289
 
290
+ let edit_action = new Classes.Alchemy.Form.Action.Url({
291
+ name : 'edit',
292
+ icon : 'edit',
293
+ placement : ['row', 'context'],
294
+ url : alchemy.routeUrl('Chimera.Editor#edit', {
295
+ model : model_name,
296
+ pk : record.$pk,
297
+ })
298
+ });
299
+
300
+ let trash_action = new Classes.Alchemy.Form.Action.Url({
301
+ name : 'trash',
302
+ icon : 'trash',
303
+ placement : ['context'],
304
+ url : alchemy.routeUrl('Chimera.Editor#trash', {
305
+ model : model_name,
306
+ pk : record.$pk,
307
+ })
308
+ });
309
+
244
310
  record.$hold.actions = [
245
- {
246
- name : 'edit',
247
- icon : 'edit',
248
- url : alchemy.routeUrl('Chimera.Editor#edit', {
249
- model : model_name,
250
- pk : record.$pk,
251
- })
252
- }
311
+ edit_action,
312
+ trash_action,
253
313
  ];
254
314
  }
255
315
 
@@ -65,7 +65,7 @@ Config.setMethod(function getFieldSet(name) {
65
65
  *
66
66
  * @author Jelle De Loecker <jelle@elevenways.be>
67
67
  * @since 1.0.0
68
- * @version 1.0.2
68
+ * @version 1.1.0
69
69
  *
70
70
  * @param {String} action
71
71
  * @param {Conduit} conduit
@@ -131,7 +131,7 @@ Config.setMethod(function getWidgetConfig(action, conduit) {
131
131
  "type": "alchemy_form",
132
132
  "config": {
133
133
  model : this.ModelClass.type_name,
134
- view_type : 'edit',
134
+ purpose : 'edit',
135
135
  widgets : field_widgets
136
136
  }
137
137
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "alchemy-chimera",
3
3
  "description": "Chimera plugin for Alchemy MVC",
4
- "version": "1.0.3",
4
+ "version": "1.1.0",
5
5
  "author": "Jelle De Loecker <jelle@elevenways.be>",
6
6
  "keywords": [
7
7
  "alchemy",
@@ -11,12 +11,13 @@
11
11
  ],
12
12
  "repository": "11ways/alchemy-chimera",
13
13
  "peerDependencies": {
14
- "alchemy-acl" : "~0.7.0",
15
- "alchemymvc" : "~1.2.1",
16
- "alchemy-widget": "~0.1.2"
14
+ "alchemy-acl" : "~0.8.0",
15
+ "alchemymvc" : "~1.2.4",
16
+ "alchemy-form" : "~0.1.11",
17
+ "alchemy-widget" : "~0.1.5"
17
18
  },
18
19
  "license": "MIT",
19
20
  "engines": {
20
- "node" : ">=12.0.0"
21
+ "node" : ">=14.0.0"
21
22
  }
22
23
  }
@@ -0,0 +1,34 @@
1
+ {% include "layouts/chimera_basics" %}
2
+
3
+ {% block "main" %}
4
+ <div class="chimera-confirm-page">
5
+ <h1>{%t "confirm-delete-title" %}</h1>
6
+
7
+ <p>
8
+ {%t "confirm-delete-text" model=record.$model_name title=record.getDisplayFieldValue() %}
9
+ </p>
10
+
11
+ <br>
12
+
13
+ <form class="action-buttons">
14
+ <a class="btn" href={% back_url %}>
15
+ {%t "cancel" %}
16
+ </a>
17
+ <button class="btn danger">
18
+ <al-ico type="trash" class="fas fa-trash"></al-ico>
19
+ {%t "delete" %}
20
+ </button>
21
+ </form>
22
+ </div>
23
+ {% /block %}
24
+
25
+ {% block "page-actions" %}
26
+ <a
27
+ !Route="Chimera.Editor#add"
28
+ #model={% model_name %}
29
+ class="btn"
30
+ >
31
+ <al-ico type="plus"></al-ico>
32
+ {%t "new" model=model_name %}
33
+ </a>
34
+ {% /block %}