mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
Added route for new admin-x settings
refs https://github.com/TryGhost/Team/issues/3151 - adds route in Admin for opening new settings screen in react - adds new config for passing `adminX` to Admin - loads adminX settings from package in Admin UI when new route is opened Co-authored-by: Peter Zimon <zimo@ghost.org>
This commit is contained in:
parent
3d6fb0d6b1
commit
bf2a2eeb63
8 changed files with 172 additions and 2 deletions
1
ghost/admin/app/components/admin-x/settings.hbs
Normal file
1
ghost/admin/app/components/admin-x/settings.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
<div {{react-render this.ReactComponent}}></div>
|
124
ghost/admin/app/components/admin-x/settings.js
Normal file
124
ghost/admin/app/components/admin-x/settings.js
Normal file
|
@ -0,0 +1,124 @@
|
|||
import * as Sentry from '@sentry/ember';
|
||||
import Component from '@glimmer/component';
|
||||
import React, {Suspense} from 'react';
|
||||
import {action} from '@ember/object';
|
||||
import {inject} from 'ghost-admin/decorators/inject';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
class ErrorHandler extends React.Component {
|
||||
state = {
|
||||
hasError: false
|
||||
};
|
||||
|
||||
static getDerivedStateFromError() {
|
||||
return {hasError: true};
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<p className="koenig-react-editor-error">Loading has failed. Try refreshing the browser!</p>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
const fetchKoenig = function () {
|
||||
let status = 'pending';
|
||||
let response;
|
||||
|
||||
const fetchPackage = async () => {
|
||||
if (window['@tryghost/admin-x-settings']) {
|
||||
return window['@tryghost/admin-x-settings'];
|
||||
}
|
||||
|
||||
// the manual specification of the protocol in the import template string is
|
||||
// required to work around ember-auto-import complaining about an unknown dynamic import
|
||||
// during the build step
|
||||
const GhostAdmin = window.GhostAdmin || window.Ember.Namespace.NAMESPACES.find(ns => ns.name === 'ghost-admin');
|
||||
const urlTemplate = GhostAdmin.__container__.lookup('config:main').adminX?.url;
|
||||
const urlVersion = GhostAdmin.__container__.lookup('config:main').adminX?.version;
|
||||
|
||||
const url = new URL(urlTemplate.replace('{version}', urlVersion));
|
||||
|
||||
if (url.protocol === 'http:') {
|
||||
await import(`http://${url.host}${url.pathname}`);
|
||||
} else {
|
||||
await import(`https://${url.host}${url.pathname}`);
|
||||
}
|
||||
|
||||
return window['@tryghost/admin-x-settings'];
|
||||
};
|
||||
|
||||
const suspender = fetchPackage().then(
|
||||
(res) => {
|
||||
status = 'success';
|
||||
response = res;
|
||||
},
|
||||
(err) => {
|
||||
status = 'error';
|
||||
response = err;
|
||||
}
|
||||
);
|
||||
|
||||
const read = () => {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
throw suspender;
|
||||
case 'error':
|
||||
throw response;
|
||||
default:
|
||||
return response;
|
||||
}
|
||||
};
|
||||
|
||||
return {read};
|
||||
};
|
||||
|
||||
const editorResource = fetchKoenig();
|
||||
|
||||
const AdminXApp = (props) => {
|
||||
const {AdminXApp: _AdminXApp} = editorResource.read();
|
||||
return <_AdminXApp {...props} />;
|
||||
};
|
||||
|
||||
export default class KoenigLexicalEditor extends Component {
|
||||
@service ajax;
|
||||
@service feature;
|
||||
@service ghostPaths;
|
||||
@service session;
|
||||
@service store;
|
||||
@service settings;
|
||||
|
||||
@inject config;
|
||||
|
||||
@action
|
||||
onError(error) {
|
||||
// ensure we're still showing errors in development
|
||||
console.error(error); // eslint-disable-line
|
||||
|
||||
if (this.config.sentry_dsn) {
|
||||
Sentry.captureException(error, {
|
||||
tags: {
|
||||
adminx: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// don't rethrow, Lexical will attempt to gracefully recover
|
||||
}
|
||||
|
||||
ReactComponent = () => {
|
||||
return (
|
||||
<div className={['koenig-react-editor', this.args.className].filter(Boolean).join(' ')}>
|
||||
<ErrorHandler>
|
||||
<Suspense fallback={<p className="koenig-react-editor-loading">Loading settings...</p>}>
|
||||
<AdminXApp />
|
||||
</Suspense>
|
||||
</ErrorHandler>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
14
ghost/admin/app/controllers/settings-x.js
Normal file
14
ghost/admin/app/controllers/settings-x.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import AboutModal from '../components/modals/settings/about';
|
||||
import Controller from '@ember/controller';
|
||||
import {action} from '@ember/object';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
export default class SettingsController extends Controller {
|
||||
@service modals;
|
||||
@service upgradeStatus;
|
||||
|
||||
@action
|
||||
openAbout() {
|
||||
this.advancedModal = this.modals.open(AboutModal);
|
||||
}
|
||||
}
|
|
@ -50,6 +50,7 @@ Router.map(function () {
|
|||
this.route('tag.new', {path: '/tags/new'});
|
||||
this.route('tag', {path: '/tags/:tag_slug'});
|
||||
|
||||
this.route('settings-x');
|
||||
this.route('settings');
|
||||
this.route('settings.general', {path: '/settings/general'});
|
||||
this.route('settings.membership', {path: '/settings/members'});
|
||||
|
|
27
ghost/admin/app/routes/settings-x.js
Normal file
27
ghost/admin/app/routes/settings-x.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
|
||||
import {inject as service} from '@ember/service';
|
||||
|
||||
export default class SettingsXRoute extends AuthenticatedRoute {
|
||||
@service session;
|
||||
@service ui;
|
||||
|
||||
beforeModel() {
|
||||
super.beforeModel(...arguments);
|
||||
|
||||
const user = this.session.user;
|
||||
|
||||
if (!user.isAdmin) {
|
||||
return this.transitionTo('settings.staff.user', user);
|
||||
}
|
||||
}
|
||||
|
||||
activate() {
|
||||
super.activate(...arguments);
|
||||
this.ui.set('isFullScreen', true);
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
super.deactivate(...arguments);
|
||||
this.ui.set('isFullScreen', false);
|
||||
}
|
||||
}
|
1
ghost/admin/app/templates/settings-x.hbs
Normal file
1
ghost/admin/app/templates/settings-x.hbs
Normal file
|
@ -0,0 +1 @@
|
|||
<AdminX::Settings />
|
|
@ -20,7 +20,8 @@ module.exports = {
|
|||
'hostSettings',
|
||||
'tenor',
|
||||
'editor',
|
||||
'pintura'
|
||||
'pintura',
|
||||
'adminX'
|
||||
];
|
||||
|
||||
frame.response = {
|
||||
|
|
|
@ -20,7 +20,8 @@ module.exports = function getConfigProperties() {
|
|||
hostSettings: config.get('hostSettings'),
|
||||
tenor: config.get('tenor'),
|
||||
editor: config.get('editor'),
|
||||
pintura: config.get('pintura')
|
||||
pintura: config.get('pintura'),
|
||||
adminX: config.get('adminX')
|
||||
};
|
||||
|
||||
const billingUrl = config.get('hostSettings:billing:enabled') ? config.get('hostSettings:billing:url') : '';
|
||||
|
|
Loading…
Add table
Reference in a new issue