Merge pull request 'release v3.1.0' (#141) from develop into master
Reviewed-on: #141
This commit is contained in:
commit
7472e4050a
|
@ -1,5 +1,11 @@
|
|||
## [Unreleased]
|
||||
|
||||
## 3.1.0
|
||||
### Added
|
||||
* add global custom app sorting for the top menu
|
||||
### Fixed
|
||||
* fix admin list/modal look
|
||||
|
||||
## 3.0.1
|
||||
### Fixed
|
||||
* Remove the gap between the window's top and menu categories (large menu)
|
||||
|
|
|
@ -26,7 +26,7 @@ If you like this application and if you want to support the development:
|
|||
* [Donate with liberapay](https://liberapay.com/deblan)
|
||||
* [Leave a comment](https://apps.nextcloud.com/apps/side_menu#comments)
|
||||
]]></description>
|
||||
<version>3.0.1</version>
|
||||
<version>3.1.0</version>
|
||||
<licence>agpl</licence>
|
||||
<author mail="contact@deblan.fr" homepage="https://www.deblan.io/">Simon Vieille</author>
|
||||
<namespace>SideMenu</namespace>
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#side-menu-section input[type="color"] {
|
||||
width: 100px;
|
||||
margin: 10px 0 10px 0;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
#-dropside-menu-section input[type="checkbox"] {
|
||||
|
@ -71,14 +73,21 @@
|
|||
|
||||
.side-menu-setting-list {
|
||||
margin: 10px 4px 4px 0px;
|
||||
border: 1px solid var(--color-border-dark);
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.side-menu-setting-list-item {
|
||||
padding: 5px 10px;
|
||||
border: 1px solid var(--color-border-dark);
|
||||
border-bottom: 1px solid var(--color-border-dark);
|
||||
max-width: 300px;
|
||||
margin: -1px 0 0 0;
|
||||
cursor: pointer;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
.side-menu-setting-list-item:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.side-menu-setting-list-drop {
|
||||
|
@ -93,8 +102,9 @@
|
|||
}
|
||||
|
||||
.side-menu-setting-list-item input {
|
||||
min-height: auto;
|
||||
margin-top: -1px;
|
||||
margin-top: 0;
|
||||
height: 21px !important;
|
||||
min-height: auto !important;
|
||||
}
|
||||
|
||||
#apps-categories-custom-list select {
|
||||
|
@ -108,11 +118,22 @@
|
|||
|
||||
.side-menu-setting-row {
|
||||
display: table;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.side-menu-setting-row code {
|
||||
margin-left: 2px;
|
||||
margin-bottom: 1px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 5px;
|
||||
display: inline-block;
|
||||
right: 2px;
|
||||
border: 1px solid var(--color-border-dark);
|
||||
}
|
||||
|
||||
.side-menu-setting-label {
|
||||
display: table-cell;
|
||||
width: 400px;
|
||||
width: 430px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ class JsController extends Controller
|
|||
{
|
||||
$topMenuApps = $this->config->getAppValueArray('top-menu-apps', '[]');
|
||||
$topSideMenuApps = $this->config->getAppValueArray('top-side-menu-apps', '[]');
|
||||
$topMenuAppsOrder = $this->config->getAppValueArray('top-menu-apps-order', '[]');
|
||||
$targetBlankApps = $this->config->getAppValueArray('target-blank-apps', '[]');
|
||||
$useAvatar = $this->config->getAppValueBool('use-avatar', '0');
|
||||
$isForced = $this->config->getAppValueBool('force', '0');
|
||||
|
@ -164,6 +165,7 @@ class JsController extends Controller
|
|||
'avatar' => $avatar,
|
||||
'top-menu-apps' => $topMenuApps,
|
||||
'top-side-menu-apps' => $topSideMenuApps,
|
||||
'top-menu-apps-order' => $topMenuAppsOrder,
|
||||
'target-blank-apps' => $targetBlankApps,
|
||||
'settings' => $settings,
|
||||
'logo' => $this->themingDefaults->getLogo(),
|
||||
|
|
|
@ -105,4 +105,23 @@ class AppRepository
|
|||
|
||||
return $visibleApps;
|
||||
}
|
||||
|
||||
public function getTopMenuOrderedApps()
|
||||
{
|
||||
$apps = $this->getVisibleApps();
|
||||
$orders = $this->config->getAppValueArray('top-menu-apps-order', '[]');
|
||||
|
||||
usort($apps, function ($a, $b) use ($orders) {
|
||||
$ak = array_keys($orders, $a['id'])[0] ?? null;
|
||||
$bk = array_keys($orders, $b['id'])[0] ?? null;
|
||||
|
||||
if ($ak === null || $bk === null) {
|
||||
return ($a['name'] < $b['name']) ? -1 : 1;
|
||||
}
|
||||
|
||||
return $ak < $bk ? -1 : 1;
|
||||
});
|
||||
|
||||
return $apps;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,9 +159,11 @@ class Admin implements ISettings
|
|||
'force' => $this->config->getAppValue('force', '0'),
|
||||
'target-blank-apps' => $this->config->getAppValueArray('target-blank-apps', '[]'),
|
||||
'top-menu-apps' => $this->config->getAppValueArray('top-menu-apps', '[]'),
|
||||
'top-menu-apps-order' => $this->config->getAppValueArray('top-menu-apps-order', '[]'),
|
||||
'top-side-menu-apps' => $this->config->getAppValueArray('top-side-menu-apps', '[]'),
|
||||
'default-enabled' => $this->config->getAppValue('default-enabled', '1'),
|
||||
'apps' => $this->appRepository->getVisibleApps(),
|
||||
'top-menu-ordered-apps' => $this->appRepository->getTopMenuOrderedApps(),
|
||||
'apps-categories-custom' => $this->config->getAppValueArray('apps-categories-custom', '[]'),
|
||||
'categories-order-type' => $this->config->getAppValue('categories-order-type', 'default'),
|
||||
'categories-order' => $this->config->getAppValueArray('categories-order', '[]'),
|
||||
|
|
|
@ -30,7 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
<div class="modal__content">
|
||||
<div v-for="lang in langs">
|
||||
<span class="lang" v-text="lang"></span>
|
||||
<input type="text" v-model="newValue[lang]" required>
|
||||
<input type="text" v-model="newValue[lang]" required style="width: calc(100% - 100px)">
|
||||
</div>
|
||||
|
||||
<NcActions>
|
||||
|
@ -43,7 +43,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
<div class="modal__content">
|
||||
<div v-for="lang in langs">
|
||||
<span class="lang" v-text="lang"></span>
|
||||
<input type="text" v-model="editValue[lang]" required>
|
||||
<input type="text" v-model="editValue[lang]" required style="width: calc(100% - 100px)">
|
||||
</div>
|
||||
|
||||
<div class="pull-right">
|
||||
|
@ -60,9 +60,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
<style>
|
||||
.modal__content {
|
||||
width: 200px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
@ -73,12 +72,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.modal__content input[type=text] {
|
||||
width: calc(100% - 85px);
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
:key="app.id"
|
||||
:data-app-id="app.id"
|
||||
class="app-menu-entry"
|
||||
:class="{ 'app-menu-entry__active': app.active }">
|
||||
:class="{ 'app-menu-entry__active': app.active }"
|
||||
:style="makeStyle(app)"
|
||||
>
|
||||
<a :href="app.href"
|
||||
:class="{ 'has-unread': app.unread > 0 }"
|
||||
:aria-label="appLabel(app)"
|
||||
|
@ -78,10 +80,16 @@ export default {
|
|||
mounted() {
|
||||
const ncApps = loadState('core', 'apps', {})
|
||||
this.apps = {}
|
||||
let orders = {}
|
||||
|
||||
Array.from(window.topMenuAppsOrder).forEach((app, order) => {
|
||||
orders[app] = order + 1
|
||||
})
|
||||
|
||||
Array.from(window.topMenuApps).forEach((id) => {
|
||||
if (ncApps.hasOwnProperty(id)) {
|
||||
this.apps[id] = ncApps[id]
|
||||
this.apps[id].order = orders[id] || null
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -122,6 +130,11 @@ export default {
|
|||
}
|
||||
this.appLimit = appCount
|
||||
},
|
||||
makeStyle(app) {
|
||||
if (app.order !== null) {
|
||||
return `order: ${app.order}`
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -82,7 +82,34 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
retrieveApps() {
|
||||
this.apps = loadState('core', 'apps', {})
|
||||
const ncApps = loadState('core', 'apps', {})
|
||||
let orders = {}
|
||||
let finalApps = []
|
||||
|
||||
Array.from(window.topMenuAppsOrder).forEach((app, order) => {
|
||||
orders[app] = order + 1
|
||||
})
|
||||
|
||||
for (let id in ncApps) {
|
||||
if (window.topMenuApps.includes(id) && !window.topSideMenuApps.includes(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let app = ncApps[id]
|
||||
app.order = orders[id] || null
|
||||
|
||||
finalApps.push(app)
|
||||
}
|
||||
|
||||
finalApps.sort((a, b) => {
|
||||
if (a.order === null || b.order === null) {
|
||||
return a.name < b.name ? -1 : 1;
|
||||
}
|
||||
|
||||
return a.order < b.order ? -1 : 1;
|
||||
})
|
||||
|
||||
this.apps = finalApps
|
||||
|
||||
document.querySelector('body').dispatchEvent(new CustomEvent('side-menu.apps', {
|
||||
detail: {apps: this.apps},
|
||||
|
|
18
src/admin.js
18
src/admin.js
|
@ -257,4 +257,22 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
})
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
sortable('#top-menu-apps-order-list .side-menu-setting-list', {
|
||||
placeholderClass: 'side-menu-setting-list-drop'
|
||||
})
|
||||
|
||||
try {
|
||||
sortable('#top-menu-apps-order-list .side-menu-setting-list')[0].addEventListener('sortstop', (e) => {
|
||||
let value = []
|
||||
|
||||
for (let item of document.querySelectorAll('#top-menu-apps-order-list .side-menu-setting-list-item')) {
|
||||
console.log(item.getAttribute('data-id'))
|
||||
value.push(item.getAttribute('data-id'))
|
||||
}
|
||||
|
||||
document.querySelector('input[name="top-menu-apps-order"]').value = JSON.stringify(value)
|
||||
})
|
||||
} catch (e) {
|
||||
}
|
||||
})
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
"Panel": "Panel"
|
||||
"Open the menu when the mouse is hover the opener (automatically disabled on touch screens)": "Otevřít nabídku při najetím ukazatelem na tlačítko nabídky (automaticky vypnuto pro dotykové obrazovky)."
|
||||
"Display the big menu": "Zobrazit velkou nabídku"
|
||||
"This menu is not compatible with AppOrder.": "Nabídka není kompatibilní s jinou aplikací (doplňkem) „Pořadí aplikací“."
|
||||
"Display the logo": "Zobrazit logo"
|
||||
"This feature is not compatible with the <code>big menu</code> display.": "Tato funkce není kompatibilní se zobrazením <code>velké nabídky</code>."
|
||||
"Icons and texts": "Ikony a texty"
|
||||
|
@ -90,3 +89,5 @@
|
|||
"Small text": "Malý text"
|
||||
"Normal text": "Normální text"
|
||||
"Big text": "Velký text"
|
||||
"Applications": "Applications"
|
||||
"This feature is not compatible with <code>big menu</code> and <code>with categories</code> displays.": "This feature is not compatible with <code>big menu</code> and <code>with categories</code> displays."
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
"Panel": "Panel"
|
||||
"Open the menu when the mouse is hover the opener (automatically disabled on touch screens)": "Öffne das Menü, wenn die Maus über das Menü-Symbol bewegt wird (auf Touchscreens automatisch deaktiviert)."
|
||||
"Display the big menu": "Großes Menü anzeigen"
|
||||
"This menu is not compatible with AppOrder.": "Dieses Menü ist nicht mit <code>AppOrder</code> kompatibel."
|
||||
"Display the logo": "Logo anzeigen"
|
||||
"This feature is not compatible with the <code>big menu</code> display.": "Diese Funktion ist nicht mit dem <code>großen Menü</code> kompatibel."
|
||||
"Icons and texts": "Symbole und Texte"
|
||||
|
@ -90,3 +89,5 @@
|
|||
"Small text": "Kleiner Text"
|
||||
"Normal text": "Normaler Text"
|
||||
"Big text": "Großer Text"
|
||||
"Applications": "Applications"
|
||||
"This feature is not compatible with <code>big menu</code> and <code>with categories</code> displays.": "This feature is not compatible with <code>big menu</code> and <code>with categories</code> displays."
|
||||
|
|
|
@ -48,9 +48,8 @@
|
|||
"Panel": "Panneau"
|
||||
"Open the menu when the mouse is hover the opener (automatically disabled on touch screens)": "Ouvrir le menu au passage de la souris (automatiquement désactivé sur les écrans tactiles)"
|
||||
"Display the big menu": "Afficher le menu large"
|
||||
"This menu is not compatible with AppOrder.": "Ce menu n'est pas compatible avec l'application AppOrder"
|
||||
"Display the logo": "Afficher le logo"
|
||||
"This feature is not compatible with the <code>big menu</code> display.": "Cette fonctionnalité n'est pas compatible avec l'affichage du menu large."
|
||||
"This feature is not compatible with the <code>big menu</code> display.": "Cette fonctionnalité n'est pas compatible avec l'affichage <code>Menu large</code>."
|
||||
"Icons and texts": "Icônes et textes"
|
||||
"Loader enabled": "Activation de l'indicateur de chargement"
|
||||
"Tips": "Astuces"
|
||||
|
@ -90,3 +89,5 @@
|
|||
"Apps only visible in the top menu": "Applications visibles uniquement dans le menu supérieur"
|
||||
"Apps visible in the top and side menus": "Applications visibles dans le menus supérieur et latéral"
|
||||
"Reset to default": "Restaurer les valeurs par défaut"
|
||||
"Applications": "Applications"
|
||||
"This feature is not compatible with <code>big menu</code> and <code>with categories</code> displays.": "Cette fonctionnalité n'est pas compatible avec les affichages <code>Menu large</code> et <code>Avec les catégories</code>"
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
"Panel": "面板"
|
||||
"Open the menu when the mouse is hover the opener (automatically disabled on touch screens)": "鼠标悬停时打开菜单 (触摸屏时将自动禁用)"
|
||||
"Display the big menu": "显示大型菜单"
|
||||
"This menu is not compatible with AppOrder.": "型菜单与应用顺序不兼容"
|
||||
"Display the logo": "显示logo"
|
||||
"This feature is not compatible with the <code>big menu<\/code> display.": "此功能与显示<code>大型菜单<\/code>不兼容。"
|
||||
"Icons and texts": "图标与文字"
|
||||
|
@ -90,3 +89,5 @@
|
|||
"Small text": "小文本"
|
||||
"Normal text": "普通文本"
|
||||
"Big text": "大文本"
|
||||
"Applications": "Applications"
|
||||
"This feature is not compatible with <code>big menu</code> and <code>with categories</code> displays.": "This feature is not compatible with <code>big menu</code> and <code>with categories</code> displays."
|
||||
|
|
|
@ -25,6 +25,7 @@ if ($_['always-displayed']) {
|
|||
const targetBlankApps = <?php echo json_encode($_['target-blank-apps']) ?>
|
||||
|
||||
window.topMenuApps = <?php echo json_encode($_['top-menu-apps']), "\n"; ?>
|
||||
window.topMenuAppsOrder = <?php echo json_encode($_['top-menu-apps-order']), "\n"; ?>
|
||||
window.topSideMenuApps = <?php echo json_encode($_['top-side-menu-apps']); ?>
|
||||
|
||||
<?php if ($display === 'big-menu'): ?>
|
||||
|
|
|
@ -509,7 +509,6 @@ $labelReset = 'Reset to default';
|
|||
<?php p($l->t('With categories')); ?>
|
||||
</label>
|
||||
</div>
|
||||
<p><em><?php echo $l->t('This menu is not compatible with AppOrder.'); ?></em></p>
|
||||
<p>
|
||||
<img
|
||||
class="side-menu-display <?php echo $displays['side-with-categories'] ? 'is-active' : '' ?>"
|
||||
|
@ -524,7 +523,6 @@ $labelReset = 'Reset to default';
|
|||
<?php p($l->t('Big menu')); ?>
|
||||
</label>
|
||||
</div>
|
||||
<p><em><?php echo $l->t('This menu is not compatible with AppOrder.'); ?></em></p>
|
||||
<p>
|
||||
<img
|
||||
class="side-menu-display <?php echo $displays['big-menu'] ? 'is-active' : '' ?>"
|
||||
|
@ -798,9 +796,7 @@ $labelReset = 'Reset to default';
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="side-menu-setting-table">
|
||||
<div class="side-menu-setting-row">
|
||||
<div class="side-menu-setting-label">
|
||||
<?php p($l->t('Apps visible in the top and side menus')); ?>
|
||||
|
@ -834,6 +830,45 @@ $labelReset = 'Reset to default';
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h2>
|
||||
<?php p($l->t('Applications')); ?>
|
||||
</h2>
|
||||
|
||||
<div class="side-menu-setting-table">
|
||||
<div class="side-menu-setting-row">
|
||||
<div class="side-menu-setting-label">
|
||||
<?php p($l->t('Customize sorting')); ?>
|
||||
<br>
|
||||
<em>
|
||||
<?php echo $l->t('This feature is not compatible with <code>big menu</code> and <code>with categories</code> displays.'); ?>
|
||||
</em>
|
||||
</div>
|
||||
<div class="side-menu-setting-form">
|
||||
<a class="side-menu-toggler" data-target="#top-menu-apps-order-list" href="#_">
|
||||
🖱️ <?php p($l->t($labelShowHideApps)); ?>
|
||||
</a>
|
||||
|
||||
<div id="top-menu-apps-order-list" style="display: none">
|
||||
<ul class="side-menu-setting-list">
|
||||
<?php foreach ($_['top-menu-ordered-apps'] as $key => $app): ?>
|
||||
<li data-id="<?php echo $app['id']; ?>" class="side-menu-setting-list-item">
|
||||
<span class="arrow">
|
||||
⇅
|
||||
</span>
|
||||
|
||||
<?php echo p($l->t($app['name'])); ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<input type="hidden" value='<?php echo json_encode(array_keys($_['top-menu-apps-order'])) ?>' name="top-menu-apps-order" class="side-menu-setting">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section">
|
||||
<h2>
|
||||
|
|
Loading…
Reference in a new issue