Skip to content

Commit

Permalink
[structure] Allow disabling icons for lists and list items (#1013)
Browse files Browse the repository at this point in the history
  • Loading branch information
rexxars authored and bjoerge committed Oct 16, 2018
1 parent f82569e commit 6d86c9e
Show file tree
Hide file tree
Showing 20 changed files with 199 additions and 10 deletions.
9 changes: 6 additions & 3 deletions packages/@sanity/desk-tool/src/defaultStructure.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import Structure from '../structure-builder'

export default () =>
Structure.list()
export default () => {
const items = Structure.documentTypeListItems()
return Structure.list()
.id('__root__')
.title('Content')
.items(Structure.documentTypeListItems())
.showIcons(items.some(item => item.getSchemaType().icon))
.items(items)
}
5 changes: 5 additions & 0 deletions packages/@sanity/desk-tool/src/pane/DocumentsListPane.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ export default withRouterHOC(
id: PropTypes.string.isRequired
})
),
displayOptions: PropTypes.shape({
showIcons: PropTypes.bool
}),
isSelected: PropTypes.bool.isRequired,
isCollapsed: PropTypes.bool.isRequired,
onExpand: PropTypes.func,
Expand All @@ -121,6 +124,7 @@ export default withRouterHOC(
styles: {},
menuItems: [],
menuItemGroups: [],
displayOptions: {},
onExpand: undefined,
onCollapse: undefined,
defaultLayout: undefined
Expand Down Expand Up @@ -190,6 +194,7 @@ export default withRouterHOC(
getLinkState={this.getLinkStateForItem}
layout={this.state.layout || this.props.defaultLayout || 'default'}
value={item}
icon={this.props.displayOptions.showIcons === false ? false : undefined}
schemaType={schema.get(item._type)}
isSelected={this.itemIsSelected(item._id)}
/>
Expand Down
19 changes: 18 additions & 1 deletion packages/@sanity/desk-tool/src/pane/ListPane.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ export default withRouterHOC(
id: PropTypes.string.isRequired
})
),
displayOptions: PropTypes.shape({
showIcons: PropTypes.bool
}),
isSelected: PropTypes.bool.isRequired,
isCollapsed: PropTypes.bool.isRequired,
onExpand: PropTypes.func,
Expand All @@ -46,6 +49,7 @@ export default withRouterHOC(
items: [],
menuItems: [],
menuItemGroups: [],
displayOptions: {},
styles: undefined,
onExpand: undefined,
onCollapse: undefined,
Expand All @@ -64,6 +68,19 @@ export default withRouterHOC(
return {panes}
}

shouldShowIconForItem = item => {
const paneShowIcons = this.props.displayOptions.showIcons
const itemShowIcon = item.displayOptions && item.displayOptions.showIcon

// Specific true/false on item should have presedence over list setting
if (typeof itemShowIcon !== 'undefined') {
return itemShowIcon === false ? false : item.icon
}

// If no item setting is defined, defer to the pane settings
return paneShowIcons === false ? false : item.icon
}

render() {
const {
title,
Expand Down Expand Up @@ -99,7 +116,7 @@ export default withRouterHOC(
id={item.id}
index={index}
value={item}
icon={item.icon}
icon={this.shouldShowIconForItem(item)}
layout={defaultLayout}
isSelected={this.itemIsSelected(item)}
getLinkState={this.getLinkStateForItem}
Expand Down
3 changes: 2 additions & 1 deletion packages/@sanity/structure/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
"^part:@sanity/base/schema$": "<rootDir>/test/mocks/schema.js",
"^part:@sanity/base/client$": "<rootDir>/test/mocks/client.js",
"^part:@sanity/data-aspects/resolver$": "<rootDir>/test/mocks/dataAspects.js",
"^part:@sanity/base/.*?-icon$": "<rootDir>/test/mocks/icon.js"
"^part:@sanity/base/.*?-icon$": "<rootDir>/test/mocks/icon.js",
"^part:@sanity/base/util/document-action-utils": "<rootDir>/test/mocks/documentActionUtils.js"
},
"coveragePathIgnorePatterns": [
"/node_modules/",
Expand Down
5 changes: 3 additions & 2 deletions packages/@sanity/structure/src/Editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ export class EditorBuilder implements Serializable {
}
}

clone(withSpec?: PartialEditorNode) {
clone(withSpec: PartialEditorNode = {}) {
const builder = new EditorBuilder()
builder.spec = {...this.spec, ...(withSpec || {})}
const options = {...(this.spec.options || {}), ...(withSpec.options || {})}
builder.spec = {...this.spec, ...withSpec, options}
return builder
}
}
16 changes: 16 additions & 0 deletions packages/@sanity/structure/src/GenericList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ function noChildResolver() {
return undefined
}

export interface ListDisplayOptions {
showIcons?: boolean
}

export interface BaseGenericList extends StructureNode {
defaultLayout?: Layout
canHandleIntent?: IntentChecker
displayOptions?: ListDisplayOptions
child: Child
}

Expand Down Expand Up @@ -100,6 +105,16 @@ export abstract class GenericListBuilder<L extends BuildableGenericList, Concret
return this.spec.canHandleIntent
}

showIcons(enabled: boolean) {
return this.clone({
displayOptions: {...(this.spec.displayOptions || {}), showIcons: enabled}
})
}

getShowIcons() {
return this.spec.displayOptions ? this.spec.displayOptions.showIcons : undefined
}

serialize(options: SerializeOptions = {path: []}): GenericList {
const id = this.spec.id || ''
const path = options.path
Expand All @@ -121,6 +136,7 @@ export abstract class GenericListBuilder<L extends BuildableGenericList, Concret
defaultLayout,
child: this.spec.child || noChildResolver,
canHandleIntent: this.spec.canHandleIntent,
displayOptions: this.spec.displayOptions,
menuItems: (this.spec.menuItems || []).map((item, i) =>
maybeSerializeMenuItem(item, i, path)
),
Expand Down
17 changes: 17 additions & 0 deletions packages/@sanity/structure/src/ListItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@ interface ListItemSerializeOptions extends SerializeOptions {
titleIsOptional?: boolean
}

interface ListItemDisplayOptions {
showIcon?: boolean
}

export interface ListItemInput {
id: string
title?: string
icon?: Function
child?: ListItemChild
displayOptions?: ListItemDisplayOptions
schemaType?: SchemaType | string
}

Expand All @@ -31,6 +36,7 @@ export interface ListItem {
title?: string
icon?: Function
child?: ListItemChild
displayOptions?: ListItemDisplayOptions
schemaType?: SchemaType
}

Expand All @@ -39,6 +45,7 @@ export interface UnserializedListItem {
title: string
icon?: Function
child?: UnserializedListItemChild
displayOptions?: ListItemDisplayOptions
schemaType?: SchemaType | string
}

Expand Down Expand Up @@ -71,6 +78,16 @@ export class ListItemBuilder implements Serializable {
return this.clone({icon})
}

showIcon(enabled: boolean) {
return this.clone({
displayOptions: {...(this.spec.displayOptions || {}), showIcon: enabled}
})
}

getShowIcon() {
return this.spec.displayOptions ? this.spec.displayOptions.showIcon : undefined
}

getIcon() {
return this.spec.icon
}
Expand Down
9 changes: 8 additions & 1 deletion packages/@sanity/structure/src/documentTypeListItems.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import memoizeOne from 'memoize-one'
import {Schema, defaultSchema} from './parts/Schema'
import {Schema, defaultSchema, SchemaType} from './parts/Schema'
import {dataAspects, DataAspectsResolver} from './parts/DataAspects'
import {getPlusIcon, getListIcon, getDetailsIcon} from './parts/Icon'
import {MenuItemBuilder, getOrderingMenuItemsForSchemaType} from './MenuItem'
Expand All @@ -19,6 +19,11 @@ const getDataAspectsForSchema: (schema: Schema) => DataAspectsResolver = memoize

export const DEFAULT_INTENT_HANDLER = Symbol('Document type list canHandleIntent')

function shouldShowIcon(schemaType: SchemaType): boolean {
const preview = schemaType.preview
return Boolean(preview && (preview.prepare || (preview.select && preview.select.media)))
}

export function getDocumentTypeListItems(schema: Schema = defaultSchema): ListItemBuilder[] {
const resolver = getDataAspectsForSchema(schema)
const types = resolver.getInferredTypes()
Expand Down Expand Up @@ -46,6 +51,7 @@ export function getDocumentTypeList(
const type = schema.get(typeName)
const resolver = getDataAspectsForSchema(schema)
const title = resolver.getDisplayName(typeName)
const showIcons = shouldShowIcon(type)
const canCreate = isActionEnabled(type, 'create')

const intentChecker: IntentChecker = (intentName, params): boolean =>
Expand All @@ -60,6 +66,7 @@ export function getDocumentTypeList(
.filter('_type == $type')
.params({type: typeName})
.schemaType(type)
.showIcons(showIcons)
.defaultOrdering(DEFAULT_SELECTED_ORDERING_OPTION.by)
.menuItemGroups([
{id: 'sorting', title: 'Sort'},
Expand Down
12 changes: 12 additions & 0 deletions packages/@sanity/structure/src/parts/Schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,24 @@ interface SchemaField {
type: SchemaType
}

interface PreviewFields {
media?: string
}

interface PreviewPreparer {
(selection: {}): PreviewFields
}

export interface SchemaType {
name: string
type?: SchemaType
to?: SchemaField[]
fields?: SchemaField[]
orderings?: Ordering[]
preview?: {
select?: PreviewFields
prepare?: PreviewPreparer
}
}

// We are lazy-loading the part to work around typescript trying to resolve it
Expand Down
16 changes: 16 additions & 0 deletions packages/@sanity/structure/test/DocumentList.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ test('builder is immutable', () => {
expect(original.filter('foo == "bar"')).not.toEqual(original)
expect(original.params({foo: 'bar'})).not.toEqual(original)
expect(original.menuItems([])).not.toEqual(original)
expect(original.showIcons(false)).not.toEqual(original)
expect(original.menuItemGroups([])).not.toEqual(original)
expect(original.defaultLayout('card')).not.toEqual(original)
expect(original.child(() => undefined)).not.toEqual(original)
Expand All @@ -128,8 +129,23 @@ test('getters work', () => {
expect(original.menuItemGroups([]).getMenuItemGroups()).toEqual([])
expect(original.defaultLayout('card').getDefaultLayout()).toEqual('card')
expect(original.child(child).getChild()).toEqual(child)
expect(original.showIcons(false).getShowIcons()).toEqual(false)
expect(original.canHandleIntent(canHandleIntent).getCanHandleIntent()).toEqual(canHandleIntent)
expect(original.defaultOrdering([{field, direction}]).getDefaultOrdering()).toEqual([
{field, direction}
])
})

test('can disable icons from being displayed', () => {
const list = S.documentList()
.title('Blåmuggost')
.filter('_type == "bluecheese"')
.showIcons(false)

expect(list.serialize()).toMatchObject({
id: 'blamuggost',
displayOptions: {showIcons: false}
})

expect(list.getShowIcons()).toBe(false)
})
13 changes: 13 additions & 0 deletions packages/@sanity/structure/test/List.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,19 @@ test('can set intent handler check', () => {
).toMatchObject({canHandleIntent: handler})
})

test('can disable icons from being displayed', () => {
const list = S.list()
.title('Blåmuggost')
.showIcons(false)

expect(list.serialize()).toMatchObject({
id: 'blamuggost',
displayOptions: {showIcons: false}
})

expect(list.getShowIcons()).toBe(false)
})

test('builder is immutable', () => {
const original = S.list()
expect(original.id('foo')).not.toEqual(original)
Expand Down
18 changes: 18 additions & 0 deletions packages/@sanity/structure/test/ListItem.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,35 @@ test('builds list items with specified schema type', () => {
).toMatchSnapshot()
})

test('builds list items with display options (dont show icon)', () => {
expect(
S.listItem({id: 'foo', title: 'Foo'})
.showIcon(false)
.serialize()
).toMatchSnapshot()
})

test('builds list items with display options (show icon)', () => {
expect(
S.listItem({id: 'foo', title: 'Foo'})
.showIcon(true)
.serialize()
).toMatchSnapshot()
})

test('builder is immutable', () => {
const original = S.listItem()
expect(original.id('foo')).not.toEqual(original)
expect(original.title('foo')).not.toEqual(original)
expect(original.child(() => undefined)).not.toEqual(original)
expect(original.schemaType('foo')).not.toEqual(original)
expect(original.showIcon(true)).not.toEqual(original)
})

test('getters work', () => {
const original = S.listItem()
expect(original.id('foo').getId()).toEqual('foo')
expect(original.title('bar').getTitle()).toEqual('bar')
expect(original.schemaType('baz').getSchemaType()).toEqual('baz')
expect(original.showIcon(true).getShowIcon()).toEqual(true)
})
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Object {
"canHandleIntent": undefined,
"child": [Function],
"defaultLayout": undefined,
"displayOptions": undefined,
"id": "books",
"menuItemGroups": Array [],
"menuItems": Array [],
Expand All @@ -31,6 +32,7 @@ Object {
"canHandleIntent": undefined,
"child": [Function],
"defaultLayout": undefined,
"displayOptions": undefined,
"id": "books",
"menuItemGroups": Array [],
"menuItems": Array [],
Expand All @@ -57,6 +59,7 @@ Object {
"canHandleIntent": undefined,
"child": [Function],
"defaultLayout": "card",
"displayOptions": undefined,
"id": "books",
"menuItemGroups": Array [],
"menuItems": Array [],
Expand All @@ -83,6 +86,7 @@ Object {
"canHandleIntent": undefined,
"child": [Function],
"defaultLayout": undefined,
"displayOptions": undefined,
"id": "foo",
"menuItemGroups": Array [],
"menuItems": Array [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ Object {
"canHandleIntent": undefined,
"child": [Function],
"defaultLayout": undefined,
"displayOptions": undefined,
"id": "asoiaf-posts",
"menuItemGroups": Array [],
"menuItems": Array [],
Expand Down

0 comments on commit 6d86c9e

Please sign in to comment.