promethee 1.11.29 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 87015a529d4f152f57fd5da02b5bf817e8cfb8420efabaf1714489b3d822f01d
4
- data.tar.gz: 3c947c382a7ebd8b3a66668708a4503197f1178a58414af19e608708db594b1e
3
+ metadata.gz: b24d3197b6a9f29120ec8849dffae52cb78cf47b309200bd6b1d228dbd930170
4
+ data.tar.gz: 4c47e50f8ea5ec4c239d9adeba78c17e41fa02801631e1896032f64016e57104
5
5
  SHA512:
6
- metadata.gz: 48fafc37b97d5dd355f11dbac04cdc00a2e526786390b7969980b915060196efbda9a75ffcf2a4d2efc56275f0d834323a5defadfc4dc0285c29ead194c0a633
7
- data.tar.gz: 8c5728fdab8c70aa73a5ebcc46aabb2ae81e3df8b1f7bf8bab350e38e5da8ab66a5ad439456e17cf494942ba4f4fd290758b098ec38a3b979124d60337885563
6
+ metadata.gz: 60837d5bb49e78e27cd9816bc78794ec2ebc74a8a25d2ed3074926ba884e80fa140e463daad482eabeb9fc9cab278e80dd569bbc21cdef16b116ccddd09086de
7
+ data.tar.gz: a36840b631435a45a53e26c40148a2e4baf2cab78d28d3938fef818391072988540dfac3cddb2523f1d7f79a0b8f1a98e02288025ce96ca791531d1e898e01cf
data/UPGRADING ADDED
@@ -0,0 +1,10 @@
1
+ ##########################################
2
+ # NOTE FOR UPGRADING TO 2.0.0 OR LATER #
3
+ ##########################################
4
+
5
+ Prométhée 2.0 brings:
6
+ - [BREAKING CHANGE] New structure for table component. A rake task is available to update them in your master models. Localization has to be manual.
7
+ - [TOOL TO FIX ISSUE] A rake task to clean your localization models.
8
+
9
+ For more details, check the documentation:
10
+ https://github.com/lespoupeesrusses/promethee/tree/dev-2.0/doc
@@ -1,127 +1,135 @@
1
1
  @import "@fancyapps/fancybox/dist/jquery.fancybox.min"
2
2
 
3
+ // aside
4
+ // blockquote
5
+ // collection
6
+ // cover
7
+ // faq
8
+ // image
9
+ // slider
10
+
3
11
  .promethee
4
- &__component
5
- &__cover
6
- min-height: 300px
7
- padding: 150px 30px
8
- text-align: center
9
- display: flex
10
- justify-content: center
11
- flex-direction: column
12
- background-repeat: no-repeat
13
- background-position: center center
14
- background-size: cover
15
- margin-bottom: 50px
16
-
17
- &__page > &__aside,
18
- &__page > &__blockquote,
19
- &__page > &__faq,
20
- &__page > &__table,
21
- &__page > &__text,
22
- &__page > &__video
23
- @extend .container
24
- margin-bottom: 50px
25
- padding-left: $grid-gutter-width/2
26
- padding-right: $grid-gutter-width/2
27
-
28
- &__page > &__collection,
29
- &__page > &__row
30
- @extend .container
31
- padding-right: 0
32
- padding-left: 0
33
- margin-bottom: 50px
34
-
35
- &__slider
36
- .promethee__component
37
- margin-bottom: 0
38
- .fontawesome-carousel-control .fa
39
- top: 50%
40
- position: absolute
41
- transform: translateY(-50%)
42
- font-size: 30px
43
-
44
- &__collection
45
- margin-top: 20px
46
- margin-bottom: 20px
47
- .clearfix
48
- margin: 40px 0
49
-
50
- &__faq
51
- h4
52
- cursor: pointer
53
- position: relative
54
- &::after
55
- content: ""
56
- display: block
57
- width: 8px
58
- height: 8px
59
- border-right: 2px solid #000
60
- border-top: 2px solid #000
61
- transform: rotate(135deg)
62
- position: absolute
63
- right: 10px
64
- top: 5px
65
- transition: transform .4s ease
66
- &[aria-expanded="true"]
67
- &::after
68
- transform: rotate(315deg)
69
- img
70
- margin-bottom: 30px
71
-
72
- &__aside
73
- .aside__button
74
- padding-top: 30px
75
- a
76
- display: inline-block
77
- &--center
78
- text-align: center
79
- &--left
80
- text-align: left
81
- &--right
82
- text-align: right
83
-
84
- &__blockquote
85
- .blockquote
86
- font-size: 30px
87
- border: none
88
-
89
- p
90
- display: inline
91
-
92
- &::before, &::after
93
- display: inline-block
94
-
95
- &::before
96
- content: '« '
97
-
98
- &::after
99
- content: ' »'
100
-
101
- .author
102
- font-size: 14px
103
- font-style: italic
104
-
105
- &__collection
106
- .collection-item__content
107
- margin-bottom: $grid-gutter-width
108
-
109
- &__slider
110
- .carousel-item__content
111
- text-align: center
12
+ &__component
13
+ &__page > div:not(&__cover):not(&__slider),
14
+ &__page > aside
15
+ @extend .container
16
+ margin-bottom: 50px
17
+ padding-left: $grid-gutter-width/2
18
+ padding-right: $grid-gutter-width/2
19
+
20
+ &__page > &__collection,
21
+ &__page > &__row
22
+ padding-left: 0
23
+ padding-right: 0
24
+
25
+ &__aside
26
+ .aside__button
27
+ padding-top: $grid-gutter-width
28
+ a
29
+ display: inline-block
30
+ &--center
31
+ text-align: center
32
+ &--left
33
+ text-align: left
34
+ &--right
35
+ text-align: right
36
+
37
+ &__blockquote
38
+ .blockquote
39
+ border: none
40
+ font-size: 30px
41
+
42
+ p
43
+ display: inline
44
+
45
+ &::before, &::after
46
+ display: inline-block
47
+
48
+ &::before
49
+ content: '« '
50
+
51
+ &::after
52
+ content: ' »'
53
+
54
+ .author
55
+ font-size: 14px
56
+ font-style: italic
57
+
58
+ &__collection
59
+ margin-bottom: 20px
60
+ margin-top: 20px
61
+ .clearfix
62
+ margin: 40px 0
63
+ .collection-item__content
64
+ margin-bottom: $grid-gutter-width
65
+ a + p
66
+ margin-top: 10px
67
+
68
+ &__cover
69
+ background-position: center center
70
+ background-repeat: no-repeat
71
+ background-size: cover
72
+ display: flex
73
+ flex-direction: column
74
+ justify-content: center
75
+ margin-bottom: 50px
76
+ min-height: 300px
77
+ padding: 150px 30px
78
+ text-align: center
79
+
80
+ p:last-of-type
81
+ margin-bottom: 0
82
+
83
+ &__image
84
+ margin-bottom: $grid-gutter-width
85
+ figcaption
86
+ margin-top: 10px
87
+
88
+ &__faq
89
+ &_item:not(:last-of-type)
90
+ padding-bottom: 10px
91
+ h4
92
+ cursor: pointer
93
+ position: relative
94
+ &::after
95
+ border-right: 2px solid #000
96
+ border-top: 2px solid #000
97
+ content: ''
98
+ display: block
99
+ height: 8px
100
+ position: absolute
101
+ right: 10px
102
+ top: 5px
103
+ transform: rotate(135deg)
104
+ transition: transform .4s ease
105
+ width: 8px
106
+ &[aria-expanded="true"]
107
+ &::after
108
+ transform: rotate(315deg)
109
+ img
110
+ margin-bottom: $grid-gutter-width
111
+
112
+ &__slider
113
+ .promethee__component
114
+ margin-bottom: 0
115
+ .fontawesome-carousel-control .fa
116
+ font-size: 30px
117
+ position: absolute
118
+ top: 50%
119
+ transform: translateY(-50%)
120
+ .carousel-item
121
+ &__content
122
+ text-align: center
123
+ p:last-of-type
124
+ margin-bottom: 0
125
+ margin-top: 10px
112
126
 
113
127
  @media print
114
- body
115
- font-size: 125%
116
- .promethee
117
- &__component
118
- &__page > &__aside,
119
- &__page > &__text,
120
- &__page > &__faq,
121
- &__page > &__table,
122
- &__page > &__video,
123
- &__page > &__collection,
124
- &__page > &__row
125
- max-width: 90% !important
126
- .container
127
- max-width: 90% !important
128
+ body
129
+ font-size: 125%
130
+ .promethee
131
+ &__component
132
+ &__page > div:not(&__cover):not(&__slider)
133
+ max-width: 90%
134
+ .container
135
+ max-width: 90%
@@ -72,6 +72,8 @@ module PrometheeData
72
72
  if key.starts_with? 'searchable_'
73
73
  clean_value = strip_tags value
74
74
  searchable += "#{clean_value} "
75
+ elsif value.class == Hash
76
+ searchable += promethee_extract_searchable_attributes(value)
75
77
  end
76
78
  end
77
79
  searchable
@@ -0,0 +1,77 @@
1
+ module Promethee
2
+ class LocalizeCleanService
3
+ DEFAULT_WHITELIST = {
4
+ "aside" => ["searchable_visible_content", "searchable_collapsed_content", "searchable_open_label"],
5
+ "blockquote" => ["searchable_body", "searchable_author"],
6
+ "collection" => [],
7
+ "collection_item" => ["searchable_caption", "video"],
8
+ "column" => [],
9
+ "cover" => ["searchable_surtitle", "searchable_title", "searchable_subtitle"],
10
+ "faq" => [],
11
+ "faq_item" => ["searchable_title", "searchable_body"],
12
+ "image" => ["searchable_alt", "searchable_caption"],
13
+ "page" => ["searchable_title", "searchable_description"],
14
+ "row" => [],
15
+ "slider" => [],
16
+ "slider_item" => ["searchable_caption", "video"],
17
+ "table" => ["cols", "cols_data", "rows", "rows_data"],
18
+ "text" => ["searchable_body"],
19
+ "video" => ["url"]
20
+ }
21
+
22
+ attr_accessor :objects
23
+
24
+ def initialize(model_name, whitelist = {})
25
+ begin
26
+ model_class = model_name.constantize
27
+ objects = model_class.all
28
+ rescue
29
+ puts 'Please provide a valid model name (e.g. `rake promethee:clean_localizations[Page]`)'
30
+ exit
31
+ end
32
+ @objects = objects
33
+ @whitelist = DEFAULT_WHITELIST.merge(whitelist)
34
+ end
35
+
36
+ def add_rule(type, attributes = [])
37
+ @whitelist[type] = attributes
38
+ end
39
+
40
+ def start
41
+ puts '= START LOCALIZE CLEAN ='
42
+ puts "Number of objects: #{objects.count}"
43
+ i = 0
44
+ objects.each do |object|
45
+ next unless can_process?(object.data)
46
+
47
+ i += 1
48
+ puts "Processing object ##{object.id}"
49
+
50
+ object.data = clean(object.data)
51
+ object.save
52
+ puts "End processing object ##{object.id}"
53
+ end
54
+ puts "Number of processed objects: #{i}"
55
+ puts '====== END CLEANER ========'
56
+ end
57
+
58
+ private
59
+
60
+ def clean(data)
61
+ i = 0
62
+ data["components"].each do |component|
63
+ component_whitelist = @whitelist[component["type"]]
64
+ next if component_whitelist.nil? # Process only types in whitelist
65
+
66
+ i += 1
67
+ component["attributes"]&.slice!(*component_whitelist)
68
+ end
69
+ puts "- #{i} components were processed"
70
+ data
71
+ end
72
+
73
+ def can_process?(data)
74
+ data.is_a?(Hash) && data.has_key?("components")
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,69 @@
1
+ module Promethee
2
+ class TableUpgradeService
3
+ attr_accessor :objects
4
+
5
+ def initialize(model_name)
6
+ begin
7
+ model_class = model_name.constantize
8
+ objects = model_class.all.select { |page| page.data&.to_json&.include? '"type":"table"' }
9
+ rescue
10
+ puts 'Please provide a valid model name (e.g. `rake promethee:clean_localizations[Page]`)'
11
+ exit
12
+ end
13
+ @objects = objects
14
+ end
15
+
16
+ def start
17
+ puts '= START TABLE UPGRADE ='
18
+ puts "Number of objects: #{objects.count}"
19
+ objects.each do |object|
20
+ puts "Processing object ##{object.id}"
21
+
22
+ object.data = process_component(object.data)
23
+ object.save
24
+ puts "End processing object ##{object.id}"
25
+ end
26
+ puts '====== END CLEANER ========'
27
+ end
28
+
29
+ private
30
+
31
+ def process_component(component)
32
+ component = upgrade(component) if component["type"] == "table"
33
+ component["children"].map do |child|
34
+ process_component(child)
35
+ end if component["children"]&.any?
36
+ component
37
+ end
38
+
39
+ def upgrade(component)
40
+ return component unless component.has_key? "attributes"
41
+
42
+ head = component["attributes"]["head"]
43
+ body = component["attributes"]["body"]
44
+ return component if head.nil? || body.nil?
45
+
46
+ cols = create_uids(head)
47
+ rows = create_uids(body)
48
+
49
+ cols_data = head.map.with_index { |col_data, i| [cols[i], col_data] }.to_h
50
+ rows_data = body.map.with_index { |row_data, i|
51
+ new_row_data = row_data.map.with_index { |cell_data, j| [cols[j], cell_data] }.to_h
52
+ [rows[i], new_row_data]
53
+ }.to_h
54
+
55
+ component["attributes"].except!("head", "body")
56
+
57
+ component["attributes"]["cols"] = cols
58
+ component["attributes"]["cols_data"] = cols_data
59
+ component["attributes"]["rows"] = rows
60
+ component["attributes"]["rows_data"] = rows_data
61
+
62
+ component
63
+ end
64
+
65
+ def create_uids(array)
66
+ (0...array.size).map { |_| SecureRandom.hex(5) }
67
+ end
68
+ end
69
+ end
@@ -8,9 +8,31 @@ back_url ||= nil
8
8
  logo = File.read "#{__dir__}/../../assets/images/icon-promethee.svg"
9
9
  %>
10
10
 
11
+ <script type="text/javascript">
12
+ angular
13
+ .module('uid', [])
14
+ .factory('uidService', function () {
15
+ // Option 3 : https://stackoverflow.com/a/27747377
16
+ return {
17
+ generate: function () {
18
+ var arr = new Uint8Array(10 / 2),
19
+ hexArr = [],
20
+ i;
21
+
22
+ (window.crypto || window.msCrypto).getRandomValues(arr);
23
+ for (i = 0; i < arr.length; i += 1) {
24
+ hexArr[i] = ('0' + arr[i].toString(16)).substr(-2);
25
+ }
26
+
27
+ return hexArr.join('');
28
+ }
29
+ };
30
+ });
31
+ </script>
32
+
11
33
  <script type="text/javascript">
12
34
  var promethee = angular
13
- .module('Promethee', ['summernote', 'ngAnimate', 'ngFileUpload', 'ui.sortable', 'colorpicker.module'], ['$rootScopeProvider', function($rootScopeProvider) {
35
+ .module('Promethee', ['summernote', 'ngAnimate', 'ngFileUpload', 'ui.sortable', 'colorpicker.module', 'uid'], ['$rootScopeProvider', function($rootScopeProvider) {
14
36
  $rootScopeProvider.digestTtl(30);
15
37
  }])
16
38
  .value('definitions', [])
@@ -92,16 +114,6 @@ promethee.controller('PrometheeController', ['$scope', 'summernoteConfig', 'pres
92
114
  $scope.inspect = function(component, event) {
93
115
  if(event.target.closest('.promethee-edit__component') === event.currentTarget) {
94
116
  $scope.promethee.inspected = component;
95
- $scope.refreshInspect(component.type);
96
- }
97
- }
98
-
99
- $scope.refreshInspect = function (componentType) {
100
- var inspectContainer = document.querySelector(".promethee-edit__inspect-content--"+componentType);
101
- var summernoteToolbars = inspectContainer.querySelectorAll('.note-toolbar-wrapper');
102
- var i;
103
- for (i = 0 ; i < summernoteToolbars.length ; i += 1) {
104
- summernoteToolbars[i].removeAttribute('style');
105
117
  }
106
118
  }
107
119
 
@@ -1,7 +1,8 @@
1
1
  <script type="text/ng-template" id="promethee/components/collection_item/localize">
2
- <div ng-show="master.attributes.searchable_caption !== ''">
2
+ <div ng-show="master.attributes.searchable_caption !== '' || master.attributes.media_type == 'video'">
3
3
  <hr>
4
- <div class="row">
4
+
5
+ <div class="row" ng-show="master.attributes.searchable_caption !== ''">
5
6
  <div class="col-md-6">
6
7
  <b>Collection Item Caption</b>
7
8
  <div class="promethee-edit__wrapper" ng-bind-html="master.attributes.searchable_caption | htmlSafe"></div>
@@ -11,5 +12,16 @@
11
12
  <summernote config="summernoteConfig" ng-model="component.attributes.searchable_caption"></summernote>
12
13
  </div>
13
14
  </div>
15
+
16
+ <div class="row" ng-show="master.attributes.media_type == 'video'">
17
+ <div class="col-md-6">
18
+ <b>Video URL</b>
19
+ <div ng-bind-html="master.attributes.video.url | htmlSafe"></div>
20
+ </div>
21
+ <div class="col-md-6">
22
+ <label class="label-control">Video URL</label>
23
+ <input class="form-control" ng-model="component.attributes.video.url" type="text">
24
+ </div>
25
+ </div>
14
26
  </div>
15
27
  </script>
@@ -4,7 +4,7 @@
4
4
 
5
5
  <div class="row">
6
6
  <div class="col-md-6">
7
- <img ng-src="/promethee/blob/{{component.attributes.image.id}}" class="img-fluid img-responsive">
7
+ <img ng-src="/promethee/blob/{{master.attributes.image.id}}" class="img-fluid img-responsive">
8
8
  </div>
9
9
  </div>
10
10
 
@@ -1,7 +1,8 @@
1
1
  <script type="text/ng-template" id="promethee/components/slider_item/localize">
2
- <div ng-show="master.attributes.text !== ''">
2
+ <div ng-show="master.attributes.searchable_caption !== '' || master.attributes.media_type == 'video'">
3
3
  <hr>
4
- <div class="row">
4
+
5
+ <div class="row" ng-show="master.attributes.searchable_caption !== ''">
5
6
  <div class="col-md-6">
6
7
  <b>Slider Item Caption</b>
7
8
  <div class="promethee-edit__wrapper" ng-bind-html="master.attributes.searchable_caption | htmlSafe"></div>
@@ -11,5 +12,16 @@
11
12
  <summernote config="summernoteConfig" ng-model="component.attributes.searchable_caption"></summernote>
12
13
  </div>
13
14
  </div>
15
+
16
+ <div class="row" ng-show="master.attributes.media_type == 'video'">
17
+ <div class="col-md-6">
18
+ <b>Video URL</b>
19
+ <div ng-bind-html="master.attributes.video.url | htmlSafe"></div>
20
+ </div>
21
+ <div class="col-md-6">
22
+ <label class="label-control">Video URL</label>
23
+ <input class="form-control" ng-model="component.attributes.video.url" type="text">
24
+ </div>
25
+ </div>
14
26
  </div>
15
27
  </script>
@@ -8,30 +8,10 @@
8
8
  data: {
9
9
  type: 'table',
10
10
  attributes: {
11
- head: [
12
- {
13
- searchable_text: 'Column 1'
14
- },
15
- {
16
- searchable_text: 'Column 2'
17
- },
18
- {
19
- searchable_text: 'Column 3'
20
- }
21
- ],
22
- body: [
23
- [
24
- {
25
- searchable_text: 'Text 1'
26
- },
27
- {
28
- searchable_text: 'Text 2'
29
- },
30
- {
31
- searchable_text: 'Text 3'
32
- }
33
- ]
34
- ]
11
+ cols: [],
12
+ cols_data: {},
13
+ rows: [],
14
+ rows_data: {}
35
15
  }
36
16
  }
37
17
  })
@@ -1,42 +1,102 @@
1
1
  <script type="text/ng-template" id="promethee/components/table/edit/inspect">
2
- <div class="form-group">
3
- <label class="label-control">Head</label><br/>
4
- <div class="btn btn-default btn-light btn-sm"
5
- ng-click="promethee.inspected.attributes.head.push({searchable_text: 'Column'})">
6
- Add column
7
- </div><br/><br/>
8
- <div ng-repeat="th in promethee.inspected.attributes.head track by $index">
9
- <div class="form-row">
10
- <div class="col-10">
11
- <input type="text" ng-model="th.searchable_text" class="form-control" />
2
+ <div ng-controller="TableInspectController" ng-init="component = promethee.inspected">
3
+ <div class="form-group">
4
+ <label class="label-control">Columns</label><br/>
5
+ <div class="btn btn-default btn-light btn-sm"
6
+ ng-click="addColumn()">
7
+ Add column
8
+ </div><br/><br/>
9
+ <div ui-sortable ng-model="component.attributes.cols">
10
+ <div ng-repeat="colUid in component.attributes.cols">
11
+ <div class="form-group row align-items-center">
12
+ <div class="col-1" style="line-height: 38px">
13
+ <i class="fas fa-bars"></i>
14
+ </div>
15
+ <div class="col-9">
16
+ <input type="text"
17
+ ng-model="component.attributes.cols_data[colUid].searchable_text"
18
+ class="form-control" />
19
+ </div>
20
+ <div class="col-2">
21
+ <a class="btn btn-default btn-light btn-sm"
22
+ ng-click="removeColumn(colUid)">
23
+ <%= icon('fa', 'close') %>
24
+ </a>
25
+ </div>
26
+ </div>
12
27
  </div>
13
- <div class="col-2">
14
- <a class="btn btn-default btn-light btn-sm"
15
- ng-click="promethee.inspected.attributes.head.splice($index, 1)">
28
+ </div>
29
+ </div>
30
+ <hr>
31
+ <div class="form-group">
32
+ <label class="label-control">Rows</label><br/>
33
+ <div class="btn btn-default btn-light btn-sm"
34
+ ng-click="addRow()">
35
+ Add row
36
+ </div><br/><br/>
37
+ <div ng-repeat="rowUid in component.attributes.rows track by $index">
38
+ <span class="small">
39
+ <b>Row {{$index+1}}</b>
40
+ <a class="btn btn-default btn-light btn-sm float-right"
41
+ ng-click="removeRow(rowUid)">
16
42
  <%= icon('fa', 'close') %>
17
43
  </a>
44
+ </span><br/>
45
+ <div ng-repeat="colUid in component.attributes.cols">
46
+ <span class="small">
47
+ {{component.attributes.cols_data[colUid].searchable_text}}
48
+ </span>
49
+ <br/>
50
+ <input type="text"
51
+ ng-model="component.attributes.rows_data[rowUid][colUid].searchable_text"
52
+ class="form-control" />
18
53
  </div>
54
+ <hr/>
19
55
  </div>
20
56
  </div>
21
- </div>
22
- <div class="form-group">
23
- <label class="label-control">Body</label><br/>
24
- <div class="btn btn-default btn-light btn-sm"
25
- ng-click="promethee.inspected.attributes.body.push([{searchable_text: 'Text'}])">
26
- Add row
27
- </div><br/><br/>
28
- <div ng-repeat="tr in promethee.inspected.attributes.body track by $index">
29
- <span class="small"><b>Row {{$index+1}}</b>
30
- <a class="btn btn-default btn-light btn-sm float-right"
31
- ng-click="promethee.inspected.attributes.body.splice($index, 1)">
32
- <%= icon('fa', 'close') %>
33
- </a>
34
- </span><br/>
35
- <div ng-repeat="th in promethee.inspected.attributes.head track by $index">
36
- <span class="small">{{th.searchable_text}}</span><br/>
37
- <input type="text" ng-model="tr[$index].searchable_text" class="form-control" />
38
- </div>
39
- <hr/>
57
+ <div class="form-group" ng-show="component.attributes.rows.length > 1">
58
+ <label class="label-control">Drag the rows below to reorder them:</label>
59
+ <ul ui-sortable
60
+ ng-model="component.attributes.rows"
61
+ class="list-unstyled">
62
+ <li ng-repeat="_ in component.attributes.rows track by $index">
63
+ <%= icon('fa', 'bars') %> Row {{$index + 1}}
64
+ </li>
65
+ </ul>
40
66
  </div>
41
67
  </div>
42
68
  </script>
69
+
70
+ <script>
71
+ promethee.controller('TableInspectController', ['$scope', 'uidService', function($scope, uidService) {
72
+ $scope.addColumn = function () {
73
+ var uid = uidService.generate();
74
+ $scope.component.attributes.cols.push(uid);
75
+ $scope.component.attributes.cols_data[uid] = { searchable_text: 'New column' };
76
+ }
77
+
78
+ $scope.addRow = function () {
79
+ var uid = uidService.generate();
80
+ $scope.component.attributes.rows.push(uid);
81
+
82
+ console.log($scope.component.attributes);
83
+ }
84
+
85
+ $scope.removeItem = function (uid, arrayKey) {
86
+ var dataKey = arrayKey + '_data';
87
+ var index = $scope.component.attributes[arrayKey].indexOf(uid);
88
+ if (index !== -1) {
89
+ $scope.component.attributes[arrayKey].splice(index, 1);
90
+ delete $scope.component.attributes[dataKey][uid];
91
+ }
92
+ }
93
+
94
+ $scope.removeColumn = function (uid) {
95
+ $scope.removeItem(uid, 'cols');
96
+ }
97
+
98
+ $scope.removeRow = function (uid) {
99
+ $scope.removeItem(uid, 'rows');
100
+ }
101
+ }]);
102
+ </script>
@@ -4,12 +4,16 @@
4
4
  <table class="table">
5
5
  <thead>
6
6
  <tr>
7
- <th ng-repeat="th in component.attributes.head track by $index">{{th.searchable_text}}</th>
7
+ <th ng-repeat="colUid in component.attributes.cols">
8
+ {{component.attributes.cols_data[colUid].searchable_text}}
9
+ </th>
8
10
  </tr>
9
11
  </thead>
10
12
  <tbody>
11
- <tr ng-repeat="tr in component.attributes.body track by $index">
12
- <td ng-repeat="td in tr track by $index">{{td.searchable_text}}</td>
13
+ <tr ng-repeat="rowUid in component.attributes.rows">
14
+ <td ng-repeat="colUid in component.attributes.cols">
15
+ {{component.attributes.rows_data[rowUid][colUid].searchable_text}}
16
+ </td>
13
17
  </tr>
14
18
  </tbody>
15
19
  </table>
@@ -6,12 +6,16 @@
6
6
  <table class="table">
7
7
  <thead>
8
8
  <tr>
9
- <th ng-repeat="th in master.attributes.head track by $index">{{th.searchable_text}}</th>
9
+ <th ng-repeat="colUid in master.attributes.cols track by $index">
10
+ {{ master.attributes.cols_data[colUid].searchable_text }}
11
+ </th>
10
12
  </tr>
11
13
  </thead>
12
14
  <tbody>
13
- <tr ng-repeat="tr in master.attributes.body track by $index">
14
- <td ng-repeat="td in tr track by $index">{{td.searchable_text}}</td>
15
+ <tr ng-repeat="rowUid in master.attributes.rows">
16
+ <td ng-repeat="colUid in master.attributes.cols">
17
+ {{ master.attributes.rows_data[rowUid][colUid].searchable_text }}
18
+ </td>
15
19
  </tr>
16
20
  </tbody>
17
21
  </table>
@@ -20,15 +24,19 @@
20
24
  <table class="table">
21
25
  <thead>
22
26
  <tr>
23
- <th ng-repeat="th in component.attributes.head track by $index">
24
- <input class="form-control" ng-model="th.searchable_text" type="text">
27
+ <th ng-repeat="colUid in master.attributes.cols track by $index">
28
+ <input type="text"
29
+ ng-model="component.attributes.cols_data[colUid].searchable_text"
30
+ class="form-control">
25
31
  </th>
26
32
  </tr>
27
33
  </thead>
28
34
  <tbody>
29
- <tr ng-repeat="tr in component.attributes.body track by $index">
30
- <td ng-repeat="td in tr track by $index">
31
- <input class="form-control" ng-model="td.searchable_text" type="text">
35
+ <tr ng-repeat="rowUid in master.attributes.rows">
36
+ <td ng-repeat="colUid in master.attributes.cols">
37
+ <input class="form-control"
38
+ ng-model="component.attributes.rows_data[rowUid][colUid].searchable_text"
39
+ type="text">
32
40
  </td>
33
41
  </tr>
34
42
  </tbody>
@@ -1,24 +1,37 @@
1
+ <%
2
+ return unless ([:cols, :cols_data, :rows, :rows_data] - component[:attributes].keys).empty?
3
+ columns = component[:attributes][:cols].map { |colUid|
4
+ colData = component[:attributes][:cols_data][colUid.to_sym] || {}
5
+ { uid: colUid, searchable_text: colData[:searchable_text] }
6
+ }
7
+
8
+ rows = component[:attributes][:rows].map { |rowUid|
9
+ rowData = component[:attributes][:rows_data][rowUid.to_sym] || {}
10
+ { uid: rowUid, data: rowData }
11
+ }
12
+ %>
13
+
1
14
  <div id="component-<%= component[:id] %>" class="<%= promethee_class_for(component) %>">
2
15
  <div class="table-responsive">
3
16
  <table class="table">
4
17
  <thead>
5
18
  <tr>
6
- <% component[:attributes][:head].each do |th| %>
7
- <th><%= th[:searchable_text] if th.has_key? :searchable_text %></th>
19
+ <% columns.each do |col| %>
20
+ <th><%= col[:searchable_text] %></th>
8
21
  <% end %>
9
22
  </tr>
10
23
  </thead>
11
24
  <tbody>
12
- <% component[:attributes][:body].each do |tr| %>
13
- <% if tr.select { |td| td[:searchable_text]&.present? }.count == 0 %>
14
- <tr></tr>
15
- <% else %>
16
- <tr>
17
- <% tr.each do |td| %>
18
- <td><%= td[:searchable_text] if td.has_key? :searchable_text %></td>
19
- <% end %>
20
- </tr>
21
- <% end %>
25
+ <% rows.each do |row| %>
26
+ <tr>
27
+ <% columns.each do |col| %>
28
+ <%
29
+ cell = row[:data][col[:uid].to_sym]
30
+ next if cell.nil?
31
+ %>
32
+ <td><%= cell[:searchable_text] %></td>
33
+ <% end %>
34
+ </tr>
22
35
  <% end %>
23
36
  </tbody>
24
37
  </table>
@@ -108,8 +108,7 @@ promethee
108
108
  // console.log('dropped', component, droppedToList, droppedToIndex);
109
109
  droppedToList.splice(droppedToIndex, 0, component);
110
110
 
111
- scope.promethee.inspected = component
112
- scope.refreshInspect(component.type);
111
+ scope.promethee.inspected = component;
113
112
 
114
113
  scope.$apply();
115
114
  }
@@ -155,7 +154,7 @@ promethee
155
154
  <div class="promethee-edit__inspect-content">
156
155
  <div ng-repeat="definition in promethee.definitions | orderBy:'position'">
157
156
  <ng-include src="'promethee/components/' + definition.data.type + '/edit/inspect'"
158
- ng-show="promethee.inspected.type == definition.data.type"
157
+ ng-if="promethee.inspected.type == definition.data.type"
159
158
  class="promethee-edit__inspect-content--{{ definition.data.type }}"></ng-include>
160
159
  </div>
161
160
  </div>
@@ -27,7 +27,7 @@
27
27
  "children": [
28
28
  {
29
29
  "type": "text",
30
- "attributes": {"body": "<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. A dicta, est quos distinctio culpa! Quasi cupiditate, totam nulla reprehenderit animi iusto qui cumque culpa repellat eum sit? Debitis, laboriosam reiciendis!</p>"}
30
+ "attributes": {"searchable_body": "<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. A dicta, est quos distinctio culpa! Quasi cupiditate, totam nulla reprehenderit animi iusto qui cumque culpa repellat eum sit? Debitis, laboriosam reiciendis!</p>"}
31
31
  }
32
32
  ]
33
33
  }
@@ -25,7 +25,8 @@ class Promethee::Data::Localization < Promethee::Data
25
25
  @master_data.flat.each do |master_component|
26
26
  localized_component = find_localized_component master_component[:id]
27
27
  # We take the localized component if it exists, the master component otherwise
28
- component = localized_component || master_component
28
+ component = localized_component || master_component.except(:attributes)
29
+ component[:attributes] ||= {}
29
30
  # We add it to the list of localized components
30
31
  @data[:components] << component
31
32
  end
@@ -18,9 +18,11 @@ class Promethee::Data::MasterLocalized < Promethee::Data
18
18
  def localize_component_attributes(component)
19
19
  localized_component = find_localized_component component[:id]
20
20
  return if (localized_component.nil? || !localized_component.include?(:attributes))
21
- component[:attributes].merge! localized_component[:attributes]
21
+ component[:attributes].deep_merge_existing_keys! localized_component[:attributes]
22
22
  end
23
23
 
24
+
25
+
24
26
  def localize_component_children(component)
25
27
  component[:children].each { |child| localize_component child }
26
28
  end
@@ -1,5 +1,5 @@
1
1
  module Promethee
2
2
  module Rails
3
- VERSION = '1.11.29'
3
+ VERSION = '2.0.0'
4
4
  end
5
5
  end
data/lib/promethee.rb CHANGED
@@ -3,6 +3,7 @@ require 'jquery-rails'
3
3
  require 'jquery-ui-rails'
4
4
  require 'angularjs-rails'
5
5
  require 'summernote-rails'
6
+ require 'deep_merge_existing_keys'
6
7
 
7
8
  module Promethee
8
9
  def self.root
@@ -1,4 +1,15 @@
1
- # desc "Explaining what the task does"
2
- # task :promethee do
3
- # # Task goes here
4
- # end
1
+ namespace :promethee do
2
+
3
+ desc "Remove useless attributes from localizations' data"
4
+ task :clean_localizations, [:model_name] => :environment do |task, args|
5
+ service = Promethee::LocalizeCleanService.new(args[:model_name])
6
+ service.start
7
+ end
8
+
9
+ desc "Upgrade your table components' to 2.x structure"
10
+ task :upgrade_table, [:model_name] => :environment do |task, args|
11
+ service = Promethee::TableUpgradeService.new(args[:model_name])
12
+ service.start
13
+ end
14
+
15
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: promethee
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.11.29
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sébastien Gaya
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
- date: 2019-04-26 00:00:00.000000000 Z
17
+ date: 2019-05-15 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: rails
@@ -128,6 +128,20 @@ dependencies:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
130
  version: 0.8.10.0
131
+ - !ruby/object:Gem::Dependency
132
+ name: deep_merge_existing_keys
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :runtime
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
131
145
  - !ruby/object:Gem::Dependency
132
146
  name: byebug
133
147
  requirement: !ruby/object:Gem::Requirement
@@ -157,6 +171,7 @@ extra_rdoc_files: []
157
171
  files:
158
172
  - README.md
159
173
  - Rakefile
174
+ - UPGRADING
160
175
  - app/assets/images/icon-promethee.png
161
176
  - app/assets/images/icon-promethee.svg
162
177
  - app/assets/images/loader.gif
@@ -176,6 +191,8 @@ files:
176
191
  - app/assets/stylesheets/promethee.sass
177
192
  - app/controllers/promethee_controller.rb
178
193
  - app/models/concerns/promethee_data.rb
194
+ - app/services/promethee/localize_clean_service.rb
195
+ - app/services/promethee/table_upgrade_service.rb
179
196
  - app/views/promethee/_edit.html.erb
180
197
  - app/views/promethee/_localize.html.erb
181
198
  - app/views/promethee/_show.html.erb
@@ -430,7 +447,17 @@ homepage: https://github.com/lespoupeesrusses/promethee
430
447
  licenses:
431
448
  - MIT
432
449
  metadata: {}
433
- post_install_message:
450
+ post_install_message: |-
451
+ ##########################################
452
+ # NOTE FOR UPGRADING TO 2.0.0 OR LATER #
453
+ ##########################################
454
+
455
+ Prométhée 2.0 brings:
456
+ - [BREAKING CHANGE] New structure for table component. A rake task is available to update them in your master models. Localization has to be manual.
457
+ - [TOOL TO FIX ISSUE] A rake task to clean your localization models.
458
+
459
+ For more details, check the documentation:
460
+ https://github.com/lespoupeesrusses/promethee/tree/dev-2.0/doc
434
461
  rdoc_options: []
435
462
  require_paths:
436
463
  - lib