populate-me 0.9.2 → 0.13.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: b2e11800f347033e3d25223ba4b1296e07e1bdd7f3231d35888b6bd56c2cb126
4
- data.tar.gz: 10a0e20a877ad1c9ae25f9096cf55f253eab4b1014e50368af6cb8ac28e39976
3
+ metadata.gz: 514291d44eb8b068db7c98d742dc8395a5a2821255ac31ba054522823f6c55d9
4
+ data.tar.gz: 5a5c76cec480ed1c057ee70d33a38f21f1bd536c3ca5eabfdbbf2bf1d14c4b3c
5
5
  SHA512:
6
- metadata.gz: 28d96b6d98af49675ee4bd2050528cdfd387032fb7390464334d789c7c7e2bd0fe5730e13e545f88383a6aa19602d95472c8a72ffeaa8ace60e580a3e6af4ca9
7
- data.tar.gz: 52692b913a4d6f3083a283c0638571d90e96aab8b1bf8ace375de6c108bccaad0f919323dbffa5be715ff52d4fc0990a3d7e9c3859bbbcfd64da757e5e86f6a0
6
+ metadata.gz: 72e7c460a58523cf8cd9a1e9dadba107f5bfa810ec552b93af0fe113d4bf98f0941cb168ac4323291ab5fee478c1d018ceaa017c2f4bf5ea3460ce6d0b4a4130
7
+ data.tar.gz: 41cf0a2e8705a2b184e3c840b001424cd4d69f00a447da72b89d2339ee0390a24b76c07e886b48127594ed73ad762e43560497097aa672dbc89ff2d7c9af2141
@@ -62,10 +62,10 @@ class PopulateMe::Admin < Sinatra::Base
62
62
  end
63
63
  items = current_level.map do |l|
64
64
  href = l[1].is_a?(String) ? l[1] : "#{request.script_name}/menu#{levels.map{|level|'/'+level}.join}/#{slugify(l[0])}"
65
- { title: l[0], href: href }
65
+ { title: l[0], href: href, new_page: (not href.start_with?('/')) }
66
66
  end
67
67
  if request.path_info=='/menu'
68
- items.push({title: '?', href: "#{request.script_name}/help"})
68
+ items.push({title: '?', href: "#{request.script_name}/help", new_page: false})
69
69
  end
70
70
  {
71
71
  template: 'template_menu',
@@ -140,10 +140,25 @@ button.admin-delete:focus, button.admin-delete-nested:focus, .handle-button:focu
140
140
  -ms-user-select: none;
141
141
  user-select: none;
142
142
  }
143
+ .documents.grid {
144
+ width: 90%; width: 90vw;
145
+ }
143
146
  .documents > li, .nested-documents > li {
144
147
  display: block;
145
148
  margin-bottom: 1em;
146
149
  }
150
+ .documents.grid > li {
151
+ display: inline-block;
152
+ vertical-align: top;
153
+ width: 200px;
154
+ margin-right: 1em;
155
+ }
156
+ .documents.grid > li > a {
157
+ word-break: break-word;
158
+ }
159
+ .documents.grid > li img {
160
+ width: 200px;
161
+ }
147
162
  .documents > li:hover, .nested-documents > li:hover {
148
163
  background-color: #eee8d5;
149
164
  outline: 0.5em solid #eee8d5;
@@ -169,16 +184,20 @@ form {
169
184
  margin-bottom: 1em;
170
185
  }
171
186
 
172
- input[type=text], input[type=email],
187
+ input[type=text], input[type=email], input[type=search],
173
188
  textarea {
174
189
  border: 0px;
175
190
  color: #839496;
176
- background: #ffffff;
191
+ background-color: #ffffff;
177
192
  width: 400px;
178
193
  padding: 0.5em;
179
194
  font-size: 1em;
195
+ outline: 0;
196
+ }
197
+ input[type=text].search-items {
198
+ border-radius: 1em;
180
199
  }
181
- input[type=text]:focus, input[type=email]:focus,
200
+ input[type=text]:focus, input[type=email]:focus, input[type=email]:focus,
182
201
  textarea:focus {
183
202
  /* color: #002b36; */
184
203
  }
@@ -45,14 +45,18 @@
45
45
  root.busy = false;
46
46
  root.on('push.columnav', function(e,data,cb) {
47
47
  var $data = $("<li class='"+settings.column_class+"'>"+data+"</li>");
48
- root.append($data);
49
- new_column($data, root);
50
- var cb_object = {event:e,column:$data,container:root,settings:settings};
51
- root.animate({scrollLeft: root.width()},function(){
48
+ async function push_callback_stack() {
49
+ await root.append($data);
50
+ await new_column($data, root);
51
+ var cb_object = {event:e,column:$data,container:root,settings:settings};
52
+ await settings.on_push(cb_object);
53
+ if (typeof cb == 'function') await cb(cb_object);
52
54
  root.busy = false;
53
- settings.on_push(cb_object);
54
- if (typeof cb == 'function') cb(cb_object);
55
- });
55
+ root.find('> li:last-child').get(0).scrollIntoView({
56
+ behavior: 'smooth', inline: 'start'
57
+ });
58
+ }
59
+ push_callback_stack();
56
60
  });
57
61
  root.on('getandpush.columnav', function(e,url,cb) {
58
62
  $.get(url, function(data) {
@@ -63,7 +67,7 @@
63
67
  });
64
68
  });
65
69
  root.on('pop.columnav', function(e,removable,cb) {
66
- removable = removable || root.children().last();
70
+ removable = removable || root.find('> li:last-child');
67
71
  removable.css({visibility:'hidden'})
68
72
  .animate({width:0},function(){
69
73
  // Trick to make sure it runs only once
@@ -94,12 +94,24 @@ PopulateMe.make_sortable = function(selector,context) {
94
94
  });
95
95
  };
96
96
 
97
+ // Copy and restore column search.
98
+ // Used when saving pops the columns.
99
+ PopulateMe.copy_column_search = function(column) {
100
+ return column.find('.search-items').val();
101
+ };
102
+ PopulateMe.restore_column_search = function(column, value) {
103
+ if (value !== '' && column.data('qs')) {
104
+ column.find('.search-items').val(value);
105
+ column.data('qs').search(value);
106
+ }
107
+ };
108
+
97
109
  // Scroll to an element, possibly in a specific column.
98
110
  PopulateMe.scroll_to = function(el, column) {
99
111
  if (!column) {
100
112
  column = el.closest('.column');
101
113
  }
102
- column.animate({scrollTop: el.position().top});
114
+ el.get(0).scrollIntoView({ behavior: 'smooth'});
103
115
  };
104
116
 
105
117
  // Mark errors for report after form validation.
@@ -162,39 +174,84 @@ PopulateMe.jsValidationsPassed = function(context) {
162
174
  // in case you have things to put in your custom javascript.
163
175
  PopulateMe.init_column = function(c) {
164
176
 
177
+ var documents = $('.documents', c);
178
+
165
179
  // Sort list item
166
- PopulateMe.make_sortable('.documents',c).bind('sortupdate', function(e, ui) {
167
- var list = $(ui.item).closest('.documents');
168
- var ids = list.children().map(function() {
169
- return $(this).data().id;
170
- }).get();
171
- $.ajax({
172
- url: list.data().sortUrl,
173
- type: 'put',
174
- data: {
175
- action: 'sort',
176
- field: list.data().sortField,
177
- ids: ids
178
- }
180
+ if (documents.data('sort-field') !== '') {
181
+ PopulateMe.make_sortable(documents).bind('sortupdate', function(e, ui) {
182
+ var list = $(ui.item).closest('.documents');
183
+ var ids = list.children().map(function() {
184
+ return $(this).data().id;
185
+ }).get();
186
+ $.ajax({
187
+ url: list.data().sortUrl,
188
+ type: 'put',
189
+ data: {
190
+ action: 'sort',
191
+ field: list.data().sortField,
192
+ ids: ids
193
+ }
194
+ });
195
+ /*
196
+ ui.item contains the current dragged element.
197
+ ui.item.index() contains the new index of the dragged element
198
+ ui.oldindex contains the old index of the dragged element
199
+ ui.startparent contains the element that the dragged item comes from
200
+ ui.endparent contains the element that the dragged item was added to
201
+ */
179
202
  });
180
- /*
181
- ui.item contains the current dragged element.
182
- ui.item.index() contains the new index of the dragged element
183
- ui.oldindex contains the old index of the dragged element
184
- ui.startparent contains the element that the dragged item comes from
185
- ui.endparent contains the element that the dragged item was added to
186
- */
187
- });
203
+ }
188
204
 
189
205
  // Sort nested documents
190
206
  PopulateMe.make_sortable('.nested-documents',c);
191
207
 
208
+ $('.search-items', c).each(function() {
209
+ var field = $(this)
210
+ var qs = field.quicksearch($('.admin-list-item', c), {
211
+ selector: '.item-title',
212
+ onAfter: function() {
213
+ if (documents.is('.ui-sortable')) {
214
+ if (field.val() == '') {
215
+ documents.sortable('enable');
216
+ } else {
217
+ documents.sortable('disable');
218
+ }
219
+ }
220
+ }
221
+ });
222
+ c.data('qs', qs);
223
+ });
224
+
192
225
  // Init textareas
193
226
  $('textarea',c).trigger('input');
194
227
 
195
228
  // Init multiple select with asmSelect
196
229
  $('select[multiple]', c).asmSelect({ sortable: true, removeLabel: '&times;' });
197
230
 
231
+ // Select with preview
232
+ $('select:not([multiple])', c).change(function() {
233
+ var $this = $(this);
234
+ var container;
235
+ if ($this.data('preview-container')) {
236
+ container = $($this.data('preview-container'), c);
237
+ } else {
238
+ container = $this.next('.preview-container');
239
+ }
240
+ if (container.size() == 0) return;
241
+ var path = $this.find(':selected:first').data('preview');
242
+ if (path) {
243
+ var img = container.find('img:first');
244
+ if (img.size() < 1) {
245
+ img = $("<img src='' alt='Preview' title='Preview' width='250' />");
246
+ container.html(img);
247
+ }
248
+ img.attr('src', path);
249
+ } else {
250
+ container.html('');
251
+ }
252
+ });
253
+ $('option:selected[data-preview]').parent().change();
254
+
198
255
  // Polymorphic selector
199
256
  $('select.polymorphic_type_values').change(function() {
200
257
  var $this = $(this);
@@ -261,11 +318,14 @@ $(function() {
261
318
  contentType: false,
262
319
  success: function(res) {
263
320
  if (res.success==true) {
264
- var reloader = PopulateMe.finder.find('> li:nth-last-child(3) .selected')
321
+ var reloader = PopulateMe.finder.find('> li:nth-last-child(3) .selected');
265
322
  if (reloader.size()>0) {
323
+ var reloadee = PopulateMe.finder.find('> li:nth-last-child(2)');
324
+ var current_search = PopulateMe.copy_column_search(reloadee);
266
325
  reloader.trigger('click.columnav',[function(cb_object) {
267
- var target = $('[data-id='+res.data.id+']', cb_object.column);
326
+ var target = $('[data-id='+res.data._id+']', cb_object.column);
268
327
  if (target.size()>0) {
328
+ PopulateMe.restore_column_search(cb_object.column, current_search);
269
329
  PopulateMe.scroll_to(target, cb_object.column);
270
330
  }
271
331
  }]);
@@ -0,0 +1 @@
1
+ (function($,window,document,undefined){$.fn.quicksearch=function(target,opt){var timeout,cache,rowcache,jq_results,val="",e=this,options=$.extend({delay:100,selector:null,stripeRows:null,loader:null,noResults:"",matchedResultsCount:0,bind:"keyup",onBefore:function(){return},onAfter:function(){return},show:function(){this.style.display=""},hide:function(){this.style.display="none"},prepareQuery:function(val){return val.toLowerCase().split(" ")},testQuery:function(query,txt,_row){for(var i=0;i<query.length;i+=1){if(txt.indexOf(query[i])===-1){return false}}return true}},opt);this.go=function(){var i=0,numMatchedRows=0,noresults=true,query=options.prepareQuery(val),val_empty=val.replace(" ","").length===0;for(var i=0,len=rowcache.length;i<len;i++){if(val_empty||options.testQuery(query,cache[i],rowcache[i])){options.show.apply(rowcache[i]);noresults=false;numMatchedRows++}else{options.hide.apply(rowcache[i])}}if(noresults){this.results(false)}else{this.results(true);this.stripe()}this.matchedResultsCount=numMatchedRows;this.loader(false);options.onAfter();return this};this.search=function(submittedVal){val=submittedVal;e.trigger()};this.currentMatchedResults=function(){return this.matchedResultsCount};this.stripe=function(){if(typeof options.stripeRows==="object"&&options.stripeRows!==null){var joined=options.stripeRows.join(" ");var stripeRows_length=options.stripeRows.length;jq_results.not(":hidden").each(function(i){$(this).removeClass(joined).addClass(options.stripeRows[i%stripeRows_length])})}return this};this.strip_html=function(input){var output=input.replace(new RegExp("<[^<]+>","g"),"");output=$.trim(output.toLowerCase());return output};this.results=function(bool){if(typeof options.noResults==="string"&&options.noResults!==""){if(bool){$(options.noResults).hide()}else{$(options.noResults).show()}}return this};this.loader=function(bool){if(typeof options.loader==="string"&&options.loader!==""){bool?$(options.loader).show():$(options.loader).hide()}return this};this.cache=function(){jq_results=$(target);if(typeof options.noResults==="string"&&options.noResults!==""){jq_results=jq_results.not(options.noResults)}var t=typeof options.selector==="string"?jq_results.find(options.selector):$(target).not(options.noResults);cache=t.map(function(){return e.strip_html(this.innerHTML)});rowcache=jq_results.map(function(){return this});val=val||this.val()||"";return this.go()};this.trigger=function(){this.loader(true);options.onBefore();window.clearTimeout(timeout);timeout=window.setTimeout(function(){e.go()},options.delay);return this};this.cache();this.results(true);this.stripe();this.loader(false);return this.each(function(){$(this).on(options.bind,function(){val=$(this).val();e.trigger()})})}})(jQuery,this,document);
@@ -26,7 +26,7 @@
26
26
  <h1>{{page_title}}</h1>
27
27
  <ol class='menu'>
28
28
  {{#items}}
29
- <li><a href="{{href}}" class='column-push' title='Open'>{{title}}</a></li>
29
+ <li><a href="{{href}}" {{#new_page}}target='_blank'{{/new_page}}{{^new_page}}class='column-push'{{/new_page}} title='Open'>{{title}}</a></li>
30
30
  {{/items}}
31
31
  </ol>
32
32
  </script>
@@ -46,7 +46,10 @@
46
46
  {{/is_polymorphic}}
47
47
  <a href="<%= request.script_name %>/form/{{dasherized_class_name}}{{#new_data}}?{{new_data}}{{/new_data}}" class='column-push new-document-btn' title='Create'>+</a>
48
48
  </p>
49
- <ol class='documents' data-sort-field='{{sort_field}}' data-sort-url='<%= request.script_name %>/api/{{dasherized_class_name}}'>
49
+ <form class='form-search-items'>
50
+ <input type='text' class='search-items' placeholder='Search'>
51
+ </form>
52
+ <ol class='documents {{#grid_view}}grid{{/grid_view}}' data-sort-field='{{sort_field}}' data-sort-url='<%= request.script_name %>/api/{{dasherized_class_name}}'>
50
53
  {{#items}}{{#custom_partial_or_default}}template_document{{/custom_partial_or_default}}{{/items}}
51
54
  </ol>
52
55
  </script>
@@ -57,7 +60,7 @@
57
60
  <button type='button' class='admin-delete' title='Delete' value='<%= request.script_name %>/api/{{admin_url}}'>&times;</button>
58
61
  </header>
59
62
  <a href="<%= request.script_name %>/form/{{admin_url}}" class='column-push' title='Edit'>
60
- {{title}}
63
+ <span class='item-title'>{{title}}</span>
61
64
  {{#image_url}}
62
65
  <br />
63
66
  <img src='{{image_url}}{{cache_buster}}' alt='{{title}}' width='300' />
@@ -134,9 +137,10 @@
134
137
  {{/multiple}}
135
138
  <select name='{{input_name}}' {{#multiple}}multiple title='?'{{/multiple}}{{{build_input_attributes}}}>
136
139
  {{#select_options}}
137
- <option value='{{value}}' {{#selected}}selected{{/selected}}>{{description}}</option>
140
+ <option value='{{value}}' {{#selected}}selected{{/selected}} {{#preview_uri}}data-preview='{{preview_uri}}'{{/preview_uri}}>{{description}}</option>
138
141
  {{/select_options}}
139
142
  </select>
143
+ <div class='preview-container'></div>
140
144
  </script>
141
145
 
142
146
  <script id="template-attachment-field" type="x-tmpl-mustache">
@@ -175,6 +179,7 @@
175
179
  <script src="<%= request.script_name %>/__assets__/js/columnav.js" type="text/javascript" charset="utf-8"></script>
176
180
  <%# <script src="<%= request.script_name %1>/__assets__/js/sortable.js" type="text/javascript" charset="utf-8"></script> %>
177
181
  <script src="<%= request.script_name %>/__assets__/js/asmselect.js" type="text/javascript" charset="utf-8"></script>
182
+ <script src="<%= request.script_name %>/__assets__/js/quicksearch.js" type="text/javascript" charset="utf-8"></script>
178
183
  <script type="text/javascript">
179
184
  window.admin_path = "<%= request.script_name %>";
180
185
  window.index_path = "<%= settings.index_path %>";
@@ -76,11 +76,16 @@ module PopulateMe
76
76
  end
77
77
 
78
78
  def admin_get id
79
+ return self.admin_get_multiple(id) if id.is_a?(Array)
79
80
  self.cast do
80
- documents.find{|doc| doc[id_string_key]==id }
81
+ documents.find{|doc| doc[id_string_key] == id }
81
82
  end
82
83
  end
83
84
 
85
+ def admin_get_multiple ids, o={sort: nil}
86
+ self.admin_find(o.merge(query: {id_string_key => {'$in' => ids.uniq.compact}}))
87
+ end
88
+
84
89
  def admin_find o={}
85
90
  o[:query] ||= {}
86
91
  docs = self.cast{documents}.find_all do |d|
@@ -119,8 +124,10 @@ module PopulateMe
119
124
  end
120
125
  new_data = Rack::Utils.build_nested_query(data: o[:params][:filter])
121
126
  end
127
+ items = self.admin_find(query: query)
122
128
  {
123
129
  template: 'template_list',
130
+ grid_view: self.settings[:grid_view]==true,
124
131
  page_title: self.to_s_short_plural,
125
132
  dasherized_class_name: WebUtils.dasherize_class_name(self.name),
126
133
  new_data: new_data,
@@ -129,7 +136,7 @@ module PopulateMe
129
136
  sort_field: self.sort_field_for(o),
130
137
  # 'command_plus'=> !self.populate_config[:no_plus],
131
138
  # 'command_search'=> !self.populate_config[:no_search],
132
- items: self.admin_find(query: query).map do |d|
139
+ items: items.map do |d|
133
140
  d.to_admin_list_item(o)
134
141
  end
135
142
  }
@@ -160,13 +160,20 @@ module PopulateMe
160
160
 
161
161
  def to_select_options o={}
162
162
  proc do
163
- items = self.admin_find(query: (o[:query]||{}), fields: [self.id_string_key, self.label_field])
163
+ items = self.admin_find({
164
+ query: (o[:query]||{}),
165
+ fields: [self.id_string_key, self.label_field, self.admin_image_field].compact.uniq
166
+ })
164
167
  output = items.sort_by do |i|
165
168
  i.to_s.downcase
166
169
  end.map do |i|
167
- [i.to_s, i.id]
170
+ item = { description: i.to_s, value: i.id }
171
+ unless self.admin_image_field.nil?
172
+ item.merge! preview_uri: i.admin_image_url
173
+ end
174
+ item
168
175
  end
169
- output.unshift(['?','']) if o[:allow_empty]
176
+ output.unshift(description: '?', value: '') if o[:allow_empty]
170
177
  output
171
178
  end
172
179
  end
@@ -88,11 +88,19 @@ module PopulateMe
88
88
  end
89
89
 
90
90
  def admin_get theid
91
+ return self.admin_get_multiple(theid) if theid.is_a?(Array)
91
92
  theid = string_or_object_id theid
92
93
  self.cast{ collection.find({id_string_key => theid}).first }
93
94
  end
94
95
  alias_method :[], :admin_get
95
96
 
97
+ def admin_get_multiple theids, o={sort: nil}
98
+ theids = theids.uniq.compact.map{|theid| string_or_object_id(theid) }
99
+ self.admin_find(o.merge({
100
+ query: {id_string_key => {'$in' => theids} }
101
+ }))
102
+ end
103
+
96
104
  def admin_find o={}
97
105
  query = o.delete(:query) || {}
98
106
  o[:sort] ||= @current_sort
@@ -1,4 +1,4 @@
1
1
  module PopulateMe
2
- VERSION = '0.9.2'
2
+ VERSION = '0.13.0'
3
3
  end
4
4
 
@@ -29,6 +29,6 @@ Gem::Specification.new do |s|
29
29
  s.add_development_dependency 'rack-grid-serve', '~> 0.0.8'
30
30
  s.add_development_dependency 'aws-sdk-s3', '~> 1'
31
31
  s.add_development_dependency 'racksh', '~> 1.0'
32
- s.add_development_dependency 'rake', '~> 10.1'
32
+ s.add_development_dependency 'rake', '>= 12.3.3'
33
33
  end
34
34
 
@@ -124,6 +124,10 @@ describe PopulateMe::Admin do
124
124
 
125
125
  describe 'Handlers' do
126
126
 
127
+ let(:help_item) {
128
+ { 'title' => '?', 'href' => '/help', 'new_page' => false }
129
+ }
130
+
127
131
  describe '/menu' do
128
132
 
129
133
  describe 'when url is root' do
@@ -133,18 +137,22 @@ describe PopulateMe::Admin do
133
137
  assert_json last_response
134
138
  assert_for_view json, 'template_menu', 'Menu'
135
139
  expected_h = {
136
- 'title'=> 'Home Details', 'href'=> '/admin/form/home-details/0'
140
+ 'title' => 'Home Details',
141
+ 'href' => '/admin/form/home-details/0',
142
+ 'new_page' => false
137
143
  }
138
144
  assert_equal expected_h, json['items'][0]
139
145
  expected_h = {
140
- 'title'=> 'Project Page', 'href'=> '/menu/project-page'
146
+ 'title' => 'Project Page',
147
+ 'href' => '/menu/project-page',
148
+ 'new_page' => false
141
149
  }
142
150
  assert_equal expected_h, json['items'][1]
143
151
  end
144
152
  it 'Adds help link' do
145
153
  get '/menu'
146
154
  assert_equal 3, json['items'].size
147
- assert_equal({'title'=>'?', 'href'=>'/help'}, json['items'].last)
155
+ assert_equal(help_item, json['items'].last)
148
156
  end
149
157
  end
150
158
  describe 'when url is nested' do
@@ -155,13 +163,15 @@ describe PopulateMe::Admin do
155
163
  assert_for_view json, 'template_menu', 'Checks'
156
164
  assert_equal 2, json['items'].size
157
165
  expected_h = {
158
- 'title'=> 'Check 1', 'href'=> '/check/1'
166
+ 'title' => 'Check 1',
167
+ 'href' => '/check/1',
168
+ 'new_page' => false
159
169
  }
160
170
  assert_equal expected_h, json['items'][0]
161
171
  end
162
172
  it 'Does not add help link' do
163
173
  get '/menu/project-page/checks'
164
- refute_equal({'title'=>'?', 'href'=>'/help'}, json['items'].last)
174
+ refute_equal(help_item, json['items'].last)
165
175
  end
166
176
  end
167
177
 
@@ -11,6 +11,11 @@ class Outcasted < PopulateMe::Document
11
11
  {description: 'medium', value: 'm'},
12
12
  {description: 'large', value: 'l'}
13
13
  ]
14
+ field :availability, type: :select, select_options: [
15
+ {description: 'Available', value: 'yes', preview_uri: 'http://www.example.org/yes.jpg' },
16
+ {description: 'On offer', value: 'almost', preview_uri: 'http://www.example.org/almost.jpg' },
17
+ {description: 'Sold', value: 'no', preview_uri: 'http://www.example.org/no.jpg' }
18
+ ]
14
19
  field :tags, type: :select, select_options: ['art','sport','science'], multiple: true
15
20
  field :related_properties, type: :select, select_options: ['prop1','prop2','prop3'], multiple: true
16
21
  field :pdf, type: :attachment
@@ -98,6 +103,17 @@ describe PopulateMe::Document, 'Outcasting' do
98
103
  formated_options?(original, output)
99
104
  end
100
105
 
106
+ it 'Can have more fields when they are already formated' do
107
+ # Mainly for adding a preview_uri but also future tweaks
108
+ original = Outcasted.fields[:availability]
109
+ output = Outcasted.new.outcast(:availability, original, {input_name_prefix: 'data'})
110
+ assert(output[:select_options].all?{|o| o.key?(:preview_uri)})
111
+ last = output[:select_options].last
112
+ assert_equal 'Sold', last[:description]
113
+ assert_equal 'no', last[:value]
114
+ assert_equal 'http://www.example.org/no.jpg', last[:preview_uri]
115
+ end
116
+
101
117
  it 'Formats the options when it is a 2 strings array' do
102
118
  original = Outcasted.fields[:size].dup
103
119
  original[:select_options] = [
@@ -85,12 +85,22 @@ describe PopulateMe::Document, 'Schema' do
85
85
  label :slug
86
86
  end
87
87
 
88
+ class Selectpreviewable < PopulateMe::Document
89
+ set :default_attachment_class, PopulateMe::Attachment
90
+ field :name
91
+ field :img, type: :attachment, variations: [
92
+ PopulateMe::Variation.default
93
+ ]
94
+ end
95
+
88
96
  before do
89
97
  Selectoptionable.documents = []
90
98
  Selectoptionable.new(id: '1', name: 'Joe', slug: 'joe').save
91
99
  Selectoptionable.new(id: '2', name: 'William', slug: 'william').save
92
100
  Selectoptionable.new(id: '3', name: 'Jack', slug: 'jack').save
93
101
  Selectoptionable.new(id: '4', name: 'Averell', slug: 'averell').save
102
+ Selectpreviewable.documents = []
103
+ Selectpreviewable.new(id: '1', name: 'Project', img: 'project.jpg').save
94
104
  end
95
105
 
96
106
  after do
@@ -102,19 +112,27 @@ describe PopulateMe::Document, 'Schema' do
102
112
  assert output_proc.is_a?(Proc)
103
113
  output = output_proc.call
104
114
  assert_equal 4, output.size
105
- assert output.all?{|o| o.is_a?(Array) and o.size==2}
106
- assert_equal '1', output.find{|o|o[0]=='joe'}[1]
115
+ assert output.all?{|o| o.is_a?(Hash) and o.size==2}
116
+ assert_equal '1', output.find{|o|o.fetch(:description)=='joe'}.fetch(:value)
107
117
  end
108
118
 
109
119
  it 'Puts items in alphabetical order of their label' do
110
120
  output= Selectoptionable.to_select_options.call
111
- assert_equal ['averell', '4'], output[0]
121
+ assert_equal({description: 'averell', value: '4'}, output[0])
112
122
  end
113
123
 
114
124
  it 'Has an option for prepending empty choice' do
115
125
  output= Selectoptionable.to_select_options(allow_empty: true).call
116
- assert_equal ['?', ''], output[0]
117
- assert_equal ['averell', '4'], output[1]
126
+ assert_equal({description: '?', value: ''}, output[0])
127
+ assert_equal({description: 'averell', value: '4'}, output[1])
128
+ end
129
+
130
+ it 'Adds a :preview_uri when there is a thumbnail' do
131
+ output= Selectpreviewable.to_select_options.call
132
+ assert output[0].key?(:preview_uri)
133
+ assert_equal 'Project', output[0][:description]
134
+ assert_equal '1', output[0][:value]
135
+ assert_equal '/attachment/selectpreviewable/project.populate_me_thumb.jpg', output[0][:preview_uri]
118
136
  end
119
137
 
120
138
  end
@@ -126,6 +126,19 @@ describe 'PopulateMe::Mongo' do
126
126
  assert_equal "regular", LowFish.admin_get(regular_fish_id).name
127
127
  end
128
128
 
129
+ it "Should get multiple items" do
130
+ # Order is not respected
131
+ alpha_id = LowFish.new(name: "alpha").perform_create
132
+ beta_id = LowFish.new(name: "beta").perform_create
133
+ gamma_id = LowFish.new(name: "gamma").perform_create
134
+ items = LowFish.admin_get([alpha_id, beta_id, nil, alpha_id])
135
+ assert items.is_a?(Array)
136
+ assert_equal 2, items.count
137
+ refute_nil items.find{|i| i.id == alpha_id}
138
+ refute_nil items.find{|i| i.id == beta_id}
139
+ assert_nil items.find{|i| i.id == gamma_id}
140
+ end
141
+
129
142
  it 'Should have the [] shortcut for admin_get' do
130
143
  LowFish.collection.insert_one(_id: 42, name: "H2G2")
131
144
  assert_equal LowFish[42], LowFish.admin_get(42)
@@ -138,7 +151,7 @@ describe 'PopulateMe::Mongo' do
138
151
  LowFish.collection.insert_one(_id: 40, name: "Bran")
139
152
  items = LowFish.admin_find
140
153
  assert items.is_a?(Array)
141
- assert 4, items.count
154
+ assert_equal 4, items.count
142
155
  assert_equal 10, items[0].id
143
156
  items = LowFish.admin_find query: {name: 'Bran'}
144
157
  assert items.is_a?(Array)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: populate-me
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mickael Riga
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-01 00:00:00.000000000 Z
11
+ date: 2020-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: web-utils
@@ -168,16 +168,16 @@ dependencies:
168
168
  name: rake
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - "~>"
171
+ - - ">="
172
172
  - !ruby/object:Gem::Version
173
- version: '10.1'
173
+ version: 12.3.3
174
174
  type: :development
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
- - - "~>"
178
+ - - ">="
179
179
  - !ruby/object:Gem::Version
180
- version: '10.1'
180
+ version: 12.3.3
181
181
  description: PopulateMe is an admin system for managing structured content of web
182
182
  applications. It is built on top of the Sinatra framework, but can be used along
183
183
  any framework using Rack.
@@ -216,6 +216,7 @@ files:
216
216
  - lib/populate_me/admin/__assets__/js/jquery-ui.min.js
217
217
  - lib/populate_me/admin/__assets__/js/main.js
218
218
  - lib/populate_me/admin/__assets__/js/mustache.js
219
+ - lib/populate_me/admin/__assets__/js/quicksearch.js
219
220
  - lib/populate_me/admin/__assets__/js/sortable.js
220
221
  - lib/populate_me/admin/views/help.erb
221
222
  - lib/populate_me/admin/views/page.erb
@@ -256,7 +257,7 @@ homepage: https://github.com/mig-hub/populate-me
256
257
  licenses:
257
258
  - MIT
258
259
  metadata: {}
259
- post_install_message:
260
+ post_install_message:
260
261
  rdoc_options: []
261
262
  require_paths:
262
263
  - lib
@@ -272,7 +273,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
272
273
  version: '0'
273
274
  requirements: []
274
275
  rubygems_version: 3.0.3
275
- signing_key:
276
+ signing_key:
276
277
  specification_version: 4
277
278
  summary: PopulateMe is an admin system for web applications.
278
279
  test_files: