Browse Source

refactor menus with separated components

tags/v1.18.0
Simon Vieille 3 days ago
parent
commit
7edd6d6d84
Signed by: deblan GPG Key ID: 03383D15A1D31745
10 changed files with 272 additions and 106 deletions
  1. +9
    -0
      src/CloserButton.vue
  2. +26
    -0
      src/Loader.vue
  3. +21
    -0
      src/Logo.vue
  4. +9
    -0
      src/OpenerButton.vue
  5. +31
    -0
      src/SettingsButton.vue
  6. +28
    -24
      src/SideMenu.vue
  7. +36
    -0
      src/SideMenuApp.vue
  8. +29
    -35
      src/SideMenuBig.vue
  9. +36
    -0
      src/SideMenuBigApp.vue
  10. +47
    -47
      webpack.js

+ 9
- 0
src/CloserButton.vue View File

@@ -0,0 +1,9 @@
<template>
<button class="side-menu-opener side-menu-closer"></button>
</template>

<script>
export default {
name: 'CloserButton',
}
</script>

+ 26
- 0
src/Loader.vue View File

@@ -0,0 +1,26 @@
<template>
<div class="side-menu-loader">
<svg width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd">
<g transform="translate(1 1)" stroke-width="2">
<circle stroke-opacity=".5" cx="18" cy="18" r="18"/>
<path d="M36 18c0-9.94-8.06-18-18-18">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="1s"
repeatCount="indefinite"/>
</path>
</g>
</g>
</svg>
</div>
</template>

<script>
export default {
name: 'Loader',
}
</script>

+ 21
- 0
src/Logo.vue View File

@@ -0,0 +1,21 @@
<template>
<div v-bind:class="classes">
<img v-bind:src="image">
</div>
</template>

<script>
export default {
name: 'Logo',
props: {
image: {
type: String,
required: true
},
classes: {
type: Object,
required: true
},
},
}
</script>

+ 9
- 0
src/OpenerButton.vue View File

@@ -0,0 +1,9 @@
<template>
<button class="side-menu-opener"></button>
</template>

<script>
export default {
name: 'OpenerButton',
}
</script>

+ 31
- 0
src/SettingsButton.vue View File

@@ -0,0 +1,31 @@
<template>
<div class="side-menu-settings">
<a v-bind:href="href">
{{ label }}

<span class="avatardiv avatardiv-shown">
<img v-bind:src="avatar" v-bind:alt="name" v-bind:title="name">
</span>
</a>
</div>
</template>

<script>
export default {
name: 'SettingsButton',
props: {
label: {
type: String,
required: true
},
href: {
type: String,
required: true
},
avatar: {
type: String,
required: true
},
},
}
</script>

+ 28
- 24
src/SideMenu.vue View File

@@ -17,33 +17,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<template>
<div id="side-menu">
<div class="side-menu-header">
<div class="side-menu-settings" v-if="settings">
<a v-bind:href="settings.href">
{{ settings.name }}

<span class="avatardiv avatardiv-shown">
<img v-bind:src="settings.avatar" v-bind:alt="settings.name" v-bind:title="settings.name">
</span>
</a>
</div>

<button class="side-menu-opener"></button>

<div v-if="!avatar && logo" v-bind:class="{'side-menu-logo': true, 'avatardiv': false}">
<img v-bind:src="logo">
</div>
<div v-if="avatar" v-bind:class="{'side-menu-logo': true, 'avatardiv': true}">
<img v-bind:src="avatar">
</div>
<SettingsButton
v-if="settings"
v-bind:href="settings.href"
v-bind:label="settings.name"
v-bind:avatar="settings.avatar" />

<OpenerButton />

<Logo v-if="!avatar && logo" v-bind:classes="{'side-menu-logo': true, 'avatardiv': false}" v-bind:image="logo" />
<Logo v-if="avatar" v-bind:classes="{'side-menu-logo': true, 'avatardiv': true}" v-bind:image="avatar" />
</div>

<ul class="side-menu-apps-list">
<li v-for="app in apps" v-bind:class="{'side-menu-app': true, 'active': app.active}">
<a v-bind:href="app.href" :target="targetBlankApps.indexOf(app.id) !== -1 ? '_blank' : undefined" v-bind:title="app.name">
<span class="side-menu-app-icon" v-html="app.icon"></span>
<span class="side-menu-app-text" v-html="app.name"></span>
</a>
</li>
<SideMenuApp
v-for="app in apps"
v-bind:classes="{'side-menu-app': true, 'active': app.active}"
v-bind:icon="app.icon"
v-bind:label="app.name"
v-bind:href="app.href"
v-bind:target="targetBlankApps.indexOf(app.id) !== -1 ? '_blank' : undefined"
/>
</ul>
</div>
</template>
@@ -51,9 +45,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<script>
import trim from 'trim'
import axios from 'axios'
import OpenerButton from './OpenerButton'
import SettingsButton from './SettingsButton'
import SideMenuApp from './SideMenuApp'
import Logo from './Logo'

export default {
name: 'SideMenu',
components: {
SettingsButton,
OpenerButton,
SideMenuApp,
Logo,
},
data() {
return {
apps: [],


+ 36
- 0
src/SideMenuApp.vue View File

@@ -0,0 +1,36 @@
<template>
<li v-bind:class="classes">
<a v-bind:href="href" :target="target" v-bind:title="label">
<span class="side-menu-app-icon" v-html="icon"></span>
<span class="side-menu-app-text" v-html="label"></span>
</a>
</li>
</template>

<script>
export default {
name: 'SideMenuApp',
props: {
label: {
type: String,
required: true
},
icon: {
type: String,
required: true
},
href: {
type: String,
required: true
},
classes: {
type: Object,
required: true
},
target: {
type: String,
required: false
},
},
}
</script>

+ 29
- 35
src/SideMenuBig.vue View File

@@ -17,52 +17,34 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<template>
<div id="side-menu" class="side-menu-big">
<div class="side-menu-header">
<button class="side-menu-opener side-menu-closer"></button>
<CloserButton />

<div class="side-menu-settings" v-if="settings">
<a v-bind:href="settings.href">
{{ settings.name }}
<SettingsButton
v-if="settings"
v-bind:href="settings.href"
v-bind:label="settings.name"
v-bind:avatar="settings.avatar"
/>

<span class="avatardiv avatardiv-shown">
<img v-bind:src="settings.avatar" v-bind:alt="settings.name" v-bind:title="settings.name">
</span>
</a>
</div>

<button class="side-menu-opener"></button>
<OpenerButton />
</div>

<div class="side-menu-categories-wrapper">
<div class="side-menu-categories">
<div v-if="!items.length" class="side-menu-loader">
<svg width="38" height="38" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd">
<g transform="translate(1 1)" stroke-width="2">
<circle stroke-opacity=".5" cx="18" cy="18" r="18"/>
<path d="M36 18c0-9.94-8.06-18-18-18">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="1s"
repeatCount="indefinite"/>
</path>
</g>
</g>
</svg>
</div>
<Loader v-if="!items.length" />

<div class="side-menu-category" v-for="category in items">
<h2 class="side-menu-category-title" v-if="category.name != ''" v-html="category.name"></h2>

<ul class="side-menu-apps-list">
<li v-bind:class="{'side-menu-app': true, 'active': activeApp === appId}" v-for="(app, appId) in category.apps">
<a v-bind:href="app.href" :target="targetBlankApps.indexOf(appId) !== -1 ? '_blank' : undefined" v-bind:title="app.name">
<img class="side-menu-app-icon" v-bind:src="app.icon"></span>
<span class="side-menu-app-text" v-html="app.name"></span>
</a>
</li>
<SideMenuBigApp
v-for="(app, appId) in category.apps"
v-bind:classes="{'side-menu-app': true, 'active': activeApp === appId}"
v-bind:icon="app.icon"
v-bind:label="app.name"
v-bind:href="app.href"
v-bind:target="targetBlankApps.indexOf(app.id) !== -1 ? '_blank' : undefined"
/>
</ul>
</div>
</div>
@@ -73,9 +55,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<script>
import trim from 'trim'
import axios from 'axios'
import OpenerButton from './OpenerButton'
import CloserButton from './CloserButton'
import SettingsButton from './SettingsButton'
import Loader from './Loader'
import SideMenuBigApp from './SideMenuBigApp'

export default {
name: 'SideMenuBig',
components: {
SettingsButton,
OpenerButton,
CloserButton,
Loader,
SideMenuBigApp,
},
data() {
return {
items: [],


+ 36
- 0
src/SideMenuBigApp.vue View File

@@ -0,0 +1,36 @@
<template>
<li v-bind:class="classes">
<a v-bind:href="href" :target="target" v-bind:title="label">
<img class="side-menu-app-icon" v-bind:src="icon"></span>
<span class="side-menu-app-text" v-html="label"></span>
</a>
</li>
</template>

<script>
export default {
name: 'SideMenuBigApp',
props: {
label: {
type: String,
required: true
},
icon: {
type: String,
required: true
},
href: {
type: String,
required: true
},
classes: {
type: Object,
required: true
},
target: {
type: String,
required: false
},
},
}
</script>

+ 47
- 47
webpack.js View File

@@ -3,51 +3,51 @@ const { VueLoaderPlugin } = require('vue-loader')
const StyleLintPlugin = require('stylelint-webpack-plugin')

module.exports = {
entry: {
'admin': path.join(__dirname, 'src', 'admin.js'),
'sideMenu': path.join(__dirname, 'src', 'SideMenu.js'),
},
output: {
path: path.resolve(__dirname, './js'),
publicPath: '/js',
filename: '[name].js?v=[hash]',
chunkFilename: 'chunks/[name]-[hash].js',
},
module: {
rules: [
{
test: /\.css$/,
use: ['vue-style-loader', 'css-loader'],
},
{
test: /\.scss$/,
use: ['vue-style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url-loader',
options: {
name: '[name].[ext]?[hash]',
limit: 8192,
},
},
],
},
plugins: [
new VueLoaderPlugin(),
new StyleLintPlugin(),
],
resolve: {
extensions: ['*', '.js', '.vue'],
symlinks: false,
},
entry: {
'admin': path.join(__dirname, 'src', 'admin.js'),
'sideMenu': path.join(__dirname, 'src', 'SideMenu.js'),
},
output: {
path: path.resolve(__dirname, './js'),
publicPath: '/js',
filename: '[name].js?v=[hash]',
chunkFilename: 'chunks/[name]-[hash].js',
},
module: {
rules: [
{
test: /\.css$/,
use: ['vue-style-loader', 'css-loader'],
},
{
test: /\.scss$/,
use: ['vue-style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.vue$/,
loader: 'vue-loader',
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url-loader',
options: {
name: '[name].[ext]?[hash]',
limit: 8192,
},
},
],
},
plugins: [
new VueLoaderPlugin(),
new StyleLintPlugin(),
],
resolve: {
extensions: ['*', '.js', '.vue'],
symlinks: false,
},
}

Loading…
Cancel
Save