diff --git a/framework/core/js/admin/src/components/ExtensionsPage.js b/framework/core/js/admin/src/components/ExtensionsPage.js
index 7b111dc54..5d7bdf35a 100644
--- a/framework/core/js/admin/src/components/ExtensionsPage.js
+++ b/framework/core/js/admin/src/components/ExtensionsPage.js
@@ -7,9 +7,36 @@ import AddExtensionModal from 'flarum/components/AddExtensionModal';
import LoadingModal from 'flarum/components/LoadingModal';
import ItemList from 'flarum/utils/ItemList';
import icon from 'flarum/helpers/icon';
+import listItems from 'flarum/helpers/listItems';
export default class ExtensionsPage extends Component {
view() {
+ const groups = [
+ {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 (
@@ -25,33 +52,31 @@ export default class ExtensionsPage extends Component {
-
- {Object.keys(app.extensions)
- .sort((a, b) => app.extensions[a].extra['flarum-extension'].title.localeCompare(app.extensions[b].extra['flarum-extension'].title))
- .map(name => {
- const extension = app.extensions[name];
-
- return -
- {Dropdown.component({
- icon: 'ellipsis-v',
- children: this.controlItems(name).toArray(),
- className: 'ExtensionListItem-controls',
- buttonClassName: 'Button Button--icon Button--flat',
- menuClassName: 'Dropdown-menu--right'
+ {groups.filter(group => group.extensions.length).map(group => (
+
+
{group.title}
+
+ {group.extensions
+ .sort((a, b) => a.extra['flarum-extension'].title.localeCompare(b.extra['flarum-extension'].title))
+ .map(extension => {
+ return -
+
+ {listItems(this.controlItems(extension.id).toArray())}
+
+
+
+ {extension.extra['flarum-extension'].icon ? icon(extension.extra['flarum-extension'].icon.name) : ''}
+
+
+ {extension.extra['flarum-extension'].title}
+
+
{extension.version}
+
+ ;
})}
-
-
- {extension.extra['flarum-extension'].icon ? icon(extension.extra['flarum-extension'].icon.name) : ''}
-
-
- {extension.extra['flarum-extension'].title} {' '}
- {extension.version}
-
-
{extension.description}
-
- ;
- })}
-
+
+
+ ))}
@@ -63,14 +88,10 @@ export default class ExtensionsPage extends Component {
const extension = app.extensions[name];
const enabled = this.isEnabled(name);
- items.add('info',
- Package Name: {extension.name}
- Installed in: {name}
- );
-
if (app.extensionSettings[name]) {
items.add('settings', Button.component({
icon: 'cog',
+ className: 'Button',
children: 'Settings',
onclick: app.extensionSettings[name]
}));
@@ -78,6 +99,7 @@ export default class ExtensionsPage extends Component {
items.add('toggle', Button.component({
icon: 'power-off',
+ className: 'Button',
children: enabled ? 'Disable' : 'Enable',
onclick: () => {
app.request({
@@ -93,6 +115,7 @@ export default class ExtensionsPage extends Component {
if (!enabled) {
items.add('uninstall', Button.component({
icon: 'trash-o',
+ className: 'Button',
children: 'Uninstall',
onclick: () => {
app.request({
@@ -105,13 +128,6 @@ export default class ExtensionsPage extends Component {
}));
}
- // items.add('separator2', Separator.component());
-
- // items.add('support', LinkButton.component({
- // icon: 'support',
- // children: 'Support'
- // }));
-
return items;
}
diff --git a/framework/core/less/admin/ExtensionsPage.less b/framework/core/less/admin/ExtensionsPage.less
index da8caf68a..bab8d548b 100644
--- a/framework/core/less/admin/ExtensionsPage.less
+++ b/framework/core/less/admin/ExtensionsPage.less
@@ -6,6 +6,16 @@
.ExtensionsPage-list {
padding: 30px 0;
}
+.ExtensionGroup {
+ margin-bottom: 20px;
+
+ h3 {
+ color: @muted-color;
+ text-transform: uppercase;
+ font-size: 12px;
+ margin: 0 0 10px;
+ }
+}
.ExtensionList {
margin: 0;
@@ -15,8 +25,8 @@
> li {
float: left;
- width: 350px;
- height: 80px;
+ text-align: center;
+ position: relative;
}
}
.ExtensionListItem.disabled .ExtensionListItem-content {
@@ -28,48 +38,64 @@
}
}
.ExtensionListItem-controls {
- float: right;
- margin-top: -5px;
- visibility: hidden;
+ 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 &, &.open {
- visibility: visible;
+ .ExtensionListItem:hover & {
+ opacity: 1;
+ }
+ > li {
+ display: flex;
+ width: 100%;
+ height: 100%;
+ margin-bottom: 5px;
+ }
+ .Button {
+ .Button--block();
}
}
.ExtensionListItem {
- padding-left: 42px;
- padding-right: 20px;
- padding-bottom: 20px;
-}
-.ExtensionListItem-icon {
- float: left;
- margin-left: -42px;
- text-align: center;
- padding: 3px;
- font-size: 14px;
+ width: 120px;
+ height: 160px;
+ margin-right: 15px;
+ margin-bottom: 15px;
}
.ExtensionListItem-title {
font-size: 14px;
- margin: 3px 0 5px;
-
- small {
- color: @muted-more-color;
- font-size: 11px;
- font-weight: normal;
- margin-left: 5px;
- }
+ margin: 10px 0 2px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
}
-.ExtensionListItem-description {
- font-size: 12px;
- color: @muted-color;
+.ExtensionListItem-version {
+ color: @muted-more-color;
+ font-size: 11px;
+ font-weight: normal;
}
.ExtensionIcon {
- width: 28px;
- height: 28px;
+ width: 120px;
+ height: 120px;
background: @control-bg;
color: @control-color;
border-radius: 6px;
display: inline-block;
+ font-size: 60px;
+ line-height: 120px;
+ text-align: center;
}
diff --git a/framework/core/src/Extension/ExtensionManager.php b/framework/core/src/Extension/ExtensionManager.php
index f1a8617a6..31c7b4700 100644
--- a/framework/core/src/Extension/ExtensionManager.php
+++ b/framework/core/src/Extension/ExtensionManager.php
@@ -53,6 +53,10 @@ class ExtensionManager
if (file_exists($manifest = $extensionsDir . '/' . $dir . '/composer.json')) {
$extension = json_decode(file_get_contents($manifest), true);
+ if (empty($extension['name'])) {
+ continue;
+ }
+
if (isset($extension['extra']['flarum-extension']['icon'])) {
$icon = &$extension['extra']['flarum-extension']['icon'];
@@ -76,6 +80,8 @@ class ExtensionManager
}
}
+ $extension['id'] = $dir;
+
$extensions[$dir] = $extension;
}
}