Commit 1c69a421 authored by Viacheslav Pavlov's avatar Viacheslav Pavlov Committed by Matija Obreza
Browse files

CMS with Transifex

added missing translations
added clearing of fetchResult on new fetchAllTranslations call
parent 025a33aa
......@@ -524,7 +524,20 @@
"create": "Create new article"
},
"edit": {
"articleSaved": "Article saved"
"articleSaved": "Article saved",
"transifex": {
"fetch": "Fetch translations",
"fetchStarted": "Fetch started",
"fetchResult": "Result for {{lang, uppercase}}: {{result}}",
"delete": "Remove from transifex",
"deleteStarted": "Started deleting from transifex",
"deleteSucceeded": "Article deleted from transifex successfully",
"deleteFailed": "Deleting article from transifex failed",
"post": "Post to transifex",
"postStarted": "Started posting to transifex",
"postSucceeded": "Article posted to transifex successfully",
"postFailed": "Posting article to transifex failed"
}
}
}
},
......
......@@ -25,7 +25,20 @@
"create": "Create new article"
},
"edit": {
"articleSaved": "Article saved"
"articleSaved": "Article saved",
"transifex": {
"fetch": "Fetch translations",
"fetchStarted": "Fetch started",
"fetchResult": "Result for {{lang, uppercase}}: {{result}}",
"delete": "Remove from transifex",
"deleteStarted": "Started deleting from transifex",
"deleteSucceeded": "Article deleted from transifex successfully",
"deleteFailed": "Deleting article from transifex failed",
"post": "Post to transifex",
"postStarted": "Started posting to transifex",
"postSucceeded": "Article posted to transifex successfully",
"postFailed": "Posting article to transifex failed"
}
}
}
},
......
......@@ -5,9 +5,12 @@ import { translate } from 'react-i18next';
import { withStyles } from '@material-ui/core';
// actions
import { loadArticle, updateArticle, createGlobalArticle } from 'cms/actions/admin';
import { createGlobalArticle, loadArticle, updateArticle } from 'cms/actions/admin';
import { showSnackbar } from 'actions/snackbar';
// model
import Article from 'model/cms/Article';
// service
import CmsService from 'service/genesys/CmsService';
// utilities
import { log } from 'utilities/debug';
// ui
......@@ -17,11 +20,28 @@ import ArticleForm from './c/ArticleForm';
import ContentHeaderWithButton from 'ui/common/heading/ContentHeaderWithButton';
import ActionButton from 'ui/common/buttons/ActionButton';
import ArticleSection from '../c/ArticleSection';
import ButtonBar from 'ui/common/buttons/ButtonBar';
const styles = () => ({
article: {
maxWidth: '100%',
},
alertWarning: {
fontSize: 16,
backgroundColor: '#fcf8e3',
color: '#8a6d3b',
border: '1px solid #faebcc',
marginBottom: '1rem',
padding: '.5rem',
},
/*tslint:disable*/
customSubHeader: {
justifyContent: 'space-between' as 'space-between',
'& > div': {
width: 'auto !important' as 'auto !important',
},
},
/*tslint:enable*/
});
interface IArticleEditPageProps extends React.ClassAttributes<any> {
......@@ -36,6 +56,7 @@ interface IArticleEditPageProps extends React.ClassAttributes<any> {
loadArticle: (lang: string, slug, targetId?: number, className?: string) => void;
createGlobalArticle: (article: Article) => void;
updateArticle: (article: Article) => void;
showSnackbar: any;
}
class ArticleEditPage extends React.Component<IArticleEditPageProps, any> {
......@@ -46,7 +67,10 @@ class ArticleEditPage extends React.Component<IArticleEditPageProps, any> {
private constructor(props, context) {
super(props, context);
this.state = { isEdit: true };
this.state = {
isEdit: true,
fetchResults: {},
};
}
private onSave = (article: any) => {
......@@ -76,7 +100,7 @@ class ArticleEditPage extends React.Component<IArticleEditPageProps, any> {
public render() {
const { slug, t, classes } = this.props;
const { isEdit } = this.state;
const { isEdit, fetchResults } = this.state;
let { article } = this.props;
if (!article && !slug) {
......@@ -90,13 +114,32 @@ class ArticleEditPage extends React.Component<IArticleEditPageProps, any> {
return (
<div>
<ContentHeaderWithButton title={ article.title } buttons={
<ActionButton
title={ isEdit ? t('common:action.view') : t('common:action.edit') }
action={ () => this.setState({ isEdit: !isEdit }) }
/>
<ContentHeaderWithButton title={ article.title } classes={ { subHeader: classes.customSubHeader } } buttons={
<ButtonBar>
<ActionButton
title={ isEdit ? t('common:action.view') : t('common:action.edit') }
action={ () => this.setState({ isEdit: !isEdit }) }
/>
<ActionButton
title={ t('cms.admin.p.edit.transifex.fetch') }
action={ this.fetchAllTranslations }
/>
<ActionButton
title={ t('cms.admin.p.edit.transifex.post') }
action={ this.postToTransifex }
/>
<ActionButton
title={ t('cms.admin.p.edit.transifex.delete') }
action={ this.deleteFromTransifex }
/>
</ButtonBar>
}/>
<PageContents className="pt-1rem pb-1rem">
{ fetchResults && Object.keys(fetchResults).length > 0 &&
<div className={ classes.alertWarning }>
{ Object.keys(fetchResults).map((lang) => <div key={ lang }>{ t('cms.admin.p.edit.transifex.fetchResult', {lang, result: fetchResults[lang]}) }</div>) }
</div>
}
<Grid item xs={ 12 }>
{ isEdit ? (
<ArticleForm
......@@ -114,6 +157,37 @@ class ArticleEditPage extends React.Component<IArticleEditPageProps, any> {
);
}
private fetchAllTranslations = () => {
const { article, showSnackbar } = this.props;
this.setState({ fetchResults: {} });
if (!article || !article.slug) {
return this.setState({ fetchResults: { en: 'Article is undefined' } });
}
showSnackbar('cms.admin.p.edit.transifex.fetchStarted');
CmsService.fetchAllFromTransifex(article.slug, article.classPk ? article.classPk.shortName : null, article.targetId, article.template)
.then((fetchResults) => this.setState({ fetchResults }));
}
private postToTransifex = () => {
const { article, showSnackbar } = this.props;
showSnackbar('cms.admin.p.edit.transifex.postStarted');
CmsService.postToTransifex(article.classPk.shortName, article.slug, article.targetId)
.then(() => showSnackbar('cms.admin.p.edit.transifex.postSucceeded'))
.catch(() => showSnackbar('cms.admin.p.edit.transifex.postFailed'));
}
private deleteFromTransifex = () => {
const { article, showSnackbar } = this.props;
showSnackbar('cms.admin.p.edit.transifex.deleteStarted');
CmsService.deleteFromTransifex(article.classPk.shortName, article.slug)
.then(() => showSnackbar('cms.admin.p.edit.transifex.deleteSucceeded'))
.catch(() => showSnackbar('cms.admin.p.edit.transifex.deleteFailed'));
}
}
const mapStateToProps = (state, ownProps) => ({
......@@ -128,6 +202,7 @@ const mapDispatchToProps = (dispatch) => bindActionCreators({
loadArticle,
updateArticle,
createGlobalArticle,
showSnackbar,
}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(translate()(ArticleEditPage)));
......@@ -26,6 +26,9 @@ const URL_GET_MENU = UrlTemplate.parse(`/api/v1/cms/menu/{menuKey}`);
const URL_PROCESS_TEMPLATE = `/api/v1/cms/process-template`;
const URL_UPDATE_ACTIVITY_POST = `/api/v1/cms/update-activity-post`;
const URL_UPDATE_ARTICLE = `/api/v1/cms/update-article`;
const URL_POST_TO_TRANSIFEX = `/api/v1/cms/transifex`;
const URL_DELETE_FROM_TRANSIFEX = `/api/v1/cms/transifex`;
const URL_FETCH_ALL_FROM_TRANSIFEX = `/api/v1/cms/transifex/fetchAll`;
const URL_UPDATE_GLOBAL_ARTICLE = `/api/v1/cms/update-global-article`;
const URL_UPDATE_MENU = UrlTemplate.parse(`/api/v1/cms/update-menu/{menuKey}`);
const URL_GET_ARTICLE = UrlTemplate.parse(`/api/v1/cms/{slug}/{clazz}/{targetId}/{language}`);
......@@ -357,6 +360,85 @@ class CmsService {
}).then(({ data }) => data as Article);
}
/**
* postToTransifex at /api/v1/cms/transifex
*
* @param classPkShortName classPkShortName
* @param slug slug
* @param targetId targetId
*/
public static postToTransifex(classPkShortName: string, slug: string, targetId?: number): Promise<Article> {
const qs = QueryString.stringify({
classPkShortName: classPkShortName || undefined,
slug: slug || undefined,
targetId: targetId || undefined,
}, {});
const apiUrl = URL_POST_TO_TRANSIFEX + (qs ? `?${qs}` : '');
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return axiosBackend({
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as Article);
}
/**
* deleteFromTransifex at /api/v1/cms/transifex
*
* @param classPkShortName classPkShortName
* @param flashAttributes undefined
* @param slug slug
* @param targetId targetId
*/
public static deleteFromTransifex(slug: string, classPkShortName: string, flashAttributes?: object, targetId?: number): Promise<boolean> {
const qs = QueryString.stringify({
classPkShortName: classPkShortName || undefined,
flashAttributes: flashAttributes || undefined,
slug: slug || undefined,
targetId: targetId || undefined,
}, {});
const apiUrl = URL_DELETE_FROM_TRANSIFEX + (qs ? `?${qs}` : '');
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return axiosBackend({
url: apiUrl,
method: 'DELETE',
...content,
}).then(({ data }) => data as boolean);
}
/**
* fetchAllFromTransifex at /api/v1/cms/transifex/fetchAll
*
* @param classPkShortName classPkShortName
* @param slug slug
* @param targetId targetId
* @param template template
*/
public static fetchAllFromTransifex(slug: string, classPkShortName?: string, targetId?: number, template?: boolean): Promise<string[]> {
const qs = QueryString.stringify({
classPkShortName: classPkShortName || undefined,
slug: slug || undefined,
targetId: targetId || undefined,
template: template || undefined,
}, {});
const apiUrl = URL_FETCH_ALL_FROM_TRANSIFEX + (qs ? `?${qs}` : '');
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return axiosBackend({
url: apiUrl,
method: 'POST',
...content,
}).then(({ data }) => data as string[]);
}
/**
* updateMenu at /api/v1/cms/update-menu/{menuKey}
*
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment