Skip to content

Commit

Permalink
Merge pull request #890 from ubyssey/peter/widget-fields
Browse files Browse the repository at this point in the history
Automatically connect field schemas
  • Loading branch information
psiemens authored Oct 26, 2018
2 parents 51d50b8 + 1b3ed64 commit 612b84f
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 129 deletions.
162 changes: 82 additions & 80 deletions dispatch/static/manager/src/js/actions/ZonesActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,89 +9,11 @@ import * as types from '../constants/ActionTypes'
import {
zoneSchema,
widgetSchema,
articleSchema,
imageSchema,
eventSchema,
topicSchema,
podcastEpisodeSchema,
} from '../constants/Schemas'

function normalizeZoneData(field, data) {
switch (field.type) {
case 'article':
return field.many ? normalize(data, arrayOf(articleSchema)) : normalize(data, articleSchema)
case 'image':
return field.many ? normalize(data, arrayOf(imageSchema)) : normalize(data, imageSchema)
case 'event':
return field.many ? normalize(data, arrayOf(eventSchema)) : normalize(data, eventSchema)
case 'topic':
return field.many ? normalize(data, arrayOf(topicSchema)) : normalize(data, topicSchema)
case 'podcast':
return field.many ? normalize(data, arrayOf(podcastEpisodeSchema)) : normalize(data, podcastEpisodeSchema)
case 'widget':
return normalizeZone(data, true)
default:
return {
result: data,
entities: {}
}
}
}
import * as fields from '../components/fields'

function normalizeZone(zone, isNestedWidget=false) {
const fields = R.path(['widget', 'fields'], zone) || []

let fieldEntities = {}

fields.forEach(field => {
if (!zone.data || !zone.data[field.name]) {
return
}

const normalizedData = normalizeZoneData(field, zone.data[field.name])

fieldEntities = R.mergeWith(
R.merge,
fieldEntities,
normalizedData.entities
)

if (field.type != 'widget') {
zone.data[field.name] = normalizedData.result
}
})

let result = !isNestedWidget ? normalize(zone, zoneSchema) : {}

result.entities = R.mergeWith(
R.merge,
result.entities,
fieldEntities
)

return result
}

function normalizeZones(zones) {
let results = []
let entities = {}

zones.forEach(zone => {
const normalizedData = normalizeZone(zone)
results.push(normalizedData.result)

entities = R.mergeWith(
R.merge,
entities,
normalizedData.entities
)
})

return {
result: results,
entities: entities
}
}
const schemaMap = initSchemaMap()

export function list(token, query) {
return {
Expand Down Expand Up @@ -160,3 +82,83 @@ export function listWidgets(token, zoneId) {
}))
}
}

function normalizeZoneData(field, data) {
if (schemaMap.has(field.type)) {
const schema = schemaMap.get(field.type)
return field.many ? normalize(data, arrayOf(schema)) : normalize(data, schema)
} else {
return {
result: data,
entities: {}
}
}
}

function normalizeZone(zone, isNestedWidget=false) {
const fields = R.path(['widget', 'fields'], zone) || []

let fieldEntities = {}

fields.forEach(field => {
if (!zone.data || !zone.data[field.name]) {
return
}

const normalizedData = normalizeZoneData(field, zone.data[field.name])

fieldEntities = R.mergeWith(
R.merge,
fieldEntities,
normalizedData.entities
)

if (field.type != 'widget') {
zone.data[field.name] = normalizedData.result
}
})

let result = !isNestedWidget ? normalize(zone, zoneSchema) : {}

result.entities = R.mergeWith(
R.merge,
result.entities,
fieldEntities
)

return result
}

function normalizeZones(zones) {
let results = []
let entities = {}

zones.forEach(zone => {
const normalizedData = normalizeZone(zone)
results.push(normalizedData.result)

entities = R.mergeWith(
R.merge,
entities,
normalizedData.entities
)
})

return {
result: results,
entities: entities
}
}

function initSchemaMap() {
var schemaMap = new Map()

for (let fieldType in fields) {
const field = fields[fieldType]
if (field.schema) {
schemaMap.set(field.type, field.schema)
}
}

return schemaMap
}
53 changes: 31 additions & 22 deletions dispatch/static/manager/src/js/components/ZoneEditor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import DocumentTitle from 'react-document-title'

import * as zonesActions from '../../actions/ZonesActions'

import ListItemToolbar from '../ItemEditor/ListItemToolbar'
import Panel from '../Panel'
import WidgetSelectInput from '../inputs/selects/WidgetSelectInput'
import * as Form from '../Form'

import Panel from '../Panel'
import FieldGroup from '../fields/FieldGroup'
import ListItemToolbar from '../ItemEditor/ListItemToolbar'
import WidgetSelectInput from '../inputs/selects/WidgetSelectInput'

class ZoneEditorComponent extends React.Component {

Expand All @@ -35,24 +34,10 @@ class ZoneEditorComponent extends React.Component {
return zone
}

function processWidget(widget, fields) {
if (!fields) {
return widget
}

fields.forEach((field) => {
if (field.type == 'widget') {
const newWidget = R.path(['data', field.name], widget)
if (newWidget) {
widget.data[field.name] = processWidget(newWidget, R.path(['widget', 'fields'], newWidget))
widget = R.dissocPath(['data', field.name, 'widget'], widget)
}
}
})
return widget
}

return processWidget(zone, R.prop('fields', this.props.widget || {}))
return processNestedWidgets(
zone,
R.prop('fields', this.props.widget || {})
)
}

saveZone() {
Expand Down Expand Up @@ -112,6 +97,30 @@ class ZoneEditorComponent extends React.Component {
}
}

function processNestedWidgets(widget, fields) {
if (!fields) {
return widget
}

fields.forEach((field) => {
if (field.type == 'widget') {
const newWidget = R.path(['data', field.name], widget)

if (newWidget) {

widget.data[field.name] = processNestedWidgets(
newWidget,
R.path(['widget', 'fields'], newWidget)
)

widget = R.dissocPath(['data', field.name, 'widget'], widget)
}
}
})

return widget
}

const mapStateToProps = (state) => {
const zone = state.app.entities.local.zones[state.app.zones.single.id]
const widget = zone ? state.app.entities.widgets[zone.widget] : null
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import React from 'react'

import { articleSchema } from '../../constants/Schemas'

import ArticleSelectInput from '../inputs/selects/ArticleSelectInput'

export default function ArticleField(props) {
function ArticleField(props) {
return (
<ArticleSelectInput
value={props.data}
many={props.field.many}
onChange={selected => props.onChange(selected)} />
)
}

ArticleField.type = 'article'
ArticleField.schema = articleSchema

export default ArticleField
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import React from 'react'

import { eventSchema } from '../../constants/Schemas'

import EventSelectInput from '../inputs/selects/EventSelectInput'

export default function EventField(props) {
function EventField(props) {
return (
<EventSelectInput
value={props.data}
many={props.field.many}
onChange={selected => props.onChange(selected)} />
)
}

EventField.type = 'event'
EventField.schema = eventSchema

export default EventField
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import React from 'react'

import { imageSchema } from '../../constants/Schemas'

import ImageInput from '../inputs/ImageInput'

export default function ImageField(props) {
function ImageField(props) {
return (
<ImageInput
removable={false}
Expand All @@ -11,3 +13,8 @@ export default function ImageField(props) {
onChange={selected => props.onChange(selected)} />
)
}

ImageField.type = 'image'
ImageField.schema = imageSchema

export default ImageField
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import React from 'react'

import { podcastEpisodeSchema } from '../../constants/Schemas'

import PodcastEpisodeSelectInput from '../inputs/selects/PodcastEpisodeSelectInput'

export default function PodcastField(props) {
function PodcastField(props) {
return (
<PodcastEpisodeSelectInput
value={props.data}
many={props.field.many}
onChange={selected => props.onChange(selected)} />
)
}

PodcastField.type = 'podcast'
PodcastField.schema = podcastEpisodeSchema

export default PodcastField
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import React from 'react'

import { pollSchema } from '../../constants/Schemas'

import PollSelectInput from '../inputs/selects/PollSelectInput'

export default function PollField(props) {
function PollField(props) {
return (
<PollSelectInput
value={props.data}
many={props.field.many}
onChange={selected => props.onChange(selected)} />
)
}

PollField.type = 'poll'
PollField.schema = pollSchema

export default PollField
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import React from 'react'

import { topicSchema } from '../../constants/Schemas'

import TopicSelectInput from '../inputs/selects/TopicSelectInput'

export default function TopicField(props) {
function TopicField(props) {
return (
<TopicSelectInput
value={props.data}
many={props.field.many}
update={selected => props.onChange(selected)} />
)
}

TopicField.type = 'topic'
TopicField.schema = topicSchema

export default TopicField
Loading

0 comments on commit 612b84f

Please sign in to comment.