Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AdminUX Overhaul #2409

Merged
merged 61 commits into from
Nov 24, 2020
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
b7caaea
Admin Component Changes
KyrneDev Oct 24, 2020
abf0229
AdminUX
KyrneDev Oct 24, 2020
4e16808
Common Changes
KyrneDev Oct 24, 2020
387af7a
WIP Admin changes
KyrneDev Oct 27, 2020
638ca5f
AdminHeader
KyrneDev Oct 27, 2020
bf4a5ab
Admin JS Update
KyrneDev Nov 7, 2020
415d13b
Admin Less Changes
KyrneDev Nov 7, 2020
810c5ba
Delete addExtensionPermission.js
KyrneDev Nov 7, 2020
7cda22b
Delete extensionData.js
KyrneDev Nov 7, 2020
c299515
Delete ExtensionsPage.js
KyrneDev Nov 7, 2020
6094706
Make prettier happy
KyrneDev Nov 7, 2020
1557c0c
Add Extensions widget title
KyrneDev Nov 8, 2020
f8c881f
Extensions Widget Title
KyrneDev Nov 8, 2020
3fb4df5
Less changes
KyrneDev Nov 9, 2020
c06e6df
JS Changes
KyrneDev Nov 9, 2020
479d81d
Delete ExtensionSetting.js
KyrneDev Nov 9, 2020
ee8da3c
JS Changes
KyrneDev Nov 9, 2020
7a0d6f0
Small Less Changes
KyrneDev Nov 9, 2020
4a421e3
Remove padding dashboard
KyrneDev Nov 9, 2020
87ed7c6
Make the source link actually work
KyrneDev Nov 10, 2020
543636c
Tighten up extension header, change ExtensionsWidget
KyrneDev Nov 10, 2020
aa5ef58
Admin LESS
KyrneDev Nov 10, 2020
06b7ec5
Js
KyrneDev Nov 10, 2020
37f3e28
De-cramp buttons
KyrneDev Nov 12, 2020
fc76546
JS Changes
KyrneDev Nov 12, 2020
b26c8ab
Alert patch + Fix select dropdown
KyrneDev Nov 12, 2020
26f2395
Mobile Optimization
KyrneDev Nov 12, 2020
de11491
More mobile fixes
KyrneDev Nov 12, 2020
bf4bf62
Fix Dirty
KyrneDev Nov 13, 2020
09ff411
Tablet friendly!
KyrneDev Nov 13, 2020
c9fd791
Delete ExtensionsPage.less
KyrneDev Nov 13, 2020
804d6c6
LESS Updates
KyrneDev Nov 13, 2020
8c3fb30
Lots of JS Changes
KyrneDev Nov 13, 2020
35c469c
Docblock
KyrneDev Nov 13, 2020
952adba
Formatting :)
KyrneDev Nov 13, 2020
ba55415
Basics page padding
KyrneDev Nov 13, 2020
259323f
Delete fullTime.js
KyrneDev Nov 13, 2020
9b3d4b5
More JS
KyrneDev Nov 13, 2020
1f10226
Revert Common
KyrneDev Nov 13, 2020
adf320c
Make Sasha happy :0
KyrneDev Nov 13, 2020
b790d16
Author emails/websites
KyrneDev Nov 13, 2020
3ea124b
Organize
KyrneDev Nov 13, 2020
020b3ad
punctuateSeries
KyrneDev Nov 14, 2020
64be01f
Less Fixes
KyrneDev Nov 14, 2020
6001cb2
JS Format
KyrneDev Nov 14, 2020
4999a34
Typo
KyrneDev Nov 16, 2020
63acd38
Remove un-used class
KyrneDev Nov 16, 2020
6dd9ace
LESS Cleanup
KyrneDev Nov 16, 2020
bc81fd7
Remove Padding
KyrneDev Nov 16, 2020
c184486
Delete humanTime.js
KyrneDev Nov 19, 2020
745aea0
Update humanTime.ts
KyrneDev Nov 19, 2020
98a96b5
Admin changes
KyrneDev Nov 22, 2020
f1d6e8d
Update AdminNav.less
KyrneDev Nov 22, 2020
db48d5d
Delete extensionEnabled.js
KyrneDev Nov 22, 2020
b6ff744
Update ExtensionPage.js
KyrneDev Nov 23, 2020
517c88b
register settings ItemList
KyrneDev Nov 23, 2020
f825d87
Update ExtensionPage.js
KyrneDev Nov 23, 2020
14fddb0
Singular setting
KyrneDev Nov 23, 2020
0f655f2
Update ExtensionData.js
KyrneDev Nov 23, 2020
25eb118
getSetting -> buildSettingComponent
KyrneDev Nov 23, 2020
a980513
Binding is cool!
KyrneDev Nov 24, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions js/src/admin/AdminApplication.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
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 = {
discussion: 70,
moderation: 60,
feature: 50,
formatting: 40,
theme: 30,
authentication: 20,
language: 10,
other: 0,
};

history = {
canGoBack: () => true,
getPrevious: () => {},
Expand All @@ -34,7 +50,13 @@ export default class AdminApplication extends Application {
m.route.prefix = '#';
super.mount();

m.mount(document.getElementById('app-navigation'), { view: () => Navigation.component({ className: 'App-backControl', drawer: true }) });
m.mount(document.getElementById('app-navigation'), {
view: () =>
Navigation.component({
className: 'App-backControl',
drawer: true,
}),
});
m.mount(document.getElementById('header-navigation'), Navigation);
m.mount(document.getElementById('header-primary'), HeaderPrimary);
m.mount(document.getElementById('header-secondary'), HeaderSecondary);
Expand All @@ -43,7 +65,7 @@ export default class AdminApplication extends Application {
// If an extension has just been enabled, then we will run its settings
// callback.
const enabled = localStorage.getItem('enabledExtension');
if (enabled && this.extensionSettings[enabled]) {
if (enabled && this.extensionSettings[enabled] && typeof this.extensionSettings[enabled] === 'function') {
this.extensionSettings[enabled]();
localStorage.removeItem('enabledExtension');
}
Expand Down
18 changes: 14 additions & 4 deletions js/src/admin/compat.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import compat from '../common/compat';

import saveSettings from './utils/saveSettings';
import ExtensionData from './utils/ExtensionData';
import isExtensionEnabled from './utils/isExtensionEnabled';
import getCategorizedExtensions from './utils/getCategorizedExtensions';
import SettingDropdown from './components/SettingDropdown';
import EditCustomFooterModal from './components/EditCustomFooterModal';
import SessionDropdown from './components/SessionDropdown';
import HeaderPrimary from './components/HeaderPrimary';
import AppearancePage from './components/AppearancePage';
import StatusWidget from './components/StatusWidget';
import ExtensionsWidget from './components/ExtensionsWidget';
import HeaderSecondary from './components/HeaderSecondary';
import SettingsModal from './components/SettingsModal';
import DashboardWidget from './components/DashboardWidget';
import AddExtensionModal from './components/AddExtensionModal';
import ExtensionsPage from './components/ExtensionsPage';
import ExtensionPage from './components/ExtensionPage';
import ExtensionLinkButton from './components/ExtensionLinkButton';
import AdminLinkButton from './components/AdminLinkButton';
import PermissionGrid from './components/PermissionGrid';
import MailPage from './components/MailPage';
Expand All @@ -23,24 +27,29 @@ import EditCustomHeaderModal from './components/EditCustomHeaderModal';
import PermissionsPage from './components/PermissionsPage';
import PermissionDropdown from './components/PermissionDropdown';
import AdminNav from './components/AdminNav';
import AdminHeader from './components/AdminHeader';
import EditCustomCssModal from './components/EditCustomCssModal';
import EditGroupModal from './components/EditGroupModal';
import routes from './routes';
import AdminApplication from './AdminApplication';

export default Object.assign(compat, {
'utils/saveSettings': saveSettings,
'utils/ExtensionData': ExtensionData,
'utils/isExtensionEnabled': isExtensionEnabled,
'utils/getCategorizedExtensions': getCategorizedExtensions,
'components/SettingDropdown': SettingDropdown,
'components/EditCustomFooterModal': EditCustomFooterModal,
'components/SessionDropdown': SessionDropdown,
'components/HeaderPrimary': HeaderPrimary,
'components/AppearancePage': AppearancePage,
'components/StatusWidget': StatusWidget,
'components/ExtensionsWidget': ExtensionsWidget,
'components/HeaderSecondary': HeaderSecondary,
'components/SettingsModal': SettingsModal,
'components/DashboardWidget': DashboardWidget,
'components/AddExtensionModal': AddExtensionModal,
'components/ExtensionsPage': ExtensionsPage,
'components/ExtensionPage': ExtensionPage,
'components/ExtensionLinkButton': ExtensionLinkButton,
'components/AdminLinkButton': AdminLinkButton,
'components/PermissionGrid': PermissionGrid,
'components/MailPage': MailPage,
Expand All @@ -52,6 +61,7 @@ export default Object.assign(compat, {
'components/PermissionsPage': PermissionsPage,
'components/PermissionDropdown': PermissionDropdown,
'components/AdminNav': AdminNav,
'components/AdminHeader': AdminHeader,
'components/EditCustomCssModal': EditCustomCssModal,
'components/EditGroupModal': EditGroupModal,
routes: routes,
Expand Down
19 changes: 19 additions & 0 deletions js/src/admin/components/AdminHeader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Component from '../../common/Component';
import classList from '../../common/utils/classList';
import icon from '../../common/helpers/icon';

export default class AdminHeader extends Component {
view(vnode) {
return [
<div className={classList(['AdminHeader', this.attrs.className])}>
<div className="container">
<h2>
{icon(this.attrs.icon)}
{vnode.children}
</h2>
<div className="AdminHeader-description">{this.attrs.description}</div>
</div>
</div>,
];
}
}
138 changes: 76 additions & 62 deletions js/src/admin/components/AdminNav.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

import ExtensionLinkButton from './ExtensionLinkButton';
import Component from '../../common/Component';
import AdminLinkButton from './AdminLinkButton';
import LinkButton from '../../common/components/LinkButton';
import SelectDropdown from '../../common/components/SelectDropdown';
import getCategorizedExtensions from '../utils/getCategorizedExtensions';
import ItemList from '../../common/utils/ItemList';
import Stream from '../../common/utils/Stream';

export default class AdminNav extends Component {
oninit(vnode) {
super.oninit(vnode);

this.query = Stream('');
}

view() {
return (
<SelectDropdown className="AdminNav App-titleControl" buttonClassName="Button">
{this.items().toArray()}
<SelectDropdown className="AdminNav App-titleControl AdminNav-Main" buttonClassName="Button">
{this.items().toArray().concat(this.extensionItems().toArray())}
</SelectDropdown>
);
}

/**
* Build an item list of links to show in the admin navigation.
* Build an item list of main links to show in the admin navigation.
*
* @return {ItemList}
*/
Expand All @@ -31,76 +31,90 @@ export default class AdminNav extends Component {

items.add(
'dashboard',
AdminLinkButton.component(
{
href: app.route('dashboard'),
icon: 'far fa-chart-bar',
description: app.translator.trans('core.admin.nav.dashboard_text'),
},
app.translator.trans('core.admin.nav.dashboard_button')
)
<LinkButton href={app.route('dashboard')} icon="far fa-chart-bar" title={app.translator.trans('core.admin.nav.dashboard_title')}>
{app.translator.trans('core.admin.nav.dashboard_button')}
</LinkButton>
);

items.add(
'basics',
AdminLinkButton.component(
{
href: app.route('basics'),
icon: 'fas fa-pencil-alt',
description: app.translator.trans('core.admin.nav.basics_text'),
},
app.translator.trans('core.admin.nav.basics_button')
)
<LinkButton href={app.route('basics')} icon="fas fa-pencil-alt" title={app.translator.trans('core.admin.nav.basics_title')}>
{app.translator.trans('core.admin.nav.basics_button')}
</LinkButton>
);

items.add(
'mail',
AdminLinkButton.component(
{
href: app.route('mail'),
icon: 'fas fa-envelope',
description: app.translator.trans('core.admin.nav.email_text'),
},
app.translator.trans('core.admin.nav.email_button')
)
<LinkButton href={app.route('mail')} icon="fas fa-envelope" title={app.translator.trans('core.admin.nav.email_title')}>
{app.translator.trans('core.admin.nav.email_button')}
</LinkButton>
);

items.add(
'permissions',
AdminLinkButton.component(
{
href: app.route('permissions'),
icon: 'fas fa-key',
description: app.translator.trans('core.admin.nav.permissions_text'),
},
app.translator.trans('core.admin.nav.permissions_button')
)
<LinkButton href={app.route('permissions')} icon="fas fa-key" title={app.translator.trans('core.admin.nav.permissions_title')}>
{app.translator.trans('core.admin.nav.permissions_button')}
</LinkButton>
);

items.add(
'appearance',
AdminLinkButton.component(
{
href: app.route('appearance'),
icon: 'fas fa-paint-brush',
description: app.translator.trans('core.admin.nav.appearance_text'),
},
app.translator.trans('core.admin.nav.appearance_button')
)
<LinkButton href={app.route('appearance')} icon="fas fa-paint-brush" title={app.translator.trans('core.admin.nav.appearance_title')}>
{app.translator.trans('core.admin.nav.appearance_button')}
</LinkButton>
);

items.add(
'extensions',
AdminLinkButton.component(
{
href: app.route('extensions'),
icon: 'fas fa-puzzle-piece',
description: app.translator.trans('core.admin.nav.extensions_text'),
},
app.translator.trans('core.admin.nav.extensions_button')
)
'search',
<div className="Search-input">
<input
className="FormControl SearchBar"
bidi={this.query}
type="search"
placeholder={app.translator.trans('core.admin.nav.search_placeholder')}
/>
</div>
);

return items;
}

extensionItems() {
const items = new ItemList();

const categorizedExtensions = getCategorizedExtensions();
const categories = app.extensionCategories;

Object.keys(categorizedExtensions).map((category) => {
if (!this.query()) {
items.add(
category,
<h4 className="ExtensionListTitle">{app.translator.trans(`core.admin.nav.categories.${category}`)}</h4>,
categories[category]
);
}

categorizedExtensions[category].map((extension) => {
const query = this.query().toUpperCase();
const title = extension.extra['flarum-extension'].title;

if (!query || title.toUpperCase().includes(query) || extension.description.toUpperCase().includes(query)) {
items.add(
extension.id,
<ExtensionLinkButton
href={app.route('extension', { id: extension.id })}
extensionId={extension.id}
className="ExtensionNavButton"
title={extension.description}
>
{title}
</ExtensionLinkButton>,
categories[category]
);
}
});
});

return items;
}
}
8 changes: 8 additions & 0 deletions js/src/admin/components/AppearancePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import EditCustomHeaderModal from './EditCustomHeaderModal';
import EditCustomFooterModal from './EditCustomFooterModal';
import UploadImageButton from './UploadImageButton';
import saveSettings from '../utils/saveSettings';
import AdminHeader from './AdminHeader';

export default class AppearancePage extends Page {
oninit(vnode) {
Expand All @@ -21,6 +22,13 @@ export default class AppearancePage extends Page {
view() {
return (
<div className="AppearancePage">
<AdminHeader
icon="fas fa-paint-brush"
description={app.translator.trans('core.admin.appearance.description')}
className="AppearancePage-header"
>
{app.translator.trans('core.admin.appearance.title')}
</AdminHeader>
<div className="container">
<form onsubmit={this.onsubmit.bind(this)}>
<fieldset className="AppearancePage-colors">
Expand Down
4 changes: 4 additions & 0 deletions js/src/admin/components/BasicsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ItemList from '../../common/utils/ItemList';
import Switch from '../../common/components/Switch';
import Stream from '../../common/utils/Stream';
import withAttr from '../../common/utils/withAttr';
import AdminHeader from './AdminHeader';

export default class BasicsPage extends Page {
oninit(vnode) {
Expand Down Expand Up @@ -49,6 +50,9 @@ export default class BasicsPage extends Page {
view() {
return (
<div className="BasicsPage">
<AdminHeader icon="fas fa-pencil-alt" description={app.translator.trans('core.admin.basics.description')} className="BasicsPage-header">
{app.translator.trans('core.admin.basics.title')}
</AdminHeader>
<div className="container">
<form onsubmit={this.onsubmit.bind(this)}>
{FieldSet.component(
Expand Down
17 changes: 15 additions & 2 deletions js/src/admin/components/DashboardPage.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
import Page from '../../common/components/Page';
import StatusWidget from './StatusWidget';
import ExtensionsWidget from './ExtensionsWidget';
import AdminHeader from './AdminHeader';
import ItemList from '../../common/utils/ItemList';
import listItems from '../../common/helpers/listItems';

export default class DashboardPage extends Page {
view() {
return (
<div className="DashboardPage">
<div className="container">{this.availableWidgets()}</div>
<AdminHeader icon="fas fa-chart-bar" description={app.translator.trans('core.admin.dashboard.description')} className="DashboardPage-header">
{app.translator.trans('core.admin.dashboard.title')}
</AdminHeader>
<div className="container">{this.availableWidgets().toArray()}</div>
</div>
);
}

availableWidgets() {
return [<StatusWidget />];
const items = new ItemList();

items.add('status', <StatusWidget />, 30);

items.add('extensions', <ExtensionsWidget />, 10);

return items;
}
}
Loading