Skip to content

Commit

Permalink
UI+server : working states displayed in UI
Browse files Browse the repository at this point in the history
  • Loading branch information
clemsos committed Jul 23, 2017
1 parent 2e6ac01 commit 678f2f4
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 87 deletions.
50 changes: 50 additions & 0 deletions client/src/components/ContentState/ContentState.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react'


const states = {
"needs_review" : {
text : "Needs Review",
color : "orange"
},
"validated" : {
text : "Validated",
color : "green"
},
"rejected" : {
text : "Rejected",
color : "red"
}
}

const style = {
border : "1px solid #ccc",
borderRadius : "5px",
fontSize : ".7em",
padding : ".5em 1em"
}

export default class ContentState extends React.Component {
render() {

let {state, errors} = this.props;

if (!errors) errors = []

let text = errors.length ?
`${errors.length} errors `
:
states[state].text

let color = errors.length ?
"red"
:
states[state].color


return (
<span style={Object.assign(style, {color, borderColor : color})}>
{text}
</span>
)
}
}
17 changes: 16 additions & 1 deletion client/src/components/Form/MultiSelect.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ export default class MultiSelect extends React.Component {

render() {

const error = this.props.error ?
<span style={{fontSize:'10pt', color : 'red'}}>
{ this.props.error }
</span>
:
null

const lis = this.props.value ?
this.props.value.map( (item, i) =>
<li key={i}
Expand All @@ -46,14 +53,21 @@ export default class MultiSelect extends React.Component {
<option key={i} value={item.value}>{item.name}</option>
)

let style= { height: '20%'};

return (
<span>
{
this.props.editing ?
<select
multiple
size={8}
style={{ height: '20%'}}
style={
this.props.error ?
Object.assign(style, {borderColor: 'red'})
:
style
}
onChange={ (e) => this.handleChange(e)}
value={this.props.value}
>
Expand All @@ -64,6 +78,7 @@ export default class MultiSelect extends React.Component {
{lis}
</ul>
}
{ this.props.error ? error : null}
</span>
)

Expand Down
1 change: 1 addition & 0 deletions client/src/components/Form/Selector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export default class Selector extends React.Component {
let optionsTags = this.props.options.map( (o,i) =>
<option key={i} value={o.value}>{o.name}</option>
)

const error = this.props.error ?
<span style={{fontSize:'10pt', color : 'red'}}>
{ this.props.error }
Expand Down
18 changes: 14 additions & 4 deletions client/src/components/GameEdit/GameEdit.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,22 @@ export default class GameEdit extends React.Component {
console.log(this.validate.errors);

if (this.validate.errors) {
this.msg.error(this.validate.errors.length + " errors.")

const errors = {}
this.validate.errors.map( error =>
errors[error.field.slice(5)] = error.message
)
let errorMsg = ""
this.validate.errors.map( error => {

let fieldName = error.field.split(".").length == 4 ?
error.field.split(".").slice(1, -1).join(".") // handle multiselect errors
:
error.field.slice(5)

errorMsg += `${fieldName} \n`
return errors[fieldName] = error.message
})

this.msg.error(`${this.validate.errors.length} errors.\n\n ${errorMsg} `)

this.setState({ errors })
} else {
this.setState({errors : {}})
Expand Down
171 changes: 112 additions & 59 deletions client/src/components/GameForm/GameForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,29 @@ import FilesList from '../Form/FilesList.jsx'

import ISO6391 from 'iso-639-1'

const requirements = [
{
name : "Nothing.",
value : "nothing"
},
{
name : "Office (printer, stationery...)",
value : "print"
},
{
name : "Wood Workshop (saw, hammer, wood...)",
value : "wood"
},
{
name : "Fab Lab (3D printer, laser cutter...)",
value : "fablab"
}
]
import ContentState from '../ContentState/ContentState.jsx'
import model from '../../../../model/game.json'

const ages = [
{ name : "Children", value : "Children"},
{ name : "Teenagers", value : "Teenagers"},
{ name : "Adults", value : "Adults"},
]
const requirements = model.properties.fabrication.properties.requirements.items.enum
.map(d => ({ value : d, name: d }))

const licenses = model.properties.credentials.properties.license.enum
.map(d => ({name : d, value : d}))

const intentions = model.properties.description.properties.intention.enum
.map(d => ({name : d, value : d}))

const gameplays = model.properties.description.properties.gameplay.enum
.map(d => ({name : d, value : d}))

const gametypes = model.properties.description.properties.type.enum
.map(d => ({name : d, value : d}))

const mechanics = model.properties.description.properties.mechanics.items.enum
.map(d => ({name : d, value : d}))

const ages = model.properties.audience.properties.age.items.enum
.map(d => ({name : d, value : d}))

// 50 last years
const years = [
Expand All @@ -48,10 +47,6 @@ const years = [
const languages = ISO6391.getLanguages(ISO6391.getAllCodes())
.map(d => ({ name : d.name, value : d.code}))

// licences
const licenses = ["CC0", "CC BY-NC-SA 4.0", "Public Domain", "No License", "Unknown"].map(d => ({name : d, value : d}))


export default class GameForm extends React.Component {

updateGame(game) {
Expand All @@ -62,12 +57,13 @@ export default class GameForm extends React.Component {
const {
audience,
credentials,
description ,
fabrication ,
source ,
description,
fabrication,
source,
state,
timestamp_add,
title ,
content_type ,
title,
content_type
} = this.props.game

const { editMode, errors } = this.props
Expand All @@ -89,31 +85,24 @@ export default class GameForm extends React.Component {
}}
/>
</h1>

{/*
// TODO : themes and genres
<FreeTagging
items={ description.themes.concat(description.genres)}
editing={editMode}
handleChange={ d => {
let game = this.props.game
game.description.themes = d.items
this.updateGame( game );
}}
/> */}

<EditableText
type="textarea"
text={description.summary}
placeholder="Add a description..."
error={errors["description.summary"]}
editing={editMode}
handleChange={ d => {
let game = this.props.game
game.description.summary = d
this.updateGame( game );
}}
/>
<p>
<ContentState
state={state}
errors={this.props.game.errors}
/>
</p>
<EditableText
type="textarea"
text={description.summary}
placeholder="Add a description..."
error={errors["description.summary"]}
editing={editMode}
handleChange={ d => {
let game = this.props.game
game.description.summary = d
this.updateGame( game );
}}
/>
<p>
Webpage:
{ !editMode ?
Expand Down Expand Up @@ -161,10 +150,74 @@ export default class GameForm extends React.Component {
this.updateGame( game );
}}
/>

</p>
<hr/>

<p>
<br/>
Intention
<Selector
editing={editMode}
value={description.intention}
error={errors["description.intention"]}
options={intentions}
handleChange={ d => {
let game = this.props.game
game.description.intention = d
this.updateGame( game );
}}
/>
<br/>
Gameplay
<Selector
editing={editMode}
value={description.gameplay}
error={errors["description.gameplay"]}
options={gameplays}
handleChange={ d => {
let game = this.props.game
game.description.gameplay = d
this.updateGame( game );
}}
/>
Type
<Selector
editing={editMode}
value={description.type}
error={errors["description.type"]}
options={gametypes}
handleChange={ d => {
let game = this.props.game
game.description.gameplay = d
this.updateGame( game );
}}
/>
<br/>
Mechanics
<MultiSelect
editing={editMode}
value={description.mechanics}
error={errors["description.mechanics"]}
options={mechanics}
handleChange={ d => {
let game = this.props.game
game.description.mechanics = d
this.updateGame( game );
}}
/>
<br />
Tags
<FreeTagging
items={description.tags}
editing={editMode}
error={errors["description.tags"]}
handleChange={ d => {
let game = this.props.game
game.description.tags = d
this.updateGame( game );
}}
/>
</p>
<hr/>
<div className="row">
<div className="six columns">
<p>
Expand Down
12 changes: 6 additions & 6 deletions client/src/components/GamesTable/GamesTable.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import DownloadButton from '../RemoteGames/DownloadButton.jsx'
import ContentState from '../ContentState/ContentState.jsx'

import ISO6391 from 'iso-639-1'

Expand Down Expand Up @@ -187,12 +188,11 @@ export default class GamesTable extends React.Component {
: null
}
</td>
<td>{
game.has_errors && game.errors.length ?
`${game.errors.length} errors `
:
game.state
}
<td>
<a style={{textDecoration: "none"}}
href={"/games/"+game.slug}>
<ContentState state={game.state} errors={game.errors} />
</a>
</td>
{
! game.existsLocally && this.props.remoteApi && this.props.localApi ?
Expand Down
6 changes: 4 additions & 2 deletions model/game.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@
"type": "array",
"minLength": 1,
"maxLength": 3,
"enum" : [
"items" : {
"enum" : [
"Jeux de rôle",
"Identité secrete",
"Bluff",
Expand All @@ -99,7 +100,8 @@
"Traditionel",
"Wargame",
"Placement"
],
]
},
"id": "mechanics",
"title": "Mechanics",
"description": "The mechanics that organize the way to play this game"
Expand Down
18 changes: 12 additions & 6 deletions public/js/bundle.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion server/ludobox/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ def read_content(path):
try :
validate_content(data)
except ValidationError as e:
data["has_errors"] = True
data["errors"] = validate_content(data, get_all_errors=True)

# add files attachments list
Expand Down

0 comments on commit 678f2f4

Please sign in to comment.