diff --git a/src/app/index.less b/src/app/index.less index 2f5294717c3..21a96482509 100644 --- a/src/app/index.less +++ b/src/app/index.less @@ -3,7 +3,6 @@ // Components @import "tour/index.less"; -@import "sidebar/index.less"; @import "network-optin/index.less"; @import "../auto-update/index.less"; diff --git a/src/app/sidebar/filter.jade b/src/app/sidebar/filter.jade deleted file mode 100644 index 4e34f4d1be1..00000000000 --- a/src/app/sidebar/filter.jade +++ /dev/null @@ -1,3 +0,0 @@ -.list-filter(data-hook='filter') - i.search.fa-search - input(type='search', data-hook='search') diff --git a/src/app/sidebar/filter.js b/src/app/sidebar/filter.js deleted file mode 100644 index 2a053038689..00000000000 --- a/src/app/sidebar/filter.js +++ /dev/null @@ -1,44 +0,0 @@ -var View = require('ampersand-view'); -var debug = require('debug')('mongodb-compass:sidebar:filter'); - -var filterTemplate = require('./filter.jade'); - -var CollectionFilterView = View.extend({ - template: filterTemplate, - props: { - search: 'string', - placeholder: { - type: 'string', - default: 'filter', - required: false - } - }, - initialize: function() { - this.listenTo(this, 'change:search', this.applyFilter); - }, - events: { - 'input [data-hook=search]': 'handleInputChanged' - }, - bindings: { - placeholder: { - type: 'attribute', - name: 'placeholder', - hook: 'search' - } - }, - render: function() { - this.renderWithTemplate(this); - this.cacheElements({ - input: '[data-hook=search]' - }); - this.input.addEventListener('input', this.handleInputChanged.bind(this), false); - }, - handleInputChanged: function() { - this.search = this.input.value.trim(); - }, - applyFilter: function() { - debug('applying filter for `%s`', this.search); - this.parent.filterItems(this.search); - } -}); -module.exports = CollectionFilterView; diff --git a/src/app/sidebar/index.jade b/src/app/sidebar/index.jade deleted file mode 100644 index d997eb285a4..00000000000 --- a/src/app/sidebar/index.jade +++ /dev/null @@ -1,6 +0,0 @@ -div - .sidebar.panel - div.widget-container(data-hook='widget-container') - div(data-hook='filter-subview') - .panel-title(data-hook='title') - div(data-hook='list-subview') diff --git a/src/app/sidebar/index.js b/src/app/sidebar/index.js deleted file mode 100644 index 4b161bccda3..00000000000 --- a/src/app/sidebar/index.js +++ /dev/null @@ -1,204 +0,0 @@ -var app = require('hadron-app'); -var View = require('ampersand-view'); -var ListView = require('./list'); -var FilterView = require('./filter'); -var _ = require('lodash'); - -var indexTemplate = require('./index.jade'); - -// var debug = require('debug')('mongodb-compass:sidebar:index'); - -/** - * Generic Sidebar class that is used in Compass. It provides optional - * filtering, widgets that can be rendered at the top of the sidebar, - * nesting (potentially multiple levels, but only one level tested so far). - * - * Collections used for the sidebar need to have the selectableMixin and - * filterableMixin (if filtering is enabled), @see ../models/ - */ -var SidebarView = View.extend({ - props: { - /** - * if provided, show a panel title between the filter and the item list. - * @type {String} - */ - title: { - type: 'string', - default: null, - required: false - }, - /** - * use this property of the model to display as string in sidebar - * @type {String} - */ - displayProp: { - type: 'any', - default: 'getId', - required: true - }, - /** - * a string corresponding to a fontawesome icon, e.g. `fa-database`. If - * provided, the string will be prepended with this icon - * @type {String} - */ - icon: { - type: 'any', - default: undefined, - required: false - }, - /** - * Provide a custom view class for the list-items. If provided, displayProp - * and icon will be ignored and will have to be set manually in the - * view class. - * @type {Object} - */ - itemViewClass: { - type: 'any', - default: undefined, - required: false - }, - /** - * Enables nested menus. Provide and object with the following keys: - * { - * collectionName {String} the nested items are in a collection with - * the given name. Default is `collection`. - * displayProp {String|Fn} displayProp for nested list items. Default - * is `name`. - * icon {String|Fn} icon for the nested list items. Default - * is '' (no icon). - * } - * Set to null to disable nesting. - * @type {Object || null} - */ - nested: { - type: 'object', - default: null, - required: false - } - }, - session: { - /** - * Provide widgets that are rendered above the sidebar. The format is - * an array of documents: - * { - * viewClass: MyWidgetView, the widget view class - * options: { ... } passed in when instantiating new view - * } - * @type {Array} - */ - widgets: { - type: 'array', - default: function() { - return []; - }, - required: true - }, - /** - * Set to true to enable the filter above the sidebar - * @type {Boolean} - */ - filterEnabled: { - type: 'boolean', - default: false, - required: true - } - }, - bindings: { - title: [ - { - hook: 'title' - }, - { - type: 'toggle', - hook: 'title' - } - ], - filterEnabled: { - type: 'toggle', - hook: 'filter' - } - }, - template: indexTemplate, - subviews: { - filter: { - hook: 'filter-subview', - waitFor: 'filterEnabled', - prepareView: function(el) { - return new FilterView({ - el: el, - parent: this - }); - } - }, - list: { - hook: 'list-subview', - prepareView: function(el) { - var listOptions = _.pick(this, ['displayProp', 'icon', - 'itemViewClass', 'nested']); - return new ListView({ - el: el, - parent: this, - collection: this.collection, - listOptions: listOptions - }); - } - } - }, - show: function(model) { - this.trigger('show', model); - }, - render: function() { - this.renderWithTemplate(this); - // render widgets - _.each(this.widgets, function(widget) { - widget.options = _.defaults({ - parent: this - }, widget.options || {}); - /* eslint new-cap: 0 */ - this.renderSubview(new widget.viewClass(widget.options), - this.queryByHook('widget-container')); - }.bind(this)); - - if (app.autoUpdate) { - this.listenToAndRun(app.autoUpdate, 'change:visible', function() { - var el = this.el.querySelector('.sidebar'); - if (app.autoUpdate.visible) { - el.classList.add('auto-update-available'); - } else { - el.classList.remove('auto-update-available'); - } - }.bind(this)); - } - }, - filterItems: function(searchString) { - var re; - try { - re = new RegExp(searchString, 'i'); - } catch (e) { - // invalid regexes are ignored and match everything - re = /.*/; - } - var displayProp = this.displayProp; - var nested = this.nested; - - this.collection.filter(function(model) { - if (re.test(_.result(model, displayProp))) { - if (nested && model[nested.collectionName]) { - // if the top-level matches, show all children - model[nested.collectionName].unfilter(); - } - return true; - } - if (nested && model[nested.collectionName]) { - model[nested.collectionName].filter(function(nestedModel) { - return re.test(_.result(nestedModel, nested.displayProp)); - }); - // show parent if at least one child matches the filter - return (model[nested.collectionName].length > 0); - } - return false; - }); - } -}); - -module.exports = SidebarView; diff --git a/src/app/sidebar/index.less b/src/app/sidebar/index.less deleted file mode 100644 index 92e2d11bca0..00000000000 --- a/src/app/sidebar/index.less +++ /dev/null @@ -1,173 +0,0 @@ -.sidebar { - display: flex; - flex-direction: column; - justify-content: flex-start; - border-radius: 0; - position: fixed; - z-index: 10; - -webkit-transform: translateZ(0); - margin-bottom: 0; - - top: 0; - left: 0; - bottom: 0; - width: @sidebar-width; - background: @sidebar-bg; - border-left-width: 0; - border-top-width: 0; - border-bottom-width: 0; - - &.auto-update-available { - top: 40px; - } - - .compass-logo { - background: @slate0 url("images/logo-compass-on-dark.png") center center no-repeat; - background-size: 162px 28px; - width: @sidebar-width; - height: 60px; - } - - .widget-container > div { - margin: 18px 10px; - width: @sidebar-width; - } - - .list-filter { - width: 100%; - box-shadow: 0 2px 0 rgba(0,0,0,0.2); - - i.search { - .fa-icon; - position: absolute; - margin-top: 9px; - margin-left: 10px; - color: @gray7; - } - input { - padding: 7px 5px 5px 30px; - height: auto; - background: lighten(@slate1, 5%); - color: @pw; - width: 100%; - border: none; - transition: all 150ms ease; - - &:focus { - background: lighten(@slate1, 8%); - } - } - input::-webkit-input-placeholder { - color: @gray5; - } - } - - .panel-title { - color: @gray5; - margin: 5px; - } - .list-group { - margin-bottom: 10px; - line-height: 24px; - overflow-y: auto; - width: 100%; - z-index: -1; - - &.root { - bottom: 0px; - } - - &.nested { - - .list-group-item, .list-group-item-heading { - a { - padding-left: 24px; - } - - i.icon { - margin-left: 0px; - } - } - } - - .list-group-item-heading { - cursor: default; - color: @gray5; - font-weight: bold; - } - - &:last-child .list-group-item:last-child { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } - - .list-group-item { - padding: 0; - cursor: pointer; - border-top-width: 0; - border-bottom-width: 0; - background: none; - color: @gray5; - font-weight: normal; - transition: all 180ms ease-out; - - &:hover { - background-color: #42494f; - a { - color: @pw; - transition: all 180ms ease-out; - text-decoration: none; - } - } - - } - - .list-group-item, .list-group-item-heading { - - &.special { - a { - color: @gray3; - } - i { - color: @gray3; - } - &:hover a { - color: @gray3; - } - } - - a { - display: block; - color: @gray5; - text-decoration: none; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - - i.icon { - margin: 0 5px; - color: @pw; - } - - &.active { - background-color: #6D7984; - a { - color: @pw; - } - i { - color: @pw; - } - } - - .close-icon { - position: absolute; - right: 0px; - - &:hover i { - color: @pw; - } - } - } - } -} diff --git a/src/app/sidebar/list-item.jade b/src/app/sidebar/list-item.jade deleted file mode 100644 index cdc89b7646e..00000000000 --- a/src/app/sidebar/list-item.jade +++ /dev/null @@ -1,10 +0,0 @@ -li.list-group-item - if nested - div - i.icon.fa.fa-fw(data-hook='icon') - span.value(data-hook-'displayValue')= displayValue - else - a - i.icon.fa.fa-fw(data-hook='icon') - span.value(data-hook='displayValue')= displayValue - div(data-hook='nested-list-subview') diff --git a/src/app/sidebar/list.jade b/src/app/sidebar/list.jade deleted file mode 100644 index a56fe0c17d7..00000000000 --- a/src/app/sidebar/list.jade +++ /dev/null @@ -1 +0,0 @@ -ul.list-group(data-hook='item-container') diff --git a/src/app/sidebar/list.js b/src/app/sidebar/list.js deleted file mode 100644 index 5692689d614..00000000000 --- a/src/app/sidebar/list.js +++ /dev/null @@ -1,161 +0,0 @@ -var View = require('ampersand-view'); -var raf = require('raf'); -var _ = require('lodash'); - -var listTemplate = require('./list.jade'); -var listItemTemplate = require('./list-item.jade'); - -var ListItemView; - -var ListView = View.extend({ - props: { - listOptions: { - type: 'object', - default: function() { - return {}; - }, - required: true - } - }, - derived: { - isNested: { - deps: ['listOptions'], - fn: function() { - return !!this.listOptions.nested; - } - } - }, - bindings: { - isNested: { - type: 'booleanClass', - yes: 'root', - no: 'nested' - } - }, - template: listTemplate, - render: function() { - var ItemViewClass = _.get(this.listOptions, 'itemViewClass', ListItemView); - this.listOptions.parent = this; - this.renderWithTemplate(this); - this.renderCollection(this.collection, ItemViewClass, - this.queryByHook('item-container'), { - viewOptions: this.listOptions - } - ); - }, - show: function(model) { - var parent = this.parent; - raf(function() { - parent.show(model); - }); - } -}); - -ListItemView = View.extend({ - template: listItemTemplate, - props: { - displayProp: ['any', false, undefined], - icon: ['any', false, undefined], - nested: ['any', false, undefined] - }, - bindings: { - iconName: [ - { - type: 'class', - hook: 'icon' - }, - { - type: 'toggle', - hook: 'icon' - } - ], - nested: { - type: 'booleanClass', - no: 'list-group-item', - yes: 'list-group-item-heading' - }, - displayValue: { - hook: 'displayValue' - }, - title: { - type: 'attribute', - hook: 'displayValue', - name: 'title' - }, - 'model.selected': { - type: 'booleanClass', - name: 'active' - } - }, - events: { - click: 'onClick' - }, - derived: { - hasChildren: { - deps: ['nested', 'model'], - fn: function() { - return (this.nested && this.model[this.nested.collectionName]); - } - }, - displayValue: { - deps: ['model', 'displayProp'], - fn: function() { - if (_.isFunction(this.displayProp)) { - return this.displayProp(this); - } - return _.result(this.model, this.displayProp, this.model.getId()); - } - }, - iconName: { - deps: ['model', 'icon'], - fn: function() { - if (!this.icon) { - return ''; - } - if (_.isFunction(this.icon)) { - return this.icon(this); - } - return this.icon; - } - }, - title: { - // in the basic item view this is identical to displayValue - deps: ['displayValue'], - fn: function() { - return this.displayValue; - } - } - }, - subviews: { - list: { - hook: 'nested-list-subview', - waitFor: 'hasChildren', - prepareView: function(el) { - var nested = this.nested; - return new ListView({ - el: el, - parent: this, - collection: this.model[nested.collectionName], - listOptions: this.nested - }); - } - } - }, - render: function() { - this.renderWithTemplate(this); - }, - show: function(model) { - // propagting up - this.parent.parent.show(model); - }, - onClick: function(evt) { - evt.preventDefault(); - evt.stopPropagation(); - if (!this.nested) { - this.parent.show(this.model); - } - } -}); - -module.exports = ListView; -module.exports.ListItemView = ListItemView;