diff --git a/src/ui/page-templates/list/PageTemplateListMenuActions.js b/src/ui/page-templates/list/PageTemplateListMenuActions.js
index 25252d356..4e38d2d86 100644
--- a/src/ui/page-templates/list/PageTemplateListMenuActions.js
+++ b/src/ui/page-templates/list/PageTemplateListMenuActions.js
@@ -11,8 +11,7 @@ import {
ROUTE_PAGE_TEMPLATE_DETAIL,
} from 'app-init/router';
-
-const PageTemplateListMenuActions = ({ onClickDelete, code }) => (
+const PageTemplateListMenuActions = ({ onClickDelete, code, locked }) => (
(
>
-
+ {
+ !locked && (
+
+ )
+ }
);
PageTemplateListMenuActions.propTypes = {
onClickDelete: PropTypes.func,
code: PropTypes.string.isRequired,
+ locked: PropTypes.bool.isRequired,
};
PageTemplateListMenuActions.defaultProps = {
diff --git a/src/ui/page-templates/list/PageTemplateListTable.js b/src/ui/page-templates/list/PageTemplateListTable.js
index 3cc14c209..c1ab470f5 100644
--- a/src/ui/page-templates/list/PageTemplateListTable.js
+++ b/src/ui/page-templates/list/PageTemplateListTable.js
@@ -81,6 +81,7 @@ class PageTemplateListTable extends Component {
Cell: ({ values }) => (
removePageTemplate(values.code)}
/>
),
diff --git a/src/ui/pages/add/PagesAddFormContainer.js b/src/ui/pages/add/PagesAddFormContainer.js
index b459e8ccb..a290cf112 100644
--- a/src/ui/pages/add/PagesAddFormContainer.js
+++ b/src/ui/pages/add/PagesAddFormContainer.js
@@ -10,7 +10,7 @@ import { getPageTemplatesList } from 'state/page-templates/selectors';
import { getCharsets, getContentTypes, getSelectedPageLocaleTitle } from 'state/pages/selectors';
import { sendPostPage, loadSelectedPage } from 'state/pages/actions';
import { history, ROUTE_PAGE_TREE, ROUTE_PAGE_CONFIG } from 'app-init/router';
-import { PAGE_INIT_VALUES, SEO_DATA_BLANK, SEO_LANGDATA_BLANK } from 'ui/pages/common/const';
+import { NEXT_PAGE_TEMPLATE, PAGE_INIT_VALUES, SEO_DATA_BLANK, SEO_LANGDATA_BLANK } from 'ui/pages/common/const';
import { getLocale } from 'state/locale/selectors';
import getSearchParam from 'helpers/getSearchParam';
import { setVisibleModal } from 'state/modal/actions';
@@ -23,6 +23,10 @@ import { getMyGroupPermissions } from 'state/permissions/selectors';
import { fetchMyGroupPermissions } from 'state/permissions/actions';
import { fetchAllGroupEntries, fetchMyGroups } from 'state/groups/actions';
import { getGroupEntries, getGroupsList } from 'state/groups/selectors';
+import getRuntimeEnv from 'helpers/getRuntimeEnv';
+import { openInNewTab } from 'helpers/urlUtils';
+
+const { WEBUI_ENABLED, WEBUI_DEV_WORKSPACE_URL } = getRuntimeEnv();
export const getDefaultLanguage = (languages) => {
const defaultLang = { code: 'en' };
@@ -194,7 +198,12 @@ export const mapDispatchToProps = dispatch => ({
dispatch(setAppTourLastStep(12));
dispatch(setTourCreatedPage(data));
}
- history.push(routeConverter(ROUTE_PAGE_CONFIG, { pageCode: data.code }));
+ if (WEBUI_ENABLED && data.pageModel === NEXT_PAGE_TEMPLATE) {
+ openInNewTab(WEBUI_DEV_WORKSPACE_URL);
+ history.push(ROUTE_PAGE_TREE);
+ } else {
+ history.push(routeConverter(ROUTE_PAGE_CONFIG, { pageCode: data.code }));
+ }
break;
}
default: history.push(ROUTE_PAGE_TREE);
diff --git a/src/ui/pages/clone/CloneFormContainer.js b/src/ui/pages/clone/CloneFormContainer.js
index c9235bb77..61dd13951 100644
--- a/src/ui/pages/clone/CloneFormContainer.js
+++ b/src/ui/pages/clone/CloneFormContainer.js
@@ -13,6 +13,11 @@ import { sendClonePage } from 'state/pages/actions';
import { history, ROUTE_PAGE_TREE, ROUTE_PAGE_CONFIG } from 'app-init/router';
import { setVisibleModal } from 'state/modal/actions';
import getSearchParam from 'helpers/getSearchParam';
+import getRuntimeEnv from 'helpers/getRuntimeEnv';
+import { openInNewTab } from 'helpers/urlUtils';
+import { NEXT_PAGE_TEMPLATE } from 'ui/pages/common/const';
+
+const { WEBUI_ENABLED, WEBUI_DEV_WORKSPACE_URL } = getRuntimeEnv();
export const mapStateToProps = state => ({
languages: getActiveLanguages(state),
@@ -47,7 +52,12 @@ export const mapDispatchToProps = dispatch => ({
break;
}
case ACTION_SAVE_AND_CONFIGURE: {
- history.push(routeConverter(ROUTE_PAGE_CONFIG, { pageCode: data.code }));
+ if (WEBUI_ENABLED && data.pageModel === NEXT_PAGE_TEMPLATE) {
+ openInNewTab(WEBUI_DEV_WORKSPACE_URL);
+ history.push(ROUTE_PAGE_TREE);
+ } else {
+ history.push(routeConverter(ROUTE_PAGE_CONFIG, { pageCode: data.code }));
+ }
break;
}
default: history.push(ROUTE_PAGE_TREE);
diff --git a/src/ui/pages/common/FindTemplateModal.js b/src/ui/pages/common/FindTemplateModal.js
index 45165628b..4bf9c42b1 100644
--- a/src/ui/pages/common/FindTemplateModal.js
+++ b/src/ui/pages/common/FindTemplateModal.js
@@ -6,6 +6,7 @@ import { Modal, Col, Row, Spinner, DropdownKebab, MenuItem, Button } from 'patte
import GenericModalContainer from 'ui/common/modal/GenericModalContainer';
import { ROUTE_PAGE_TEMPLATE_DETAIL } from 'app-init/router';
import { TEMPLATE_THUMBNAIL } from 'ui/pages/common/const';
+import { openInNewTab } from 'helpers/urlUtils';
export const MODAL_ID = 'FindTemplateModal';
@@ -59,7 +60,7 @@ const FindTemplateModal = ({
onClick={() => {
const templatePath = ROUTE_PAGE_TEMPLATE_DETAIL.replace(':pageTemplateCode', code);
const link = `${global.location.href.split('/page')[0]}${templatePath}`;
- window.open(link);
+ openInNewTab(link);
}}
>
diff --git a/src/ui/pages/common/PageTree.js b/src/ui/pages/common/PageTree.js
index a995493c2..fc5dc3f45 100644
--- a/src/ui/pages/common/PageTree.js
+++ b/src/ui/pages/common/PageTree.js
@@ -17,6 +17,10 @@ import UnpublishPageModalContainer from 'ui/pages/common/UnpublishPageModalConta
import PageListSearchTable from 'ui/pages/list/PageListSearchTable';
import MovePageModalContainer from 'ui/pages/common/MovePageModalContainer';
import { PAGE_MOVEMENT_OPTIONS } from 'state/pages/const';
+import { NEXT_PAGE_TYPE } from 'ui/pages/common/const';
+import getRuntimeEnv from 'helpers/getRuntimeEnv';
+
+const { WEBUI_ENABLED } = getRuntimeEnv();
class PageTree extends Component {
constructor(props) {
@@ -28,7 +32,8 @@ class PageTree extends Component {
componentDidMount() {
const { columnOrder, onSetColumnOrder } = this.props;
if (!columnOrder.length) {
- onSetColumnOrder(['title', 'status', 'displayedInMenu']);
+ onSetColumnOrder(WEBUI_ENABLED ? ['title', 'type', 'status', 'displayedInMenu'] :
+ ['title', 'status', 'displayedInMenu']);
}
}
@@ -103,6 +108,22 @@ class PageTree extends Component {
return { className: className.join(' ') };
},
},
+ ...(WEBUI_ENABLED && {
+ type: {
+ Header: ,
+ attributes: {
+ className: 'text-center PageTree__thead',
+ style: { width: '5%', verticalAlign: 'middle' },
+ },
+ Cell: ({ value }) => (
+
+ ),
+ cellAttributes: {
+ className: 'text-center',
+ style: { verticalAlign: 'middle' },
+ },
+ },
+ }),
status: {
Header: ,
attributes: {
@@ -229,6 +250,7 @@ PageTree.propTypes = {
code: PropTypes.string.isRequired,
status: PropTypes.string.isRequired,
displayedInMenu: PropTypes.bool.isRequired,
+ type: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
depth: PropTypes.number.isRequired,
expanded: PropTypes.bool.isRequired,
@@ -266,7 +288,8 @@ PageTree.defaultProps = {
onExpandAll: () => {},
onCollapseAll: () => {},
onSetColumnOrder: () => {},
- columnOrder: ['title', 'status', 'displayedInMenu'],
+ columnOrder: WEBUI_ENABLED ? ['title', 'type', 'status', 'displayedInMenu'] :
+ ['title', 'status', 'displayedInMenu'],
};
export default PageTree;
diff --git a/src/ui/pages/common/PageTreeActionMenu.js b/src/ui/pages/common/PageTreeActionMenu.js
index b79a84003..5e5aeacc7 100644
--- a/src/ui/pages/common/PageTreeActionMenu.js
+++ b/src/ui/pages/common/PageTreeActionMenu.js
@@ -3,6 +3,11 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { DropdownKebab, MenuItem } from 'patternfly-react';
import { PAGE_STATUS_PUBLISHED, PAGE_STATUS_UNPUBLISHED } from 'state/pages/const';
+import { NEXT_PAGE_TYPE } from 'ui/pages/common/const';
+import getRuntimeEnv from 'helpers/getRuntimeEnv';
+import { openInNewTab } from 'helpers/urlUtils';
+
+const { WEBUI_APP_URL, WEBUI_DEV_WORKSPACE_URL } = getRuntimeEnv();
class PageTreeActionMenu extends Component {
constructor(props) {
@@ -89,6 +94,8 @@ class PageTreeActionMenu extends Component {
);
+ const handleDesignNextPage = () => openInNewTab(WEBUI_DEV_WORKSPACE_URL);
+ const handlePreviewNextPage = () => openInNewTab(`${WEBUI_APP_URL}/${this.props.locale}/${page.code}.page`);
return (
e.stopPropagation()} role="none" data-testid={`${page.code}-actions`}>
@@ -109,7 +116,8 @@ class PageTreeActionMenu extends Component {
{onClickConfigure && (
@@ -130,12 +138,16 @@ class PageTreeActionMenu extends Component {
)}
{renderDeleteItem()}
-
+ {
+
+
+ }
{viewPublishedPage}
@@ -151,6 +163,7 @@ PageTreeActionMenu.propTypes = {
hasPublishedChildren: PropTypes.bool,
code: PropTypes.string,
parentStatus: PropTypes.string,
+ type: PropTypes.string,
}).isRequired,
onClickAdd: PropTypes.func,
onClickEdit: PropTypes.func,
diff --git a/src/ui/pages/common/PageTreeContainer.js b/src/ui/pages/common/PageTreeContainer.js
index 7e78203b3..37a026647 100644
--- a/src/ui/pages/common/PageTreeContainer.js
+++ b/src/ui/pages/common/PageTreeContainer.js
@@ -34,6 +34,7 @@ import { PAGE_INIT_VALUES } from 'ui/pages/common/const';
import { setAppTourLastStep } from 'state/app-tour/actions';
import { getDomain } from '@entando/apimanager';
import { PREVIEW_NAMESPACE } from 'ui/pages/config/const';
+import { openInNewTab } from 'helpers/urlUtils';
export const mapStateToProps = state => ({
locale: getLocale(state),
@@ -89,10 +90,10 @@ export const mapDispatchToProps = (dispatch, ownProps) => ({
dispatch(clearSearchPage());
},
onClickViewPublishedPage: (page, domain, locale) => {
- window.open(`${domain}/${locale}/${page.code}.page`, '_blank');
+ openInNewTab(`${domain}/${locale}/${page.code}.page`);
},
onClickPreview: (page, domain) => {
- window.open(`${domain}/${PREVIEW_NAMESPACE}?pageCode=${page.code}&token=${page.token}`, '_blank');
+ openInNewTab(`${domain}/${PREVIEW_NAMESPACE}?pageCode=${page.code}&token=${page.token}`);
},
onDropPage: (sourcePageCode, targetPageCode, action) => {
dispatch(setVisibleModal(MOVE_MODAL_ID));
diff --git a/src/ui/pages/common/const.js b/src/ui/pages/common/const.js
index c5c0e8201..2181fc2b2 100644
--- a/src/ui/pages/common/const.js
+++ b/src/ui/pages/common/const.js
@@ -44,3 +44,6 @@ export const TEMPLATE_THUMBNAIL = {
'1-column': `${publicUrl}/images/1-column.svg`,
custom: `${publicUrl}/images/custom-template.svg`,
};
+
+export const NEXT_PAGE_TYPE = 'NX';
+export const NEXT_PAGE_TEMPLATE = 'nx-page-template';
diff --git a/src/ui/pages/config/ContentPagesContainer.js b/src/ui/pages/config/ContentPagesContainer.js
index 71a4b1e2b..b5ebbe265 100644
--- a/src/ui/pages/config/ContentPagesContainer.js
+++ b/src/ui/pages/config/ContentPagesContainer.js
@@ -26,6 +26,7 @@ import { getUserPreferences } from 'state/user-preferences/selectors';
import { history, ROUTE_PAGE_CONFIG } from 'app-init/router';
import { getDomain } from '@entando/apimanager';
import { PREVIEW_NAMESPACE } from 'ui/pages/config/const';
+import { openInNewTab } from 'helpers/urlUtils';
export const mapStateToProps = state => ({
loading: getLoading(state).pageTree,
@@ -72,10 +73,10 @@ export const mapDispatchToProps = dispatch => ({
dispatch(clearSearchPage());
},
onClickPreview: (page, domain) => {
- window.open(`${domain}/${PREVIEW_NAMESPACE}?pageCode=${page.code}&token=${page.token}`, '_blank');
+ openInNewTab(`${domain}/${PREVIEW_NAMESPACE}?pageCode=${page.code}&token=${page.token}`);
},
onClickViewPublishedPage: (page, domain, locale) => {
- window.open(`${domain}/${locale}/${page.code}.page`, '_blank');
+ openInNewTab(`${domain}/${locale}/${page.code}.page`);
},
onExpandAll: (currentPage) => {
dispatch(fetchPageTreeAll());
diff --git a/src/ui/pages/config/PageConfigPage.js b/src/ui/pages/config/PageConfigPage.js
index 9dfa42b5c..85b7aae44 100644
--- a/src/ui/pages/config/PageConfigPage.js
+++ b/src/ui/pages/config/PageConfigPage.js
@@ -15,6 +15,7 @@ import AppTourContainer from 'ui/app-tour/AppTourContainer';
import { APP_TOUR_STARTED } from 'state/app-tour/const';
import { PAGE_STATUS_PUBLISHED, PAGE_STATUS_UNPUBLISHED } from 'state/pages/const';
import PagesEditFormContainer from 'ui/pages/edit/PagesEditFormContainer';
+import { openInNewTab } from 'helpers/urlUtils';
const msgs = defineMessages({
appYes: {
@@ -107,7 +108,7 @@ class PageConfigPage extends Component {
openLinkPublishedPage() {
if (this.props.pageStatus !== PAGE_STATUS_UNPUBLISHED) {
- window.open(this.props.publishedPageUri, '_blank');
+ openInNewTab(this.props.publishedPageUri);
}
}
diff --git a/src/ui/pages/edit/PagesEditFormContainer.js b/src/ui/pages/edit/PagesEditFormContainer.js
index a5cf3104e..058c0eadf 100644
--- a/src/ui/pages/edit/PagesEditFormContainer.js
+++ b/src/ui/pages/edit/PagesEditFormContainer.js
@@ -14,6 +14,11 @@ import { fetchPageTemplates } from 'state/page-templates/actions';
import { history, ROUTE_PAGE_TREE, ROUTE_PAGE_CONFIG } from 'app-init/router';
import { fetchLanguages } from 'state/languages/actions';
import { setVisibleModal } from 'state/modal/actions';
+import getRuntimeEnv from 'helpers/getRuntimeEnv';
+import { openInNewTab } from 'helpers/urlUtils';
+import { NEXT_PAGE_TEMPLATE } from 'ui/pages/common/const';
+
+const { WEBUI_ENABLED, WEBUI_DEV_WORKSPACE_URL } = getRuntimeEnv();
export const FORM_ID = 'pageEdit';
@@ -44,7 +49,12 @@ export const mapDispatchToProps = (dispatch, ownProps) => ({
break;
}
case ACTION_SAVE_AND_CONFIGURE: {
- history.push(routeConverter(ROUTE_PAGE_CONFIG, { pageCode: data.code }));
+ if (WEBUI_ENABLED && data.pageModel === NEXT_PAGE_TEMPLATE) {
+ openInNewTab(WEBUI_DEV_WORKSPACE_URL);
+ history.push(ROUTE_PAGE_TREE);
+ } else {
+ history.push(routeConverter(ROUTE_PAGE_CONFIG, { pageCode: data.code }));
+ }
break;
}
default: history.push(ROUTE_PAGE_TREE);
diff --git a/test/api/pages.test.js b/test/api/pages.test.js
index 5397f4c84..a6010db77 100644
--- a/test/api/pages.test.js
+++ b/test/api/pages.test.js
@@ -2,7 +2,8 @@ import 'test/enzyme-init';
import {
getPage, getPageChildren, setPagePosition, postPage, putPage, patchPage, deletePage,
getSearchPages, getPageSettings, getFreePages, getPageConfig, deletePageWidget, putPageWidget,
- getReferencesPage, restorePageConfig, applyDefaultPageConfig, putPageSettings,
+ getReferencesPage, restorePageConfig, applyDefaultPageConfig, putPageSettings, deleteWebuiPage,
+ postWebuiPage, putWebuiPageStatus, postWebuiClonePage, putWebuiPage,
} from 'api/pages';
import { CONTACTS_PAYLOAD, FREE_PAGES_PAYLOAD, PAGE_SETTINGS_PAYLOAD, SEARCH_PAGES } from 'test/mocks/pages';
@@ -101,6 +102,38 @@ describe('api/pages', () => {
});
});
+ describe('postWebuiPage', () => {
+ it('returns a promise', () => {
+ expect(postWebuiPage(CONTACTS_PAYLOAD)).toBeInstanceOf(Promise);
+ });
+
+ it('makes the correct request', () => {
+ postWebuiPage(CONTACTS_PAYLOAD);
+ expect(makeRequest).toHaveBeenCalledWith(expect.objectContaining({
+ uri: '/api/pages',
+ body: CONTACTS_PAYLOAD,
+ method: METHODS.POST,
+ useAuthentication: true,
+ }));
+ });
+ });
+
+ describe('postWebuiClonePage', () => {
+ it('returns a promise', () => {
+ expect(postWebuiClonePage('contacts', CONTACTS_PAYLOAD)).toBeInstanceOf(Promise);
+ });
+
+ it('makes the correct request', () => {
+ postWebuiPage('contacts', CONTACTS_PAYLOAD);
+ expect(makeRequest).toHaveBeenCalledWith(expect.objectContaining({
+ uri: '/api/pages/contacts/clone',
+ body: CONTACTS_PAYLOAD,
+ method: METHODS.POST,
+ useAuthentication: true,
+ }));
+ });
+ });
+
fdescribe('patchPage', () => {
const jsonPatch = [
{
@@ -160,6 +193,22 @@ describe('api/pages', () => {
});
});
+ describe('deleteWebuiPage', () => {
+ it('returns a promise', () => {
+ expect(deleteWebuiPage(CONTACTS_PAYLOAD)).toBeInstanceOf(Promise);
+ });
+
+ it('makes the correct request', () => {
+ deleteWebuiPage(CONTACTS_PAYLOAD);
+ expect(makeRequest).toHaveBeenCalledWith(expect.objectContaining({
+ uri: `/api/pages/${CONTACTS_PAYLOAD.code}`,
+ method: METHODS.DELETE,
+ mockResponse: { code: CONTACTS_PAYLOAD.code },
+ useAuthentication: true,
+ }));
+ });
+ });
+
describe('getPageSettings', () => {
it('returns a promise', () => {
expect(getPageSettings()).toBeInstanceOf(Promise);
@@ -326,4 +375,37 @@ describe('api/pages', () => {
}));
});
});
+
+ describe('putWebuiPageStatus', () => {
+ it('returns a promise', () => {
+ expect(putWebuiPageStatus(CONTACTS_PAYLOAD)).toBeInstanceOf(Promise);
+ });
+
+ it('makes the correct request', () => {
+ putWebuiPageStatus('code1', 'published');
+ expect(makeRequest).toHaveBeenCalledWith(expect.objectContaining({
+ uri: '/api/pages/code1/status',
+ body: { status: 'published' },
+ method: METHODS.PUT,
+ useAuthentication: true,
+ }));
+ });
+ });
+
+ describe('putWebuiPage', () => {
+ it('returns a promise', () => {
+ expect(putWebuiPage(CONTACTS_PAYLOAD)).toBeInstanceOf(Promise);
+ });
+
+ it('makes the correct request', () => {
+ putWebuiPage(CONTACTS_PAYLOAD);
+ expect(makeRequest).toHaveBeenCalledWith(expect.objectContaining({
+ uri: `/api/pages/${CONTACTS_PAYLOAD.code}`,
+ body: CONTACTS_PAYLOAD,
+ method: METHODS.PUT,
+ errors: expect.any(Function),
+ useAuthentication: true,
+ }));
+ });
+ });
});
diff --git a/test/test/mocks/pages.js b/test/test/mocks/pages.js
index da426ceb1..bb75ca2af 100644
--- a/test/test/mocks/pages.js
+++ b/test/test/mocks/pages.js
@@ -87,6 +87,7 @@ export const SERVICE_PAYLOAD = {
parentCode: 'homepage',
seo: false,
position: 3,
+ type: 'NX',
titles: {
it: 'Pagina di servizio',
en: 'Service page',