mirror of
https://github.com/flarum/core.git
synced 2025-07-29 04:30:56 +02:00
Further refinements to admin extensions page
This commit is contained in:
@@ -11,31 +11,7 @@ import listItems from 'flarum/helpers/listItems';
|
|||||||
|
|
||||||
export default class ExtensionsPage extends Component {
|
export default class ExtensionsPage extends Component {
|
||||||
view() {
|
view() {
|
||||||
const groups = [
|
const extensions = Object.keys(app.extensions).map(id => app.extensions[id]);
|
||||||
{keyword: 'discussion', title: 'Discussions', extensions: []},
|
|
||||||
{keyword: 'formatting', title: 'Formatting', extensions: []},
|
|
||||||
{keyword: 'moderation', title: 'Moderation', extensions: []},
|
|
||||||
{keyword: 'theme', title: 'Themes', extensions: []},
|
|
||||||
{keyword: 'authentication', title: 'Authentication', extensions: []},
|
|
||||||
{keyword: 'locale', title: 'Language Packs', extensions: []},
|
|
||||||
{title: 'Other', extensions: []}
|
|
||||||
];
|
|
||||||
|
|
||||||
Object.keys(app.extensions).forEach(id => {
|
|
||||||
const extension = app.extensions[id];
|
|
||||||
const keywords = extension.keywords;
|
|
||||||
|
|
||||||
const grouped = keywords && groups.some(group => {
|
|
||||||
if (keywords.indexOf(group.keyword) !== -1) {
|
|
||||||
group.extensions.push(extension);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!grouped) {
|
|
||||||
groups[groups.length - 1].extensions.push(extension);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ExtensionsPage">
|
<div className="ExtensionsPage">
|
||||||
@@ -52,32 +28,36 @@ export default class ExtensionsPage extends Component {
|
|||||||
|
|
||||||
<div className="ExtensionsPage-list">
|
<div className="ExtensionsPage-list">
|
||||||
<div className="container">
|
<div className="container">
|
||||||
{groups.filter(group => group.extensions.length).map(group => (
|
|
||||||
<div className="ExtensionGroup">
|
|
||||||
<h3>{group.title}</h3>
|
|
||||||
<ul className="ExtensionList">
|
<ul className="ExtensionList">
|
||||||
{group.extensions
|
{extensions
|
||||||
.sort((a, b) => a.extra['flarum-extension'].title.localeCompare(b.extra['flarum-extension'].title))
|
.sort((a, b) => a.extra['flarum-extension'].title.localeCompare(b.extra['flarum-extension'].title))
|
||||||
.map(extension => {
|
.map(extension => {
|
||||||
|
const controls = this.controlItems(extension.id).toArray();
|
||||||
|
|
||||||
return <li className={'ExtensionListItem ' + (!this.isEnabled(extension.id) ? 'disabled' : '')}>
|
return <li className={'ExtensionListItem ' + (!this.isEnabled(extension.id) ? 'disabled' : '')}>
|
||||||
<ul className="ExtensionListItem-controls" style={extension.extra['flarum-extension'].icon}>
|
|
||||||
{listItems(this.controlItems(extension.id).toArray())}
|
|
||||||
</ul>
|
|
||||||
<div className="ExtensionListItem-content">
|
<div className="ExtensionListItem-content">
|
||||||
<span className="ExtensionListItem-icon ExtensionIcon" style={extension.extra['flarum-extension'].icon}>
|
<span className="ExtensionListItem-icon ExtensionIcon" style={extension.extra['flarum-extension'].icon}>
|
||||||
{extension.extra['flarum-extension'].icon ? icon(extension.extra['flarum-extension'].icon.name) : ''}
|
{extension.extra['flarum-extension'].icon ? icon(extension.extra['flarum-extension'].icon.name) : ''}
|
||||||
</span>
|
</span>
|
||||||
<h4 className="ExtensionListItem-title" title={extension.description}>
|
{controls.length ? (
|
||||||
|
<Dropdown
|
||||||
|
className="ExtensionListItem-controls"
|
||||||
|
buttonClassName="Button Button--icon Button--flat"
|
||||||
|
menuClassName="Dropdown-menu--right"
|
||||||
|
icon="ellipsis-h">
|
||||||
|
{controls}
|
||||||
|
</Dropdown>
|
||||||
|
) : ''}
|
||||||
|
<label className="ExtensionListItem-title">
|
||||||
|
<input type="checkbox" checked={this.isEnabled(extension.id)} onclick={this.toggle.bind(this, extension.id)}/> {' '}
|
||||||
{extension.extra['flarum-extension'].title}
|
{extension.extra['flarum-extension'].title}
|
||||||
</h4>
|
</label>
|
||||||
<div className="ExtensionListItem-version">{extension.version}</div>
|
<div className="ExtensionListItem-version">{extension.version}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>;
|
</li>;
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -85,37 +65,19 @@ export default class ExtensionsPage extends Component {
|
|||||||
|
|
||||||
controlItems(name) {
|
controlItems(name) {
|
||||||
const items = new ItemList();
|
const items = new ItemList();
|
||||||
const extension = app.extensions[name];
|
|
||||||
const enabled = this.isEnabled(name);
|
const enabled = this.isEnabled(name);
|
||||||
|
|
||||||
if (app.extensionSettings[name]) {
|
if (app.extensionSettings[name]) {
|
||||||
items.add('settings', Button.component({
|
items.add('settings', Button.component({
|
||||||
icon: 'cog',
|
icon: 'cog',
|
||||||
className: 'Button',
|
|
||||||
children: 'Settings',
|
children: 'Settings',
|
||||||
onclick: app.extensionSettings[name]
|
onclick: app.extensionSettings[name]
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
items.add('toggle', Button.component({
|
|
||||||
icon: 'power-off',
|
|
||||||
className: 'Button',
|
|
||||||
children: enabled ? 'Disable' : 'Enable',
|
|
||||||
onclick: () => {
|
|
||||||
app.request({
|
|
||||||
url: app.forum.attribute('apiUrl') + '/extensions/' + name,
|
|
||||||
method: 'PATCH',
|
|
||||||
data: {enabled: !enabled}
|
|
||||||
}).then(() => window.location.reload());
|
|
||||||
|
|
||||||
app.modal.show(new LoadingModal());
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
items.add('uninstall', Button.component({
|
items.add('uninstall', Button.component({
|
||||||
icon: 'trash-o',
|
icon: 'trash-o',
|
||||||
className: 'Button',
|
|
||||||
children: 'Uninstall',
|
children: 'Uninstall',
|
||||||
onclick: () => {
|
onclick: () => {
|
||||||
app.request({
|
app.request({
|
||||||
@@ -136,4 +98,19 @@ export default class ExtensionsPage extends Component {
|
|||||||
|
|
||||||
return enabled.indexOf(name) !== -1;
|
return enabled.indexOf(name) !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggle(id) {
|
||||||
|
const enabled = this.isEnabled(id);
|
||||||
|
|
||||||
|
app.request({
|
||||||
|
url: app.forum.attribute('apiUrl') + '/extensions/' + id,
|
||||||
|
method: 'PATCH',
|
||||||
|
data: {enabled: !enabled}
|
||||||
|
}).then(() => {
|
||||||
|
if (enabled) localStorage.setItem('enabledExtension', id);
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.modal.show(new LoadingModal());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -54,4 +54,12 @@ export default function boot(app) {
|
|||||||
}).start();
|
}).start();
|
||||||
|
|
||||||
app.booted = true;
|
app.booted = true;
|
||||||
|
|
||||||
|
// If an extension has just been enabled, then we will run its settings
|
||||||
|
// callback.
|
||||||
|
const enabled = localStorage.getItem('enabledExtension');
|
||||||
|
if (enabled && app.extensionSettings[enabled]) {
|
||||||
|
app.extensionSettings[enabled]();
|
||||||
|
localStorage.removeItem('enabledExtension');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -25,50 +25,19 @@
|
|||||||
|
|
||||||
> li {
|
> li {
|
||||||
float: left;
|
float: left;
|
||||||
text-align: center;
|
text-align: left;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ExtensionListItem.disabled .ExtensionListItem-content {
|
.ExtensionListItem.disabled {
|
||||||
|
.ExtensionListItem-title {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
color: @muted-color;
|
color: @muted-color;
|
||||||
|
}
|
||||||
.ExtensionListItem-icon {
|
.ExtensionListItem-icon {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ExtensionListItem-controls {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
height: 120px;
|
|
||||||
border-radius: 6px;
|
|
||||||
background-image: none !important;
|
|
||||||
opacity: 0;
|
|
||||||
z-index: 1;
|
|
||||||
margin: 0;
|
|
||||||
padding: 5px 5px 0;
|
|
||||||
.light-contents();
|
|
||||||
.transition(opacity 0.2s);
|
|
||||||
display: flex;
|
|
||||||
align-items: stretch;
|
|
||||||
align-content: stretch;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.ExtensionListItem:hover & {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
> li {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
.Button {
|
|
||||||
.Button--block();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ExtensionListItem {
|
.ExtensionListItem {
|
||||||
width: 120px;
|
width: 120px;
|
||||||
height: 160px;
|
height: 160px;
|
||||||
@@ -76,17 +45,30 @@
|
|||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
.ExtensionListItem-title {
|
.ExtensionListItem-title {
|
||||||
font-size: 14px;
|
display: block;
|
||||||
margin: 10px 0 2px;
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 8px 0 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.ExtensionListItem-version {
|
.ExtensionListItem-version {
|
||||||
color: @muted-more-color;
|
color: @muted-more-color;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
.ExtensionListItem-controls {
|
||||||
|
float: right;
|
||||||
|
display: none;
|
||||||
|
margin-right: -5px;
|
||||||
|
margin-top: 1px;
|
||||||
|
|
||||||
|
.ExtensionListItem:hover &, &.open {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ExtensionIcon {
|
.ExtensionIcon {
|
||||||
width: 120px;
|
width: 120px;
|
||||||
|
Reference in New Issue
Block a user