Skip to content

Commit

Permalink
AdminUX Patch and Admin Page (#2593)
Browse files Browse the repository at this point in the history
* AdminPage

* More fixes

* Settings Modal Drop

* Translation and docblock

* settingS

* Convert Fieldset to JSX

* info -> headerInfo, className

* Overflow fixes

* MailPage

* Admin Less

* Basics Page

* Changes

* Cleanup

* Permission Page

* Add padding
  • Loading branch information
KyrneDev authored and askvortsov1 committed Feb 21, 2021
1 parent b28a6ba commit e40fed5
Show file tree
Hide file tree
Showing 21 changed files with 578 additions and 782 deletions.
12 changes: 0 additions & 12 deletions js/src/admin/AdminApplication.js
@@ -1,16 +1,12 @@
import HeaderPrimary from './components/HeaderPrimary';
import HeaderSecondary from './components/HeaderSecondary';
import routes from './routes';
import ExtensionPage from './components/ExtensionPage';
import Application from '../common/Application';
import Navigation from '../common/components/Navigation';
import AdminNav from './components/AdminNav';
import ExtensionData from './utils/ExtensionData';

export default class AdminApplication extends Application {
// Deprecated as of beta 15
extensionSettings = {};

extensionData = new ExtensionData();

extensionCategories = {
Expand Down Expand Up @@ -61,14 +57,6 @@ export default class AdminApplication extends Application {
m.mount(document.getElementById('header-primary'), HeaderPrimary);
m.mount(document.getElementById('header-secondary'), HeaderSecondary);
m.mount(document.getElementById('admin-navigation'), AdminNav);

// If an extension has just been enabled, then we will run its settings
// callback.
const enabled = localStorage.getItem('enabledExtension');
if (enabled && this.extensionSettings[enabled] && typeof this.extensionSettings[enabled] === 'function') {
this.extensionSettings[enabled]();
localStorage.removeItem('enabledExtension');
}
}

getRequiredPermissions(permission) {
Expand Down
4 changes: 2 additions & 2 deletions js/src/admin/compat.js
Expand Up @@ -8,6 +8,7 @@ import SettingDropdown from './components/SettingDropdown';
import EditCustomFooterModal from './components/EditCustomFooterModal';
import SessionDropdown from './components/SessionDropdown';
import HeaderPrimary from './components/HeaderPrimary';
import AdminPage from './components/AdminPage';
import AppearancePage from './components/AppearancePage';
import StatusWidget from './components/StatusWidget';
import ExtensionsWidget from './components/ExtensionsWidget';
Expand All @@ -16,7 +17,6 @@ import SettingsModal from './components/SettingsModal';
import DashboardWidget from './components/DashboardWidget';
import ExtensionPage from './components/ExtensionPage';
import ExtensionLinkButton from './components/ExtensionLinkButton';
import AdminLinkButton from './components/AdminLinkButton';
import PermissionGrid from './components/PermissionGrid';
import ExtensionPermissionGrid from './components/ExtensionPermissionGrid';
import MailPage from './components/MailPage';
Expand All @@ -43,6 +43,7 @@ export default Object.assign(compat, {
'components/EditCustomFooterModal': EditCustomFooterModal,
'components/SessionDropdown': SessionDropdown,
'components/HeaderPrimary': HeaderPrimary,
'components/AdminPage': AdminPage,
'components/AppearancePage': AppearancePage,
'components/StatusWidget': StatusWidget,
'components/ExtensionsWidget': ExtensionsWidget,
Expand All @@ -51,7 +52,6 @@ export default Object.assign(compat, {
'components/DashboardWidget': DashboardWidget,
'components/ExtensionPage': ExtensionPage,
'components/ExtensionLinkButton': ExtensionLinkButton,
'components/AdminLinkButton': AdminLinkButton,
'components/PermissionGrid': PermissionGrid,
'components/ExtensionPermissionGrid': ExtensionPermissionGrid,
'components/MailPage': MailPage,
Expand Down
32 changes: 0 additions & 32 deletions js/src/admin/components/AddExtensionModal.js

This file was deleted.

16 changes: 0 additions & 16 deletions js/src/admin/components/AdminLinkButton.js

This file was deleted.

174 changes: 174 additions & 0 deletions js/src/admin/components/AdminPage.js
@@ -0,0 +1,174 @@
import Page from '../../common/components/Page';
import Button from '../../common/components/Button';
import Switch from '../../common/components/Switch';
import Select from '../../common/components/Select';
import classList from '../../common/utils/classList';
import Stream from '../../common/utils/Stream';
import saveSettings from '../utils/saveSettings';
import AdminHeader from './AdminHeader';

export default class AdminPage extends Page {
oninit(vnode) {
super.oninit(vnode);

this.settings = {};

this.loading = false;
}

view() {
const className = classList(['AdminPage', this.headerInfo().className]);

return (
<div className={className}>
{this.header()}
<div className="container">{this.content()}</div>
</div>
);
}

content() {
return '';
}

submitButton() {
return (
<Button onclick={this.saveSettings.bind(this)} className="Button Button--primary" loading={this.loading} disabled={!this.isChanged()}>
{app.translator.trans('core.admin.settings.submit_button')}
</Button>
);
}

header() {
const headerInfo = this.headerInfo();

return (
<AdminHeader icon={headerInfo.icon} description={headerInfo.description} className={headerInfo.className + '-header'}>
{headerInfo.title}
</AdminHeader>
);
}

headerInfo() {
return {
className: '',
icon: '',
title: '',
description: '',
};
}

/**
* buildSettingComponent takes a settings object and turns it into a component.
* Depending on the type of input, you can set the type to 'bool', 'select', or
* any standard <input> type. Any values inside the 'extra' object will be added
* to the component as an attribute.
*
* Alternatively, you can pass a callback that will be executed in ExtensionPage's
* context to include custom JSX elements.
*
* @example
*
* {
* setting: 'acme.checkbox',
* label: app.translator.trans('acme.admin.setting_label'),
* type: 'bool',
* help: app.translator.trans('acme.admin.setting_help'),
* className: 'Setting-item'
* }
*
* @example
*
* {
* setting: 'acme.select',
* label: app.translator.trans('acme.admin.setting_label'),
* type: 'select',
* options: {
* 'option1': 'Option 1 label',
* 'option2': 'Option 2 label',
* },
* default: 'option1',
* }
*
* @param setting
* @returns {JSX.Element}
*/
buildSettingComponent(entry) {
if (typeof entry === 'function') {
return entry.call(this);
}

const setting = entry.setting;
const help = entry.help;
delete entry.help;

const value = this.setting([setting])();
if (['bool', 'checkbox', 'switch', 'boolean'].includes(entry.type)) {
return (
<div className="Form-group">
<Switch state={!!value && value !== '0'} onchange={this.settings[setting]} {...entry}>
{entry.label}
</Switch>
<div className="helpText">{help}</div>
</div>
);
} else if (['select', 'dropdown', 'selectdropdown'].includes(entry.type)) {
return (
<div className="Form-group">
<label>{entry.label}</label>
<div className="helpText">{help}</div>
<Select value={value || entry.default} options={entry.options} buttonClassName="Button" onchange={this.settings[setting]} {...entry} />
</div>
);
} else {
entry.className = classList(['FormControl', entry.className]);
return (
<div className="Form-group">
{entry.label ? <label>{entry.label}</label> : ''}
<div className="helpText">{help}</div>
<input type={entry.type} bidi={this.setting(setting)} {...entry} />
</div>
);
}
}

onsaved() {
this.loading = false;

app.alerts.show({ type: 'success' }, app.translator.trans('core.admin.settings.saved_message'));
}

setting(key, fallback = '') {
this.settings[key] = this.settings[key] || Stream(app.data.settings[key] || fallback);

return this.settings[key];
}

dirty() {
const dirty = {};

Object.keys(this.settings).forEach((key) => {
const value = this.settings[key]();

if (value !== app.data.settings[key]) {
dirty[key] = value;
}
});

return dirty;
}

isChanged() {
return Object.keys(this.dirty()).length;
}

saveSettings(e) {
e.preventDefault();

app.alerts.clear();

this.loading = true;

return saveSettings(this.dirty()).then(this.onsaved.bind(this));
}
}

0 comments on commit e40fed5

Please sign in to comment.