From 71273558126decfeb242518107bea192afe18db6 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sat, 28 Mar 2020 17:40:53 +0100 Subject: [PATCH] init --- .eslintrc.js | 5 + appinfo/app.php | 22 +++++ appinfo/info.xml | 22 +++++ appinfo/routes.php | 16 ++++ css/sideMenu.css | 60 ++++++++++++ img/side-menu-opener.svg | 159 +++++++++++++++++++++++++++++++ lib/Controller/ApiController.php | 47 +++++++++ package.json | 58 +++++++++++ src/SideMenu.js | 21 ++++ src/SideMenu.vue | 49 ++++++++++ src/main.js | 10 ++ webpack.js | 53 +++++++++++ 12 files changed, 522 insertions(+) create mode 100644 .eslintrc.js create mode 100644 appinfo/app.php create mode 100644 appinfo/info.xml create mode 100644 appinfo/routes.php create mode 100644 css/sideMenu.css create mode 100644 img/side-menu-opener.svg create mode 100644 lib/Controller/ApiController.php create mode 100644 package.json create mode 100644 src/SideMenu.js create mode 100644 src/SideMenu.vue create mode 100644 src/main.js create mode 100644 webpack.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..ff00609 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + rules: { + 'no-console': 'off', + }, +}; diff --git a/appinfo/app.php b/appinfo/app.php new file mode 100644 index 0000000..d681089 --- /dev/null +++ b/appinfo/app.php @@ -0,0 +1,22 @@ +getConfig(); +$cspnm = \OC::$server->getContentSecurityPolicyNonceManager(); + +Util::addScript('side_menu', 'main'); +Util::addScript('side_menu', 'sideMenu'); +Util::addStyle('side_menu', 'sideMenu'); + + +// whitelist the URL to allow loading JS from this external domain +// $CSPManager = \OC::$server->getContentSecurityPolicyManager(); +// $policy = new ContentSecurityPolicy(); +// $policy->addAllowedScriptDomain($url); +// $policy->addAllowedImageDomain($url); +// $policy->addAllowedConnectDomain($url); +// $CSPManager->addDefaultPolicy($policy); diff --git a/appinfo/info.xml b/appinfo/info.xml new file mode 100644 index 0000000..b64a538 --- /dev/null +++ b/appinfo/info.xml @@ -0,0 +1,22 @@ + + + side_menu + Side menu + Create a side menu + + agpl + Simon Vieille + 0.0.1 + SideMenu + customization + https://www.deblan.io + https://github.com/ONLYOFFICE/onlyoffice-nextcloud/issues + https://gitnet.fr + + + + + OCA\Onlyoffice\AdminSettings + OCA\Onlyoffice\AdminSection + + diff --git a/appinfo/routes.php b/appinfo/routes.php new file mode 100644 index 0000000..b20256f --- /dev/null +++ b/appinfo/routes.php @@ -0,0 +1,16 @@ + [ + [ + 'name' => 'Javascript#sideMenu', + 'url' => '/side_menu/javascript/side_menu', + 'verb' => 'GET', + ], + [ + 'name' => 'Api#apps', + 'url' => '/side_menu/api/apps', + 'verb' => 'GET', + ] + ], +]; diff --git a/css/sideMenu.css b/css/sideMenu.css new file mode 100644 index 0000000..a2cd8cd --- /dev/null +++ b/css/sideMenu.css @@ -0,0 +1,60 @@ +#appmenu { + display: none; +} + +#side-menu { + position: absolute; + top: 0; + left: 0; + height: 100vh; + overflow: hidden; + width: 100%; + max-width: 250px; + background: #333; + z-index: 3000; + color: #fff; + box-shadow: rgba(0, 0, 0, 0.22) 0px 25.6px 57.6px 0px, rgba(0, 0, 0, 0.18) 0px 4.8px 14.4px 0px; + padding: 2px 0 0 0; + display: none; +} + +#side-menu.is-active { + display: block; +} + +.side-menu-opener { + background: url('../img/side-menu-opener.svg'); + height: 40px; + width: 40px; + border-radius: 0; + border: 0; +} + +.side-menu-apps-list { + padding: 30px 0; +} + +.side-menu-app-icon { + width: 20px; + vertical-align: middle; + margin-right: 10px; +} + +.side-menu-app a { + line-height: 30px; + color: #fff; + display: block; + padding: 7px 15px; +} + +.side-menu-app a:hover { + background: #444; +} + +.side-menu-logo { + text-align: center; +} + +.side-menu-logo img { + width: 60%; +} diff --git a/img/side-menu-opener.svg b/img/side-menu-opener.svg new file mode 100644 index 0000000..f8f55aa --- /dev/null +++ b/img/side-menu-opener.svg @@ -0,0 +1,159 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php new file mode 100644 index 0000000..5e4b351 --- /dev/null +++ b/lib/Controller/ApiController.php @@ -0,0 +1,47 @@ +navigationManager = $navigationManager; + } + + /** + * @NoAdminRequired + * @NoCSRFRequired + * + * @return JSONResponse + */ + public function apps(): JSONResponse + { + $apps = $this->navigationManager->getAll(); + + $data = [ + 'apps' => $apps, + ]; + + return new JSONResponse($apps); + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..b81851b --- /dev/null +++ b/package.json @@ -0,0 +1,58 @@ +{ + "license": "agpl", + "private": true, + "scripts": { + "build": "NODE_ENV=production webpack --progress --hide-modules --config webpack.js", + "dev": "NODE_ENV=development webpack --progress --config webpack.js", + "watch": "NODE_ENV=development webpack --progress --watch --config webpack.js", + "lint": "eslint --ext .js,.vue src", + "lint:fix": "eslint --ext .js,.vue src --fix", + "stylelint": "stylelint src", + "stylelint:fix": "stylelint src --fix" + }, + "dependencies": { + "@nextcloud/axios": "^1.3.2", + "@nextcloud/vue": "^1.4.0", + "vue": "^2.6.11" + }, + "browserslist": [ + "extends @nextcloud/browserslist-config" + ], + "engines": { + "node": ">=10.0.0" + }, + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/preset-env": "^7.9.0", + "@nextcloud/browserslist-config": "^1.0.0", + "babel-eslint": "^10.1.0", + "babel-loader": "^8.1.0", + "css-loader": "^3.4.2", + "eslint": "^5.16.0", + "eslint-config-nextcloud": "0.1.1", + "eslint-config-standard": "^12.0.0", + "eslint-import-resolver-webpack": "^0.12.1", + "eslint-loader": "^3.0.3", + "eslint-plugin-import": "^2.20.0", + "eslint-plugin-nextcloud": "^0.3.0", + "eslint-plugin-node": "^10.0.0", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-standard": "^4.0.1", + "eslint-plugin-vue": "^5.2.3", + "file-loader": "^6.0.0", + "node-sass": "^4.13.1", + "sass-loader": "^8.0.2", + "stylelint": "^8.4.0", + "stylelint-config-recommended-scss": "^3.3.0", + "stylelint-scss": "^3.16.0", + "stylelint-webpack-plugin": "^0.10.5", + "url-loader": "^4.0.0", + "vue-loader": "^15.9.1", + "vue-template-compiler": "^2.6.11", + "webpack": "^4.42.0", + "webpack-cli": "^3.3.11", + "webpack-merge": "^4.2.2", + "webpack-node-externals": "^1.7.2" + } +} diff --git a/src/SideMenu.js b/src/SideMenu.js new file mode 100644 index 0000000..69c5292 --- /dev/null +++ b/src/SideMenu.js @@ -0,0 +1,21 @@ +import Vue from 'vue' +import SideMenu from './SideMenu.vue' + +Vue.prototype.t = t +Vue.prototype.OC = OC + +const View = Vue.extend(SideMenu) +const sideMenu = new View({ +}) + +const mountSideMenuComponent = () => { + const sideMenuContainer = document.querySelector('#side-menu') + + if (sideMenuContainer) { + sideMenu.$mount('#side-menu') + } else { + window.setTimeout(mountSideMenuComponent, 50) + } +} + +mountSideMenuComponent() diff --git a/src/SideMenu.vue b/src/SideMenu.vue new file mode 100644 index 0000000..14364e3 --- /dev/null +++ b/src/SideMenu.vue @@ -0,0 +1,49 @@ + + + diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..a33e9e1 --- /dev/null +++ b/src/main.js @@ -0,0 +1,10 @@ +const sideMenuContainer = $('
') +const sideMenuOpener = $('') + +$('body').append(sideMenuContainer); + +sideMenuOpener.insertBefore('#nextcloud'); + +$('body').on('click', '.side-menu-opener', () => { + $('#side-menu').toggleClass('is-active'); +}) diff --git a/webpack.js b/webpack.js new file mode 100644 index 0000000..b9c370b --- /dev/null +++ b/webpack.js @@ -0,0 +1,53 @@ +const path = require('path') +const { VueLoaderPlugin } = require('vue-loader') +const StyleLintPlugin = require('stylelint-webpack-plugin') + +module.exports = { + entry: { + 'main': path.join(__dirname, 'src', 'main.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, + }, +}