Skip to content

Commit

Permalink
Merge 0fc5f71 into a728be2
Browse files Browse the repository at this point in the history
  • Loading branch information
twjohnston committed Apr 10, 2018
2 parents a728be2 + 0fc5f71 commit 8e020dd
Show file tree
Hide file tree
Showing 19 changed files with 412 additions and 18 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Detailed API and example usage can be found in the sample application in tests/d
| `Attribute` | `expansion` | `hash` | | component which handles expansion and collapsing for entire list. This component should be wrapped inside component helper. |
| `Sub Attribute` | `onExpandAll` | `action closure` | | callback functions user provided to handle all list items collapsing. This is an attribute on frost-list-expansion component.|
| `Sub Attribute` | `onCollapseAll` | `action closure` | | callback functions user provided to handle all list items expansion. This is an attribute on frost-list-expansion component. |
| `Attribute` | `sorting` | `hash` | | component which handles expansion and collapsing for entire list. This component should be wrapped inside component helper. |
| `Attribute` | `sorting` | `hash` | | component which handles sorting for the list. This component should be wrapped inside component helper. |
| `Sub Attribute` | `activeSorting` | `array` | | Array that specifies the sort order. eg. [{"direction: "asc/desc", "value": <attr-name>}], This is an attribute on frost-list-expansion component.|
| `Sub Attribute` | `properties` | `array` | | Array of sortable attributes. eg. [{"label: "foo", "value": "bar"}], This is an attribute on frost-sort component.|
| `Sub Attribute` | `onSort` | `action closure` | | callback functions user provided to handle sorting. This is an attribute on frost-sort component.|
Expand All @@ -66,7 +66,9 @@ Detailed API and example usage can be found in the sample application in tests/d
| `Attribute` | `itemTypeKey` | `string` | | Optional: With `itemTypeKey` set, it will be used to identify a list item's type. It will also be used for accessing the hash of components within `componentKeyNamesForTypes`. |
| `Attribute` | `itemDefinitions` | `hash` | | Optional: A set of components that are to be used in the list as the `item` component. Note that this had to be used in conjunction with `componentKeyNamesForTypes` |
| `Attribute` | `itemExpansionDefinitions` | `hash` | | Optional: A set of components that are to be used in the list as the `itemExpansion` component. Note that this had to be used in conjunction with `componentKeyNamesForTypes` |
| `Attribute` | `disableDeselectAll` | `boolean` | false | Optional: disables deselect all click turning frost list into a multi-select type list |
| `Attribute` | `disableDeselectAll` | `boolean` | false | Optional: disables deselect all click turning frost list into a multi-select type list |
| `Attribute` | `expansionType` | `string` | | Optional: controls the expand/collapse capability for items in the list. If set to `always`, items will always be expanded, and the ability to expand/collapse items will be disabled. If set to `initial`, all items will be expanded initially, but may still be collapsed/expanded as usual. |
| `Attribute` | `singleSelection` | `boolean` | false | Optional: disables multiple selection entirely and displays radio buttons instead of checkboxes in frost-list-item-selection to clarify the list's behavior. |


### Infinite scroll
Expand Down
16 changes: 12 additions & 4 deletions addon/components/frost-list-item-content.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import layout from '../templates/components/frost-list-item-content'
import expansionTypeEnum from '../utils/expansion-types'
import computed, {readOnly} from 'ember-computed-decorators'
import {Component} from 'ember-frost-core'
import {PropTypes} from 'ember-prop-types'

import layout from '../templates/components/frost-list-item-content'

export default Component.extend({
// == Dependencies ==========================================================

Expand All @@ -27,16 +28,23 @@ export default Component.extend({
itemExpansion: PropTypes.oneOfType([
PropTypes.null,
PropTypes.EmberComponent
])
]),
expansionType: PropTypes.string,
singleSelection: PropTypes.bool
},

getDefaultProps () {
return {
isAnyItemExpansion: false
}
}
},

// == Computed Properties ===================================================
@readOnly
@computed('itemExpansion', 'expansionType')
isExpansionIconVisible (itemExpansion, expansionType) {
return itemExpansion && expansionType !== expansionTypeEnum.ALWAYS
}

// == Functions =============================================================

Expand Down
2 changes: 2 additions & 0 deletions addon/components/frost-list-item-selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ export default Component.extend({
PropTypes.EmberObject,
PropTypes.object
]),
index: PropTypes.number,
isSelected: PropTypes.bool,
singleSelection: PropTypes.bool,

onSelect: PropTypes.func.isRequired
},
Expand Down
25 changes: 23 additions & 2 deletions addon/components/frost-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import Ember from 'ember'
const {$, A, ObjectProxy, String: EmberString, get, isEmpty, isNone, isPresent, run, set} = Ember
import layout from '../templates/components/frost-list'
import expansionTypeEnum from '../utils/expansion-types'
import getComponentName from '../utils/get-component-name'
import computed, {readOnly} from 'ember-computed-decorators'
import {Component} from 'ember-frost-core'
Expand Down Expand Up @@ -66,6 +67,8 @@ export default Component.extend({
PropTypes.EmberObject,
PropTypes.object
]),
expansionType: PropTypes.string,
singleSelection: PropTypes.bool,

// Options - sub-components
pagination: PropTypes.EmberComponent,
Expand Down Expand Up @@ -110,6 +113,8 @@ export default Component.extend({
item: 'itemName',
itemExpansion: 'itemExpansionName'
},
expansionType: '',
singleSelection: false,

// Smoke and mirrors options
alwaysUseDefaultHeight: false,
Expand Down Expand Up @@ -207,6 +212,12 @@ export default Component.extend({
return pagination && isAnyItemExpansion
},

@readOnly
@computed('isAnyItemExpansion', 'expansionType')
isCollapseExpandAllVisible (isAnyItemExpansion, expansionType) {
return isAnyItemExpansion && expansionType !== expansionTypeEnum.ALWAYS
},

// == Functions =============================================================

setShift (event) {
Expand Down Expand Up @@ -290,6 +301,12 @@ export default Component.extend({
this.setDefaultItemExpansion()
}

const expansionType = this.get('expansionType')
if (expansionType === expansionTypeEnum.ALWAYS || expansionType === expansionTypeEnum.INITIAL) {
const clonedItems = this.get('items').slice()
this.set('expandedItems', clonedItems)
}

this._keyHandler = this.setShift.bind(this)
$(document).on(`keyup.${this.elementId} keydown.${this.elementId}`, this._keyHandler)
},
Expand Down Expand Up @@ -331,14 +348,18 @@ export default Component.extend({
const _itemComparator = this.get('_itemComparator')
const clonedSelectedItems = A(this.get('selectedItems').slice())
const _rangeState = this.get('_rangeState')
const singleSelection = this.get('singleSelection')

if (isRangeSelect === false && this.get('disableDeselectAll') === true) {
// Ensure we are not interrupting a range select prior to forcing a isSpecificSelect
isSpecificSelect = true
}

// Selects are proccessed in order of precedence: specific, range, basic
if (isSpecificSelect) {
// If single selection is enabled, we can just use the basic selection
// Otherwise, selects are proccessed in order of precedence: specific, range, basic
if (singleSelection) {
selection.basic(clonedSelectedItems, item, _rangeState, _itemComparator)
} else if (isSpecificSelect) {
selection.specific(clonedSelectedItems, item, _rangeState, _itemComparator)
} else if (isRangeSelect) {
selection.range(items, clonedSelectedItems, item, _rangeState, _itemComparator, itemKey)
Expand Down
4 changes: 3 additions & 1 deletion addon/templates/components/frost-list-item-content.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
data-test={{hook (concat hook '-item-container') index=index }}
>
<div class='frost-list-item-container-base' style={{listRowHeightString}}>
{{#if itemExpansion}}
{{#if isExpansionIconVisible}}
{{frost-list-item-expansion
hook=(concat hookPrefix '-expansion')
hookQualifiers=(hash index=index)
Expand All @@ -23,9 +23,11 @@
hook=(concat hookPrefix '-selection')
hookQualifiers=(hash index=index)
model=model.content
index=index
isSelected=model.states.isSelected
onSelect=onSelect
size=size
singleSelection=singleSelection
}}
{{/if}}

Expand Down
22 changes: 15 additions & 7 deletions addon/templates/components/frost-list-item-selection.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
{{! Template for the frost-list-item-selection component }}

{{frost-checkbox
checked=isSelected
hook=(concat hookPrefix '-checkbox')
size=size
}}
{{#if singleSelection}}
{{!-- frost-radio-button requires a string value, so we concat '' --}}
{{frost-radio-button
checked=isSelected
hook=(concat hookPrefix '-radio-button')
size=size
value=(concat index '')
}}
{{else}}
{{frost-checkbox
checked=isSelected
hook=(concat hookPrefix '-checkbox')
size=size
}}
{{/if}}
4 changes: 3 additions & 1 deletion addon/templates/components/frost-list.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<div class='frost-list-header-divider'></div>
{{/if}}

{{#if isAnyItemExpansion}}
{{#if isCollapseExpandAllVisible}}
{{frost-list-expansion
hook=(concat hookPrefix '-expansion')
onCollapseAll=(action '_collapseAll')
Expand Down Expand Up @@ -63,6 +63,8 @@
onSelectionChange=onSelectionChange
onExpand=(action '_expand')
onSelect=(action '_select')
expansionType=expansionType
singleSelection=singleSelection
}}
{{else}}
{{yield to="inverse"}}
Expand Down
4 changes: 4 additions & 0 deletions addon/utils/expansion-types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default {
ALWAYS: 'always',
INITIAL: 'initial'
}
1 change: 1 addition & 0 deletions app/utils/expansion-types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {default} from 'ember-frost-list/utils/expansion-types'
2 changes: 2 additions & 0 deletions tests/dummy/app/pods/application/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
{{#link-to 'infinite'}}Infinite{{/link-to}}
{{#link-to 'paged'}}Paged{{/link-to}}
{{#link-to 'typed'}}Typed{{/link-to}}
{{#link-to 'single'}}Single select{{/link-to}}
{{#link-to 'expansion-type'}}Initial expansion{{/link-to}}
</div>
{{/frost-scroll}}
</div>
Expand Down
49 changes: 49 additions & 0 deletions tests/dummy/app/pods/expansion-type/controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Ember from 'ember'
const {A, Controller, isEmpty} = Ember
import computed, {readOnly} from 'ember-computed-decorators'
import {sort} from 'ember-frost-sort'

export default Controller.extend({

// == Dependencies ==========================================================

// == Properties ============================================================

selectedItems: A([]),
sortOrder: A(['-id']),
sortingProperties: [
{label: 'Id', value: 'id'},
{label: 'Label', value: 'label'}
],

// == Computed Properties ===================================================

@readOnly
@computed('model.[]', 'sortOrder.[]')
items (model, sortOrder) {
if (isEmpty(model)) {
return []
}
return sort(model, sortOrder) // Client side sorting
},

// == Functions =============================================================

// == Lifecycle Hooks =======================================================

// == Actions ===============================================================

actions: {
onExpansionChange (expandedItems) {
this.set('expandedItems', expandedItems)
},

onSelectionChange (selectedItems) {
this.get('selectedItems').setObjects(selectedItems)
},

onSortingChange (sortOrder) {
this.get('sortOrder').setObjects(sortOrder)
}
}
})
8 changes: 8 additions & 0 deletions tests/dummy/app/pods/expansion-type/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Ember from 'ember'
const {Route} = Ember

export default Route.extend({
model () {
return this.store.findAll('list-item')
}
})
17 changes: 17 additions & 0 deletions tests/dummy/app/pods/expansion-type/template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{frost-list
class='demo'
hook='demo'
item=(component 'list-item')
itemExpansion=(component 'list-item-expansion')
items=items
expandedItems=expandedItems
selectedItems=selectedItems
onExpansionChange=(action 'onExpansionChange')
onSelectionChange=(action 'onSelectionChange')
sorting=(component 'frost-sort'
sortOrder=sortOrder
sortingProperties=sortingProperties
onChange=(action 'onSortingChange')
)
expansionType='initial'
}}
50 changes: 50 additions & 0 deletions tests/dummy/app/pods/single/controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import Ember from 'ember'
const {A, Controller, isEmpty} = Ember
import computed, {readOnly} from 'ember-computed-decorators'
import {sort} from 'ember-frost-sort'

export default Controller.extend({

// == Dependencies ==========================================================

// == Properties ============================================================

expandedItems: A([]),
selectedItems: A([]),
sortOrder: A(['-id']),
sortingProperties: [
{label: 'Id', value: 'id'},
{label: 'Label', value: 'label'}
],

// == Computed Properties ===================================================

@readOnly
@computed('model.[]', 'sortOrder.[]')
items (model, sortOrder) {
if (isEmpty(model)) {
return []
}
return sort(model, sortOrder) // Client side sorting
},

// == Functions =============================================================

// == Lifecycle Hooks =======================================================

// == Actions ===============================================================

actions: {
onExpansionChange (expandedItems) {
this.get('expandedItems').setObjects(expandedItems)
},

onSelectionChange (selectedItems) {
this.get('selectedItems').setObjects(selectedItems)
},

onSortingChange (sortOrder) {
this.get('sortOrder').setObjects(sortOrder)
}
}
})
8 changes: 8 additions & 0 deletions tests/dummy/app/pods/single/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Ember from 'ember'
const {Route} = Ember

export default Route.extend({
model () {
return this.store.findAll('list-item')
}
})
17 changes: 17 additions & 0 deletions tests/dummy/app/pods/single/template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{frost-list
class='demo'
hook='demo'
item=(component 'list-item')
itemExpansion=(component 'list-item-expansion')
items=items
expandedItems=expandedItems
selectedItems=selectedItems
onExpansionChange=(action 'onExpansionChange')
onSelectionChange=(action 'onSelectionChange')
sorting=(component 'frost-sort'
sortOrder=sortOrder
sortingProperties=sortingProperties
onChange=(action 'onSortingChange')
)
singleSelection=true
}}
2 changes: 2 additions & 0 deletions tests/dummy/app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Router.map(function () {
this.route('paged')
this.route('size')
this.route('typed')
this.route('single')
this.route('expansion-type')
})

export default Router
Loading

0 comments on commit 8e020dd

Please sign in to comment.