diff --git a/addon/mixins/draggable-column.js b/addon/mixins/draggable-column.js index 97aa9992..9223d3d4 100644 --- a/addon/mixins/draggable-column.js +++ b/addon/mixins/draggable-column.js @@ -81,6 +81,14 @@ export default Mixin.create({ if (this.get('isDropTarget')) { e.preventDefault(); + /* + NOTE: dragLeave will be triggered by any child elements inside the + column. This code ensures the column being dragged over continues to be + identified as the current drop target + */ + if (!this.get('isDragTarget')) { + this.set('isDragTarget', this.get('column') !== sourceColumn); + } } }, @@ -112,29 +120,31 @@ export default Mixin.create({ drop(e) { this._super(...arguments); - let table = this.get('table'); let targetColumn = this.get('column'); - let columns = this.get('dragColumnGroup'); + if (targetColumn.droppable) { + let table = this.get('table'); + let columns = this.get('dragColumnGroup'); - let _columns = columns.toArray(); - let targetColumnIdx = _columns.indexOf(targetColumn); + let _columns = columns.toArray(); + let targetColumnIdx = _columns.indexOf(targetColumn); - e.dataTransfer.dropEffect = 'move'; - e.preventDefault(); - e.stopPropagation(); + e.dataTransfer.dropEffect = 'move'; + e.preventDefault(); + e.stopPropagation(); - table.propertyWillChange('columns'); + table.propertyWillChange('columns'); - _columns.removeObject(sourceColumn); - _columns.insertAt(targetColumnIdx, sourceColumn); - columns.setObjects(_columns); + _columns.removeObject(sourceColumn); + _columns.insertAt(targetColumnIdx, sourceColumn); + columns.setObjects(_columns); - table.propertyDidChange('columns'); + table.propertyDidChange('columns'); - this.setProperties({ isDragTarget: false, isDragging: false }); + this.setProperties({ isDragTarget: false, isDragging: false }); - this.sendAction('onColumnDrop', sourceColumn, true, ...arguments); - sourceColumn = null; + this.sendAction('onColumnDrop', sourceColumn, true, ...arguments); + sourceColumn = null; + } }, destroy() { diff --git a/addon/mixins/table-header.js b/addon/mixins/table-header.js index 450b1514..6c549685 100644 --- a/addon/mixins/table-header.js +++ b/addon/mixins/table-header.js @@ -106,6 +106,15 @@ export default Mixin.create({ */ iconDescending: '', + /** + * Custom sorting component name to use instead of the default `` template. + * See `iconSortable`, `iconAsending`, or `iconDescending`. + * @property iconComponent + * @type {String} + * @default false + */ + iconComponent: null, + /** * ID of main table component. Used to generate divs for ember-wormhole * @type {String} @@ -117,8 +126,8 @@ export default Mixin.create({ subColumns: computed.readOnly('table.visibleSubColumns'), columns: computed.readOnly('table.visibleColumns'), - sortIcons: computed('iconSortable', 'iconAscending', 'iconDescending', function() { - return this.getProperties(['iconSortable', 'iconAscending', 'iconDescending']); + sortIcons: computed('iconSortable', 'iconAscending', 'iconDescending', 'iconComponent', function() { + return this.getProperties(['iconSortable', 'iconAscending', 'iconDescending', 'iconComponent']); }).readOnly(), init() { diff --git a/addon/templates/components/columns/base.hbs b/addon/templates/components/columns/base.hbs index bfb7193d..81f8cca4 100644 --- a/addon/templates/components/columns/base.hbs +++ b/addon/templates/components/columns/base.hbs @@ -2,7 +2,9 @@ {{component column.component column=column table=table tableActions=tableActions extra=extra sortIcons=sortIcons}} {{else}} {{label}} - {{#if sortIconProperty}} + {{#if (and sortIcons.iconComponent sortIconProperty)}} + {{component sortIcons.iconComponent sortIcons=sortIcons sortIconProperty=sortIconProperty}} + {{else if sortIconProperty}} {{/if}} {{/if}} diff --git a/package.json b/package.json index b461c295..f5f06faf 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "ember-get-config": "^0.2.2", "ember-in-viewport": "2.1.1", "ember-scrollable": "^0.4.7", - "ember-truth-helpers": "1.3.0", + "ember-truth-helpers": "^2.0.0", "ember-wormhole": "^0.5.1" }, "devDependencies": { @@ -63,7 +63,7 @@ "ember-font-awesome": "^3.0.5", "ember-load-initializers": "^1.0.0", "ember-native-dom-helpers": "^0.5.0", - "ember-one-way-controls": "2.0.0", + "ember-one-way-controls": "^2.0.0", "ember-owner-test-utils": "^0.1.2", "ember-resolver": "^4.0.0", "ember-responsive": "^2.0.4", diff --git a/tests/dummy/app/components/cookbook/custom-sort-icon-table.js b/tests/dummy/app/components/cookbook/custom-sort-icon-table.js new file mode 100644 index 00000000..8579cfcb --- /dev/null +++ b/tests/dummy/app/components/cookbook/custom-sort-icon-table.js @@ -0,0 +1,34 @@ +// BEGIN-SNIPPET custom-sort-icon-table +import Component from '@ember/component'; +import TableCommon from '../../mixins/table-common'; +import { computed } from '@ember/object'; + +export default Component.extend(TableCommon, { + columns: computed(function() { + return [{ + label: 'Avatar', + valuePath: 'avatar', + width: '60px', + sortable: false, + cellComponent: 'user-avatar' + }, { + label: 'First Name', + valuePath: 'firstName', + width: '150px' + }, { + label: 'Last Name', + valuePath: 'lastName', + width: '150px' + }, { + label: 'Address', + valuePath: 'address' + }, { + label: 'State', + valuePath: 'state' + }, { + label: 'Country', + valuePath: 'country' + }]; + }) +}); +// END-SNIPPET diff --git a/tests/dummy/app/components/materialize-icon.js b/tests/dummy/app/components/materialize-icon.js new file mode 100644 index 00000000..d880d448 --- /dev/null +++ b/tests/dummy/app/components/materialize-icon.js @@ -0,0 +1,9 @@ +// BEGIN-SNIPPET materialize-icon +import Component from '@ember/component'; +import layout from '../templates/components/materialize-icon'; + +export default Component.extend({ + tagName: 'span', + layout +}); +// END-SNIPPET diff --git a/tests/dummy/app/index.html b/tests/dummy/app/index.html index 23ea3bf2..1b1c999b 100644 --- a/tests/dummy/app/index.html +++ b/tests/dummy/app/index.html @@ -13,6 +13,7 @@ + {{content-for "head-footer"}} diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js index 93afae07..a620ebd6 100644 --- a/tests/dummy/app/router.js +++ b/tests/dummy/app/router.js @@ -28,6 +28,7 @@ Router.map(function() { this.route('custom-row'); this.route('table-actions'); this.route('horizontal-scrolling'); + this.route('custom-sort-icon'); }); }); diff --git a/tests/dummy/app/routes/cookbook/custom-sort-icon.js b/tests/dummy/app/routes/cookbook/custom-sort-icon.js new file mode 100644 index 00000000..0040140d --- /dev/null +++ b/tests/dummy/app/routes/cookbook/custom-sort-icon.js @@ -0,0 +1 @@ +export { default } from '../table-route'; diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs index 4553c6e6..7bf2183b 100644 --- a/tests/dummy/app/templates/application.hbs +++ b/tests/dummy/app/templates/application.hbs @@ -71,6 +71,9 @@ {{#link-to 'cookbook.pagination' tagName="li"}} {{link-to 'Pagination' 'cookbook.pagination'}} {{/link-to}} + {{#link-to 'cookbook.custom-sort-icon' tagName="li"}} + {{link-to 'Custom Sort Icon' 'cookbook.custom-sort-icon'}} + {{/link-to}} {{/link-to}}
  • Documentation
  • diff --git a/tests/dummy/app/templates/components/cookbook/custom-sort-icon-table.hbs b/tests/dummy/app/templates/components/cookbook/custom-sort-icon-table.hbs new file mode 100644 index 00000000..1a1f1cdc --- /dev/null +++ b/tests/dummy/app/templates/components/cookbook/custom-sort-icon-table.hbs @@ -0,0 +1,26 @@ +{{!-- BEGIN-SNIPPET custom-sort-icon-table --}} +{{#light-table table height='65vh' as |t|}} + + {{t.head + onColumnClick=(action 'onColumnClick') + iconSortable='unfold_more' + iconAscending='keyboard_arrow_up' + iconDescending='keyboard_arrow_down' + iconComponent='materialize-icon' + fixed=true + }} + + {{#t.body + canSelect=false + onScrolledToBottom=(action 'onScrolledToBottom') + as |body| + }} + {{#if isLoading}} + {{#body.loader}} + {{table-loader}} + {{/body.loader}} + {{/if}} + {{/t.body}} + +{{/light-table}} +{{!-- END-SNIPPET --}} diff --git a/tests/dummy/app/templates/components/materialize-icon.hbs b/tests/dummy/app/templates/components/materialize-icon.hbs new file mode 100644 index 00000000..02ee0d69 --- /dev/null +++ b/tests/dummy/app/templates/components/materialize-icon.hbs @@ -0,0 +1,3 @@ +{{!-- BEGIN-SNIPPET materialize-icon --}} +{{get sortIcons sortIconProperty}} +{{!-- END-SNIPPET --}} diff --git a/tests/dummy/app/templates/cookbook/custom-sort-icon.hbs b/tests/dummy/app/templates/cookbook/custom-sort-icon.hbs new file mode 100644 index 00000000..7e783bd4 --- /dev/null +++ b/tests/dummy/app/templates/cookbook/custom-sort-icon.hbs @@ -0,0 +1,12 @@ +{{#code-panel + title="Custom Sort Icon" + snippets=(array + "custom-sort-icon-table.js" + "table-common.js" + "custom-sort-icon-table.hbs" + "user-avatar.hbs" + "table-loader.hbs" + "materialize-icon.hbs" +)}} + {{cookbook/custom-sort-icon-table model=model}} +{{/code-panel}} diff --git a/tests/integration/components/lt-head-test.js b/tests/integration/components/lt-head-test.js index 45c1699f..cf9378b8 100644 --- a/tests/integration/components/lt-head-test.js +++ b/tests/integration/components/lt-head-test.js @@ -4,6 +4,8 @@ import hbs from 'htmlbars-inline-precompile'; import Table from 'ember-light-table'; import Columns, { GroupedColumns } from '../../helpers/table-columns'; import hasClass from '../../helpers/has-class'; +import Component from '@ember/component'; +import { isPresent } from '@ember/utils'; moduleForComponent('lt-head', 'Integration | Component | lt head', { integration: true @@ -92,6 +94,39 @@ test('render sort icons', function(assert) { assert.notOk(hasClass(sortIcon, 'fa-sort-asc')); }); +test('custom iconComponent has arguments', function(assert) { + const sortableColumns = Columns.filter((column) => { + return column.sortable !== false; + }); + + assert.expect(6 * sortableColumns.length); + const iconSortable = 'unfold_more'; + const iconAscending = 'fa-sort-asc'; + const iconDescending = 'fa-sort-desc'; + const iconComponent = 'custom-icon-component'; + + this.setProperties({ + iconSortable, + iconAscending, + iconDescending, + iconComponent, + table: new Table(Columns) + }); + this.register(`component:${iconComponent}`, Component.extend({ + init() { + this._super(...arguments); + assert.ok(isPresent(this.get('sortIconProperty'))); + assert.ok(isPresent(this.get('sortIcons'))); + assert.equal(this.get('sortIcons.iconSortable'), iconSortable); + assert.equal(this.get('sortIcons.iconAscending'), iconAscending); + assert.equal(this.get('sortIcons.iconDescending'), iconDescending); + assert.equal(this.get('sortIcons.iconComponent'), iconComponent); + } + })); + + this.render(hbs`{{lt-head table=table renderInPlace=true iconSortable=iconSortable iconAscending=iconAscending iconDescending=iconDescending iconComponent=iconComponent}}`); +}), + test('double click', function(assert) { this.set('table', new Table(Columns)); this.on('onColumnDoubleClick', (column) => { diff --git a/yarn.lock b/yarn.lock index c1a6d32a..0569707a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -178,6 +178,12 @@ amd-name-resolver@0.0.6: dependencies: ensure-posix-path "^1.0.1" +amd-name-resolver@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/amd-name-resolver/-/amd-name-resolver-0.0.7.tgz#814301adfe8a2f109f6e84d5e935196efb669615" + dependencies: + ensure-posix-path "^1.0.1" + amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -683,6 +689,12 @@ babel-plugin-ember-modules-api-polyfill@^1.4.1: dependencies: ember-rfc176-data "^0.2.0" +babel-plugin-ember-modules-api-polyfill@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/babel-plugin-ember-modules-api-polyfill/-/babel-plugin-ember-modules-api-polyfill-2.1.0.tgz#78848cc4fcc2274882a6c15cbb23fefcdc771301" + dependencies: + ember-rfc176-data "^0.3.0" + babel-plugin-eval@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/babel-plugin-eval/-/babel-plugin-eval-1.0.1.tgz#a2faed25ce6be69ade4bfec263f70169195950da" @@ -2600,6 +2612,23 @@ ember-cli-babel@^6.6.0: clone "^2.0.0" ember-cli-version-checker "^2.0.0" +ember-cli-babel@^6.8.2: + version "6.8.2" + resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-6.8.2.tgz#eac2785964f4743f4c815cd53c6288f00cc087d7" + dependencies: + amd-name-resolver "0.0.7" + babel-plugin-debug-macros "^0.1.11" + babel-plugin-ember-modules-api-polyfill "^2.0.1" + babel-plugin-transform-es2015-modules-amd "^6.24.0" + babel-polyfill "^6.16.0" + babel-preset-env "^1.5.1" + broccoli-babel-transpiler "^6.1.2" + broccoli-debug "^0.6.2" + broccoli-funnel "^1.0.0" + broccoli-source "^1.1.0" + clone "^2.0.0" + ember-cli-version-checker "^2.0.0" + ember-cli-broccoli-sane-watcher@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/ember-cli-broccoli-sane-watcher/-/ember-cli-broccoli-sane-watcher-2.0.4.tgz#f43f42f75b7509c212fb926cd9aea86ae19264c6" @@ -2688,7 +2717,7 @@ ember-cli-htmlbars-inline-precompile@^0.4.0: hash-for-dep "^1.0.2" silent-error "^1.1.0" -ember-cli-htmlbars@^1.0.0, ember-cli-htmlbars@^1.0.10, ember-cli-htmlbars@^1.0.3, ember-cli-htmlbars@^1.1.1: +ember-cli-htmlbars@^1.0.0, ember-cli-htmlbars@^1.0.3, ember-cli-htmlbars@^1.1.1: version "1.3.3" resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-1.3.3.tgz#06815262c1577736235bd42ce99db559ce5ebfd1" dependencies: @@ -2698,6 +2727,15 @@ ember-cli-htmlbars@^1.0.0, ember-cli-htmlbars@^1.0.10, ember-cli-htmlbars@^1.0.3 json-stable-stringify "^1.0.0" strip-bom "^2.0.0" +ember-cli-htmlbars@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-2.0.3.tgz#e116e1500dba12f29c94b05b9ec90f52cb8bb042" + dependencies: + broccoli-persistent-filter "^1.0.3" + hash-for-dep "^1.0.2" + json-stable-stringify "^1.0.0" + strip-bom "^3.0.0" + ember-cli-htmlbars@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/ember-cli-htmlbars/-/ember-cli-htmlbars-2.0.2.tgz#230a9ace7c3454b3acff2768a50f963813a90c38" @@ -3188,15 +3226,15 @@ ember-native-dom-helpers@^0.5.0: broccoli-funnel "^1.1.0" ember-cli-babel "^6.1.0" -ember-one-way-controls@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ember-one-way-controls/-/ember-one-way-controls-2.0.0.tgz#7a79f1a56094c44fe1012fd0f9b75bd92d136fe9" +ember-one-way-controls@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ember-one-way-controls/-/ember-one-way-controls-2.0.1.tgz#45bd9367554f69e10fa37dfac8f1a6c72360a7f1" dependencies: - ember-cli-babel "^5.1.7" - ember-cli-htmlbars "^1.0.10" + ember-cli-babel "^6.0.0" + ember-cli-htmlbars "^2.0.1" ember-get-helper "~1.1.0" ember-invoke-action "1.4.0" - ember-runtime-enumerable-includes-polyfill "^1.0.1" + ember-runtime-enumerable-includes-polyfill "^2.0.0" ember-owner-test-utils@^0.1.2: version "0.1.2" @@ -3233,19 +3271,16 @@ ember-rfc176-data@^0.2.0: version "0.2.7" resolved "https://registry.yarnpkg.com/ember-rfc176-data/-/ember-rfc176-data-0.2.7.tgz#bd355bc9b473e08096b518784170a23388bc973b" +ember-rfc176-data@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/ember-rfc176-data/-/ember-rfc176-data-0.3.0.tgz#6aee728cb521c5f80710990965027b9c320f6f08" + ember-router-generator@^1.0.0: version "1.2.3" resolved "https://registry.yarnpkg.com/ember-router-generator/-/ember-router-generator-1.2.3.tgz#8ed2ca86ff323363120fc14278191e9e8f1315ee" dependencies: recast "^0.11.3" -ember-runtime-enumerable-includes-polyfill@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/ember-runtime-enumerable-includes-polyfill/-/ember-runtime-enumerable-includes-polyfill-1.0.4.tgz#16a7612e347a2edf07da8b2f2f09dbfee70deba0" - dependencies: - ember-cli-babel "^5.1.6" - ember-cli-version-checker "^1.1.6" - ember-runtime-enumerable-includes-polyfill@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ember-runtime-enumerable-includes-polyfill/-/ember-runtime-enumerable-includes-polyfill-2.0.0.tgz#6e9ba118bc909d1d7762de1b03a550d8955308a9" @@ -3293,11 +3328,11 @@ ember-test-helpers@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/ember-test-helpers/-/ember-test-helpers-0.6.3.tgz#f864cdf6f4e75f3f8768d6537785b5ab6e82d907" -ember-truth-helpers@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/ember-truth-helpers/-/ember-truth-helpers-1.3.0.tgz#6ed9f83ce9a49f52bb416d55e227426339a64c60" +ember-truth-helpers@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ember-truth-helpers/-/ember-truth-helpers-2.0.0.tgz#f3e2eef667859197f1328bb4f83b0b35b661c1ac" dependencies: - ember-cli-babel "^5.1.6" + ember-cli-babel "^6.8.2" ember-try-config@^2.0.1: version "2.1.0"