├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── active_admin_filters_visibility.gemspec ├── app └── assets │ └── javascripts │ └── active_admin_filters_visibility.js ├── lib ├── active_admin_filters_visibility.rb └── active_admin_filters_visibility │ └── version.rb ├── package.json └── screen ├── example_aa_filters_ordering.gif └── example_aa_filters_visibility.gif /Gemfile: -------------------------------------------------------------------------------- 1 | source 'http://rubygems.org' 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Gena M. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Gem Version](https://badge.fury.io/rb/active_admin_filters_visibility.svg)](https://badge.fury.io/rb/active_admin_filters_visibility) 2 | [![NPM Version](https://badge.fury.io/js/@activeadmin-plugins%2Factive_admin_filters_visibility.svg)](https://badge.fury.io/js/@activeadmin-plugins%2Factive_admin_filters_visibility) 3 | ![npm](https://img.shields.io/npm/dm/@activeadmin-plugins/active_admin_filters_visibility) 4 | 5 | # ActiveAdminFiltersVisibility 6 | 7 | ActiveAdmin plugin allows to hide any filter from Filters Sidebar. 8 | Useful when page has many filters, but admin user needs only some of them. 9 | Every filter saves its state using browser's LocalStorage. 10 | 11 | ![Demonstration](https://raw.githubusercontent.com/activeadmin-plugins/active_admin_filters_visibility/master/screen/example_aa_filters_visibility.gif "Visibility example") 12 | 13 | Also you can use drag&drop to change filters order 14 | 15 | ![Demonstration](https://raw.githubusercontent.com/activeadmin-plugins/active_admin_filters_visibility/master/screen/example_aa_filters_ordering.gif "Ordering example") 16 | 17 | ## Install 18 | 19 | In Gemfile add 20 | 21 | ```ruby 22 | gem 'active_admin_filters_visibility', git: 'https://github.com/activeadmin-plugins/active_admin_filters_visibility' 23 | ``` 24 | 25 | ##### Using assets via Sprockets 26 | in the 27 | ``` 28 | app/assets/javascript/active_admin.coffee 29 | ``` 30 | 31 | and 32 | 33 | ```coffeescript 34 | #= require active_admin_filters_visibility 35 | ``` 36 | 37 | ##### Using assets via Webpacker (or any other assets bundler) as a NPM module (Yarn package) 38 | 39 | Execute: 40 | 41 | $ npm i @activeadmin-plugins/active_admin_filters_visibility 42 | 43 | Or 44 | 45 | $ yarn add @activeadmin-plugins/active_admin_filters_visibility 46 | 47 | Or add manually to `package.json`: 48 | 49 | ```json 50 | "dependencies": { 51 | "@activeadmin-plugins/active_admin_filters_visibility": "1.2.0" 52 | } 53 | ``` 54 | and execute: 55 | 56 | $ yarn 57 | 58 | Add the following line into `app/assets/javascripts/active_admin.js`: 59 | 60 | ```javascript 61 | import '@activeadmin-plugins/active_admin_filters_visibility'; 62 | ``` 63 | 64 | ##### Initialization: 65 | 66 | ```javascript 67 | $(document).ready(function() { 68 | $('#filters_sidebar_section').activeAdminFiltersVisibility(); 69 | }); 70 | ``` 71 | 72 | ## Customization 73 | 74 | ```coffeescript 75 | $('.jquery-selector').activeAdminFiltersVisibility(options) 76 | ``` 77 | 78 | ActiveAdminFiltersVisibility is a standard jQuery Plugin, and accepts some "options" as a hash. 79 | Default is: 80 | 81 | ```javascript 82 | { 83 | sidebarUniqId: function() { 84 | return window.location.pathname; 85 | }, 86 | icon: '☶', 87 | iconClass: '', 88 | iconStyle: '', 89 | skipDefaultCss: false, 90 | title: 'Visibility:', 91 | ordering: false, 92 | orderHint: 'Drag&Drop to reorder filters', 93 | resetButtonTitle: 'Reset' 94 | } 95 | ``` 96 | 97 | You can change icon - this is a HTML text or symbol. You can pass empty string and customize it with your CSS. 98 | Or you can set class("iconClass") for icon or inline styles("iconStyle"). 99 | 100 | This plugin has minimal CSS styling. 101 | In case you want to use custom CSS, default styling can be ignored: 102 | set ```skipDefaultCss``` to ```true``` 103 | 104 | 105 | ### Ordering 106 | 107 | By default ordering is disabled. You can turn it: set option ```ordering``` to ```true```. 108 | 109 | 110 | ### Texts 111 | Change text in options: ```title```, ```orderHint``` and ```resetButtonTitle``` 112 | 113 | 114 | ### Dont hide filters which has selected value 115 | 116 | If filter has selected value - that filter will not be hidden on page reload. Even if "visibility checkbox" is unchecked. 117 | This was made for preventing unpredictable filtering: for example when user came to page by some link with predefined filtering params. 118 | All default filters types(string, numeric, date range, etc.) are implemented. 119 | But if you have some specific filter, you need to add custom handler. 120 | 121 | For example you have customized filter by ID. 122 | And you want to consider "1" as default value and allow hiding it. 123 | In this case you should add uniq class to wrapper. 124 | 125 | ```ruby 126 | filter :id, wrapper_html: { class: 'filter_customized_id' } 127 | ``` 128 | 129 | ```javascript 130 | // return TRUE if this filter has value 131 | // elWrapper is jQuery element "div.filter_form_field.filter_customized_id" 132 | // if not "1" then consider this filter as active, and return TRUE to prevent hiding 133 | $.fn.activeAdminFiltersVisibility.registerFilterType('customized_id', function(elWrapper) { 134 | var inputValue = elWrapper.find('input').val(); 135 | return inputValue != '1'; 136 | }); 137 | ``` 138 | 139 | 140 | ### Saving state 141 | 142 | Plugin saves list of hidden filters in LocalStorage, using jQuery plugin "Lockr" https://github.com/tsironis/lockr 143 | If you need to save this in cookies or user profile, you should write your own implementation - rewrite "$.fn.activeAdminFiltersVisibility.storage". 144 | For example: 145 | 146 | ```javascript 147 | $.fn.activeAdminFiltersVisibility.storage = function(storageUniqId) { 148 | // initialize storage with "storageUniqId" 149 | // every page(sidebar filters) must has its uniq storageUniqId 150 | var myStorage = new MyCustomizedStorage(storageUniqId); 151 | 152 | return { 153 | add: function(labelText) { 154 | // add hidden filter "labelText" to storage myStorage 155 | myStorage.add(labelText); 156 | }, 157 | remove: function(labelText) { 158 | // drop hidden filter "labelText" to storage myStorage 159 | // makes filter visible again 160 | myStorage.remove(labelText); 161 | }, 162 | has: function(labelText) { 163 | // check if labelText already hidden(in storage) 164 | // should return true if exists 165 | return myStorage.find(labelText) ? true : false; 166 | }, 167 | all: function() { 168 | // return array of hidden labels(filters) 169 | return myStorage.getAll(); // ['Id', 'Name', 'Created At'] 170 | }, 171 | any: function() { 172 | // check if current Sidebar Filter has some hidden elements 173 | return this.all().length > 0; 174 | } 175 | } 176 | }; 177 | ``` 178 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | -------------------------------------------------------------------------------- /active_admin_filters_visibility.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path('../lib', __FILE__) 3 | require 'active_admin_filters_visibility/version' 4 | 5 | Gem::Specification.new do |s| 6 | s.name = 'active_admin_filters_visibility' 7 | s.version = ActiveAdminFiltersVisibility::VERSION 8 | s.authors = ['Gena M.'] 9 | s.email = ['workgena@gmail.com'] 10 | s.homepage = 'https://github.com/workgena/active_admin_filters_visibility' 11 | s.summary = %q{active_admin_filters_visibility gem} 12 | s.description = %q{extension for activeadmin gem to hide any filters from sidebar-filters panel} 13 | 14 | s.add_dependency 'activeadmin' 15 | 16 | s.files = `git ls-files`.split("\n") 17 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 18 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 19 | s.require_paths = ['lib'] 20 | end 21 | -------------------------------------------------------------------------------- /app/assets/javascripts/active_admin_filters_visibility.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | 3 | // Plugin definition 4 | $.fn.activeAdminFiltersVisibility = function(options) { 5 | var settings = $.extend({}, $.fn.activeAdminFiltersVisibility.defaults, options || {}); 6 | 7 | var storageKey = settings.sidebarUniqId(), 8 | storage = $.fn.activeAdminFiltersVisibility.storage(storageKey), 9 | panel = $(this); 10 | 11 | if (panel.length > 1) { 12 | console.log('Cant be applied to multiple sidebars'); 13 | return panel; 14 | } 15 | 16 | 17 | function diffArray(arr1, arr2) { 18 | return arr1.concat(arr2).filter(function (val) { 19 | if (!(arr1.includes(val) && arr2.includes(val))) 20 | return val; 21 | }); 22 | } 23 | 24 | 25 | 26 | function findFilterWrapperByLabelText(labelText) { 27 | return panel.find(".filter_form_field label").filter(function() { 28 | var nodeText = $(this)[0].childNodes[0].textContent; 29 | return nodeText === labelText; 30 | }).closest('.filter_form_field'); 31 | } 32 | 33 | function buildCheckboxesHtml() { 34 | var html = ''; 35 | 36 | var labels = panel.find('.filter_form_field label:first-child').map(function() { 37 | var text = $(this)[0].childNodes[0].textContent.trim() 38 | $(this).closest('.filter_form_field').attr('data-pseudo-id', encodeURIComponent(text)); 39 | return text; 40 | }).get(); 41 | 42 | var orderedLabels = storage.getOrder(); 43 | 44 | //diffArray 45 | if (orderedLabels.length > 0) { 46 | if (diffArray(labels, orderedLabels).length) { 47 | storage.reset(); 48 | } else { 49 | labels = orderedLabels; 50 | } 51 | } 52 | 53 | $.each(labels, function(i, text) { 54 | var checked = storage.has(text) ? '' : 'checked="checked"'; 55 | html += '
'; 56 | }); 57 | 58 | return html; 59 | } 60 | 61 | function renderNotice() { 62 | var btn = panel.find('.filters-visibility-button'); 63 | if (storage.any()) { 64 | btn.addClass('active'); 65 | } else { 66 | btn.removeClass('active'); 67 | } 68 | } 69 | 70 | function render() { 71 | // Button 72 | panel.find('h3:first') 73 | .append('' + settings.icon + ''); 74 | 75 | // Settings Panel 76 | panel.find('.panel_contents').prepend( 77 | '
' + 78 | '
' + settings.title + '
' + 79 | buildCheckboxesHtml() + 80 | '
' 81 | ); 82 | 83 | // Hide filters 84 | $.each(storage.all(), function(i, labelText) { 85 | var elWrapper = findFilterWrapperByLabelText(labelText); 86 | if ( false == isFilterFilled(elWrapper) ) { 87 | elWrapper.hide(); 88 | } 89 | }); 90 | 91 | // Mark button if some filters are hidden 92 | renderNotice(); 93 | } 94 | 95 | 96 | 97 | function hide(labelText) { 98 | findFilterWrapperByLabelText(labelText).hide(); 99 | storage.add(labelText); 100 | renderNotice(); 101 | } 102 | 103 | function show(labelText) { 104 | findFilterWrapperByLabelText(labelText).show(); 105 | storage.remove(labelText); 106 | renderNotice(); 107 | } 108 | 109 | // prevent hiding filter if it is no empty (triggers only on page render) 110 | function isFilterFilled(elWrapper) { 111 | if (elWrapper.length == 0) { 112 | return false; 113 | } 114 | var klasses = elWrapper.attr('class').split(' '); 115 | 116 | var filterTypeName = $.grep(klasses, function(v) { 117 | return v != 'filter_form_field' && /^filter_/.test(v) 118 | })[0].replace(/^filter_/, ""); 119 | 120 | function _detectIsFilled(filterTypeName, elWrapper) { 121 | var functionOrString = $.fn.activeAdminFiltersVisibility.filtersTypesDefinitions[filterTypeName]; 122 | 123 | if (typeof functionOrString == 'string' && functionOrString != filterTypeName) { 124 | return $.fn.activeAdminFiltersVisibility.filtersTypesDefinitions[functionOrString].call(this, elWrapper); 125 | } else if (typeof functionOrString == 'function') { 126 | return functionOrString.call(this, elWrapper); 127 | } else { 128 | return $.fn.activeAdminFiltersVisibility.filtersTypesDefinitions['default'].call(this, elWrapper); 129 | } 130 | } 131 | 132 | return _detectIsFilled(filterTypeName, elWrapper); 133 | } 134 | 135 | 136 | // apply styles 137 | if (settings.skipDefaultCss == false) { 138 | $.fn.activeAdminFiltersVisibility.css(); 139 | } 140 | 141 | 142 | panel.on('click', '.filters-visibility-button', function() { 143 | panel.find('.filters-visibility-panel').toggle(); 144 | }); 145 | 146 | panel.on('change', '.filters-visibility-panel input[type=checkbox]', function() { 147 | var $this = $(this), 148 | labelText = $this.parent().text().trim(); 149 | 150 | if ($this.prop('checked')) { 151 | show(labelText); 152 | } else { 153 | hide(labelText); 154 | } 155 | }); 156 | 157 | render(); 158 | 159 | if (settings.ordering) { 160 | $.fn.activeAdminFiltersVisibility.applyOrder(panel, storage); 161 | var resetButtonHtml = '' + settings.resetButtonTitle + ''; 162 | panel.find('.filters-visibility-panel div:first') 163 | .append(resetButtonHtml) 164 | .after('
' + settings.orderHint + '
'); 165 | 166 | panel.on('click', '.filters-visibility-reset-btn', function(e) { 167 | e.preventDefault(); 168 | storage.reset(); 169 | window.location.reload(); 170 | }); 171 | } 172 | 173 | return panel; 174 | }; 175 | 176 | // Ordering 177 | $.fn.activeAdminFiltersVisibility.applyOrder = function(panel, storage) { 178 | 179 | // re-render sidebar filters(even if they are not visible, show/hide event is independent and knows nothing about order) 180 | function renderReorderedFilters() { 181 | var wrapper = panel.find('form'); 182 | var order = storage.getOrder(); 183 | 184 | var existingOrder = panel.find('.filter_form_field label:first-child').map(function() { 185 | return $(this)[0].childNodes[0].textContent.trim(); 186 | }).get(); 187 | 188 | if (order.length > 0 && JSON.stringify(order) != JSON.stringify(existingOrder)) { 189 | var pos = 0; 190 | $.each(order, function(i, text) { 191 | var textEncoded = encodeURIComponent(text); 192 | var el = wrapper.find('div[data-pseudo-id="' + textEncoded + '"]'); 193 | if (el.length > 0) { 194 | var elOnThisPosition = wrapper.find('.filter_form_field').eq(pos); 195 | if (elOnThisPosition.data('pseudo-id') != textEncoded) { 196 | wrapper[0].insertBefore(el[0], elOnThisPosition[0]); 197 | } 198 | pos++; 199 | } 200 | }); 201 | } 202 | } 203 | 204 | 205 | var isOrdered = storage.getOrder().length > 0; 206 | 207 | // define draggable elements 208 | 209 | panel.find('.filters-visibility-panel label').attr('draggable', 'true'); 210 | 211 | // Attach events 212 | panel.on('drop', '.filters-visibility-panel label', function(e) { 213 | e.preventDefault(); 214 | var drag_el_id = e.originalEvent.dataTransfer.getData("text"), 215 | drag_el = panel.find('label[data-pseudo-id="' + drag_el_id + '"]'), 216 | drop_el = $(this), 217 | wrapper = panel.find('.filters-visibility-panel'); 218 | 219 | if (drag_el != drop_el) { 220 | wrapper[0].insertBefore(drag_el.parent()[0], drop_el.parent()[0]); 221 | 222 | var orderedList = wrapper.find('label').map(function() { 223 | return $(this).text().trim(); 224 | }).get(); 225 | 226 | storage.setOrder(orderedList); 227 | 228 | renderReorderedFilters(); 229 | } 230 | }); 231 | 232 | panel.on('dragover', '.filters-visibility-panel', function(e) { 233 | e.preventDefault(); 234 | }); 235 | 236 | panel.find('.filters-visibility-panel label').on('dragstart', function(e) { 237 | var key = $(this).data('pseudo-id'); 238 | e.originalEvent.dataTransfer.setData("text", key); 239 | }); 240 | 241 | 242 | // Apply Order 243 | if (isOrdered) { 244 | // Apply reorder !!! 245 | renderReorderedFilters(); 246 | } 247 | 248 | return panel; 249 | }; 250 | 251 | 252 | 253 | // Plugin Storage method 254 | $.fn.activeAdminFiltersVisibility.storage = function(storageUniqId) { 255 | // https://github.com/tsironis/lockr 256 | var Lockr = function(){ 257 | if (!Array.prototype.indexOf) { 258 | Array.prototype.indexOf = function(elt) 259 | { 260 | var len = this.length >>> 0; 261 | 262 | var from = Number(arguments[1]) || 0; 263 | from = (from < 0) 264 | ? Math.ceil(from) 265 | : Math.floor(from); 266 | if (from < 0) 267 | from += len; 268 | 269 | for (; from < len; from++) 270 | { 271 | if (from in this && 272 | this[from] === elt) 273 | return from; 274 | } 275 | return -1; 276 | }; 277 | } 278 | 279 | var Lockr = {}; 280 | 281 | Lockr.prefix = ""; 282 | 283 | Lockr._getPrefixedKey = function(key, options) { 284 | options = options || {}; 285 | 286 | if (options.noPrefix) { 287 | return key; 288 | } else { 289 | return this.prefix + key; 290 | } 291 | 292 | }; 293 | 294 | Lockr.set = function (key, value, options) { 295 | var query_key = this._getPrefixedKey(key, options); 296 | 297 | try { 298 | localStorage.setItem(query_key, JSON.stringify({"data": value})); 299 | } catch (e) { 300 | if (console) console.warn("Lockr didn't successfully save the '{"+ key +": "+ value +"}' pair, because the localStorage is full."); 301 | } 302 | }; 303 | 304 | Lockr.get = function (key, missing, options) { 305 | var query_key = this._getPrefixedKey(key, options), 306 | value; 307 | 308 | try { 309 | value = JSON.parse(localStorage.getItem(query_key)); 310 | } catch (e) { 311 | if(localStorage[query_key]) { 312 | value = {data: localStorage.getItem(query_key)}; 313 | } else{ 314 | value = null; 315 | } 316 | } 317 | if(value === null) { 318 | return missing; 319 | } else if (typeof value === 'object' && typeof value.data !== 'undefined') { 320 | return value.data; 321 | } else { 322 | return missing; 323 | } 324 | }; 325 | 326 | Lockr.sadd = function(key, value, options) { 327 | var query_key = this._getPrefixedKey(key, options), 328 | json; 329 | 330 | var values = Lockr.smembers(key); 331 | 332 | if (values.indexOf(value) > -1) { 333 | return null; 334 | } 335 | 336 | try { 337 | values.push(value); 338 | json = JSON.stringify({"data": values}); 339 | localStorage.setItem(query_key, json); 340 | } catch (e) { 341 | console.log(e); 342 | if (console) console.warn("Lockr didn't successfully add the "+ value +" to "+ key +" set, because the localStorage is full."); 343 | } 344 | }; 345 | 346 | Lockr.smembers = function(key, options) { 347 | var query_key = this._getPrefixedKey(key, options), 348 | value; 349 | 350 | try { 351 | value = JSON.parse(localStorage.getItem(query_key)); 352 | } catch (e) { 353 | value = null; 354 | } 355 | 356 | if (value === null) 357 | return []; 358 | else 359 | return (value.data || []); 360 | }; 361 | 362 | Lockr.sismember = function(key, value, options) { 363 | return Lockr.smembers(key).indexOf(value) > -1; 364 | }; 365 | 366 | Lockr.keys = function() { 367 | var keys = []; 368 | var allKeys = Object.keys(localStorage); 369 | 370 | if (Lockr.prefix.length === 0) { 371 | return allKeys; 372 | } 373 | 374 | allKeys.forEach(function (key) { 375 | if (key.indexOf(Lockr.prefix) !== -1) { 376 | keys.push(key.replace(Lockr.prefix, '')); 377 | } 378 | }); 379 | 380 | return keys; 381 | }; 382 | 383 | Lockr.getAll = function () { 384 | var keys = Lockr.keys(); 385 | return keys.map(function (key) { 386 | return Lockr.get(key); 387 | }); 388 | }; 389 | 390 | Lockr.srem = function(key, value, options) { 391 | var query_key = this._getPrefixedKey(key, options), 392 | json, 393 | index; 394 | 395 | var values = Lockr.smembers(key, value); 396 | 397 | index = values.indexOf(value); 398 | 399 | if (index > -1) 400 | values.splice(index, 1); 401 | 402 | json = JSON.stringify({"data": values}); 403 | 404 | try { 405 | localStorage.setItem(query_key, json); 406 | } catch (e) { 407 | if (console) console.warn("Lockr couldn't remove the "+ value +" from the set "+ key); 408 | } 409 | }; 410 | 411 | Lockr.rm = function (key) { 412 | localStorage.removeItem(key); 413 | }; 414 | 415 | Lockr.flush = function () { 416 | if (Lockr.prefix.length) { 417 | Lockr.keys().forEach(function(key) { 418 | localStorage.removeItem(Lockr._getPrefixedKey(key)); 419 | }); 420 | } else { 421 | localStorage.clear(); 422 | } 423 | }; 424 | return Lockr; 425 | 426 | }(); 427 | 428 | var storageIdForOrder = '__ordered__' + storageUniqId; 429 | 430 | return { 431 | setOrder: function(orderedList) { 432 | Lockr.set(storageIdForOrder, orderedList); 433 | }, 434 | getOrder: function() { 435 | return Lockr.get(storageIdForOrder) || []; 436 | }, 437 | reset: function() { 438 | Lockr.rm(storageIdForOrder); 439 | Lockr.rm(storageUniqId); 440 | }, 441 | add: function(key) { 442 | Lockr.sadd(storageUniqId, key); 443 | }, 444 | remove: function(key) { 445 | Lockr.srem(storageUniqId, key); 446 | }, 447 | has: function(key) { 448 | return Lockr.sismember(storageUniqId, key); 449 | }, 450 | all: function() { 451 | return Lockr.smembers(storageUniqId); 452 | }, 453 | any: function() { 454 | return this.all().length > 0; 455 | } 456 | } 457 | }; 458 | 459 | 460 | // Style 461 | $.fn.activeAdminFiltersVisibility.css = function() { 462 | var lines = []; 463 | 464 | lines.push('.filters-visibility-button { margin: 0 5px 0 5px; padding: 0 4px 0 4px; background-color: rgba(0, 0, 0, 0.05); float: right; cursor: pointer; }'); 465 | lines.push('.filters-visibility-button.active { color: #007ab8; }'); 466 | lines.push('.filters-visibility-panel { display: none; border-left: 10px solid rgba(0, 0, 0, 0.1); background-color: rgba(0, 0, 0, 0.02); margin-bottom: 10px; }'); 467 | lines.push('.filters-visibility-panel > div { margin-left: 5px; }'); 468 | lines.push('.filters-visibility-panel > div:first-child { display: flex; }'); 469 | lines.push('.filters-visibility-panel .filters-visibility-reset-btn { display: inline-block; margin-left: auto; }'); 470 | 471 | var sheet = document.createElement('style'); 472 | sheet.type = 'text/css'; 473 | sheet.innerHTML = lines.join(' '); 474 | document.body.appendChild(sheet); 475 | }; 476 | 477 | 478 | // Prevent filter from being hidden this filter is was used for filtering data 479 | $.fn.activeAdminFiltersVisibility.filtersTypesDefinitions = { 480 | 'default': function (elWrapper) { 481 | var notEmptyInput = elWrapper.find('input[id!=""][type!="hidden"][value][value!=""]'); 482 | return notEmptyInput.length > 0; 483 | } 484 | }; 485 | 486 | $.fn.activeAdminFiltersVisibility.registerFilterType = function(name, filterTypeDefinitionFunc) { 487 | $.fn.activeAdminFiltersVisibility.filtersTypesDefinitions[name] = filterTypeDefinitionFunc; 488 | }; 489 | 490 | $.fn.activeAdminFiltersVisibility.registerFilterType('check_boxes', function(elWrapper) { 491 | return elWrapper.find('input[id!=""][type!="hidden"][value][value!=""]:checked').length > 0; 492 | }); 493 | 494 | $.fn.activeAdminFiltersVisibility.registerFilterType('select', function(elWrapper) { 495 | return elWrapper.find('select[id]:first').val().length > 0; 496 | }); 497 | 498 | $.fn.activeAdminFiltersVisibility.registerFilterType('boolean', 'select'); 499 | 500 | 501 | 502 | // Plugin defaults 503 | $.fn.activeAdminFiltersVisibility.defaults = { 504 | sidebarUniqId: function() { 505 | return window.location.pathname; 506 | }, 507 | icon: '☶', 508 | iconClass: '', 509 | iconStyle: '', 510 | skipDefaultCss: false, 511 | ordering: false, 512 | title: 'Visibility:', 513 | orderHint: 'Drag&Drop to reorder filters', 514 | resetButtonTitle: 'Reset' 515 | }; 516 | 517 | })(jQuery); 518 | -------------------------------------------------------------------------------- /lib/active_admin_filters_visibility.rb: -------------------------------------------------------------------------------- 1 | require 'activeadmin' 2 | require 'active_admin_filters_visibility/version' 3 | 4 | module ActiveAdminFiltersVisibility 5 | module Rails 6 | class Engine < ::Rails::Engine 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/active_admin_filters_visibility/version.rb: -------------------------------------------------------------------------------- 1 | module ActiveAdminFiltersVisibility 2 | VERSION = '1.2.0' 3 | end 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@activeadmin-plugins/active_admin_filters_visibility", 3 | "version": "1.2.0", 4 | "description": "Extension for activeadmin gem to hide any filters from sidebar-filters panel", 5 | "main": "src/active_admin_filters_visibility.js", 6 | "repository": "git@github.com:activeadmin-plugins/active_admin_filters_visibility.git", 7 | "author": "Gena M. ", 8 | "license": "MIT", 9 | "private": false, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/activeadmin-plugins/active_admin_filters_visibility.git" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/activeadmin-plugins/active_admin_filters_visibility/issues" 16 | }, 17 | "homepage": "https://github.com/activeadmin-plugins/active_admin_filters_visibility#readme", 18 | "keywords": [ 19 | "active", 20 | "admin", 21 | "filters", 22 | "visibility" 23 | ], 24 | "files": [ 25 | "src/**/*" 26 | ], 27 | "scripts": { 28 | "prepublishOnly": "rm -rf src && cp -R app/assets/javascripts/ src" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /screen/example_aa_filters_ordering.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/activeadmin-plugins/active_admin_filters_visibility/7f3a827a1870996320040274dff10c3a13d7c4f9/screen/example_aa_filters_ordering.gif -------------------------------------------------------------------------------- /screen/example_aa_filters_visibility.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/activeadmin-plugins/active_admin_filters_visibility/7f3a827a1870996320040274dff10c3a13d7c4f9/screen/example_aa_filters_visibility.gif --------------------------------------------------------------------------------