Projet

Général

Profil

0001-card-infos-cell-form-add-UI-to-customize-content-lay.patch

Voir les différences:

Subject: [PATCH] card infos cell form: add UI to customize content layout
 (#52073)

 .../wcs/manager/card-infos-cell-form.html     |  74 ++++-
 combo/manager/static/css/combo.manager.css    |  79 +++++
 combo/manager/static/js/combo.manager.js      | 300 ++++++++++++++++++
 3 files changed, 452 insertions(+), 1 deletion(-)
combo/apps/wcs/templates/combo/wcs/manager/card-infos-cell-form.html
4 4
{{ block.super }}
5 5
{% if card_schema %}
6 6
{{ card_schema|json_script:card_schema_id }}
7

  
8
{# Grille de personalisation #}
9
<div class="wcs-cards-cell--grid">
10
  <div class="wcs-cards-cell--grid-options">
11
    <span class="wcs-cards-cell--grid-layout-label">auto</span>
12
    <a role="button" class="wcs-cards-cell--grid-layout-btn">
13
      Modifier
14
    </a>
15
  </div>
16
  <div class="wcs-cards-cell--grid-cells">
17
  </div>
18
  <div class="wcs-cards-cell--grid-buttons">
19
    <button type="button" class="wcs-cards-cell--add-grid-cell-btn">Ajouter</button>
20
  </div>
21
</div>
22

  
23
{# templates utilisés par le JS #}
24
<script type="text/template" class="wcs-cards-cell--grid-form-tpl">
25
  <form>
26
    <p>
27
      Disposition
28
      <select name="grid-layout">
29
        <option value="fx-grid--auto">auto</option>
30
        <option value="fx-grid">1 colonne</option>
31
        <option value="fx-grid--t2">2 colonnes</option>
32
        <option value="fx-grid--t3">3 colonnes</option>
33
      </select>
34
    </p>
35
  </form>
36
</script>
37
<script type="text/template" class="wcs-cards-cell--grid-cell-form-tpl">
38
  <form>
39
    <p>
40
      <label>
41
        Champ
42
        <select name="card_field_varname"></select>
43
      </label>
44
    </p>
45
    <p>
46
      <label>
47
        Afficher
48
        <select name="card_field_elements">
49
          <option value="key,value">Label & valeur</option>
50
          <option value="key">Label uniquement</option>
51
          <option value="value">Valeur uniquement</option>
52
          <option value="title">Titre</option>
53
        </select>
54
      </label>
55
    </p>
56
    <p>
57
      <label>
58
        Taille
59
        <select name="cell_size">
60
          <option value="">auto</option>
61
          <option value="size--1-1">1/1</option>
62
          <option value="size--t1-2">1/2</option>
63
          <option value="size--t1-3">1/3</option>
64
          <option value="size--t2-3">2/3</option>
65
        </select>
66
      </label>
67
    </p>
68
  </form>
69
</script>
70
<script  type="text/template" class="wcs-cards-cell--grid-cell-tpl">
71
  <div class="wcs-cards-cell--grid-cell">
72
    <div class="wcs-cards-cell--grid-cell-content"></div>
73
    <div class="wcs-cards-cell--grid-cell-buttons">
74
      <a role="button" class="wcs-cards-cell--grid-cell-edit">Modifier</a>
75
      <a role="button" class="wcs-cards-cell--grid-cell-delete">Supprimer</a>
76
    </div>
77
  </div>
78
</script>
7 79
{% endif %}
8
{% endblock %}
80
{% endblock %}
combo/manager/static/css/combo.manager.css
602 602
	margin: 0 0 0 1em;
603 603
	padding: 0;
604 604
}
605

  
606

  
607
.wcs-cards-cell--grid {
608
	border : 1px solid #aaa;
609
  	/*resize: horizontal;*/
610
  	overflow: hidden;
611
}
612
.wcs-cards-cell--grid-options {
613
	background-color: #eee;
614
	padding: 3px;
615
}
616
.wcs-cards-cell--grid-cells[class*="fx-grid--"],
617
.wcs-cards-cell--grid-buttons {
618
	padding: 3px;
619
}
620
.wcs-cards-cell--grid-cell {
621
	box-sizing: border-box;
622
	border: 1px solid #aaa;
623
	padding: 3px;
624
	margin-top: 3px;
625
	margin-bottom: 3px;
626
	background-color: #fff;
627
	cursor: move;
628
	display: flex;
629
	flex-direction: column;
630
}
631
.wcs-cards-cell--grid-cell.ui-sortable-helper {
632
	opacity: 0.7;
633
}
634
.wcs-cards-cell--grid-cell-placeholder {
635
	background-color: #eee;
636
}
637
.wcs-cards-cell--grid-cell-content {
638
	flex-grow: 1;
639
}
640
.wcs-cards-cell--grid-cell-content > * {
641
	display: block;
642
}
643
.wcs-cards-cell--grid-cell-content > .key {
644
	font-weight: bold;
645
}
646
.wcs-cards-cell--grid-cell-content > .title {
647
	font-size: 1.2em;
648
	font-weight: bold;
649
}
650
.wcs-cards-cell--grid-cell-content > .key::before {
651
	content: "Label ";
652
	font-style: italic;
653
}
654
.wcs-cards-cell--grid-cell-content > .value::before {
655
	content: "Valeur ";
656
	font-style: italic;
657
}
658
.wcs-cards-cell--grid-cell-content > .title::before {
659
	content: "Titre valeur ";
660
	font-style: italic;
661
}
662
.wcs-cards-cell--grid-layout-label,
663
.wcs-cards-cell--grid-cell-content > .cell-size-label {
664
	color: #666;
665
}
666
.wcs-cards-cell--grid-layout-label::before,
667
.wcs-cards-cell--grid-cell-content > .cell-size-label::before {
668
	content: "[ ";
669
}
670
.wcs-cards-cell--grid-layout-label::after,
671
.wcs-cards-cell--grid-cell-content > .cell-size-label::after {
672
	content: " ]";
673
}
674
.wcs-cards-cell--grid-cell-buttons {
675
	cursor: default;
676
	display: flex;
677
	justify-content: space-between;
678
}
679
.wcs-cards-cell--grid a[class^="icon-"],
680
.wcs-cards-cell--grid a[class*=" icon-"] {
681
	font-size: 150%;
682
}
683

  
combo/manager/static/js/combo.manager.js
398 398
    return false;
399 399
  });
400 400
});
401

  
402

  
403
// UI to customize the layout of the content of a wcs-card-infos-cell
404
const Card_cell_custom = function(cell) {
405
  this.cell = cell;
406
  this.gridShema_default = {
407
    "grid_class": "fx-grid--auto",
408
    "grid_layout_label": "auto",
409
    "cells": []
410
  }
411
  this.init();
412
}
413
Card_cell_custom.prototype = {
414
  parse_string_tpl: function(string_tpl) {
415
    const wrapper = document.createElement('div');
416
    wrapper.innerHTML = string_tpl;
417
    return wrapper.firstElementChild;
418
  },
419
  field_with_varname: function(varname) {
420
    const field = this.cardSchema.fields.filter(function(i) {
421
      return i.varname === varname;
422
    })
423
    return field[0];
424
  },
425
  //  Grid methods
426
  grid__form_dialog: function(callback){
427
    const _self = this;
428
    $(this.grid_form).dialog({
429
      modal: true,
430
      'title': "Disposition de la grille",
431
      width: 'auto',
432
      buttons: [
433
        {
434
          text: "Annuler",
435
          class:"cancel-button",
436
          click: function() {
437
              $(this).dialog("close");
438
          }
439
        },{
440
          text: "Modifier",
441
          class: "submit-button",
442
          click: function() {
443
            const form_datas = {};
444
            const select_layout = _self.grid_form[0];
445
            form_datas.grid_class = select_layout.value;
446
            form_datas.label = select_layout[select_layout.selectedIndex].text;
447
            callback(form_datas);
448
            $(this).dialog("close");
449
          }
450
        }
451
      ]
452
    });
453
  },
454
  grid__set_shema: function(form_datas){
455
    this.gridShema.grid_class = form_datas.grid_class;
456
    this.gridShema.grid_layout_label = form_datas.label;
457
    this.grid__set_layout();
458
    $(this.cell).trigger("custom_cell:change");
459
  },
460
  grid__set_layout: function() {
461
    this.grid_layout_label.textContent = this.gridShema.grid_layout_label;
462
    if (this.grid_wrapper.dataset.grid_layout) {
463
      this.grid_wrapper.classList.remove(this.grid_wrapper.dataset.grid_layout); }
464
    this.grid_wrapper.classList.add(this.gridShema.grid_class);
465
    this.grid_wrapper.dataset.grid_layout = this.gridShema.grid_class;
466
  },
467
  grid_toggle: function() {
468
    if (this.toggleBtn.checked) {
469
      this.grid.hidden = false;
470
    } else {
471
      this.grid.hidden = true;
472
    }
473
  },
474
  //  Grid cell methods
475
  grid_cell__init_form: function() {
476
    this.grid_cell_form.varname = this.grid_cell_form[0];
477
    this.grid_cell_form.display = this.grid_cell_form[1];
478
    this.grid_cell_form.size = this.grid_cell_form[2];
479
    const varname_select = this.grid_cell_form.varname;
480
    this.cardSchema.fields.forEach(function(el, id) {
481
      if (el.varname) {
482
        $('<option />')
483
          .attr('value', el.varname)
484
          .text(el.label)
485
          .appendTo(varname_select);
486
      }
487
    })
488
  },
489
  grid_cell__form_dialog: function(button_label, callback){
490
    const _self = this;
491
    $(this.grid_cell_form).dialog({
492
      modal: true,
493
      'title': button_label,
494
      width: 'auto',
495
      buttons: [
496
        {
497
          text: "Annuler",
498
          class:"cancel-button",
499
          click: function() {
500
              $(this).dialog("close");
501
          }
502
        },{
503
          text: button_label,
504
          class: "submit-button",
505
          click: function() {
506
            const form_datas = {};
507
            $(_self.grid_cell_form).serializeArray().forEach(function(el){
508
              form_datas[el.name] = el.value;
509
            });
510
            form_datas.cell_size_label = _self.grid_cell_form.size[_self.grid_cell_form.size.selectedIndex].textContent;
511
            callback(form_datas);
512
            $(this).dialog("close");
513
          }
514
        }
515
      ]
516
    });
517
  },
518
  grid_cell__new: function() {
519
    const el = this.grid_cell_tpl.cloneNode(true);
520
    el.deletBtn = el.querySelector('.wcs-cards-cell--grid-cell-delete');
521
    el.editBtn = el.querySelector('.wcs-cards-cell--grid-cell-edit');
522
    el.contentEl = el.querySelector('.wcs-cards-cell--grid-cell-content');
523
    return el;
524
  },
525
  grid_cell__set: function(grid_cell, shema_cell) {
526
    const _self = this;
527
    // Set size css class
528
    if (!grid_cell.classList.contains(shema_cell.cell_size)) {
529
      if (grid_cell.dataset.cell_size) grid_cell.classList.remove(grid_cell.dataset.cell_size);
530
      if (shema_cell.cell_size) grid_cell.classList.add(shema_cell.cell_size);
531
    }
532
    // Store Shema in el data
533
    for (const key in shema_cell) {
534
      grid_cell.dataset[key] = shema_cell[key];
535
    }
536
    // set cell text
537
    let cell_text = "";
538
    shema_cell.display.forEach(function(el){
539
      cell_text += '<span class="' + el + '">' + _self.field_with_varname(shema_cell.varname).label + '</span>';
540
    });
541
    cell_text += '<span class="cell-size-label">' + shema_cell.cell_size_label + '</span>';
542
    grid_cell.contentEl.innerHTML = cell_text;
543
  },
544
  grid_cell__add: function(shema_cell) {
545
    const _self = this;
546
    const new_grid_cell = this.grid_cell__new();
547
    this.grid_cell__set(new_grid_cell, shema_cell);
548
    new_grid_cell.deletBtn.addEventListener('click', function() {_self.grid_cell__delete(new_grid_cell)});
549
    new_grid_cell.editBtn.addEventListener('click', function() {_self.grid_cell__edit(new_grid_cell)});
550
    this.grid_wrapper.append(new_grid_cell);
551
  },
552
  grid_cell__delete: function(grid_cell) {
553
    const cell_id = $(grid_cell).index();
554
    this.gridShema.cells = this.gridShema.cells.filter(function(el, i){
555
      return i !== cell_id;
556
    });
557
    $(grid_cell).remove();
558
    $(this.cell).trigger("custom_cell:change");
559
  },
560
  grid_cell__edit: function(grid_cell) {
561
    const _self = this;
562
    this.grid_cell_form.varname.value = grid_cell.dataset.varname;
563
    this.grid_cell_form.size.value = grid_cell.dataset.cell_size;
564
    this.grid_cell_form.display.value = grid_cell.dataset.display;
565
    const cell_id = $(grid_cell).index();
566
    const grid_cell_shema = this.gridShema.cells[cell_id];
567
    this.grid_cell__form_dialog("Modifier", function(form_datas){
568
      const grid_cell_shema_mod = _self.grid_cell__set_shema(form_datas, grid_cell_shema);
569
      _self.grid_cell__set(grid_cell, grid_cell_shema_mod);
570
      $(_self.cell).trigger("custom_cell:change");
571
    });
572
  },
573
  grid_cell__set_shema: function(form_datas, shema_cell) {
574
    shema_cell.varname = form_datas.card_field_varname;
575
    shema_cell.cell_size = form_datas.cell_size;
576
    shema_cell.display = form_datas.card_field_elements.split(',');
577
    shema_cell.cell_size_label = form_datas.cell_size_label;
578
    return shema_cell
579
  },
580
  grid_cell__add_shema: function(form_datas) {
581
    let shema_cell = {};
582
    shema_cell = this.grid_cell__set_shema(form_datas, shema_cell);
583

  
584
    this.gridShema.cells.push(shema_cell);
585

  
586
    this.grid_cell__add(shema_cell);
587
    $(this.cell).trigger("custom_cell:change");
588
    compute_max_height($(this.cell));
589
  },
590
  grid_cell__init: function() {
591
    if (!this.gridShema_existing) return;
592

  
593
    const _self = this;
594
    this.gridShema.cells.forEach(function(el){
595
      _self.grid_cell__add(el);
596
    });
597

  
598
    $(this.cell).on("cell:open", function(){
599
      compute_max_height($(this));
600
    })
601
  },
602
  // Init methods
603
  on: function() {
604
    if (!(this.toggleBtn.checked && !this.is_on)) {
605
      return false;
606
    }
607

  
608
    this.store = this.cell.querySelector('input[id$="-custom_schema"]');
609
    try {
610
      const storeShema = JSON.parse(this.store.value);
611
      this.gridShema_existing = (Object.keys(storeShema).length) ? storeShema : undefined;
612
    } catch(e) {
613
      console.error(e);
614
      this.gridShema_existing = undefined;
615
    }
616
    this.gridShema =  this.gridShema_existing || this.gridShema_default;
617

  
618
    this.grid__set_layout();
619
    this.grid_cell__init();
620
    this.grid_cell__init_form();
621

  
622
    const _self = this;
623
    // Edit grid layout btn click
624
    $(this.edit_grid_btn).on('click', function() {
625
      _self.grid__form_dialog(_self.grid__set_shema.bind(_self));
626
    })
627
    // Add grid cell Btn click
628
    $(this.add_grid_cell_btn).on('click', function() {
629
      _self.grid_cell__form_dialog("Ajouter", _self.grid_cell__add_shema.bind(_self));
630
    });
631
    // Grid cells sortable
632
    $(_self.grid_wrapper).sortable({
633
      items: "> .wcs-cards-cell--grid-cell",
634
      placeholder: "wcs-cards-cell--grid-cell-placeholder",
635
      update: function(event, ui) {
636
        ui.item.data('update_index', ui.item.index());
637
        const moved_cell_shema = _self.gridShema.cells[ui.item.data('start_index')];
638
        _self.gridShema.cells.splice(ui.item.data('start_index'), 1);
639
        _self.gridShema.cells.splice(ui.item.data('update_index'), 0, moved_cell_shema);
640
        $(_self.cell).trigger("custom_cell:change");
641
      },
642
      start: function(event, ui) {
643
        ui.item.data("start_index", ui.item.index());
644
        ui.placeholder.addClass(ui.item[0].dataset.cell_size).css('height', ui.item[0].offsetHeight);
645
      }
646
    });
647
    // when shema change
648
    $(this.cell).on("custom_cell:change", function() {
649
      _self.store.value = JSON.stringify(_self.gridShema);
650
    })
651

  
652
    this.is_on = true;
653
  },
654

  
655
  init: function() {
656
    const cell = this.cell;
657
    const cardSchema_el = cell.querySelector('[id*="card-schema-eservices"]');
658
    this.cardSchema = cardSchema_el ? JSON.parse(cardSchema_el.innerText) : undefined;
659

  
660
    if (!this.cardSchema) {
661
      return;
662
    }
663

  
664
    this.is_on = false;
665
    this.grid = cell.querySelector('.wcs-cards-cell--grid');
666
    this.edit_grid_btn = cell.querySelector('.wcs-cards-cell--grid-layout-btn');
667
    this.grid_layout_label = cell.querySelector('.wcs-cards-cell--grid-layout-label');
668

  
669
    const grid_form_tpl_string = cell.querySelector('.wcs-cards-cell--grid-form-tpl').innerText;
670
    this.grid_form = this.parse_string_tpl(grid_form_tpl_string);
671

  
672
    this.add_grid_cell_btn = cell.querySelector('.wcs-cards-cell--add-grid-cell-btn');
673

  
674
    const grid_cell_form_tpl_string = cell.querySelector('.wcs-cards-cell--grid-cell-form-tpl').innerText;
675
    this.grid_cell_form = this.parse_string_tpl(grid_cell_form_tpl_string);
676

  
677
    const grid_cell_tpl_string = cell.querySelector('.wcs-cards-cell--grid-cell-tpl').innerText;
678
    this.grid_cell_tpl = this.parse_string_tpl(grid_cell_tpl_string);
679

  
680
    this.grid_wrapper = cell.querySelector('.wcs-cards-cell--grid-cells');
681

  
682
    this.toggleBtn = this.cell.querySelector('input[id$="-customize_display"]');
683

  
684
    const _self = this;
685
    $(this.toggleBtn).on('change', function(e) {
686
        _self.on();
687
        _self.grid_toggle();
688
    }).change();
689
  }
690
}
691

  
692
// Active custom card UI for each card cell
693
$(function() {
694
  $('.wcs-card-infos-cell').each(function(i, el) {
695
    const custom_card = new Card_cell_custom(el);
696
    $(el).on('combo:cellform-reloaded', function() {
697
      custom_card.init();
698
    });
699
  })
700
});
401
-