Ivan - WIP [skip ci]
This commit is contained in:
parent
88f7e82e77
commit
7b9b3392a3
|
@ -0,0 +1,72 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import i18n from 'lib-app/i18n';
|
||||||
|
import API from 'lib-app/api-call';
|
||||||
|
|
||||||
|
import Header from 'core-components/header';
|
||||||
|
import Button from 'core-components/button';
|
||||||
|
import Form from 'core-components/form';
|
||||||
|
import FormField from 'core-components/form-field';
|
||||||
|
import SubmitButton from 'core-components/submit-button';
|
||||||
|
import IconSelector from 'core-components/icon-selector';
|
||||||
|
import ColorSelector from 'core-components/color-selector';
|
||||||
|
|
||||||
|
class TopicEditModal extends React.Component {
|
||||||
|
|
||||||
|
static contextTypes = {
|
||||||
|
closeModal: React.PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
defaultValues: React.PropTypes.object,
|
||||||
|
topicId: React.PropTypes.number
|
||||||
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
values: this.props.defaultValues
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="topic-edit-modal">
|
||||||
|
<Header title={i18n('EDIT_TOPIC')} description={i18n('EDIT_TOPIC_DESCRIPTION')} />
|
||||||
|
<Form values={this.state.values} onChange={this.onFormChange.bind(this)} onSubmit={this.onSubmit.bind(this)}>
|
||||||
|
<FormField name="title" label={i18n('TITLE')} />
|
||||||
|
<FormField name="icon" label={i18n('ICON')} decorator={IconSelector} />
|
||||||
|
<FormField name="color" label={i18n('COLOR')} decorator={ColorSelector} />
|
||||||
|
|
||||||
|
<SubmitButton type="secondary" size="small">
|
||||||
|
{i18n('SAVE')}
|
||||||
|
</SubmitButton>
|
||||||
|
<Button onDiscardClick={this.onDiscardClick.bind(this)}>{i18n('DISCARD_CHANGES')}</Button>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
API.call({
|
||||||
|
path: '/article/edit-topic',
|
||||||
|
data: {
|
||||||
|
topicId: this.props.topicId,
|
||||||
|
name: this.state.values['name'],
|
||||||
|
icon: this.state.values['icon'],
|
||||||
|
iconColor: this.state.values['color']
|
||||||
|
}
|
||||||
|
}).then(this.context.closeModal);
|
||||||
|
}
|
||||||
|
|
||||||
|
onFormChange(form) {
|
||||||
|
this.setState({
|
||||||
|
values: form
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onDiscardClick() {
|
||||||
|
this.setState({
|
||||||
|
values: this.props.defaultValues
|
||||||
|
}, this.context.closeModal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TopicEditModal;
|
|
@ -1,29 +1,78 @@
|
||||||
import React from 'react'
|
import React from 'react';
|
||||||
import Icon from 'core-components/icon'
|
import {Link} from 'react-router';
|
||||||
|
|
||||||
|
import i18n from 'lib-app/i18n';
|
||||||
|
import API from 'lib-app/api-call';
|
||||||
|
import ModalContainer from 'app-components/modal-container';
|
||||||
|
import TopicEditModal from 'app-components/topic-edit-modal';
|
||||||
|
|
||||||
|
import Header from 'core-components/header';
|
||||||
|
import Icon from 'core-components/icon';
|
||||||
|
import Button from 'core-components/button';
|
||||||
|
|
||||||
class TopicViewer extends React.Component {
|
class TopicViewer extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
topicId: React.PropTypes.number.isRequired,
|
||||||
name: React.PropTypes.string.isRequired,
|
name: React.PropTypes.string.isRequired,
|
||||||
icon: React.PropTypes.string.isRequired,
|
icon: React.PropTypes.string.isRequired,
|
||||||
iconColor: React.PropTypes.string.isRequired,
|
iconColor: React.PropTypes.string.isRequired,
|
||||||
articles: React.PropTypes.array.isRequired
|
articles: React.PropTypes.array.isRequired,
|
||||||
|
articlePath: React.PropTypes.string,
|
||||||
|
editable: React.PropTypes.bool
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
articlePath: '/admin/panel/articles/view-article/',
|
||||||
|
editable: true
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="topic-viewer">
|
<div className="topic-viewer">
|
||||||
<div className="topic-viewer__header">
|
<div className="topic-viewer__header">
|
||||||
<Icon className="topic-viewer__icon" name={this.props.icon} size="2x" color={this.props.iconColor}/>
|
<Icon className="topic-viewer__icon" name={this.props.icon} color={this.props.iconColor}/>
|
||||||
<span className="topic-viewer__title">{this.props.name}</span>
|
<span className="topic-viewer__title">{this.props.name}</span>
|
||||||
|
{(this.props.editable) ? this.renderEditButton() : null}
|
||||||
</div>
|
</div>
|
||||||
<ul className="topic-viewer__list">
|
<ul className="topic-viewer__list">
|
||||||
{this.props.articles.map(function (article) {
|
{this.props.articles.map(this.renderArticleItem.bind(this))}
|
||||||
return <li className="topic-viewer__list-item">{article.title}</li>
|
|
||||||
})}
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderEditButton() {
|
||||||
|
return (
|
||||||
|
<span onClick={() => {ModalContainer.openModal(this.renderEditModal());}}>
|
||||||
|
<Icon className="topic-viewer__edit-icon" name="pencil" />
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderArticleItem(article) {
|
||||||
|
return (
|
||||||
|
<li className="topic-viewer__list-item">
|
||||||
|
<Link className="topic-viewer__list-item-button" to={this.props.articlePath + article.id}>
|
||||||
|
{article.title}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEditModal() {
|
||||||
|
let props = {
|
||||||
|
topicId: this.props.topicId,
|
||||||
|
defaultValues: {
|
||||||
|
title: this.props.name,
|
||||||
|
icon: this.props.icon,
|
||||||
|
iconColor: this.props.iconColor
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TopicEditModal {...props} />
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TopicViewer;
|
export default TopicViewer;
|
|
@ -2,17 +2,35 @@
|
||||||
|
|
||||||
.topic-viewer {
|
.topic-viewer {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
//font-weight: bold;
|
|
||||||
&__header {
|
&__header {
|
||||||
|
cursor: default;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
|
font-size: $font-size--bg;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.topic-viewer__edit-icon {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__icon {
|
&__icon {
|
||||||
color: $primary-green;
|
color: $primary-green;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
font-size: $font-size--lg;
|
font-size: $font-size--md;
|
||||||
margin-left: 15px;
|
margin-left: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__edit-icon {
|
||||||
|
color: $grey;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-left: 10px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
&__list {
|
&__list {
|
||||||
&-item {
|
&-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -31,5 +49,9 @@
|
||||||
&-item:nth-child(odd) {
|
&-item:nth-child(odd) {
|
||||||
//background: green;
|
//background: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-item-button {
|
||||||
|
color: $secondary-blue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -97,7 +97,7 @@ export default (
|
||||||
<Route path="articles">
|
<Route path="articles">
|
||||||
<IndexRedirect to="list-articles" />
|
<IndexRedirect to="list-articles" />
|
||||||
<Route path="list-articles" component={AdminPanelListArticles} />
|
<Route path="list-articles" component={AdminPanelListArticles} />
|
||||||
<Route path="view-article" component={AdminPanelViewArticle} />
|
<Route path="view-article/:articleId" component={AdminPanelViewArticle} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<Route path="staff">
|
<Route path="staff">
|
||||||
|
|
|
@ -29,7 +29,7 @@ class AdminPanelListArticles extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{this.state.topics.map(function (topic) {
|
{this.state.topics.map(function (topic) {
|
||||||
return <TopicViewer {...topic} />
|
return <TopicViewer {...topic} topicId={topic.id} />
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Tooltip from 'core-components/tooltip';
|
||||||
|
|
||||||
|
const colors = ['#ff6900', '#fcb900', '#7bdcb5', '#00d084', '#8ed1fc', '#0693e3', '#abb8c3', '#eb144c', '#f78da7', '#9900ef'];
|
||||||
|
|
||||||
|
class ColorSelector extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
value: React.PropTypes.string,
|
||||||
|
onChange: React.PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
value: '#ff6900'
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="color-selector">
|
||||||
|
<Tooltip content={this.renderTooltipContent()}>
|
||||||
|
<span className="color-selector__current" style={{backgroundColor: this.props.value}} />
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTooltipContent() {
|
||||||
|
return (
|
||||||
|
<div className="color-selector__tooltip">
|
||||||
|
{colors.map(this.renderTooltipColor.bind(this))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTooltipColor(color) {
|
||||||
|
return (
|
||||||
|
<span className="color-selector__tooltip-color" onClick={this.onColorClick.bind(this, color)} style={{backgroundColor: color}}/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onColorClick(color) {
|
||||||
|
if(this.props.onChange) {
|
||||||
|
this.props.onChange({target: {value: color}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default ColorSelector;
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,3 @@
|
||||||
|
.icon-selector {
|
||||||
|
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ module.exports = [
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Membership Settings',
|
name: 'Membership Settings',
|
||||||
icon: 'user',
|
icon: 'user',
|
||||||
iconColor: 'green',
|
iconColor: '#82CA9C',
|
||||||
articles: [
|
articles: [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
|
@ -95,5 +95,45 @@ module.exports = [
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/article/edit-topic',
|
||||||
|
time: 100,
|
||||||
|
response: function () {
|
||||||
|
return {
|
||||||
|
status: 'success',
|
||||||
|
data: {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/article/edit',
|
||||||
|
time: 100,
|
||||||
|
response: function () {
|
||||||
|
return {
|
||||||
|
status: 'success',
|
||||||
|
data: {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/article/add',
|
||||||
|
time: 100,
|
||||||
|
response: function () {
|
||||||
|
return {
|
||||||
|
status: 'success',
|
||||||
|
data: {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/article/add-topic',
|
||||||
|
time: 100,
|
||||||
|
response: function () {
|
||||||
|
return {
|
||||||
|
status: 'success',
|
||||||
|
data: {}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
|
@ -23,5 +23,6 @@ $half-space: 20px;
|
||||||
$font-size--xs: 11px;
|
$font-size--xs: 11px;
|
||||||
$font-size--sm: 13px;
|
$font-size--sm: 13px;
|
||||||
$font-size--md: 16px;
|
$font-size--md: 16px;
|
||||||
|
$font-size--bg: 19px;
|
||||||
$font-size--lg: 24px;
|
$font-size--lg: 24px;
|
||||||
$font-size--xl: 32px;
|
$font-size--xl: 32px;
|
Loading…
Reference in New Issue