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:
LautaroCesso 2020-11-19 17:37:59 -03:00 committed by GitHub
parent 3dd76f214d
commit af3d95cf4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 523 additions and 291 deletions

View File

@ -32,11 +32,11 @@ class ArticleAddModal extends React.Component {
<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="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) => {
event.preventDefault();
ModalContainer.closeModal();
}}>{i18n('CANCEL')}</Button>
<SubmitButton className="article-add-modal__submit-button" type="secondary">{i18n('ADD_ARTICLE')}</SubmitButton>
</Form>
</div>
);

View File

@ -2,7 +2,11 @@
width: 800px;
&__cancel-button {
float: right;
float: left;
margin-top: 15px;
}
&__submit-button {
float: right;
}
}

View File

@ -36,11 +36,13 @@ class ArticlesList extends React.Component {
}
render() {
if(this.props.errored) {
const { errored, loading } = this.props;
if(errored) {
return <Message type="error">{i18n('ERROR_RETRIEVING_ARTICLES')}</Message>;
}
return (this.props.loading) ? <Loading /> : this.renderContent();
return loading ? <Loading /> : this.renderContent();
}
renderContent() {
@ -53,17 +55,19 @@ class ArticlesList extends React.Component {
}
renderTopics() {
const { topics, editable, articlePath } = this.props;
return (
<div className="articles-list__topics">
{this.props.topics.map((topic, index) => {
{topics.map((topic, index) => {
return (
<div key={index}>
<TopicViewer
{...topic}
id={topic.id * 1}
editable={this.props.editable}
editable={editable}
onChange={this.retrieveArticles.bind(this)}
articlePath={this.props.articlePath} />
articlePath={articlePath} />
<span className="separator" />
</div>
);
@ -76,7 +80,7 @@ class ArticlesList extends React.Component {
return (
<div className="articles-list__add-topic-button">
<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>
</div>
);
@ -88,9 +92,11 @@ class ArticlesList extends React.Component {
}
export default connect((store) => {
const { topics, errored, loading } = store.articles;
return {
topics: store.articles.topics.map((topic) => {return {...topic, private: topic.private === "1"}}),
errored: store.articles.errored,
loading: store.articles.loading
topics: topics.map((topic) => {return {...topic, private: topic.private === "1"}}),
errored,
loading
};
})(ArticlesList);

View File

@ -1,14 +1,14 @@
@import "../scss/vars";
.articles-list {
&__add {
position: relative;
}
&__add-icon {
position: absolute;
left: 10px;
margin-top: -4px;
&__add-topic-button {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
}
}
}

View File

@ -37,15 +37,16 @@ class TopicEditModal extends React.Component {
<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="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')} />
<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">
{i18n('CANCEL')}
</Button>
<div className="topic-edit-modal__buttons-container">
<Button className="topic-edit-modal__discard-button" onClick={this.onDiscardClick.bind(this)} size="small">
{i18n('CANCEL')}
</Button>
<SubmitButton className="topic-edit-modal__save-button" type="secondary" size="small">
{i18n('SAVE')}
</SubmitButton>
</div>
</Form>
</div>
);

View File

@ -13,9 +13,19 @@
}
&__discard-button {
float: right;
&__buttons-container {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding: 20px 0 0 0;
}
&__discard-button {
float: left;
}
&__private {
display: inline-block;
padding-right: 10px;

View File

@ -66,12 +66,12 @@ class AdminPanelViewArticle extends React.Component {
return (
<div className="admin-panel-view-article__content">
<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)}>
{i18n('DELETE')}
</Button>
<Button className="admin-panel-view-article__edit-button" size="medium" onClick={this.onEditClick.bind(this, article)} type="tertiary">
{i18n('EDIT')}
</Button>
</div>
<div className="admin-panel-view-article__article">
<Header title={article.title}/>
@ -91,10 +91,10 @@ class AdminPanelViewArticle extends React.Component {
return (
<Form values={this.state.form} onChange={(form) => this.setState({form})} onSubmit={this.onFormSubmit.bind(this)}>
<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)}>
{i18n('CANCEL')}
</Button>
<SubmitButton className="admin-panel-view-article__button" type="secondary" size="medium">{i18n('SAVE')}</SubmitButton>
</div>
<FormField name="title" label={i18n('TITLE')} />
<FormField name="content" label={i18n('CONTENT')} field="textarea" validation="TEXT_AREA" required fieldProps={{allowImages: this.props.allowAttachments}}/>

View File

@ -5,7 +5,11 @@
}
&__edit-buttons {
text-align: left;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 200px;
margin-bottom: 20px;
}

View File

@ -12,7 +12,8 @@ import ColorSelector from 'core-components/color-selector';
class AdminPanelCustomTagsModal extends React.Component {
static contextTypes = {
closeModal: React.PropTypes.func
closeModal: React.PropTypes.func,
createTag: React.PropTypes.bool
};
static propTypes = {
@ -27,57 +28,50 @@ class AdminPanelCustomTagsModal extends React.Component {
render() {
return (
this.props.createTag ? this.renderCreateTagContent() : this.renderEditTagContent()
this.renderTagContentPopUp(this.props.createTag)
);
}
renderEditTagContent() {
return (
<div className='admin-panel-custom-tags-modal'>
<Header title={i18n('EDIT_CUSTOM_TAG')} description={i18n('DESCRIPTION_EDIT_CUSTOM_TAG')} />
<Form
values={this.state.form}
onChange={this.onFormChange.bind(this)}
onSubmit={this.onSubmitEditTag.bind(this)}
errors={this.state.errors}
onValidateErrors={errors => this.setState({errors})}
loading={this.state.loading}>
<FormField name="name" label={i18n('NAME')} fieldProps={{size: 'large'}}/>
<FormField name="color" label={i18n('COLOR')} decorator={ColorSelector} />
<div className='admin-panel-custom-tags-modal__actions'>
<SubmitButton type="secondary" size="small">
{i18n('SAVE')}
</SubmitButton>
<Button onClick={this.onDiscardClick.bind(this)} size="small">
{i18n('CANCEL')}
</Button>
</div>
</Form>
</div>
);
}
renderTagContentPopUp(create) {
const {
form,
errors,
loading,
} = this.state;
let title, description, nameRequired, submitFunction;
if(create) {
title = i18n('ADD_CUSTOM_TAG');
description = i18n('DESCRIPTION_ADD_CUSTOM_TAG');
submitFunction = this.onSubmitNewTag.bind(this);
nameRequired = true;
} else {
title = i18n('EDIT_CUSTOM_TAG');
description = i18n('DESCRIPTION_EDIT_CUSTOM_TAG');
nameRequired = false;
submitFunction = this.onSubmitEditTag.bind(this);
}
renderCreateTagContent() {
return (
<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
values={this.state.form}
values={form}
onChange={this.onFormChange.bind(this)}
onSubmit={this.onSubmitNewTag.bind(this)}
errors={this.state.errors}
onSubmit={submitFunction}
errors={errors}
onValidateErrors={errors => this.setState({errors})}
loading={this.state.loading}>
<FormField name="name" label={i18n('NAME')} fieldProps={{size: 'large'}} required />
<FormField name="color" label={i18n('COLOR')} decorator={ColorSelector} />
<div className='admin-panel-custom-tags-modal__actions'>
<SubmitButton type="secondary" size="small">
{i18n('SAVE')}
</SubmitButton>
<Button onClick={this.onDiscardClick.bind(this)} size="small">
{i18n('CANCEL')}
</Button>
</div>
loading={loading}>
<FormField name="name" label={i18n('NAME')} fieldProps={{size: 'large'}} required={nameRequired} />
<FormField name="color" label={i18n('COLOR')} decorator={ColorSelector} />
<div className='admin-panel-custom-tags-modal__actions'>
<Button onClick={this.onDiscardClick.bind(this)} size="small">
{i18n('CANCEL')}
</Button>
<SubmitButton type="secondary" size="small">
{i18n('SAVE')}
</SubmitButton>
</div>
</Form>
</div>
);
@ -118,7 +112,7 @@ class AdminPanelCustomTagsModal extends React.Component {
});
}
onSubmitNewTag(form) {
this.setState({
loading: true

View File

@ -44,7 +44,7 @@ class AdminPanelCustomTags extends React.Component {
<div className="admin-panel-custom-tags__content">
<div>
<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>
</div>
<div className="admin-panel-custom-tags__tag-list">
@ -77,13 +77,13 @@ class AdminPanelCustomTags extends React.Component {
openEditTagModal(tagId,tagName,tagColor, event) {
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) {
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) {

View File

@ -138,11 +138,12 @@ class AdminPanelEmailSettings extends React.Component {
<FormField name="smtp-user" label={i18n('SMTP_USER')} fieldProps={{size: 'large'}} />
<FormField name="smtp-pass" label={i18n('SMTP_PASSWORD')} fieldProps={{size: 'large', autoComplete: 'off'}} />
<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)}>
{i18n('TEST')}
</SubmitButton>
<SubmitButton className="admin-panel-email-settings__submit" type="secondary" size="small">
{i18n('SAVE')}
</SubmitButton>
</div>
</Form>
</div>
@ -160,11 +161,12 @@ class AdminPanelEmailSettings extends React.Component {
infoMessage={i18n('IMAP_TOKEN_DESCRIPTION')}
fieldProps={{size: 'large', icon: 'refresh', onIconClick: this.generateImapToken.bind(this)}} />
<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)}>
{i18n('TEST')}
</SubmitButton>
<SubmitButton className="admin-panel-email-settings__submit" type="secondary" size="small">
{i18n('SAVE')}
</SubmitButton>
</div>
</Form>
<Message className="admin-panel-email-settings__imap-message" type="info">
@ -177,10 +179,16 @@ class AdminPanelEmailSettings extends React.Component {
}
renderForm() {
const {
form,
language,
selectedIndex,
edited
} = this.state;
return (
<div className="col-md-9">
<FormField label={i18n('LANGUAGE')} decorator={LanguageSelector} value={this.state.language}
onChange={event => this.onItemChange(this.state.selectedIndex, event.target.value)}
<FormField label={i18n('LANGUAGE')} decorator={LanguageSelector} value={language}
onChange={event => this.onItemChange(selectedIndex, event.target.value)}
fieldProps={{
type: 'allowed',
size: 'medium'
@ -196,29 +204,32 @@ class AdminPanelEmailSettings extends React.Component {
<FormField key="text1" label={i18n('TEXT') + '1'} name="text1" validation="TEXT_AREA" required
decorator={'textarea'}
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
decorator={'textarea'}
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
decorator={'textarea'}
fieldProps={{className: 'admin-panel-email-settings__text-area'}} /> : null}
<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">
{(this.state.edited) ? this.renderDiscardButton() : null}
<div className="admin-panel-email-settings__recover-button">
<Button onClick={this.onRecoverClick.bind(this)} size="medium">
{i18n('RECOVER_DEFAULT')}
</Button>
</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>
</Form>

View File

@ -17,12 +17,12 @@
&__save-button {
display: inline-block;
float: left;
float: right;
}
&__optional-buttons {
display: inline-block;
float: right;
float: left;
}
&__discard-button {
@ -31,7 +31,7 @@
&__recover-button {
display: inline-block;
margin-left: 10px;
margin: 0 10px;
}
&__image-container,

View File

@ -100,10 +100,10 @@ class AdminPanelSystemPreferences extends React.Component {
</div>
<div className="row admin-panel-system-preferences__container">
<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 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>
</Form>

View File

@ -14,7 +14,6 @@ import ModalContainer from 'app-components/modal-container';
import InviteStaffModal from 'app/admin/panel/staff/invite-staff-modal';
import Header from 'core-components/header';
import DropDown from 'core-components/drop-down';
import Button from 'core-components/button';
import Icon from 'core-components/icon';
import Loading from 'core-components/loading';
@ -48,7 +47,7 @@ class AdminPanelStaffMembers extends React.Component {
<div className="admin-panel-staff-members__wrapper">
<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">
<Icon name="user-plus" className=""/> {i18n('INVITE_STAFF')}
<Icon name="user-plus" className="" /> {i18n('INVITE_STAFF')}
</Button>
</div>
{(this.props.loading) ? <Loading backgrounded /> : <PeopleList list={this.getStaffList()} page={this.state.page} onPageSelect={(index) => this.setState({page: index+1})} />}

View File

@ -61,7 +61,7 @@ class AdminPanelCustomResponses extends React.Component {
return (
<div className="row">
<div className="col-md-3">
<Listing {...this.getListingProps()}/>
<Listing {...this.getListingProps()} />
</div>
{this.state.showForm ? this.renderForm() : null}
</div>
@ -71,7 +71,7 @@ class AdminPanelCustomResponses extends React.Component {
renderLoading() {
return (
<div className="admin-panel-custom-responses__loading">
<Loading backgrounded size="large"/>
<Loading backgrounded size="large" />
</div>
);
}
@ -82,7 +82,7 @@ class AdminPanelCustomResponses extends React.Component {
<Form {...this.getFormProps()}>
<div className="row">
<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 className="col-md-5">
<FormField label={i18n('LANGUAGE')} name="language" field="input" decorator={LanguageSelector} fieldProps={{size: 'medium'}} />
@ -90,10 +90,10 @@ class AdminPanelCustomResponses extends React.Component {
</div>
<FormField label={i18n('CONTENT')} name="content" validation="TEXT_AREA" required field="textarea" />
<div className="admin-panel-custom-responses__actions">
{(this.state.selectedIndex !== -1) ? this.renderOptionalButtons() : null}
<div className="admin-panel-custom-responses__save-button">
<SubmitButton type="secondary" size="small">{i18n('SAVE')}</SubmitButton>
</div>
{(this.state.selectedIndex !== -1) ? this.renderOptionalButtons() : null}
</div>
</Form>
</div>
@ -103,12 +103,12 @@ class AdminPanelCustomResponses extends React.Component {
renderOptionalButtons() {
return (
<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">
<Button onClick={this.onDeleteClick.bind(this)}>{i18n('DELETE')}</Button>
</div>
<div className="admin-panel-custom-responses__discard-button">
{this.isEdited() ? <Button onClick={this.onDiscardChangesClick.bind(this)}>{i18n('DISCARD_CHANGES')}</Button> : null}
</div>
</div>
);
}
@ -125,10 +125,16 @@ class AdminPanelCustomResponses extends React.Component {
}
getFormProps() {
const {
form,
errors,
formLoading
} = this.state;
return {
values: this.state.form,
errors: this.state.errors,
loading: this.state.formLoading,
values: form,
errors,
loading: formLoading,
onClick: () => this.setState({formClicked: true}),
onChange: (form) => this.setState({form}),
onValidateErrors: (errors) => {this.setState({errors})},
@ -143,7 +149,7 @@ class AdminPanelCustomResponses extends React.Component {
<span>
{item.name}
<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>
)
@ -161,13 +167,15 @@ class AdminPanelCustomResponses extends React.Component {
onFormSubmit(form) {
const {items, allowedLanguages} = this.props;
const { selectedIndex } = this.state;
this.setState({formLoading: true});
if(this.state.selectedIndex !== -1) {
if(selectedIndex !== -1) {
API.call({
path: '/ticket/edit-custom-response',
data: {
id: items[this.state.selectedIndex].id,
id: items[selectedIndex].id,
name: form.title,
content: form.content,
language: _.includes(allowedLanguages, form.language) ? form.language : allowedLanguages[0]
@ -215,11 +223,17 @@ class AdminPanelCustomResponses extends React.Component {
}
updateForm(index) {
const {
items,
language
} = this.props;
const item = items[index];
let form = _.clone(this.state.form);
form.title = (this.props.items[index] && this.props.items[index].name) || '';
form.content = TextEditor.getEditorStateFromHTML((this.props.items[index] && this.props.items[index].content) || '');
form.language = (this.props.items[index] && this.props.items[index].language) || this.props.language;
form.title = (item && item.name) || '';
form.content = TextEditor.getEditorStateFromHTML((item && item.content) || '');
form.language = (item && item.language) || language;
this.setState({
formClicked: false,
@ -227,7 +241,7 @@ class AdminPanelCustomResponses extends React.Component {
selectedIndex: index,
formLoading: false,
originalForm: form,
form: form,
form,
errors: {}
});
}
@ -237,10 +251,18 @@ class AdminPanelCustomResponses extends React.Component {
}
isEdited() {
return this.state.form.title && this.state.formClicked && (
this.state.form.title != this.state.originalForm.title ||
this.state.form.content != this.state.originalForm.content ||
this.state.form.language != this.state.originalForm.language
const {
form,
formClicked,
originalForm
} = this.state;
return (
form.title && formClicked && (
form.title != originalForm.title ||
form.content != originalForm.content ||
form.language != originalForm.language
)
);
}
}

View File

@ -7,25 +7,25 @@
float: right;
}
&__actions {
text-align: left;
&__actions,
&__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 {
display: inline-block;
margin-right: 30px;
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
width: 100%;
}
&__optional-buttons {
display: inline;
}
&__discard-button {
display: inline-block;
}
&__delete-button {
display: inline-block;
float: right;
}
}
}

View File

@ -36,10 +36,10 @@ class AdminPanelMyTickets extends React.Component {
return (
<div className="admin-panel-my-tickets">
<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}}>
<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>
</div>
</div>
@ -47,21 +47,31 @@ class AdminPanelMyTickets extends React.Component {
}
getProps() {
const { closedTicketsShown } = this.state;
const {
userId,
departments,
tickets,
loading,
pages,
page
} = this.props;
return {
userId: this.props.userId,
departments: this.props.departments,
tickets: this.props.tickets,
userId,
departments ,
tickets,
type: 'secondary',
loading: this.props.loading,
loading,
ticketPath: '/admin/panel/tickets/view-ticket/',
closedTicketsShown: this.state.closedTicketsShown,
closedTicketsShown,
onClosedTicketsShownChange: this.onClosedTicketsShownChange.bind(this),
pages: this.props.pages,
page: this.props.page,
pages,
page,
onPageChange: event => this.retrieveMyTickets(event.target.value),
onDepartmentChange: 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() {
ModalContainer.openModal(
<div>
<CreateTicketForm isStaff={true} onSuccess={this.onCreateTicketSuccess.bind(this)} />
<div style={{textAlign: 'center'}}>
<Button onClick={ModalContainer.closeModal} type="link">{i18n('CLOSE')}</Button>
<div className="admin-panel-my-tickets__create-ticket-form-container">
<CreateTicketForm
className="admin-panel-my-tickets__create-ticket-form"
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>
);

View File

@ -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%;
}
}

View File

@ -26,24 +26,30 @@ class AdminPanelCustomFieldForm extends React.Component {
};
render() {
const {
loading,
addForm,
error
} = this.state;
return (
<div className="admin-panel-custom-field-form">
<Header title={i18n('NEW_CUSTOM_FIELD')} description={i18n('NEW_CUSTOM_FIELD_DESCRIPTION')} />
<div className="admin-panel-custom-field-form__form-container">
<Form
className="admin-panel-custom-field-form__form"
loading={this.state.loading}
values={this.state.addForm}
loading={loading}
values={addForm}
onChange={this.onAddFormChange.bind(this)}
onSubmit={this.onSubmit.bind(this)}>
<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="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}
{this.state.error ? this.renderErrorMessage() : null}
{addForm.type ? this.renderOptionFormFields() : null}
{error ? this.renderErrorMessage() : null}
<div className="admin-panel-custom-field-form__buttons">
<SubmitButton>{i18n('SUBMIT')}</SubmitButton>
<Button onClick={this.props.onClose} type="link">{i18n('CLOSE')}</Button>
<SubmitButton type="secondary">{i18n('SUBMIT')}</SubmitButton>
</div>
</Form>
</div>

View File

@ -29,9 +29,9 @@ class AdminPanelCustomFields extends React.Component {
<div className="admin-panel-custom-fields">
<Header title={i18n('CUSTOM_FIELDS')} description={i18n('CUSTOM_FIELDS_DESCRIPTION')} />
{this.renderCustomFieldList()}
<div className="admin-panel-custom-fields__add-button">
<Button type="secondary" onClick={this.onNewCustomFieldClick.bind(this)}>
<Icon name="plus"/> {i18n('NEW_CUSTOM_FIELD')}
<div className="admin-panel-custom-fields__container-button">
<Button className="admin-panel-custom-fields__container-button__add-button" type="secondary" onClick={this.onNewCustomFieldClick.bind(this)}>
<Icon name="plus" /> {i18n('NEW_CUSTOM_FIELD')}
</Button>
</div>
</div>
@ -48,8 +48,7 @@ class AdminPanelCustomFields extends React.Component {
{key: 'options', value: i18n('OPTIONS')},
{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() {
ModalContainer.openModal(
<AdminPanelCustomFieldForm
onClose={ModalContainer.closeModal}
onClose={(e) => {e.preventDefault(); ModalContainer.closeModal();}}
onChange={() => {
this.retrieveCustomFields();
ModalContainer.closeModal();
}}/>
}} />
);
}

View File

@ -4,8 +4,14 @@
text-align: left;
}
&__add-button {
text-align: left;
margin-top: 14px;
&__container-button {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
margin-top: 20px;
&__add-button {
}
}
}

View File

@ -48,10 +48,10 @@ class AdminPanelListUsers extends React.Component {
return (
<div>
<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}}>
<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>
</div>
</div>
@ -138,11 +138,17 @@ class AdminPanelListUsers extends React.Component {
}
onPageChange(event) {
const {
orderBy,
desc,
search
} = this.state;
this.retrieveUsers({
page: event.target.value,
orderBy: this.state.orderBy,
desc: this.state.desc,
search: this.state.search
orderBy,
desc,
search
});
}
@ -179,9 +185,6 @@ class AdminPanelListUsers extends React.Component {
ModalContainer.openModal(
<div className="admin-panel-list-users__invite-user-form">
<InviteUserWidget onSuccess={this.onInviteUserSuccess.bind(this)} />
<div style={{textAlign: 'center'}}>
<Button onClick={ModalContainer.closeModal} type="link">{i18n('CLOSE')}</Button>
</div>
</div>
);
}

View File

@ -51,31 +51,40 @@ class AdminPanelViewUser extends React.Component {
}
renderUserInfo() {
const {
name,
disabled,
email,
verified,
customfields,
loading
} = this.state;
return (
<div className="admin-panel-view-user__content">
<div className="admin-panel-view-user__info">
<div className="admin-panel-view-user__info-item">
{i18n('NAME')}
<div className="admin-panel-view-user__info-box">
{this.state.name}
{(this.state.disabled) ? this.renderDisabled() : null}
{name}
{disabled ? this.renderDisabled() : null}
</div>
</div>
<div className="admin-panel-view-user__info-item">
{i18n('EMAIL')}
<div className="admin-panel-view-user__info-box">
{this.state.email}
{(!this.state.verified) ? this.renderNotVerified() : null}
{email}
{(!verified) ? this.renderNotVerified() : null}
</div>
</div>
{this.state.customfields.map(this.renderCustomField.bind(this))}
{customfields.map(this.renderCustomField.bind(this))}
<div className="admin-panel-view-user__action-buttons">
<Button
className="admin-panel-view-user__action-button"
onClick={this.onDisableClick.bind(this)}
size="medium"
type={this.state.disabled ? 'tertiary' : 'primary'}>
{i18n(this.state.disabled ? 'ENABLE_USER' : 'DISABLE_USER')}
type={disabled ? 'tertiary' : 'primary'}>
{i18n(disabled ? 'ENABLE_USER' : 'DISABLE_USER')}
</Button>
<Button className="admin-panel-view-user__action-button" onClick={this.onDeleteClick.bind(this)} size="medium">
{i18n('DELETE_AND_BAN')}
@ -89,15 +98,14 @@ class AdminPanelViewUser extends React.Component {
<Autocomplete
onChange={this.onChangeValues.bind(this)}
getItemListFromQuery={this.searchUsers.bind(this)}
values={this.transformUserListToAutocomplete()}
/>
values={this.transformUserListToAutocomplete()} />
<Button
disabled = {this.state.loading}
disabled={loading}
type="secondary"
className="admin-panel-view-user__submit-button"
onClick={this.onClickSupervisorUserButton.bind(this)}
size="medium"
>
{i18n('UPDATE')}
size="medium">
{i18n('UPDATE')}
</Button>
</div>
{this.renderSupervisedUserMessage()}
@ -105,26 +113,28 @@ class AdminPanelViewUser extends React.Component {
<span className="separator" />
<div className="admin-panel-view-user__tickets">
<div className="admin-panel-view-user__tickets-title">{i18n('TICKETS')}</div>
<TicketList {...this.getTicketListProps()}/>
<TicketList {...this.getTicketListProps()} />
</div>
</div>
);
}
renderSupervisedUserMessage(){
if(this.state.message) {
if(this.state.message != 'success'){
return(
const { message } = this.state;
if(message) {
if(message != 'success') {
return (
<div className="admin-panel-view-user__supervised-users-message">
<Message type="error">{i18n(this.state.message)}</Message>
<Message type="error">{i18n(message)}</Message>
</div>
)
}else{
return(
);
} else {
return (
<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>
)
);
}
}
}
@ -133,11 +143,11 @@ class AdminPanelViewUser extends React.Component {
this.setState({
loading: true
});
const userIdList = this.state.userList.map((item) => {
return item.id;
});
API.call({
path: '/user/edit-supervised-list',
data: {
@ -177,11 +187,16 @@ class AdminPanelViewUser extends React.Component {
const authorsListWithoutMe = r.data.authors.filter(author => author.id != this.props.params.userId);
return authorsListWithoutMe.map(author => {
const {
id,
name
} = author;
return {
name: author.name,
name,
color: "gray",
id: author.id*1,
content: <div>{author.name}</div>,
id: id*1,
content: <div>{name}</div>,
isStaff: false
}});
}).catch((r) => {
@ -192,10 +207,15 @@ class AdminPanelViewUser extends React.Component {
transformUserListToAutocomplete() {
return(
this.state.userList.map((user) => {
const {
id,
name
} = user;
return ({
id: user.id*1,
name: user.name,
content: <div>{user.name}</div>,
id: id*1,
name,
content: <div>{name}</div>,
color: 'grey',
isStaff: false
});
@ -215,37 +235,58 @@ class AdminPanelViewUser extends React.Component {
);
}
renderCustomField(customfield) {
renderCustomField(_customfield) {
const {
customfield,
value,
id
} = _customfield;
return (
<div className="admin-panel-view-user__info-item">
{customfield.customfield}
<div className="admin-panel-view-user__info-item" key={`customFieldId__${id}`}>
{customfield}
<div className="admin-panel-view-user__info-box">
{customfield.value}
{value}
</div>
</div>
);
}
getTicketListProps() {
const {
tickets,
loading
} = this.state;
return {
type: 'secondary',
tickets: this.state.tickets,
loading: this.state.loading,
tickets,
loading,
departments: this.props.departments,
ticketPath: '/admin/panel/tickets/view-ticket/'
};
}
onUserRetrieved(result) {
const {
name,
email,
verified,
tickets,
disabled,
customfields,
userList
} = result.data;
this.setState({
name: result.data.name,
email: result.data.email,
verified: result.data.verified,
tickets: result.data.tickets,
disabled: result.data.disabled,
customfields: result.data.customfields,
name,
email,
verified,
tickets,
disabled,
customfields,
loading: false,
userList: result.data.userList
userList
});
}

View File

@ -1,5 +1,4 @@
import React from 'react';
import ReactDOM from 'react-dom';
import _ from 'lodash';
import classNames from 'classnames';
@ -13,6 +12,8 @@ import Form from 'core-components/form';
import FormField from 'core-components/form-field';
import Widget from 'core-components/widget';
import Header from 'core-components/header';
import Button from 'core-components/button';
import ModalContainer from 'app-components/modal-container';
class InviteUserWidget extends React.Component {
@ -52,9 +53,11 @@ class InviteUserWidget extends React.Component {
<div className="invite-user-widget__captcha">
<Captcha ref="captcha"/>
</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>
{this.renderMessage()}
</Widget>
);
@ -88,9 +91,9 @@ class InviteUserWidget extends React.Component {
renderMessage() {
switch (this.state.message) {
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':
return <Message type="error">{i18n('EMAIL_EXISTS')}</Message>;
return <Message className="invite-user-widget__error-message" type="error">{i18n('EMAIL_EXISTS')}</Message>;
default:
return null;
}

View File

@ -1,9 +1,8 @@
.invite-user-widget {
padding: 30px;
padding: 10px;
text-align: center;
&__form {
margin-bottom: 20px;
}
&__inputs {
@ -16,4 +15,16 @@
height: 78px;
width: 304px;
}
&__buttons-container {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
&__success-message,
&__error-message {
margin-top: 20px;
}
}

View File

@ -2,7 +2,6 @@ import React from 'react';
import _ from 'lodash';
import {connect} from 'react-redux';
import history from 'lib-app/history';
import i18n from 'lib-app/i18n';
import API from 'lib-app/api-call';
import SessionStore from 'lib-app/session-store';
@ -45,36 +44,46 @@ class CreateTicketForm extends React.Component {
};
render() {
const {
userLogged,
isDefaultDepartmentLocked,
isStaff,
onlyOneSupportedLanguage,
allowAttachments
} = this.props;
return (
<div className="create-ticket-form">
<Header title={i18n('CREATE_TICKET')} description={i18n('CREATE_TICKET_DESCRIPTION')} />
<Form {...this.getFormProps()}>
{(!this.props.userLogged) ? this.renderEmailAndName() : null}
<FormField label={i18n('TITLE')} name="title" validation="TITLE" required field="input" fieldProps={{size: 'large'}}/>
{(!userLogged) ? this.renderEmailAndName() : null}
<FormField label={i18n('TITLE')} name="title" validation="TITLE" required field="input" fieldProps={{size: 'large'}} />
<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={{
departments: SessionStore.getDepartments(),
size: 'medium'
}} /> : null
}
{!this.props.onlyOneSupportedLanguage ?
{!onlyOneSupportedLanguage ?
<FormField className="col-md-5" label={i18n('LANGUAGE')} name="language" field="select" decorator={LanguageSelector} fieldProps={{
type: 'supported',
size: 'medium'
}}/> : null
}} /> : null
}
</div>
<FormField
label={i18n('CONTENT')}
name="content"
validation="TEXT_AREA"
fieldProps={{allowImages: this.props.allowAttachments}}
fieldProps={{allowImages: allowAttachments}}
required
field="textarea" />
{(this.props.allowAttachments) ? this.renderFileUpload() : null}
{(!this.props.userLogged) ? this.renderCaptcha() : null}
<SubmitButton>{i18n('CREATE_TICKET')}</SubmitButton>
<div className="create-ticket-form__buttons-container">
{allowAttachments ? this.renderFileUpload() : null}
{(!userLogged) ? this.renderCaptcha() : null}
<SubmitButton type="secondary">{i18n('CREATE_TICKET')}</SubmitButton>
</div>
</Form>
{this.renderMessage()}
</div>
@ -84,8 +93,8 @@ class CreateTicketForm extends React.Component {
renderEmailAndName() {
return (
<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('FULL_NAME')} name="name" validation="NAME" 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'}} />
</div>
);
}
@ -101,7 +110,7 @@ class CreateTicketForm extends React.Component {
renderCaptcha() {
return (
<div className="create-ticket-form__captcha">
<Captcha ref="captcha"/>
<Captcha ref="captcha" />
</div>
);
}
@ -118,10 +127,15 @@ class CreateTicketForm extends React.Component {
}
getFormProps() {
const {
loading,
form
} = this.state;
return {
loading: this.state.loading,
loading,
onSubmit: this.onSubmit.bind(this),
values: this.state.form,
values: form,
onChange: form => this.setState({form})
};
}
@ -148,15 +162,16 @@ class CreateTicketForm extends React.Component {
}
onTicketSuccess(email, result) {
let message = 'success'
this.setState({
loading: false,
message: message
}, () => {
if(this.props.onSuccess) {
this.props.onSuccess(result, email, message);
}
});
const { onSuccess } = this.props;
const message = 'success';
this.setState(
{
loading: false,
message
},
() => {onSuccess && onSuccess(result, email, message);}
);
}
onTicketFail() {

View File

@ -8,6 +8,13 @@
margin-top: 20px;
}
&__buttons-container {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
&__captcha {
margin: 0 auto 20px;
height: 78px;

View File

@ -43,54 +43,97 @@ class DashboardEditProfilePage extends React.Component {
return (
<div className="edit-profile-page">
<Header title={i18n('EDIT_PROFILE')} description={i18n('EDIT_PROFILE_VIEW_DESCRIPTION')} />
<div className="edit-profile-page__title">{i18n('EDIT_EMAIL')}</div>
<Form loading={this.state.loadingEmail} onSubmit={this.onSubmitEditEmail.bind(this)}>
<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.renderEditEmail()}
{this.renderEditPassword()}
{this.state.customFields.length ? this.renderCustomFields() : null}
</div>
);
}
renderCustomFields() {
renderEditEmail() {
return (
<div>
<div className="edit-profile-page__edit-email">
<span className="separator" />
<div className="edit-profile-page__title">{i18n('EDIT_EMAIL')}</div>
<Form loading={this.state.loadingEmail} onSubmit={this.onSubmitEditEmail.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>
{this.renderMessageEmail()}
</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 loading={this.state.loadingCustomFields} values={this.state.customFieldsFrom} onChange={form => this.setState({customFieldsFrom: form})} onSubmit={this.onCustomFieldsSubmit.bind(this)}>
<div className="edit-profile-page__custom-fields">
{this.state.customFields.map(this.renderCustomField.bind(this))}
</div>
<div className="row">
<SubmitButton>{i18n('SAVE')}</SubmitButton>
</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>
</Form>
</div>
);
}
renderCustomField(customField, key) {
if(customField.type === 'text') {
const {
type,
name,
description,
options
} = customField;
if(type === 'text') {
return (
<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>
);
} 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 (
<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>
);
}
@ -105,7 +148,6 @@ class DashboardEditProfilePage extends React.Component {
default:
return null;
}
}
renderMessagePass() {
@ -121,13 +163,19 @@ class DashboardEditProfilePage extends React.Component {
onCustomFieldsSubmit(form) {
const {customFields} = this.state;
const parsedFrom = {}
const parsedFrom = {};
customFields.forEach(customField => {
if(customField.type === 'select') {
parsedFrom[getCustomFieldParamName(customField.name)] = customField.options[form[customField.name]].name;
const {
type,
name,
options
} = customField;
if(type === 'select') {
parsedFrom[getCustomFieldParamName(name)] = options[form[name]].name;
} 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.props.dispatch(SessionActions.getUserData());
});
}
onSubmitEditEmail(formState) {
@ -157,6 +204,7 @@ class DashboardEditProfilePage extends React.Component {
this.setState({
loadingEmail: true
});
return API.call({
path: "/user/edit-email",
data: {
@ -179,6 +227,7 @@ class DashboardEditProfilePage extends React.Component {
this.setState({
loadingPass: true
});
return API.call({
path: "/user/edit-password",
data: {
@ -206,12 +255,19 @@ class DashboardEditProfilePage extends React.Component {
.then(result => {
const customFieldsFrom = {};
const {userCustomFields} = this.props;
result.data.forEach(customField => {
if(customField.type === 'select') {
const index = _.indexOf(customField.options.map(option => option.name), userCustomFields[customField.name]);
customFieldsFrom[customField.name] = (index === -1 ? 0 : index);
const {
type,
name,
options
} = customField;
if(type === 'select') {
const index = _.indexOf(options.map(option => option.name), userCustomFields[name]);
customFieldsFrom[name] = ((index === -1) ? 0 : index);
} else {
customFieldsFrom[customField.name] = userCustomFields[customField.name] || '';
customFieldsFrom[name] = userCustomFields[name] || '';
}
});

View File

@ -22,4 +22,13 @@
display: inline-block;
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;
}
}

View File

@ -42,7 +42,7 @@ class MainCheckTicketPage extends React.Component {
<div className="main-check-ticket-page__captcha">
<Captcha ref="captcha"/>
</div>
<SubmitButton>{i18n('CHECK_TICKET')}</SubmitButton>
<SubmitButton type="secondary">{i18n('CHECK_TICKET')}</SubmitButton>
</Form>
</Widget>
</div>

View File

@ -37,7 +37,7 @@ class Listing extends React.Component {
return (
<div className="listing__add">
<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>
</div>
);

View File

@ -137,6 +137,7 @@ export default {
'UPDATE_EMAIL': 'Update email',
'UPDATE_PASSWORD': 'Update password',
'UPDATE_LEVEL': 'Update level',
'UPDATE_CUSTOM_FIELDS': 'Update custom fields',
'UPDATE_DEPARTMENTS': 'Update departments',
'EDIT_STAFF': 'Edit staff member',
'ADD_DEPARTMENT': 'Add department',
@ -416,6 +417,7 @@ export default {
'OLD_PASSWORD_INCORRECT': 'Old password is incorrect',
'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_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.',
'NO_STAFF_ASSIGNED': 'No staff member is assigned to this department.',
'NO_DEPARTMENT_ASSIGNED': 'No ticket department is assigned you.',