mirror of
https://github.com/opensupports/opensupports.git
synced 2025-07-27 15:54:23 +02:00
Styles standardization (#934)
* WIP tag create and tag edit pop up * WIP admin panel email settings * WIP admin panel viwe article, article list, edit topic, add article * WIP admin panel list users and invite user widget * WIP admin panel view user * WIP admin panel custom fields and admin panel custom field form * WIP fix plus icon position and type * WIP admin panel custom responses * WIP admin panle my tickets and create ticket form * change check ticket button to green color * WIP dashboard edit profile page * Change icon in invite user button * WIP
This commit is contained in:
parent
3dd76f214d
commit
af3d95cf4d
@ -32,11 +32,11 @@ class ArticleAddModal extends React.Component {
|
|||||||
<Form onSubmit={this.onAddNewArticleFormSubmit.bind(this)} loading={this.state.loading}>
|
<Form onSubmit={this.onAddNewArticleFormSubmit.bind(this)} loading={this.state.loading}>
|
||||||
<FormField name="title" label={i18n('TITLE')} field="input" fieldProps={{size: 'large'}} validation="TITLE" required/>
|
<FormField name="title" label={i18n('TITLE')} field="input" fieldProps={{size: 'large'}} validation="TITLE" required/>
|
||||||
<FormField name="content" label={i18n('CONTENT')} field="textarea" validation="TEXT_AREA" required fieldProps={{allowImages: this.props.allowAttachments}}/>
|
<FormField name="content" label={i18n('CONTENT')} field="textarea" validation="TEXT_AREA" required fieldProps={{allowImages: this.props.allowAttachments}}/>
|
||||||
<SubmitButton type="secondary">{i18n('ADD_ARTICLE')}</SubmitButton>
|
|
||||||
<Button className="article-add-modal__cancel-button" type="link" onClick={(event) => {
|
<Button className="article-add-modal__cancel-button" type="link" onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
ModalContainer.closeModal();
|
ModalContainer.closeModal();
|
||||||
}}>{i18n('CANCEL')}</Button>
|
}}>{i18n('CANCEL')}</Button>
|
||||||
|
<SubmitButton className="article-add-modal__submit-button" type="secondary">{i18n('ADD_ARTICLE')}</SubmitButton>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
width: 800px;
|
width: 800px;
|
||||||
|
|
||||||
&__cancel-button {
|
&__cancel-button {
|
||||||
float: right;
|
float: left;
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__submit-button {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
}
|
}
|
@ -36,11 +36,13 @@ class ArticlesList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if(this.props.errored) {
|
const { errored, loading } = this.props;
|
||||||
|
|
||||||
|
if(errored) {
|
||||||
return <Message type="error">{i18n('ERROR_RETRIEVING_ARTICLES')}</Message>;
|
return <Message type="error">{i18n('ERROR_RETRIEVING_ARTICLES')}</Message>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (this.props.loading) ? <Loading /> : this.renderContent();
|
return loading ? <Loading /> : this.renderContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderContent() {
|
renderContent() {
|
||||||
@ -53,17 +55,19 @@ class ArticlesList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderTopics() {
|
renderTopics() {
|
||||||
|
const { topics, editable, articlePath } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="articles-list__topics">
|
<div className="articles-list__topics">
|
||||||
{this.props.topics.map((topic, index) => {
|
{topics.map((topic, index) => {
|
||||||
return (
|
return (
|
||||||
<div key={index}>
|
<div key={index}>
|
||||||
<TopicViewer
|
<TopicViewer
|
||||||
{...topic}
|
{...topic}
|
||||||
id={topic.id * 1}
|
id={topic.id * 1}
|
||||||
editable={this.props.editable}
|
editable={editable}
|
||||||
onChange={this.retrieveArticles.bind(this)}
|
onChange={this.retrieveArticles.bind(this)}
|
||||||
articlePath={this.props.articlePath} />
|
articlePath={articlePath} />
|
||||||
<span className="separator" />
|
<span className="separator" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -76,7 +80,7 @@ class ArticlesList extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="articles-list__add-topic-button">
|
<div className="articles-list__add-topic-button">
|
||||||
<Button onClick={() => ModalContainer.openModal(<TopicEditModal addForm onChange={this.retrieveArticles.bind(this)} />)} type="secondary" className="articles-list__add">
|
<Button onClick={() => ModalContainer.openModal(<TopicEditModal addForm onChange={this.retrieveArticles.bind(this)} />)} type="secondary" className="articles-list__add">
|
||||||
<Icon name="plus-circle" size="2x" className="articles-list__add-icon"/> {i18n('ADD_TOPIC')}
|
<Icon name="plus" className="articles-list__add-icon" /> {i18n('ADD_TOPIC')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -88,9 +92,11 @@ class ArticlesList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default connect((store) => {
|
export default connect((store) => {
|
||||||
|
const { topics, errored, loading } = store.articles;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
topics: store.articles.topics.map((topic) => {return {...topic, private: topic.private === "1"}}),
|
topics: topics.map((topic) => {return {...topic, private: topic.private === "1"}}),
|
||||||
errored: store.articles.errored,
|
errored,
|
||||||
loading: store.articles.loading
|
loading
|
||||||
};
|
};
|
||||||
})(ArticlesList);
|
})(ArticlesList);
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
@import "../scss/vars";
|
@import "../scss/vars";
|
||||||
|
|
||||||
.articles-list {
|
.articles-list {
|
||||||
|
|
||||||
&__add {
|
&__add {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__add-icon {
|
&__add-topic-button {
|
||||||
position: absolute;
|
display: flex;
|
||||||
left: 10px;
|
flex-direction: row;
|
||||||
margin-top: -4px;
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -37,15 +37,16 @@ class TopicEditModal extends React.Component {
|
|||||||
<FormField name="title" label={i18n('TITLE')} fieldProps={{size: 'large'}} validation="TITLE" required />
|
<FormField name="title" label={i18n('TITLE')} fieldProps={{size: 'large'}} validation="TITLE" required />
|
||||||
<FormField name="icon" className="topic-edit-modal__icon" label={i18n('ICON')} decorator={IconSelector} />
|
<FormField name="icon" className="topic-edit-modal__icon" label={i18n('ICON')} decorator={IconSelector} />
|
||||||
<FormField name="color" className="topic-edit-modal__color" label={i18n('COLOR')} decorator={ColorSelector} />
|
<FormField name="color" className="topic-edit-modal__color" label={i18n('COLOR')} decorator={ColorSelector} />
|
||||||
<FormField className="topic-edit-modal__private" label={i18n('PRIVATE')} name="private" field="checkbox"/>
|
<FormField className="topic-edit-modal__private" label={i18n('PRIVATE')} name="private" field="checkbox" />
|
||||||
<InfoTooltip className="topic-edit-modal__private" text={i18n('PRIVATE_TOPIC_DESCRIPTION')} />
|
<InfoTooltip className="topic-edit-modal__private" text={i18n('PRIVATE_TOPIC_DESCRIPTION')} />
|
||||||
|
<div className="topic-edit-modal__buttons-container">
|
||||||
<SubmitButton className="topic-edit-modal__save-button" type="secondary" size="small">
|
|
||||||
{i18n('SAVE')}
|
|
||||||
</SubmitButton>
|
|
||||||
<Button className="topic-edit-modal__discard-button" onClick={this.onDiscardClick.bind(this)} size="small">
|
<Button className="topic-edit-modal__discard-button" onClick={this.onDiscardClick.bind(this)} size="small">
|
||||||
{i18n('CANCEL')}
|
{i18n('CANCEL')}
|
||||||
</Button>
|
</Button>
|
||||||
|
<SubmitButton className="topic-edit-modal__save-button" type="secondary" size="small">
|
||||||
|
{i18n('SAVE')}
|
||||||
|
</SubmitButton>
|
||||||
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -13,9 +13,19 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__discard-button {
|
&__buttons-container {
|
||||||
float: right;
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 20px 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__discard-button {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
&__private {
|
&__private {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
|
@ -66,12 +66,12 @@ class AdminPanelViewArticle extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="admin-panel-view-article__content">
|
<div className="admin-panel-view-article__content">
|
||||||
<div className="admin-panel-view-article__edit-buttons">
|
<div className="admin-panel-view-article__edit-buttons">
|
||||||
<Button className="admin-panel-view-article__edit-button" size="medium" onClick={this.onEditClick.bind(this, article)} type="tertiary">
|
|
||||||
{i18n('EDIT')}
|
|
||||||
</Button>
|
|
||||||
<Button size="medium" onClick={this.onDeleteClick.bind(this, article)}>
|
<Button size="medium" onClick={this.onDeleteClick.bind(this, article)}>
|
||||||
{i18n('DELETE')}
|
{i18n('DELETE')}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button className="admin-panel-view-article__edit-button" size="medium" onClick={this.onEditClick.bind(this, article)} type="tertiary">
|
||||||
|
{i18n('EDIT')}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="admin-panel-view-article__article">
|
<div className="admin-panel-view-article__article">
|
||||||
<Header title={article.title}/>
|
<Header title={article.title}/>
|
||||||
@ -91,10 +91,10 @@ class AdminPanelViewArticle extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<Form values={this.state.form} onChange={(form) => this.setState({form})} onSubmit={this.onFormSubmit.bind(this)}>
|
<Form values={this.state.form} onChange={(form) => this.setState({form})} onSubmit={this.onFormSubmit.bind(this)}>
|
||||||
<div className="admin-panel-view-article__buttons">
|
<div className="admin-panel-view-article__buttons">
|
||||||
<SubmitButton className="admin-panel-view-article__button" type="secondary" size="medium">{i18n('SAVE')}</SubmitButton>
|
|
||||||
<Button className="admin-panel-view-article__button" size="medium" onClick={this.onFormCancel.bind(this)}>
|
<Button className="admin-panel-view-article__button" size="medium" onClick={this.onFormCancel.bind(this)}>
|
||||||
{i18n('CANCEL')}
|
{i18n('CANCEL')}
|
||||||
</Button>
|
</Button>
|
||||||
|
<SubmitButton className="admin-panel-view-article__button" type="secondary" size="medium">{i18n('SAVE')}</SubmitButton>
|
||||||
</div>
|
</div>
|
||||||
<FormField name="title" label={i18n('TITLE')} />
|
<FormField name="title" label={i18n('TITLE')} />
|
||||||
<FormField name="content" label={i18n('CONTENT')} field="textarea" validation="TEXT_AREA" required fieldProps={{allowImages: this.props.allowAttachments}}/>
|
<FormField name="content" label={i18n('CONTENT')} field="textarea" validation="TEXT_AREA" required fieldProps={{allowImages: this.props.allowAttachments}}/>
|
||||||
|
@ -5,7 +5,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__edit-buttons {
|
&__edit-buttons {
|
||||||
text-align: left;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 200px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@ import ColorSelector from 'core-components/color-selector';
|
|||||||
|
|
||||||
class AdminPanelCustomTagsModal extends React.Component {
|
class AdminPanelCustomTagsModal extends React.Component {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
closeModal: React.PropTypes.func
|
closeModal: React.PropTypes.func,
|
||||||
|
createTag: React.PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -27,56 +28,49 @@ class AdminPanelCustomTagsModal extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
this.props.createTag ? this.renderCreateTagContent() : this.renderEditTagContent()
|
this.renderTagContentPopUp(this.props.createTag)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderEditTagContent() {
|
renderTagContentPopUp(create) {
|
||||||
return (
|
const {
|
||||||
<div className='admin-panel-custom-tags-modal'>
|
form,
|
||||||
<Header title={i18n('EDIT_CUSTOM_TAG')} description={i18n('DESCRIPTION_EDIT_CUSTOM_TAG')} />
|
errors,
|
||||||
<Form
|
loading,
|
||||||
values={this.state.form}
|
} = this.state;
|
||||||
onChange={this.onFormChange.bind(this)}
|
let title, description, nameRequired, submitFunction;
|
||||||
onSubmit={this.onSubmitEditTag.bind(this)}
|
|
||||||
errors={this.state.errors}
|
if(create) {
|
||||||
onValidateErrors={errors => this.setState({errors})}
|
title = i18n('ADD_CUSTOM_TAG');
|
||||||
loading={this.state.loading}>
|
description = i18n('DESCRIPTION_ADD_CUSTOM_TAG');
|
||||||
<FormField name="name" label={i18n('NAME')} fieldProps={{size: 'large'}}/>
|
submitFunction = this.onSubmitNewTag.bind(this);
|
||||||
<FormField name="color" label={i18n('COLOR')} decorator={ColorSelector} />
|
nameRequired = true;
|
||||||
<div className='admin-panel-custom-tags-modal__actions'>
|
} else {
|
||||||
<SubmitButton type="secondary" size="small">
|
title = i18n('EDIT_CUSTOM_TAG');
|
||||||
{i18n('SAVE')}
|
description = i18n('DESCRIPTION_EDIT_CUSTOM_TAG');
|
||||||
</SubmitButton>
|
nameRequired = false;
|
||||||
<Button onClick={this.onDiscardClick.bind(this)} size="small">
|
submitFunction = this.onSubmitEditTag.bind(this);
|
||||||
{i18n('CANCEL')}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCreateTagContent() {
|
|
||||||
return (
|
return (
|
||||||
<div className='admin-panel-custom-tags-modal'>
|
<div className='admin-panel-custom-tags-modal'>
|
||||||
<Header title={i18n('ADD_CUSTOM_TAG')} description={i18n('DESCRIPTION_ADD_CUSTOM_TAG')} />
|
<Header title={title} description={description} />
|
||||||
<Form
|
<Form
|
||||||
values={this.state.form}
|
values={form}
|
||||||
onChange={this.onFormChange.bind(this)}
|
onChange={this.onFormChange.bind(this)}
|
||||||
onSubmit={this.onSubmitNewTag.bind(this)}
|
onSubmit={submitFunction}
|
||||||
errors={this.state.errors}
|
errors={errors}
|
||||||
onValidateErrors={errors => this.setState({errors})}
|
onValidateErrors={errors => this.setState({errors})}
|
||||||
loading={this.state.loading}>
|
loading={loading}>
|
||||||
<FormField name="name" label={i18n('NAME')} fieldProps={{size: 'large'}} required />
|
<FormField name="name" label={i18n('NAME')} fieldProps={{size: 'large'}} required={nameRequired} />
|
||||||
<FormField name="color" label={i18n('COLOR')} decorator={ColorSelector} />
|
<FormField name="color" label={i18n('COLOR')} decorator={ColorSelector} />
|
||||||
<div className='admin-panel-custom-tags-modal__actions'>
|
<div className='admin-panel-custom-tags-modal__actions'>
|
||||||
<SubmitButton type="secondary" size="small">
|
|
||||||
{i18n('SAVE')}
|
|
||||||
</SubmitButton>
|
|
||||||
<Button onClick={this.onDiscardClick.bind(this)} size="small">
|
<Button onClick={this.onDiscardClick.bind(this)} size="small">
|
||||||
{i18n('CANCEL')}
|
{i18n('CANCEL')}
|
||||||
</Button>
|
</Button>
|
||||||
|
<SubmitButton type="secondary" size="small">
|
||||||
|
{i18n('SAVE')}
|
||||||
|
</SubmitButton>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,7 +44,7 @@ class AdminPanelCustomTags extends React.Component {
|
|||||||
<div className="admin-panel-custom-tags__content">
|
<div className="admin-panel-custom-tags__content">
|
||||||
<div>
|
<div>
|
||||||
<Button onClick={this.openTagModal.bind(this)} type="secondary">
|
<Button onClick={this.openTagModal.bind(this)} type="secondary">
|
||||||
{i18n('ADD_CUSTOM_TAG')}<Icon className="admin-panel-custom-tags__add-button-icon" name="plus"/>
|
<Icon className="admin-panel-custom-tags__add-button-icon" name="plus" /> {i18n('ADD_CUSTOM_TAG')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="admin-panel-custom-tags__tag-list">
|
<div className="admin-panel-custom-tags__tag-list">
|
||||||
@ -77,13 +77,13 @@ class AdminPanelCustomTags extends React.Component {
|
|||||||
|
|
||||||
openEditTagModal(tagId,tagName,tagColor, event) {
|
openEditTagModal(tagId,tagName,tagColor, event) {
|
||||||
ModalContainer.openModal(
|
ModalContainer.openModal(
|
||||||
<AdminPanelCustomTagsModal defaultValues={{name: tagName , color: tagColor}} id={tagId} onTagChange={this.retrieveCustomTags.bind(this)}/>
|
<AdminPanelCustomTagsModal defaultValues={{name: tagName , color: tagColor}} id={tagId} onTagChange={this.retrieveCustomTags.bind(this)} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDeleteClick(tagId, event) {
|
onDeleteClick(tagId, event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
AreYouSure.openModal(i18n('WILL_DELETE_CUSTOM_RESPONSE'), this.deleteCustomTag.bind(this, tagId));
|
AreYouSure.openModal(i18n('WILL_DELETE_CUSTOM_TAG'), this.deleteCustomTag.bind(this, tagId));
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteCustomTag(tagId) {
|
deleteCustomTag(tagId) {
|
||||||
|
@ -138,11 +138,12 @@ class AdminPanelEmailSettings extends React.Component {
|
|||||||
<FormField name="smtp-user" label={i18n('SMTP_USER')} fieldProps={{size: 'large'}} />
|
<FormField name="smtp-user" label={i18n('SMTP_USER')} fieldProps={{size: 'large'}} />
|
||||||
<FormField name="smtp-pass" label={i18n('SMTP_PASSWORD')} fieldProps={{size: 'large', autoComplete: 'off'}} />
|
<FormField name="smtp-pass" label={i18n('SMTP_PASSWORD')} fieldProps={{size: 'large', autoComplete: 'off'}} />
|
||||||
<div className="admin-panel-email-settings__server-form-buttons">
|
<div className="admin-panel-email-settings__server-form-buttons">
|
||||||
<SubmitButton className="admin-panel-email-settings__submit" type="secondary"
|
|
||||||
size="small">{i18n('SAVE')}</SubmitButton>
|
|
||||||
<SubmitButton type="tertiary" size="small" onClick={this.testSMTP.bind(this)}>
|
<SubmitButton type="tertiary" size="small" onClick={this.testSMTP.bind(this)}>
|
||||||
{i18n('TEST')}
|
{i18n('TEST')}
|
||||||
</SubmitButton>
|
</SubmitButton>
|
||||||
|
<SubmitButton className="admin-panel-email-settings__submit" type="secondary" size="small">
|
||||||
|
{i18n('SAVE')}
|
||||||
|
</SubmitButton>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
@ -160,11 +161,12 @@ class AdminPanelEmailSettings extends React.Component {
|
|||||||
infoMessage={i18n('IMAP_TOKEN_DESCRIPTION')}
|
infoMessage={i18n('IMAP_TOKEN_DESCRIPTION')}
|
||||||
fieldProps={{size: 'large', icon: 'refresh', onIconClick: this.generateImapToken.bind(this)}} />
|
fieldProps={{size: 'large', icon: 'refresh', onIconClick: this.generateImapToken.bind(this)}} />
|
||||||
<div className="admin-panel-email-settings__server-form-buttons">
|
<div className="admin-panel-email-settings__server-form-buttons">
|
||||||
<SubmitButton className="admin-panel-email-settings__submit" type="secondary"
|
|
||||||
size="small">{i18n('SAVE')}</SubmitButton>
|
|
||||||
<SubmitButton type="tertiary" size="small" onClick={this.testIMAP.bind(this)}>
|
<SubmitButton type="tertiary" size="small" onClick={this.testIMAP.bind(this)}>
|
||||||
{i18n('TEST')}
|
{i18n('TEST')}
|
||||||
</SubmitButton>
|
</SubmitButton>
|
||||||
|
<SubmitButton className="admin-panel-email-settings__submit" type="secondary" size="small">
|
||||||
|
{i18n('SAVE')}
|
||||||
|
</SubmitButton>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
<Message className="admin-panel-email-settings__imap-message" type="info">
|
<Message className="admin-panel-email-settings__imap-message" type="info">
|
||||||
@ -177,10 +179,16 @@ class AdminPanelEmailSettings extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderForm() {
|
renderForm() {
|
||||||
|
const {
|
||||||
|
form,
|
||||||
|
language,
|
||||||
|
selectedIndex,
|
||||||
|
edited
|
||||||
|
} = this.state;
|
||||||
return (
|
return (
|
||||||
<div className="col-md-9">
|
<div className="col-md-9">
|
||||||
<FormField label={i18n('LANGUAGE')} decorator={LanguageSelector} value={this.state.language}
|
<FormField label={i18n('LANGUAGE')} decorator={LanguageSelector} value={language}
|
||||||
onChange={event => this.onItemChange(this.state.selectedIndex, event.target.value)}
|
onChange={event => this.onItemChange(selectedIndex, event.target.value)}
|
||||||
fieldProps={{
|
fieldProps={{
|
||||||
type: 'allowed',
|
type: 'allowed',
|
||||||
size: 'medium'
|
size: 'medium'
|
||||||
@ -196,29 +204,32 @@ class AdminPanelEmailSettings extends React.Component {
|
|||||||
<FormField key="text1" label={i18n('TEXT') + '1'} name="text1" validation="TEXT_AREA" required
|
<FormField key="text1" label={i18n('TEXT') + '1'} name="text1" validation="TEXT_AREA" required
|
||||||
decorator={'textarea'}
|
decorator={'textarea'}
|
||||||
fieldProps={{className: 'admin-panel-email-settings__text-area'}} />
|
fieldProps={{className: 'admin-panel-email-settings__text-area'}} />
|
||||||
{(this.state.form.text2) ?
|
{(form.text2) ?
|
||||||
<FormField key="text2" label={i18n('TEXT') + '2'} name="text2" validation="TEXT_AREA" required
|
<FormField key="text2" label={i18n('TEXT') + '2'} name="text2" validation="TEXT_AREA" required
|
||||||
decorator={'textarea'}
|
decorator={'textarea'}
|
||||||
fieldProps={{className: 'admin-panel-email-settings__text-area'}} /> : null}
|
fieldProps={{className: 'admin-panel-email-settings__text-area'}} /> : null}
|
||||||
{(this.state.form.text3) ?
|
{(form.text3) ?
|
||||||
<FormField key="text3" label={i18n('TEXT') + '3'} name="text3" validation="TEXT_AREA" required
|
<FormField key="text3" label={i18n('TEXT') + '3'} name="text3" validation="TEXT_AREA" required
|
||||||
decorator={'textarea'}
|
decorator={'textarea'}
|
||||||
fieldProps={{className: 'admin-panel-email-settings__text-area'}} /> : null}
|
fieldProps={{className: 'admin-panel-email-settings__text-area'}} /> : null}
|
||||||
|
|
||||||
<div className="admin-panel-email-settings__actions">
|
<div className="admin-panel-email-settings__actions">
|
||||||
<div className="admin-panel-email-settings__save-button">
|
|
||||||
<SubmitButton key="submit-email-template" type="secondary" size="small" onClick={e => {
|
|
||||||
e.preventDefault();
|
|
||||||
this.onFormSubmit(this.state.form);
|
|
||||||
}}>{i18n('SAVE')}</SubmitButton>
|
|
||||||
</div>
|
|
||||||
<div className="admin-panel-email-settings__optional-buttons">
|
<div className="admin-panel-email-settings__optional-buttons">
|
||||||
{(this.state.edited) ? this.renderDiscardButton() : null}
|
|
||||||
<div className="admin-panel-email-settings__recover-button">
|
<div className="admin-panel-email-settings__recover-button">
|
||||||
<Button onClick={this.onRecoverClick.bind(this)} size="medium">
|
<Button onClick={this.onRecoverClick.bind(this)} size="medium">
|
||||||
{i18n('RECOVER_DEFAULT')}
|
{i18n('RECOVER_DEFAULT')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
{edited ? this.renderDiscardButton() : null}
|
||||||
|
</div>
|
||||||
|
<div className="admin-panel-email-settings__save-button">
|
||||||
|
<SubmitButton
|
||||||
|
key="submit-email-template"
|
||||||
|
type="secondary"
|
||||||
|
size="small"
|
||||||
|
onClick={(e) => {e.preventDefault(); this.onFormSubmit(form);}}>
|
||||||
|
{i18n('SAVE')}
|
||||||
|
</SubmitButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
|
|
||||||
&__save-button {
|
&__save-button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
float: left;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__optional-buttons {
|
&__optional-buttons {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
float: right;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__discard-button {
|
&__discard-button {
|
||||||
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
&__recover-button {
|
&__recover-button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-left: 10px;
|
margin: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__image-container,
|
&__image-container,
|
||||||
|
@ -100,10 +100,10 @@ class AdminPanelSystemPreferences extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
<div className="row admin-panel-system-preferences__container">
|
<div className="row admin-panel-system-preferences__container">
|
||||||
<div className="col-md-4 col-md-offset-2">
|
<div className="col-md-4 col-md-offset-2">
|
||||||
<SubmitButton className="admin-panel-system-preferences__container__button" type="secondary">{i18n('UPDATE_SETTINGS')}</SubmitButton>
|
<Button className="admin-panel-system-preferences__container__button" onClick={this.onDiscardChangesSubmit.bind(this)}>{i18n('DISCARD_CHANGES')}</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-4">
|
<div className="col-md-4">
|
||||||
<Button className="admin-panel-system-preferences__container__button" onClick={this.onDiscardChangesSubmit.bind(this)}>{i18n('DISCARD_CHANGES')}</Button>
|
<SubmitButton className="admin-panel-system-preferences__container__button" type="secondary">{i18n('UPDATE_SETTINGS')}</SubmitButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -14,7 +14,6 @@ import ModalContainer from 'app-components/modal-container';
|
|||||||
import InviteStaffModal from 'app/admin/panel/staff/invite-staff-modal';
|
import InviteStaffModal from 'app/admin/panel/staff/invite-staff-modal';
|
||||||
|
|
||||||
import Header from 'core-components/header';
|
import Header from 'core-components/header';
|
||||||
import DropDown from 'core-components/drop-down';
|
|
||||||
import Button from 'core-components/button';
|
import Button from 'core-components/button';
|
||||||
import Icon from 'core-components/icon';
|
import Icon from 'core-components/icon';
|
||||||
import Loading from 'core-components/loading';
|
import Loading from 'core-components/loading';
|
||||||
@ -48,7 +47,7 @@ class AdminPanelStaffMembers extends React.Component {
|
|||||||
<div className="admin-panel-staff-members__wrapper">
|
<div className="admin-panel-staff-members__wrapper">
|
||||||
<DepartmentDropdown {...this.getDepartmentDropdownProps()} className="admin-panel-staff-members__dropdown" />
|
<DepartmentDropdown {...this.getDepartmentDropdownProps()} className="admin-panel-staff-members__dropdown" />
|
||||||
<Button onClick={this.onInviteStaff.bind(this)} size="medium" type="secondary" className="admin-panel-staff-members__button">
|
<Button onClick={this.onInviteStaff.bind(this)} size="medium" type="secondary" className="admin-panel-staff-members__button">
|
||||||
<Icon name="user-plus" className=""/> {i18n('INVITE_STAFF')}
|
<Icon name="user-plus" className="" /> {i18n('INVITE_STAFF')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{(this.props.loading) ? <Loading backgrounded /> : <PeopleList list={this.getStaffList()} page={this.state.page} onPageSelect={(index) => this.setState({page: index+1})} />}
|
{(this.props.loading) ? <Loading backgrounded /> : <PeopleList list={this.getStaffList()} page={this.state.page} onPageSelect={(index) => this.setState({page: index+1})} />}
|
||||||
|
@ -61,7 +61,7 @@ class AdminPanelCustomResponses extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-3">
|
<div className="col-md-3">
|
||||||
<Listing {...this.getListingProps()}/>
|
<Listing {...this.getListingProps()} />
|
||||||
</div>
|
</div>
|
||||||
{this.state.showForm ? this.renderForm() : null}
|
{this.state.showForm ? this.renderForm() : null}
|
||||||
</div>
|
</div>
|
||||||
@ -71,7 +71,7 @@ class AdminPanelCustomResponses extends React.Component {
|
|||||||
renderLoading() {
|
renderLoading() {
|
||||||
return (
|
return (
|
||||||
<div className="admin-panel-custom-responses__loading">
|
<div className="admin-panel-custom-responses__loading">
|
||||||
<Loading backgrounded size="large"/>
|
<Loading backgrounded size="large" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ class AdminPanelCustomResponses extends React.Component {
|
|||||||
<Form {...this.getFormProps()}>
|
<Form {...this.getFormProps()}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-7">
|
<div className="col-md-7">
|
||||||
<FormField label={i18n('TITLE')} name="title" validation="TITLE" required fieldProps={{size: 'large'}}/>
|
<FormField label={i18n('TITLE')} name="title" validation="TITLE" required fieldProps={{size: 'large'}} />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-md-5">
|
<div className="col-md-5">
|
||||||
<FormField label={i18n('LANGUAGE')} name="language" field="input" decorator={LanguageSelector} fieldProps={{size: 'medium'}} />
|
<FormField label={i18n('LANGUAGE')} name="language" field="input" decorator={LanguageSelector} fieldProps={{size: 'medium'}} />
|
||||||
@ -90,10 +90,10 @@ class AdminPanelCustomResponses extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
<FormField label={i18n('CONTENT')} name="content" validation="TEXT_AREA" required field="textarea" />
|
<FormField label={i18n('CONTENT')} name="content" validation="TEXT_AREA" required field="textarea" />
|
||||||
<div className="admin-panel-custom-responses__actions">
|
<div className="admin-panel-custom-responses__actions">
|
||||||
|
{(this.state.selectedIndex !== -1) ? this.renderOptionalButtons() : null}
|
||||||
<div className="admin-panel-custom-responses__save-button">
|
<div className="admin-panel-custom-responses__save-button">
|
||||||
<SubmitButton type="secondary" size="small">{i18n('SAVE')}</SubmitButton>
|
<SubmitButton type="secondary" size="small">{i18n('SAVE')}</SubmitButton>
|
||||||
</div>
|
</div>
|
||||||
{(this.state.selectedIndex !== -1) ? this.renderOptionalButtons() : null}
|
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
@ -103,12 +103,12 @@ class AdminPanelCustomResponses extends React.Component {
|
|||||||
renderOptionalButtons() {
|
renderOptionalButtons() {
|
||||||
return (
|
return (
|
||||||
<div className="admin-panel-custom-responses__optional-buttons">
|
<div className="admin-panel-custom-responses__optional-buttons">
|
||||||
<div className="admin-panel-custom-responses__discard-button">
|
|
||||||
{this.isEdited() ? <Button onClick={this.onDiscardChangesClick.bind(this)}>{i18n('DISCARD_CHANGES')}</Button> : null}
|
|
||||||
</div>
|
|
||||||
<div className="admin-panel-custom-responses__delete-button">
|
<div className="admin-panel-custom-responses__delete-button">
|
||||||
<Button onClick={this.onDeleteClick.bind(this)}>{i18n('DELETE')}</Button>
|
<Button onClick={this.onDeleteClick.bind(this)}>{i18n('DELETE')}</Button>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="admin-panel-custom-responses__discard-button">
|
||||||
|
{this.isEdited() ? <Button onClick={this.onDiscardChangesClick.bind(this)}>{i18n('DISCARD_CHANGES')}</Button> : null}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -125,10 +125,16 @@ class AdminPanelCustomResponses extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getFormProps() {
|
getFormProps() {
|
||||||
|
const {
|
||||||
|
form,
|
||||||
|
errors,
|
||||||
|
formLoading
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
values: this.state.form,
|
values: form,
|
||||||
errors: this.state.errors,
|
errors,
|
||||||
loading: this.state.formLoading,
|
loading: formLoading,
|
||||||
onClick: () => this.setState({formClicked: true}),
|
onClick: () => this.setState({formClicked: true}),
|
||||||
onChange: (form) => this.setState({form}),
|
onChange: (form) => this.setState({form}),
|
||||||
onValidateErrors: (errors) => {this.setState({errors})},
|
onValidateErrors: (errors) => {this.setState({errors})},
|
||||||
@ -143,7 +149,7 @@ class AdminPanelCustomResponses extends React.Component {
|
|||||||
<span>
|
<span>
|
||||||
{item.name}
|
{item.name}
|
||||||
<span className="admin-panel-custom-responses__item-flag">
|
<span className="admin-panel-custom-responses__item-flag">
|
||||||
<Icon name={(item.language != 'en') ? item.language : 'us'}/>
|
<Icon name={(item.language != 'en') ? item.language : 'us'} />
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
@ -161,13 +167,15 @@ class AdminPanelCustomResponses extends React.Component {
|
|||||||
|
|
||||||
onFormSubmit(form) {
|
onFormSubmit(form) {
|
||||||
const {items, allowedLanguages} = this.props;
|
const {items, allowedLanguages} = this.props;
|
||||||
|
const { selectedIndex } = this.state;
|
||||||
|
|
||||||
this.setState({formLoading: true});
|
this.setState({formLoading: true});
|
||||||
|
|
||||||
if(this.state.selectedIndex !== -1) {
|
if(selectedIndex !== -1) {
|
||||||
API.call({
|
API.call({
|
||||||
path: '/ticket/edit-custom-response',
|
path: '/ticket/edit-custom-response',
|
||||||
data: {
|
data: {
|
||||||
id: items[this.state.selectedIndex].id,
|
id: items[selectedIndex].id,
|
||||||
name: form.title,
|
name: form.title,
|
||||||
content: form.content,
|
content: form.content,
|
||||||
language: _.includes(allowedLanguages, form.language) ? form.language : allowedLanguages[0]
|
language: _.includes(allowedLanguages, form.language) ? form.language : allowedLanguages[0]
|
||||||
@ -215,11 +223,17 @@ class AdminPanelCustomResponses extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateForm(index) {
|
updateForm(index) {
|
||||||
|
const {
|
||||||
|
items,
|
||||||
|
language
|
||||||
|
} = this.props;
|
||||||
|
const item = items[index];
|
||||||
|
|
||||||
let form = _.clone(this.state.form);
|
let form = _.clone(this.state.form);
|
||||||
|
|
||||||
form.title = (this.props.items[index] && this.props.items[index].name) || '';
|
form.title = (item && item.name) || '';
|
||||||
form.content = TextEditor.getEditorStateFromHTML((this.props.items[index] && this.props.items[index].content) || '');
|
form.content = TextEditor.getEditorStateFromHTML((item && item.content) || '');
|
||||||
form.language = (this.props.items[index] && this.props.items[index].language) || this.props.language;
|
form.language = (item && item.language) || language;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
formClicked: false,
|
formClicked: false,
|
||||||
@ -227,7 +241,7 @@ class AdminPanelCustomResponses extends React.Component {
|
|||||||
selectedIndex: index,
|
selectedIndex: index,
|
||||||
formLoading: false,
|
formLoading: false,
|
||||||
originalForm: form,
|
originalForm: form,
|
||||||
form: form,
|
form,
|
||||||
errors: {}
|
errors: {}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -237,10 +251,18 @@ class AdminPanelCustomResponses extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isEdited() {
|
isEdited() {
|
||||||
return this.state.form.title && this.state.formClicked && (
|
const {
|
||||||
this.state.form.title != this.state.originalForm.title ||
|
form,
|
||||||
this.state.form.content != this.state.originalForm.content ||
|
formClicked,
|
||||||
this.state.form.language != this.state.originalForm.language
|
originalForm
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
form.title && formClicked && (
|
||||||
|
form.title != originalForm.title ||
|
||||||
|
form.content != originalForm.content ||
|
||||||
|
form.language != originalForm.language
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,25 +7,25 @@
|
|||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__actions {
|
&__actions,
|
||||||
text-align: left;
|
&__optional-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__discard-button,
|
||||||
|
&__delete-button {
|
||||||
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__save-button {
|
&__save-button {
|
||||||
display: inline-block;
|
display: flex;
|
||||||
margin-right: 30px;
|
flex-direction: row;
|
||||||
}
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
&__optional-buttons {
|
width: 100%;
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__discard-button {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__delete-button {
|
|
||||||
display: inline-block;
|
|
||||||
float: right;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -36,10 +36,10 @@ class AdminPanelMyTickets extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="admin-panel-my-tickets">
|
<div className="admin-panel-my-tickets">
|
||||||
<Header title={i18n('MY_TICKETS')} description={i18n('MY_TICKETS_DESCRIPTION')} />
|
<Header title={i18n('MY_TICKETS')} description={i18n('MY_TICKETS_DESCRIPTION')} />
|
||||||
{(this.props.error) ? <Message type="error">{i18n('ERROR_RETRIEVING_TICKETS')}</Message> : <TicketList {...this.getProps()}/>}
|
{(this.props.error) ? <Message type="error">{i18n('ERROR_RETRIEVING_TICKETS')}</Message> : <TicketList {...this.getProps()} />}
|
||||||
<div style={{textAlign: 'right', marginTop: 10}}>
|
<div style={{textAlign: 'right', marginTop: 10}}>
|
||||||
<Button onClick={this.onCreateTicket.bind(this)} type="secondary" size="medium">
|
<Button onClick={this.onCreateTicket.bind(this)} type="secondary" size="medium">
|
||||||
<Icon size="sm" name="plus"/> {i18n('CREATE_TICKET')}
|
<Icon size="sm" name="plus" /> {i18n('CREATE_TICKET')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -47,21 +47,31 @@ class AdminPanelMyTickets extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getProps() {
|
getProps() {
|
||||||
|
const { closedTicketsShown } = this.state;
|
||||||
|
const {
|
||||||
|
userId,
|
||||||
|
departments,
|
||||||
|
tickets,
|
||||||
|
loading,
|
||||||
|
pages,
|
||||||
|
page
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
userId: this.props.userId,
|
userId,
|
||||||
departments: this.props.departments,
|
departments ,
|
||||||
tickets: this.props.tickets,
|
tickets,
|
||||||
type: 'secondary',
|
type: 'secondary',
|
||||||
loading: this.props.loading,
|
loading,
|
||||||
ticketPath: '/admin/panel/tickets/view-ticket/',
|
ticketPath: '/admin/panel/tickets/view-ticket/',
|
||||||
closedTicketsShown: this.state.closedTicketsShown,
|
closedTicketsShown,
|
||||||
onClosedTicketsShownChange: this.onClosedTicketsShownChange.bind(this),
|
onClosedTicketsShownChange: this.onClosedTicketsShownChange.bind(this),
|
||||||
pages: this.props.pages,
|
pages,
|
||||||
page: this.props.page,
|
page,
|
||||||
onPageChange: event => this.retrieveMyTickets(event.target.value),
|
onPageChange: event => this.retrieveMyTickets(event.target.value),
|
||||||
onDepartmentChange: departmentId => {
|
onDepartmentChange: departmentId => {
|
||||||
this.setState({departmentId});
|
this.setState({departmentId});
|
||||||
this.retrieveMyTickets(1, this.state.closedTicketsShown, departmentId);
|
this.retrieveMyTickets(1, closedTicketsShown, departmentId);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -76,10 +86,13 @@ class AdminPanelMyTickets extends React.Component {
|
|||||||
|
|
||||||
onCreateTicket() {
|
onCreateTicket() {
|
||||||
ModalContainer.openModal(
|
ModalContainer.openModal(
|
||||||
<div>
|
<div className="admin-panel-my-tickets__create-ticket-form-container">
|
||||||
<CreateTicketForm isStaff={true} onSuccess={this.onCreateTicketSuccess.bind(this)} />
|
<CreateTicketForm
|
||||||
<div style={{textAlign: 'center'}}>
|
className="admin-panel-my-tickets__create-ticket-form"
|
||||||
<Button onClick={ModalContainer.closeModal} type="link">{i18n('CLOSE')}</Button>
|
isStaff={true}
|
||||||
|
onSuccess={this.onCreateTicketSuccess.bind(this)} />
|
||||||
|
<div className="admin-panel-my-tickets__close-button-container">
|
||||||
|
<Button className="admin-panel-my-tickets__close-button" onClick={ModalContainer.closeModal} type="link">{i18n('CLOSE')}</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
.admin-panel-my-tickets {
|
||||||
|
&__close-button-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -26,24 +26,30 @@ class AdminPanelCustomFieldForm extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const {
|
||||||
|
loading,
|
||||||
|
addForm,
|
||||||
|
error
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="admin-panel-custom-field-form">
|
<div className="admin-panel-custom-field-form">
|
||||||
<Header title={i18n('NEW_CUSTOM_FIELD')} description={i18n('NEW_CUSTOM_FIELD_DESCRIPTION')} />
|
<Header title={i18n('NEW_CUSTOM_FIELD')} description={i18n('NEW_CUSTOM_FIELD_DESCRIPTION')} />
|
||||||
<div className="admin-panel-custom-field-form__form-container">
|
<div className="admin-panel-custom-field-form__form-container">
|
||||||
<Form
|
<Form
|
||||||
className="admin-panel-custom-field-form__form"
|
className="admin-panel-custom-field-form__form"
|
||||||
loading={this.state.loading}
|
loading={loading}
|
||||||
values={this.state.addForm}
|
values={addForm}
|
||||||
onChange={this.onAddFormChange.bind(this)}
|
onChange={this.onAddFormChange.bind(this)}
|
||||||
onSubmit={this.onSubmit.bind(this)}>
|
onSubmit={this.onSubmit.bind(this)}>
|
||||||
<FormField name="name" validation="NAME" label={i18n('NAME')} field="input" fieldProps={{size: 'large'}} required/>
|
<FormField name="name" validation="NAME" label={i18n('NAME')} field="input" fieldProps={{size: 'large'}} required/>
|
||||||
<FormField name="description" label={i18n('FIELD_DESCRIPTION')} field="input" fieldProps={{size: 'large'}}/>
|
<FormField name="description" label={i18n('FIELD_DESCRIPTION')} field="input" fieldProps={{size: 'large'}}/>
|
||||||
<FormField name="type" label={i18n('TYPE')} field="select" fieldProps={{size: 'large', items: [{content: i18n('TEXT_INPUT')}, {content: i18n('SELECT_INPUT')}]}} required/>
|
<FormField name="type" label={i18n('TYPE')} field="select" fieldProps={{size: 'large', items: [{content: i18n('TEXT_INPUT')}, {content: i18n('SELECT_INPUT')}]}} required/>
|
||||||
{this.state.addForm.type ? this.renderOptionFormFields() : null}
|
{addForm.type ? this.renderOptionFormFields() : null}
|
||||||
{this.state.error ? this.renderErrorMessage() : null}
|
{error ? this.renderErrorMessage() : null}
|
||||||
<div className="admin-panel-custom-field-form__buttons">
|
<div className="admin-panel-custom-field-form__buttons">
|
||||||
<SubmitButton>{i18n('SUBMIT')}</SubmitButton>
|
|
||||||
<Button onClick={this.props.onClose} type="link">{i18n('CLOSE')}</Button>
|
<Button onClick={this.props.onClose} type="link">{i18n('CLOSE')}</Button>
|
||||||
|
<SubmitButton type="secondary">{i18n('SUBMIT')}</SubmitButton>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,9 +29,9 @@ class AdminPanelCustomFields extends React.Component {
|
|||||||
<div className="admin-panel-custom-fields">
|
<div className="admin-panel-custom-fields">
|
||||||
<Header title={i18n('CUSTOM_FIELDS')} description={i18n('CUSTOM_FIELDS_DESCRIPTION')} />
|
<Header title={i18n('CUSTOM_FIELDS')} description={i18n('CUSTOM_FIELDS_DESCRIPTION')} />
|
||||||
{this.renderCustomFieldList()}
|
{this.renderCustomFieldList()}
|
||||||
<div className="admin-panel-custom-fields__add-button">
|
<div className="admin-panel-custom-fields__container-button">
|
||||||
<Button type="secondary" onClick={this.onNewCustomFieldClick.bind(this)}>
|
<Button className="admin-panel-custom-fields__container-button__add-button" type="secondary" onClick={this.onNewCustomFieldClick.bind(this)}>
|
||||||
<Icon name="plus"/> {i18n('NEW_CUSTOM_FIELD')}
|
<Icon name="plus" /> {i18n('NEW_CUSTOM_FIELD')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -48,8 +48,7 @@ class AdminPanelCustomFields extends React.Component {
|
|||||||
{key: 'options', value: i18n('OPTIONS')},
|
{key: 'options', value: i18n('OPTIONS')},
|
||||||
{key: 'actions', value: ''},
|
{key: 'actions', value: ''},
|
||||||
]}
|
]}
|
||||||
rows={this.state.customFields.map(this.getCustomField.bind(this))}
|
rows={this.state.customFields.map(this.getCustomField.bind(this))} />
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,11 +71,11 @@ class AdminPanelCustomFields extends React.Component {
|
|||||||
onNewCustomFieldClick() {
|
onNewCustomFieldClick() {
|
||||||
ModalContainer.openModal(
|
ModalContainer.openModal(
|
||||||
<AdminPanelCustomFieldForm
|
<AdminPanelCustomFieldForm
|
||||||
onClose={ModalContainer.closeModal}
|
onClose={(e) => {e.preventDefault(); ModalContainer.closeModal();}}
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
this.retrieveCustomFields();
|
this.retrieveCustomFields();
|
||||||
ModalContainer.closeModal();
|
ModalContainer.closeModal();
|
||||||
}}/>
|
}} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,14 @@
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__container-button {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
&__add-button {
|
&__add-button {
|
||||||
text-align: left;
|
}
|
||||||
margin-top: 14px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,10 +48,10 @@ class AdminPanelListUsers extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SearchBox className="admin-panel-list-users__search-box" placeholder={i18n('SEARCH_USERS')} onSearch={this.onSearch.bind(this)} />
|
<SearchBox className="admin-panel-list-users__search-box" placeholder={i18n('SEARCH_USERS')} onSearch={this.onSearch.bind(this)} />
|
||||||
<Table {...this.getTableProps()}/>
|
<Table {...this.getTableProps()} />
|
||||||
<div style={{textAlign: 'right', marginTop: 10}}>
|
<div style={{textAlign: 'right', marginTop: 10}}>
|
||||||
<Button onClick={this.onInviteUser.bind(this)} type="secondary" size="medium">
|
<Button onClick={this.onInviteUser.bind(this)} type="secondary" size="medium">
|
||||||
<Icon size="sm" name="plus"/> {i18n('INVITE_USER')}
|
<Icon size="sm" name="user-plus" /> {i18n('INVITE_USER')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -138,11 +138,17 @@ class AdminPanelListUsers extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onPageChange(event) {
|
onPageChange(event) {
|
||||||
|
const {
|
||||||
|
orderBy,
|
||||||
|
desc,
|
||||||
|
search
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
this.retrieveUsers({
|
this.retrieveUsers({
|
||||||
page: event.target.value,
|
page: event.target.value,
|
||||||
orderBy: this.state.orderBy,
|
orderBy,
|
||||||
desc: this.state.desc,
|
desc,
|
||||||
search: this.state.search
|
search
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,9 +185,6 @@ class AdminPanelListUsers extends React.Component {
|
|||||||
ModalContainer.openModal(
|
ModalContainer.openModal(
|
||||||
<div className="admin-panel-list-users__invite-user-form">
|
<div className="admin-panel-list-users__invite-user-form">
|
||||||
<InviteUserWidget onSuccess={this.onInviteUserSuccess.bind(this)} />
|
<InviteUserWidget onSuccess={this.onInviteUserSuccess.bind(this)} />
|
||||||
<div style={{textAlign: 'center'}}>
|
|
||||||
<Button onClick={ModalContainer.closeModal} type="link">{i18n('CLOSE')}</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -51,31 +51,40 @@ class AdminPanelViewUser extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderUserInfo() {
|
renderUserInfo() {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
disabled,
|
||||||
|
email,
|
||||||
|
verified,
|
||||||
|
customfields,
|
||||||
|
loading
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="admin-panel-view-user__content">
|
<div className="admin-panel-view-user__content">
|
||||||
<div className="admin-panel-view-user__info">
|
<div className="admin-panel-view-user__info">
|
||||||
<div className="admin-panel-view-user__info-item">
|
<div className="admin-panel-view-user__info-item">
|
||||||
{i18n('NAME')}
|
{i18n('NAME')}
|
||||||
<div className="admin-panel-view-user__info-box">
|
<div className="admin-panel-view-user__info-box">
|
||||||
{this.state.name}
|
{name}
|
||||||
{(this.state.disabled) ? this.renderDisabled() : null}
|
{disabled ? this.renderDisabled() : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="admin-panel-view-user__info-item">
|
<div className="admin-panel-view-user__info-item">
|
||||||
{i18n('EMAIL')}
|
{i18n('EMAIL')}
|
||||||
<div className="admin-panel-view-user__info-box">
|
<div className="admin-panel-view-user__info-box">
|
||||||
{this.state.email}
|
{email}
|
||||||
{(!this.state.verified) ? this.renderNotVerified() : null}
|
{(!verified) ? this.renderNotVerified() : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{this.state.customfields.map(this.renderCustomField.bind(this))}
|
{customfields.map(this.renderCustomField.bind(this))}
|
||||||
<div className="admin-panel-view-user__action-buttons">
|
<div className="admin-panel-view-user__action-buttons">
|
||||||
<Button
|
<Button
|
||||||
className="admin-panel-view-user__action-button"
|
className="admin-panel-view-user__action-button"
|
||||||
onClick={this.onDisableClick.bind(this)}
|
onClick={this.onDisableClick.bind(this)}
|
||||||
size="medium"
|
size="medium"
|
||||||
type={this.state.disabled ? 'tertiary' : 'primary'}>
|
type={disabled ? 'tertiary' : 'primary'}>
|
||||||
{i18n(this.state.disabled ? 'ENABLE_USER' : 'DISABLE_USER')}
|
{i18n(disabled ? 'ENABLE_USER' : 'DISABLE_USER')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button className="admin-panel-view-user__action-button" onClick={this.onDeleteClick.bind(this)} size="medium">
|
<Button className="admin-panel-view-user__action-button" onClick={this.onDeleteClick.bind(this)} size="medium">
|
||||||
{i18n('DELETE_AND_BAN')}
|
{i18n('DELETE_AND_BAN')}
|
||||||
@ -89,14 +98,13 @@ class AdminPanelViewUser extends React.Component {
|
|||||||
<Autocomplete
|
<Autocomplete
|
||||||
onChange={this.onChangeValues.bind(this)}
|
onChange={this.onChangeValues.bind(this)}
|
||||||
getItemListFromQuery={this.searchUsers.bind(this)}
|
getItemListFromQuery={this.searchUsers.bind(this)}
|
||||||
values={this.transformUserListToAutocomplete()}
|
values={this.transformUserListToAutocomplete()} />
|
||||||
/>
|
|
||||||
<Button
|
<Button
|
||||||
disabled = {this.state.loading}
|
disabled={loading}
|
||||||
|
type="secondary"
|
||||||
className="admin-panel-view-user__submit-button"
|
className="admin-panel-view-user__submit-button"
|
||||||
onClick={this.onClickSupervisorUserButton.bind(this)}
|
onClick={this.onClickSupervisorUserButton.bind(this)}
|
||||||
size="medium"
|
size="medium">
|
||||||
>
|
|
||||||
{i18n('UPDATE')}
|
{i18n('UPDATE')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@ -105,26 +113,28 @@ class AdminPanelViewUser extends React.Component {
|
|||||||
<span className="separator" />
|
<span className="separator" />
|
||||||
<div className="admin-panel-view-user__tickets">
|
<div className="admin-panel-view-user__tickets">
|
||||||
<div className="admin-panel-view-user__tickets-title">{i18n('TICKETS')}</div>
|
<div className="admin-panel-view-user__tickets-title">{i18n('TICKETS')}</div>
|
||||||
<TicketList {...this.getTicketListProps()}/>
|
<TicketList {...this.getTicketListProps()} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSupervisedUserMessage(){
|
renderSupervisedUserMessage(){
|
||||||
if(this.state.message) {
|
const { message } = this.state;
|
||||||
if(this.state.message != 'success'){
|
|
||||||
return(
|
if(message) {
|
||||||
|
if(message != 'success') {
|
||||||
|
return (
|
||||||
<div className="admin-panel-view-user__supervised-users-message">
|
<div className="admin-panel-view-user__supervised-users-message">
|
||||||
<Message type="error">{i18n(this.state.message)}</Message>
|
<Message type="error">{i18n(message)}</Message>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}else{
|
} else {
|
||||||
return(
|
return (
|
||||||
<div className= "admin-panel-view-user__supervised-users-message">
|
<div className= "admin-panel-view-user__supervised-users-message">
|
||||||
<Message type="success">{i18n('SUPERVISED_USERS_UPDATED')}</Message>
|
<Message type="success">{i18n('SUPERVISED_USERS_UPDATED')}</Message>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,11 +187,16 @@ class AdminPanelViewUser extends React.Component {
|
|||||||
const authorsListWithoutMe = r.data.authors.filter(author => author.id != this.props.params.userId);
|
const authorsListWithoutMe = r.data.authors.filter(author => author.id != this.props.params.userId);
|
||||||
|
|
||||||
return authorsListWithoutMe.map(author => {
|
return authorsListWithoutMe.map(author => {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
name
|
||||||
|
} = author;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: author.name,
|
name,
|
||||||
color: "gray",
|
color: "gray",
|
||||||
id: author.id*1,
|
id: id*1,
|
||||||
content: <div>{author.name}</div>,
|
content: <div>{name}</div>,
|
||||||
isStaff: false
|
isStaff: false
|
||||||
}});
|
}});
|
||||||
}).catch((r) => {
|
}).catch((r) => {
|
||||||
@ -192,10 +207,15 @@ class AdminPanelViewUser extends React.Component {
|
|||||||
transformUserListToAutocomplete() {
|
transformUserListToAutocomplete() {
|
||||||
return(
|
return(
|
||||||
this.state.userList.map((user) => {
|
this.state.userList.map((user) => {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
name
|
||||||
|
} = user;
|
||||||
|
|
||||||
return ({
|
return ({
|
||||||
id: user.id*1,
|
id: id*1,
|
||||||
name: user.name,
|
name,
|
||||||
content: <div>{user.name}</div>,
|
content: <div>{name}</div>,
|
||||||
color: 'grey',
|
color: 'grey',
|
||||||
isStaff: false
|
isStaff: false
|
||||||
});
|
});
|
||||||
@ -215,37 +235,58 @@ class AdminPanelViewUser extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCustomField(customfield) {
|
renderCustomField(_customfield) {
|
||||||
|
const {
|
||||||
|
customfield,
|
||||||
|
value,
|
||||||
|
id
|
||||||
|
} = _customfield;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="admin-panel-view-user__info-item">
|
<div className="admin-panel-view-user__info-item" key={`customFieldId__${id}`}>
|
||||||
{customfield.customfield}
|
{customfield}
|
||||||
<div className="admin-panel-view-user__info-box">
|
<div className="admin-panel-view-user__info-box">
|
||||||
{customfield.value}
|
{value}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTicketListProps() {
|
getTicketListProps() {
|
||||||
|
const {
|
||||||
|
tickets,
|
||||||
|
loading
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'secondary',
|
type: 'secondary',
|
||||||
tickets: this.state.tickets,
|
tickets,
|
||||||
loading: this.state.loading,
|
loading,
|
||||||
departments: this.props.departments,
|
departments: this.props.departments,
|
||||||
ticketPath: '/admin/panel/tickets/view-ticket/'
|
ticketPath: '/admin/panel/tickets/view-ticket/'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
onUserRetrieved(result) {
|
onUserRetrieved(result) {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
verified,
|
||||||
|
tickets,
|
||||||
|
disabled,
|
||||||
|
customfields,
|
||||||
|
userList
|
||||||
|
} = result.data;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
name: result.data.name,
|
name,
|
||||||
email: result.data.email,
|
email,
|
||||||
verified: result.data.verified,
|
verified,
|
||||||
tickets: result.data.tickets,
|
tickets,
|
||||||
disabled: result.data.disabled,
|
disabled,
|
||||||
customfields: result.data.customfields,
|
customfields,
|
||||||
loading: false,
|
loading: false,
|
||||||
userList: result.data.userList
|
userList
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
@ -13,6 +12,8 @@ import Form from 'core-components/form';
|
|||||||
import FormField from 'core-components/form-field';
|
import FormField from 'core-components/form-field';
|
||||||
import Widget from 'core-components/widget';
|
import Widget from 'core-components/widget';
|
||||||
import Header from 'core-components/header';
|
import Header from 'core-components/header';
|
||||||
|
import Button from 'core-components/button';
|
||||||
|
import ModalContainer from 'app-components/modal-container';
|
||||||
|
|
||||||
class InviteUserWidget extends React.Component {
|
class InviteUserWidget extends React.Component {
|
||||||
|
|
||||||
@ -52,9 +53,11 @@ class InviteUserWidget extends React.Component {
|
|||||||
<div className="invite-user-widget__captcha">
|
<div className="invite-user-widget__captcha">
|
||||||
<Captcha ref="captcha"/>
|
<Captcha ref="captcha"/>
|
||||||
</div>
|
</div>
|
||||||
<SubmitButton type="primary">{i18n('INVITE_USER')}</SubmitButton>
|
<div className="invite-user-widget__buttons-container">
|
||||||
|
<Button onClick={(e) => {e.preventDefault(); ModalContainer.closeModal();}} type="link">{i18n('CANCEL')}</Button>
|
||||||
|
<SubmitButton type="secondary">{i18n('INVITE_USER')}</SubmitButton>
|
||||||
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
||||||
{this.renderMessage()}
|
{this.renderMessage()}
|
||||||
</Widget>
|
</Widget>
|
||||||
);
|
);
|
||||||
@ -88,9 +91,9 @@ class InviteUserWidget extends React.Component {
|
|||||||
renderMessage() {
|
renderMessage() {
|
||||||
switch (this.state.message) {
|
switch (this.state.message) {
|
||||||
case 'success':
|
case 'success':
|
||||||
return <Message type="success">{i18n('INVITE_USER_SUCCESS')}</Message>;
|
return <Message className="invite-user-widget__success-message" type="success">{i18n('INVITE_USER_SUCCESS')}</Message>;
|
||||||
case 'fail':
|
case 'fail':
|
||||||
return <Message type="error">{i18n('EMAIL_EXISTS')}</Message>;
|
return <Message className="invite-user-widget__error-message" type="error">{i18n('EMAIL_EXISTS')}</Message>;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
.invite-user-widget {
|
.invite-user-widget {
|
||||||
padding: 30px;
|
padding: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
&__form {
|
&__form {
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__inputs {
|
&__inputs {
|
||||||
@ -16,4 +15,16 @@
|
|||||||
height: 78px;
|
height: 78px;
|
||||||
width: 304px;
|
width: 304px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__buttons-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__success-message,
|
||||||
|
&__error-message {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ import React from 'react';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
|
|
||||||
import history from 'lib-app/history';
|
|
||||||
import i18n from 'lib-app/i18n';
|
import i18n from 'lib-app/i18n';
|
||||||
import API from 'lib-app/api-call';
|
import API from 'lib-app/api-call';
|
||||||
import SessionStore from 'lib-app/session-store';
|
import SessionStore from 'lib-app/session-store';
|
||||||
@ -45,36 +44,46 @@ class CreateTicketForm extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const {
|
||||||
|
userLogged,
|
||||||
|
isDefaultDepartmentLocked,
|
||||||
|
isStaff,
|
||||||
|
onlyOneSupportedLanguage,
|
||||||
|
allowAttachments
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="create-ticket-form">
|
<div className="create-ticket-form">
|
||||||
<Header title={i18n('CREATE_TICKET')} description={i18n('CREATE_TICKET_DESCRIPTION')} />
|
<Header title={i18n('CREATE_TICKET')} description={i18n('CREATE_TICKET_DESCRIPTION')} />
|
||||||
<Form {...this.getFormProps()}>
|
<Form {...this.getFormProps()}>
|
||||||
{(!this.props.userLogged) ? this.renderEmailAndName() : null}
|
{(!userLogged) ? this.renderEmailAndName() : null}
|
||||||
<FormField label={i18n('TITLE')} name="title" validation="TITLE" required field="input" fieldProps={{size: 'large'}}/>
|
<FormField label={i18n('TITLE')} name="title" validation="TITLE" required field="input" fieldProps={{size: 'large'}} />
|
||||||
<div className="row">
|
<div className="row">
|
||||||
{!(this.props.isDefaultDepartmentLocked*1) || this.props.isStaff ?
|
{!(isDefaultDepartmentLocked*1) || isStaff ?
|
||||||
<FormField className="col-md-5" label={i18n('DEPARTMENT')} name="departmentIndex" field="select" decorator={DepartmentDropdown} fieldProps={{
|
<FormField className="col-md-5" label={i18n('DEPARTMENT')} name="departmentIndex" field="select" decorator={DepartmentDropdown} fieldProps={{
|
||||||
departments: SessionStore.getDepartments(),
|
departments: SessionStore.getDepartments(),
|
||||||
size: 'medium'
|
size: 'medium'
|
||||||
}} /> : null
|
}} /> : null
|
||||||
}
|
}
|
||||||
{!this.props.onlyOneSupportedLanguage ?
|
{!onlyOneSupportedLanguage ?
|
||||||
<FormField className="col-md-5" label={i18n('LANGUAGE')} name="language" field="select" decorator={LanguageSelector} fieldProps={{
|
<FormField className="col-md-5" label={i18n('LANGUAGE')} name="language" field="select" decorator={LanguageSelector} fieldProps={{
|
||||||
type: 'supported',
|
type: 'supported',
|
||||||
size: 'medium'
|
size: 'medium'
|
||||||
}}/> : null
|
}} /> : null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<FormField
|
<FormField
|
||||||
label={i18n('CONTENT')}
|
label={i18n('CONTENT')}
|
||||||
name="content"
|
name="content"
|
||||||
validation="TEXT_AREA"
|
validation="TEXT_AREA"
|
||||||
fieldProps={{allowImages: this.props.allowAttachments}}
|
fieldProps={{allowImages: allowAttachments}}
|
||||||
required
|
required
|
||||||
field="textarea" />
|
field="textarea" />
|
||||||
{(this.props.allowAttachments) ? this.renderFileUpload() : null}
|
<div className="create-ticket-form__buttons-container">
|
||||||
{(!this.props.userLogged) ? this.renderCaptcha() : null}
|
{allowAttachments ? this.renderFileUpload() : null}
|
||||||
<SubmitButton>{i18n('CREATE_TICKET')}</SubmitButton>
|
{(!userLogged) ? this.renderCaptcha() : null}
|
||||||
|
<SubmitButton type="secondary">{i18n('CREATE_TICKET')}</SubmitButton>
|
||||||
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
{this.renderMessage()}
|
{this.renderMessage()}
|
||||||
</div>
|
</div>
|
||||||
@ -84,8 +93,8 @@ class CreateTicketForm extends React.Component {
|
|||||||
renderEmailAndName() {
|
renderEmailAndName() {
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<FormField className="col-md-6" label={i18n('EMAIL')} name="email" validation="EMAIL" required field="input" fieldProps={{size: 'large'}}/>
|
<FormField className="col-md-6" label={i18n('EMAIL')} name="email" validation="EMAIL" required field="input" fieldProps={{size: 'large'}} />
|
||||||
<FormField className="col-md-6" label={i18n('FULL_NAME')} name="name" validation="NAME" required field="input" fieldProps={{size: 'large'}}/>
|
<FormField className="col-md-6" label={i18n('FULL_NAME')} name="name" validation="NAME" required field="input" fieldProps={{size: 'large'}} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -101,7 +110,7 @@ class CreateTicketForm extends React.Component {
|
|||||||
renderCaptcha() {
|
renderCaptcha() {
|
||||||
return (
|
return (
|
||||||
<div className="create-ticket-form__captcha">
|
<div className="create-ticket-form__captcha">
|
||||||
<Captcha ref="captcha"/>
|
<Captcha ref="captcha" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -118,10 +127,15 @@ class CreateTicketForm extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getFormProps() {
|
getFormProps() {
|
||||||
|
const {
|
||||||
|
loading,
|
||||||
|
form
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loading: this.state.loading,
|
loading,
|
||||||
onSubmit: this.onSubmit.bind(this),
|
onSubmit: this.onSubmit.bind(this),
|
||||||
values: this.state.form,
|
values: form,
|
||||||
onChange: form => this.setState({form})
|
onChange: form => this.setState({form})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -148,15 +162,16 @@ class CreateTicketForm extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onTicketSuccess(email, result) {
|
onTicketSuccess(email, result) {
|
||||||
let message = 'success'
|
const { onSuccess } = this.props;
|
||||||
this.setState({
|
const message = 'success';
|
||||||
|
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
loading: false,
|
loading: false,
|
||||||
message: message
|
message
|
||||||
}, () => {
|
},
|
||||||
if(this.props.onSuccess) {
|
() => {onSuccess && onSuccess(result, email, message);}
|
||||||
this.props.onSuccess(result, email, message);
|
);
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onTicketFail() {
|
onTicketFail() {
|
||||||
|
@ -8,6 +8,13 @@
|
|||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__buttons-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
&__captcha {
|
&__captcha {
|
||||||
margin: 0 auto 20px;
|
margin: 0 auto 20px;
|
||||||
height: 78px;
|
height: 78px;
|
||||||
|
@ -43,35 +43,71 @@ class DashboardEditProfilePage extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="edit-profile-page">
|
<div className="edit-profile-page">
|
||||||
<Header title={i18n('EDIT_PROFILE')} description={i18n('EDIT_PROFILE_VIEW_DESCRIPTION')} />
|
<Header title={i18n('EDIT_PROFILE')} description={i18n('EDIT_PROFILE_VIEW_DESCRIPTION')} />
|
||||||
<div className="edit-profile-page__title">{i18n('EDIT_EMAIL')}</div>
|
{this.renderEditEmail()}
|
||||||
<Form loading={this.state.loadingEmail} onSubmit={this.onSubmitEditEmail.bind(this)}>
|
{this.renderEditPassword()}
|
||||||
<FormField name="newEmail" label={i18n('NEW_EMAIL')} field="input" validation="EMAIL" fieldProps={{size:'large'}} required/>
|
|
||||||
<SubmitButton>{i18n('CHANGE_EMAIL')}</SubmitButton>
|
|
||||||
{this.renderMessageEmail()}
|
|
||||||
</Form>
|
|
||||||
<div className="edit-profile-page__title">{i18n('EDIT_PASSWORD')}</div>
|
|
||||||
<Form loading={this.state.loadingPass} onSubmit={this.onSubmitEditPassword.bind(this)}>
|
|
||||||
<FormField name="oldPassword" label={i18n('OLD_PASSWORD')} field="input" validation="PASSWORD" fieldProps={{password:true, size:'large'}} required/>
|
|
||||||
<FormField name="password" label={i18n('NEW_PASSWORD')} field="input" validation="PASSWORD" fieldProps={{password:true, size:'large'}} required/>
|
|
||||||
<FormField name="repeatNewPassword" label={i18n('REPEAT_NEW_PASSWORD')} field="input" validation="REPEAT_PASSWORD" fieldProps={{password:true ,size:'large'}} required/>
|
|
||||||
<SubmitButton>{i18n('CHANGE_PASSWORD')}</SubmitButton>
|
|
||||||
{this.renderMessagePass()}
|
|
||||||
</Form>
|
|
||||||
{this.state.customFields.length ? this.renderCustomFields() : null}
|
{this.state.customFields.length ? this.renderCustomFields() : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderCustomFields() {
|
renderEditEmail() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="edit-profile-page__edit-email">
|
||||||
<div className="edit-profile-page__title">{i18n('ADDITIONAL_FIELDS')}</div>
|
<span className="separator" />
|
||||||
<Form loading={this.state.loadingCustomFields} values={this.state.customFieldsFrom} onChange={form => this.setState({customFieldsFrom: form})} onSubmit={this.onCustomFieldsSubmit.bind(this)}>
|
<div className="edit-profile-page__title">{i18n('EDIT_EMAIL')}</div>
|
||||||
<div className="edit-profile-page__custom-fields">
|
<Form loading={this.state.loadingEmail} onSubmit={this.onSubmitEditEmail.bind(this)}>
|
||||||
{this.state.customFields.map(this.renderCustomField.bind(this))}
|
<div className="edit-profile-page__change-email-container">
|
||||||
|
<FormField name="newEmail" label={i18n('NEW_EMAIL')} field="input" validation="EMAIL" fieldProps={{size: 'large'}} required />
|
||||||
|
<SubmitButton type="secondary">{i18n('CHANGE_EMAIL')}</SubmitButton>
|
||||||
</div>
|
</div>
|
||||||
<div className="row">
|
{this.renderMessageEmail()}
|
||||||
<SubmitButton>{i18n('SAVE')}</SubmitButton>
|
</Form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEditPassword() {
|
||||||
|
return (
|
||||||
|
<div className="edit-profile-page__edit-password">
|
||||||
|
<span className="separator" />
|
||||||
|
<div className="edit-profile-page__title">{i18n('EDIT_PASSWORD')}</div>
|
||||||
|
<Form loading={this.state.loadingPass} onSubmit={this.onSubmitEditPassword.bind(this)}>
|
||||||
|
<div className="edit-profile-page__change-password-container">
|
||||||
|
<div className="edit-profile-page__change-password-form-fields">
|
||||||
|
<FormField name="oldPassword" label={i18n('OLD_PASSWORD')} field="input" validation="PASSWORD" fieldProps={{password: true, size: 'large'}} required />
|
||||||
|
<FormField name="password" label={i18n('NEW_PASSWORD')} field="input" validation="PASSWORD" fieldProps={{password: true, size: 'large'}} required />
|
||||||
|
<FormField name="repeatNewPassword" label={i18n('REPEAT_NEW_PASSWORD')} field="input" validation="REPEAT_PASSWORD" fieldProps={{password: true, size: 'large'}} required />
|
||||||
|
</div>
|
||||||
|
<SubmitButton type="secondary">{i18n('CHANGE_PASSWORD')}</SubmitButton>
|
||||||
|
</div>
|
||||||
|
{this.renderMessagePass()}
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCustomFields() {
|
||||||
|
const {
|
||||||
|
loadingCustomFields,
|
||||||
|
customFieldsFrom,
|
||||||
|
customFields
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="edit-profile-page__edit-custom-field">
|
||||||
|
<span className="separator" />
|
||||||
|
<div className="edit-profile-page__title">{i18n('ADDITIONAL_FIELDS')}</div>
|
||||||
|
<Form
|
||||||
|
className="edit-profile-page__edit-custom-field-form"
|
||||||
|
loading={loadingCustomFields}
|
||||||
|
values={customFieldsFrom}
|
||||||
|
onChange={form => this.setState({customFieldsFrom: form})}
|
||||||
|
onSubmit={this.onCustomFieldsSubmit.bind(this)}>
|
||||||
|
<div className="edit-profile-page__custom-fields">
|
||||||
|
{customFields.map(this.renderCustomField.bind(this))}
|
||||||
|
</div>
|
||||||
|
<div className="edit-profile-page__update-custom-fields-button-container">
|
||||||
|
<SubmitButton className="edit-profile-page__update-custom-fields-button" type="secondary">{i18n('UPDATE_CUSTOM_FIELDS')}</SubmitButton>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
@ -79,18 +115,25 @@ class DashboardEditProfilePage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderCustomField(customField, key) {
|
renderCustomField(customField, key) {
|
||||||
if(customField.type === 'text') {
|
const {
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
options
|
||||||
|
} = customField;
|
||||||
|
|
||||||
|
if(type === 'text') {
|
||||||
return (
|
return (
|
||||||
<div className="edit-profile-page__custom-field" key={key}>
|
<div className="edit-profile-page__custom-field" key={key}>
|
||||||
<FormField name={customField.name} label={customField.name} infoMessage={customField.description} field="input" fieldProps={{size:'small'}}/>
|
<FormField name={name} label={name} infoMessage={description} field="input" fieldProps={{size: 'small'}} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const items = customField.options.map(option => ({content: option.name, value: option.name}));
|
const items = options.map(option => ({content: option.name, value: option.name}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="edit-profile-page__custom-field" key={key}>
|
<div className="edit-profile-page__custom-field" key={key}>
|
||||||
<FormField name={customField.name} label={customField.name} infoMessage={customField.description} field="select" fieldProps={{size:'small', items}}/>
|
<FormField name={name} label={name} infoMessage={description} field="select" fieldProps={{size: 'small', items}} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -105,7 +148,6 @@ class DashboardEditProfilePage extends React.Component {
|
|||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMessagePass() {
|
renderMessagePass() {
|
||||||
@ -121,13 +163,19 @@ class DashboardEditProfilePage extends React.Component {
|
|||||||
|
|
||||||
onCustomFieldsSubmit(form) {
|
onCustomFieldsSubmit(form) {
|
||||||
const {customFields} = this.state;
|
const {customFields} = this.state;
|
||||||
const parsedFrom = {}
|
const parsedFrom = {};
|
||||||
|
|
||||||
customFields.forEach(customField => {
|
customFields.forEach(customField => {
|
||||||
if(customField.type === 'select') {
|
const {
|
||||||
parsedFrom[getCustomFieldParamName(customField.name)] = customField.options[form[customField.name]].name;
|
type,
|
||||||
|
name,
|
||||||
|
options
|
||||||
|
} = customField;
|
||||||
|
|
||||||
|
if(type === 'select') {
|
||||||
|
parsedFrom[getCustomFieldParamName(name)] = options[form[name]].name;
|
||||||
} else {
|
} else {
|
||||||
parsedFrom[getCustomFieldParamName(customField.name)] = form[customField.name];
|
parsedFrom[getCustomFieldParamName(name)] = form[name];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -142,7 +190,6 @@ class DashboardEditProfilePage extends React.Component {
|
|||||||
this.setState({loadingCustomFields: false});
|
this.setState({loadingCustomFields: false});
|
||||||
this.props.dispatch(SessionActions.getUserData());
|
this.props.dispatch(SessionActions.getUserData());
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmitEditEmail(formState) {
|
onSubmitEditEmail(formState) {
|
||||||
@ -157,6 +204,7 @@ class DashboardEditProfilePage extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
loadingEmail: true
|
loadingEmail: true
|
||||||
});
|
});
|
||||||
|
|
||||||
return API.call({
|
return API.call({
|
||||||
path: "/user/edit-email",
|
path: "/user/edit-email",
|
||||||
data: {
|
data: {
|
||||||
@ -179,6 +227,7 @@ class DashboardEditProfilePage extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
loadingPass: true
|
loadingPass: true
|
||||||
});
|
});
|
||||||
|
|
||||||
return API.call({
|
return API.call({
|
||||||
path: "/user/edit-password",
|
path: "/user/edit-password",
|
||||||
data: {
|
data: {
|
||||||
@ -206,12 +255,19 @@ class DashboardEditProfilePage extends React.Component {
|
|||||||
.then(result => {
|
.then(result => {
|
||||||
const customFieldsFrom = {};
|
const customFieldsFrom = {};
|
||||||
const {userCustomFields} = this.props;
|
const {userCustomFields} = this.props;
|
||||||
|
|
||||||
result.data.forEach(customField => {
|
result.data.forEach(customField => {
|
||||||
if(customField.type === 'select') {
|
const {
|
||||||
const index = _.indexOf(customField.options.map(option => option.name), userCustomFields[customField.name]);
|
type,
|
||||||
customFieldsFrom[customField.name] = (index === -1 ? 0 : index);
|
name,
|
||||||
|
options
|
||||||
|
} = customField;
|
||||||
|
|
||||||
|
if(type === 'select') {
|
||||||
|
const index = _.indexOf(options.map(option => option.name), userCustomFields[name]);
|
||||||
|
customFieldsFrom[name] = ((index === -1) ? 0 : index);
|
||||||
} else {
|
} else {
|
||||||
customFieldsFrom[customField.name] = userCustomFields[customField.name] || '';
|
customFieldsFrom[name] = userCustomFields[name] || '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -22,4 +22,13 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__change-email-container,
|
||||||
|
&__change-password-container,
|
||||||
|
&__edit-custom-field-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ class MainCheckTicketPage extends React.Component {
|
|||||||
<div className="main-check-ticket-page__captcha">
|
<div className="main-check-ticket-page__captcha">
|
||||||
<Captcha ref="captcha"/>
|
<Captcha ref="captcha"/>
|
||||||
</div>
|
</div>
|
||||||
<SubmitButton>{i18n('CHECK_TICKET')}</SubmitButton>
|
<SubmitButton type="secondary">{i18n('CHECK_TICKET')}</SubmitButton>
|
||||||
</Form>
|
</Form>
|
||||||
</Widget>
|
</Widget>
|
||||||
</div>
|
</div>
|
||||||
|
@ -37,7 +37,7 @@ class Listing extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div className="listing__add">
|
<div className="listing__add">
|
||||||
<Button type="secondary" size="auto" className="listing__add-button" onClick={this.props.onAddClick}>
|
<Button type="secondary" size="auto" className="listing__add-button" onClick={this.props.onAddClick}>
|
||||||
<Icon name="plus-circle"/> {this.props.addNewText}
|
<Icon name="plus-circle" /> {this.props.addNewText}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -137,6 +137,7 @@ export default {
|
|||||||
'UPDATE_EMAIL': 'Update email',
|
'UPDATE_EMAIL': 'Update email',
|
||||||
'UPDATE_PASSWORD': 'Update password',
|
'UPDATE_PASSWORD': 'Update password',
|
||||||
'UPDATE_LEVEL': 'Update level',
|
'UPDATE_LEVEL': 'Update level',
|
||||||
|
'UPDATE_CUSTOM_FIELDS': 'Update custom fields',
|
||||||
'UPDATE_DEPARTMENTS': 'Update departments',
|
'UPDATE_DEPARTMENTS': 'Update departments',
|
||||||
'EDIT_STAFF': 'Edit staff member',
|
'EDIT_STAFF': 'Edit staff member',
|
||||||
'ADD_DEPARTMENT': 'Add department',
|
'ADD_DEPARTMENT': 'Add department',
|
||||||
@ -416,6 +417,7 @@ export default {
|
|||||||
'OLD_PASSWORD_INCORRECT': 'Old password is incorrect',
|
'OLD_PASSWORD_INCORRECT': 'Old password is incorrect',
|
||||||
'WILL_LOSE_CHANGES': 'You haven\'t save. Your changes will be lost.',
|
'WILL_LOSE_CHANGES': 'You haven\'t save. Your changes will be lost.',
|
||||||
'WILL_DELETE_CUSTOM_RESPONSE': 'The custom response will be deleted.',
|
'WILL_DELETE_CUSTOM_RESPONSE': 'The custom response will be deleted.',
|
||||||
|
'WILL_DELETE_CUSTOM_TAG': 'The custom tag will be deleted.',
|
||||||
'WILL_DELETE_DEPARTMENT': 'The department will be deleted. All the tickets will be transfer to the department selected.',
|
'WILL_DELETE_DEPARTMENT': 'The department will be deleted. All the tickets will be transfer to the department selected.',
|
||||||
'NO_STAFF_ASSIGNED': 'No staff member is assigned to this department.',
|
'NO_STAFF_ASSIGNED': 'No staff member is assigned to this department.',
|
||||||
'NO_DEPARTMENT_ASSIGNED': 'No ticket department is assigned you.',
|
'NO_DEPARTMENT_ASSIGNED': 'No ticket department is assigned you.',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user