Use webpack global config & @nextcloud/browserslist-config

Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
John Molakvoæ (skjnldsv) 2020-08-02 15:53:33 +02:00 committed by Marcel Klehr
parent 02124f5cb7
commit 5386aa7792
27 changed files with 1247 additions and 1225 deletions

View File

@ -21,7 +21,7 @@ create-tag:
dev-setup: clean clean-dev npm-init dev-setup: clean clean-dev npm-init
npm-init: npm-init:
npm install npm ci
npm-update: npm-update:
npm update npm update

View File

@ -16,14 +16,3 @@ namespace OCA\Bookmarks\AppInfo;
if ((@include_once __DIR__ . '/../vendor/autoload.php')===false) { if ((@include_once __DIR__ . '/../vendor/autoload.php')===false) {
throw new \Exception('Cannot include autoload. Did you run install dependencies using composer?'); throw new \Exception('Cannot include autoload. Did you run install dependencies using composer?');
} }
$navigationEntry = function () {
return [
'id' => 'bookmarks',
'order' => 10,
'name' => \OC::$server->getL10N('bookmarks')->t('Bookmarks'),
'href' => \OC::$server->getURLGenerator()->linkToRoute('bookmarks.web_view.index'),
'icon' => \OC::$server->getURLGenerator()->imagePath('bookmarks', 'bookmarks.svg'),
];
};
\OC::$server->getNavigationManager()->add($navigationEntry);

View File

@ -28,19 +28,23 @@ Requirements:
<bugs>https://github.com/nextcloud/bookmarks/issues</bugs> <bugs>https://github.com/nextcloud/bookmarks/issues</bugs>
<repository type="git">https://github.com/nextcloud/bookmarks.git</repository> <repository type="git">https://github.com/nextcloud/bookmarks.git</repository>
<screenshot small-thumbnail="https://raw.githubusercontent.com/nextcloud/bookmarks/master/screenshots/Bookmarks-small.png">https://raw.githubusercontent.com/nextcloud/bookmarks/master/screenshots/Bookmarks.png</screenshot> <screenshot small-thumbnail="https://raw.githubusercontent.com/nextcloud/bookmarks/master/screenshots/Bookmarks-small.png">https://raw.githubusercontent.com/nextcloud/bookmarks/master/screenshots/Bookmarks.png</screenshot>
<dependencies> <dependencies>
<php min-version="7.2" /> <php min-version="7.2" />
<lib>intl</lib> <lib>intl</lib>
<lib>mbstring</lib> <lib>mbstring</lib>
<nextcloud min-version="17" max-version="20" /> <nextcloud min-version="17" max-version="20" />
</dependencies> </dependencies>
<background-jobs> <background-jobs>
<job>OCA\Bookmarks\BackgroundJobs\PreviewsJob</job> <job>OCA\Bookmarks\BackgroundJobs\PreviewsJob</job>
</background-jobs> </background-jobs>
<settings> <settings>
<admin>OCA\Bookmarks\Settings\AdminSettings</admin> <admin>OCA\Bookmarks\Settings\AdminSettings</admin>
<admin-section>OCA\Bookmarks\Settings\AdminSection</admin-section> <admin-section>OCA\Bookmarks\Settings\AdminSection</admin-section>
</settings> </settings>
<repair-steps> <repair-steps>
<post-migration> <post-migration>
<step>OCA\Bookmarks\Migration\DeduplicateSharedFoldersRepairStep</step> <step>OCA\Bookmarks\Migration\DeduplicateSharedFoldersRepairStep</step>
@ -50,6 +54,16 @@ Requirements:
<step>OCA\Bookmarks\Migration\GroupSharesUpdateRepairStep</step> <step>OCA\Bookmarks\Migration\GroupSharesUpdateRepairStep</step>
</post-migration> </post-migration>
</repair-steps> </repair-steps>
<navigations>
<navigation>
<name>Bookmarks</name>
<route>bookmarks.web_view.index</route>
<icon>bookmarks.svg</icon>
<order>10</order>
</navigation>
</navigations>
<activity> <activity>
<settings> <settings>
<setting>OCA\Bookmarks\Activity\Setting</setting> <setting>OCA\Bookmarks\Activity\Setting</setting>

View File

@ -31,10 +31,13 @@ use OCP\IUser;
use OCP\User\Events\BeforeUserDeletedEvent; use OCP\User\Events\BeforeUserDeletedEvent;
class Application extends App { class Application extends App {
public function __construct(array $urlParams = []) { public const APP_ID = 'bookmarks';
parent::__construct('bookmarks', $urlParams);
public function __construct() {
parent::__construct(self::APP_ID);
$container = $this->getContainer(); $container = $this->getContainer();
$server = $container->getServer();
$container->registerService('UserId', static function ($c) { $container->registerService('UserId', static function ($c) {
/** @var IUser|null $user */ /** @var IUser|null $user */
@ -47,20 +50,22 @@ class Application extends App {
return $c->query('Request'); return $c->query('Request');
}); });
$dispatcher = $this->getContainer()->query(IEventDispatcher::class); /** @var IEventDispatcher $eventDispatcher */
$eventDispatcher = $server->query(IEventDispatcher::class);
$dispatcher->addServiceListener(CreateEvent::class, HashManager::class);
$dispatcher->addServiceListener(UpdateEvent::class, HashManager::class);
$dispatcher->addServiceListener(BeforeDeleteEvent::class, HashManager::class);
$dispatcher->addServiceListener(MoveEvent::class, HashManager::class);
$dispatcher->addServiceListener(CreateEvent::class, ActivityPublisher::class); $eventDispatcher->addServiceListener(CreateEvent::class, HashManager::class);
$dispatcher->addServiceListener(UpdateEvent::class, ActivityPublisher::class); $eventDispatcher->addServiceListener(UpdateEvent::class, HashManager::class);
$dispatcher->addServiceListener(BeforeDeleteEvent::class, ActivityPublisher::class); $eventDispatcher->addServiceListener(BeforeDeleteEvent::class, HashManager::class);
$dispatcher->addServiceListener(MoveEvent::class, ActivityPublisher::class); $eventDispatcher->addServiceListener(MoveEvent::class, HashManager::class);
$dispatcher->addServiceListener(BeforeUserDeletedEvent::class, UserGroupListener::class); $eventDispatcher->addServiceListener(CreateEvent::class, ActivityPublisher::class);
$dispatcher->addServiceListener(UserAddedEvent::class, UserGroupListener::class); $eventDispatcher->addServiceListener(UpdateEvent::class, ActivityPublisher::class);
$dispatcher->addServiceListener(UserRemovedEvent::class, UserGroupListener::class); $eventDispatcher->addServiceListener(BeforeDeleteEvent::class, ActivityPublisher::class);
$eventDispatcher->addServiceListener(MoveEvent::class, ActivityPublisher::class);
$eventDispatcher->addServiceListener(BeforeUserDeletedEvent::class, UserGroupListener::class);
$eventDispatcher->addServiceListener(UserAddedEvent::class, UserGroupListener::class);
$eventDispatcher->addServiceListener(UserRemovedEvent::class, UserGroupListener::class);
} }
} }

View File

@ -22,6 +22,7 @@ use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\AppFramework\Http\JSONResponse; use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\NotFoundResponse; use OCP\AppFramework\Http\NotFoundResponse;
use OCP\AppFramework\Http\Response; use OCP\AppFramework\Http\Response;
use OCP\AppFramework\Http\StreamResponse;
use OCP\AppFramework\Http\Template\PublicTemplateResponse; use OCP\AppFramework\Http\Template\PublicTemplateResponse;
use OCP\AppFramework\Http\TemplateResponse; use OCP\AppFramework\Http\TemplateResponse;
use OCP\IL10N; use OCP\IL10N;
@ -137,7 +138,7 @@ class WebViewController extends Controller {
* @NoCSRFRequired * @NoCSRFRequired
*/ */
public function serviceWorker() { public function serviceWorker() {
$response = new \OCP\AppFramework\Http\StreamResponse(__DIR__.'/../../js/bookmarks.service-worker.js'); $response = new StreamResponse(__DIR__.'/../../js/bookmarks-service-worker.js');
$response->setHeaders(['Content-Type' => 'application/javascript']); $response->setHeaders(['Content-Type' => 'application/javascript']);
$policy = new ContentSecurityPolicy(); $policy = new ContentSecurityPolicy();
$policy->addAllowedWorkerSrcDomain("'self'"); $policy->addAllowedWorkerSrcDomain("'self'");

2209
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,9 @@
"version": "3.3.2", "version": "3.3.2",
"main": "js/index.js", "main": "js/index.js",
"scripts": { "scripts": {
"dev": "webpack --config webpack.dev.js", "build": "NODE_ENV=production webpack --progress --hide-modules --config webpack.js",
"watch": "webpack --progress --watch --config webpack.dev.js", "dev": "NODE_ENV=development webpack --progress --config webpack.js",
"build": "webpack --progress --hide-modules --config webpack.prod.js", "watch": "NODE_ENV=development webpack --progress --watch --config webpack.js",
"lint": "eslint --ext .js,.vue src", "lint": "eslint --ext .js,.vue src",
"lint:fix": "eslint --ext .js,.vue src --fix", "lint:fix": "eslint --ext .js,.vue src --fix",
"stylelint": "stylelint src", "stylelint": "stylelint src",
@ -20,7 +20,6 @@
}, },
"homepage": "https://github.com/nextcloud/bookmarks#readme", "homepage": "https://github.com/nextcloud/bookmarks#readme",
"dependencies": { "dependencies": {
"@babel/polyfill": "^7.10.4",
"@nextcloud/auth": "^1.3.0", "@nextcloud/auth": "^1.3.0",
"@nextcloud/axios": "^1.3.3", "@nextcloud/axios": "^1.3.3",
"@nextcloud/dialogs": "^1.4.0", "@nextcloud/dialogs": "^1.4.0",
@ -35,20 +34,23 @@
"vuex": "^3.5.1", "vuex": "^3.5.1",
"vuex-router-sync": "^5.0.0" "vuex-router-sync": "^5.0.0"
}, },
"license": "AGPL-3.0-or-later",
"devDependencies": { "devDependencies": {
"@babel/core": "^7.11.0", "@babel/core": "^7.11.0",
"@babel/plugin-syntax-dynamic-import": "^7.7.4", "@babel/plugin-syntax-dynamic-import": "^7.7.4",
"@babel/preset-env": "^7.11.0", "@babel/preset-env": "^7.11.0",
"@nextcloud/eslint-config": "^2.0.0", "@nextcloud/browserslist-config": "^1.0.0",
"@nextcloud/eslint-config": "^2.2.0",
"@nextcloud/eslint-plugin": "^1.4.0", "@nextcloud/eslint-plugin": "^1.4.0",
"@nextcloud/webpack-vue-config": "^1.1.0",
"@vue/test-utils": "^1.0.3", "@vue/test-utils": "^1.0.3",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"babel-loader": "^8.0.6", "babel-loader": "^8.0.6",
"css-loader": "^3.6.0", "css-loader": "^3.6.0",
"eslint": "^6.8.0", "eslint": "^6.8.0",
"eslint-config-standard": "^12.0.0", "eslint-config-standard": "^14.1.1",
"eslint-import-resolver-webpack": "^0.12.1", "eslint-import-resolver-webpack": "^0.12.2",
"eslint-loader": "^3.0.4", "eslint-loader": "^4.0.2",
"eslint-plugin-import": "^2.22.0", "eslint-plugin-import": "^2.22.0",
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.1.1", "eslint-plugin-promise": "^4.1.1",
@ -57,18 +59,20 @@
"file-loader": "^6.0.0", "file-loader": "^6.0.0",
"node-sass": "^4.14.1", "node-sass": "^4.14.1",
"sass-loader": "^8.0.2", "sass-loader": "^8.0.2",
"stylelint": "^8.4.0", "stylelint": "^13.6.1",
"stylelint-config-recommended-scss": "^3.3.0", "stylelint-config-recommended-scss": "^4.2.0",
"stylelint-scss": "^3.17.2", "stylelint-scss": "^3.18.0",
"stylelint-webpack-plugin": "^0.10.5", "stylelint-webpack-plugin": "^2.1.0",
"vue-loader": "^15.9.3", "vue-loader": "^15.9.3",
"vue-template-compiler": "^2.6.11", "vue-template-compiler": "^2.6.11",
"webpack": "^4.44.1", "webpack": "^4.44.1",
"webpack-cli": "^3.3.12", "webpack-cli": "^3.3.12",
"webpack-merge": "^4.2.2", "webpack-merge": "^5.0.9"
"webpack-node-externals": "^1.7.2"
}, },
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
} },
"browserslist": [
"extends @nextcloud/browserslist-config"
]
} }

View File

@ -28,7 +28,7 @@ import AppGlobal from './mixins/AppGlobal'
Vue.mixin(AppGlobal) Vue.mixin(AppGlobal)
Vue.directive('tooltip', Tooltip) Vue.directive('tooltip', Tooltip)
const BookmarksApp = (global['Bookmarks'] = new Vue({ const BookmarksApp = (global.Bookmarks = new Vue({
el: '#bookmarks', el: '#bookmarks',
store, store,
render: h => h(App), render: h => h(App),

View File

@ -160,7 +160,7 @@ export default {
async onRename() { async onRename() {
this.renaming = true this.renaming = true
await Vue.nextTick() await Vue.nextTick()
this.$refs['input'].focus() this.$refs.input.focus()
}, },
async onRenameSubmit() { async onRenameSubmit() {
this.bookmark.title = this.title this.bookmark.title = this.title
@ -242,6 +242,7 @@ export default {
overflow: hidden; overflow: hidden;
min-width: 20px; min-width: 20px;
} }
.bookmark__description figure { .bookmark__description figure {
display: none !important; display: none !important;
} }
@ -290,7 +291,7 @@ export default {
margin: 0; margin: 0;
} }
.bookmark--gridview .bookmark__checkbox input[type="checkbox"].checkbox + label::before { .bookmark--gridview .bookmark__checkbox input[type='checkbox'].checkbox + label::before {
margin: 0 3px 3px 3px; margin: 0 3px 3px 3px;
} }

View File

@ -138,7 +138,7 @@ export default {
} }
.bookmarkslist .bookmarkslist
> *:first-child:not(.bookmarkslist__loading):not(.bookmarkslist__empty) { > *:first-child:not(.bookmarkslist__loading):not(.bookmarkslist__empty) {
border-top: 1px solid var(--color-border); border-top: 1px solid var(--color-border);
} }

View File

@ -44,7 +44,7 @@ export default {
}, },
}, },
mounted() { mounted() {
this.$refs['input'].focus() this.$refs.input.focus()
}, },
methods: { methods: {
submit() { submit() {

View File

@ -45,7 +45,7 @@ export default {
}, },
}, },
mounted() { mounted() {
this.$refs['input'].focus() this.$refs.input.focus()
}, },
methods: { methods: {
submit() { submit() {

View File

@ -137,7 +137,7 @@ export default {
async onRename() { async onRename() {
this.renaming = true this.renaming = true
await Vue.nextTick() await Vue.nextTick()
this.$refs['input'].focus() this.$refs.input.focus()
}, },
onRenameSubmit() { onRenameSubmit() {
this.folder.title = this.title this.folder.title = this.title

View File

@ -108,7 +108,7 @@ const SETTINGS = [
export default { export default {
name: 'ViewAdmin', name: 'ViewAdmin',
components: { SettingsSection }, components: { SettingsSection },
data: function() { data() {
return { return {
settings: SETTINGS.reduce((obj, key) => ({ ...obj, [key]: '' }), {}), settings: SETTINGS.reduce((obj, key) => ({ ...obj, [key]: '' }), {}),
loading: false, loading: false,
@ -201,31 +201,31 @@ export default {
</script> </script>
<style> <style>
figure[class^='icon-'] { figure[class^='icon-'] {
display: inline-block; display: inline-block;
} }
#bookmarks h2 { #bookmarks h2 {
margin-top: 40px; margin-top: 40px;
} }
#bookmarks { #bookmarks {
position: relative; position: relative;
} }
#bookmarks .loading, #bookmarks .loading,
#bookmarks .success { #bookmarks .success {
position: absolute; position: absolute;
top: 20px; top: 20px;
right: 20px; right: 20px;
} }
#bookmarks label { #bookmarks label {
margin-top: 10px; margin-top: 10px;
display: block; display: block;
} }
#bookmarks input { #bookmarks input {
width: 100%; width: 100%;
display: block; display: block;
} }
</style> </style>

View File

@ -68,7 +68,7 @@ export default {
default: '', default: '',
}, },
}, },
data: function() { data() {
return { return {
bookmark: { bookmark: {
title: this.title, title: this.title,

View File

@ -35,7 +35,7 @@ export default {
SidebarFolder, SidebarFolder,
MoveDialog, MoveDialog,
}, },
data: function() { data() {
return { return {
newBookmark: false, newBookmark: false,
} }

View File

@ -22,7 +22,7 @@ export default {
Breadcrumbs, Breadcrumbs,
BookmarksList, BookmarksList,
}, },
data: function() { data() {
return { return {
newBookmark: false, newBookmark: false,
} }

View File

@ -30,7 +30,7 @@ import { generateUrl } from '@nextcloud/router'
Vue.mixin(AppGlobal) Vue.mixin(AppGlobal)
Vue.directive('tooltip', Tooltip) Vue.directive('tooltip', Tooltip)
const BookmarksApp = (global['Bookmarks'] = new Vue({ const BookmarksApp = (global.Bookmarks = new Vue({
el: '#content', el: '#content',
store, store,
router, router,

View File

@ -293,7 +293,7 @@ export default {
}, },
[actions.DELETE_BOOKMARKS]({ commit, dispatch, state }) { [actions.DELETE_BOOKMARKS]({ commit, dispatch, state }) {
return axios return axios
.delete(url(state, `/bookmark`)) .delete(url(state, '/bookmark'))
.then(response => { .then(response => {
const { const {
data: { status }, data: { status },
@ -439,7 +439,7 @@ export default {
{ parentFolder, title } { parentFolder, title }
) { ) {
return axios return axios
.post(url(state, `/folder`), { .post(url(state, '/folder'), {
parent_folder: parentFolder, parent_folder: parentFolder,
title, title,
}) })

View File

@ -44,7 +44,7 @@ export default {
state.authToken = authToken state.authToken = authToken
axios.defaults.headers = { axios.defaults.headers = {
requesttoken: OC.requesttoken, requesttoken: OC.requesttoken,
'Authorization': 'bearer ' + authToken, Authorization: 'bearer ' + authToken,
} }
}, },
[mutations.SET_VIEW_MODE](state, viewMode) { [mutations.SET_VIEW_MODE](state, viewMode) {
@ -159,8 +159,8 @@ export default {
Vue.set(state.fetchState, 'query', query) Vue.set(state.fetchState, 'query', query)
// cancel currently running request // cancel currently running request
if (typeof state.loading['bookmarks'] === 'function') { if (typeof state.loading.bookmarks === 'function') {
state.loading['bookmarks']() state.loading.bookmarks()
} }
// stop loading // stop loading
Vue.set(state.loading, 'bookmarks', false) Vue.set(state.loading, 'bookmarks', false)

View File

@ -7,20 +7,26 @@ module.exports = {
'rule-empty-line-before': [ 'rule-empty-line-before': [
'always', 'always',
{ {
ignore: ['after-comment', 'inside-block'] ignore: ['after-comment', 'inside-block'],
} },
], ],
'declaration-empty-line-before': [ 'declaration-empty-line-before': [
'never', 'never',
{ {
ignore: ['after-declaration'] ignore: ['after-declaration'],
} },
], ],
'comment-empty-line-before': null, 'comment-empty-line-before': null,
'selector-type-case': null, 'selector-type-case': null,
'selector-list-comma-newline-after': null, 'selector-list-comma-newline-after': null,
'no-descending-specificity': null, 'no-descending-specificity': null,
'string-quotes': 'single' 'string-quotes': 'single',
'selector-pseudo-element-no-unknown': [
true,
{
ignorePseudoElements: ['v-deep'],
},
],
}, },
plugins: ['stylelint-scss'] plugins: ['stylelint-scss'],
} }

View File

@ -1,4 +1,4 @@
<?php <?php
script('bookmarks', 'bookmarks.admin'); script('bookmarks', 'bookmarks-admin');
?> ?>
<div id="bookmarks" class="section"></div> <div id="bookmarks" class="section"></div>

View File

@ -1,4 +1,4 @@
<?php <?php
script('bookmarks', 'bookmarks.main'); script('bookmarks', 'bookmarks-main');
?> ?>
<div id="vue-content"></div> <div id="vue-content"></div>

View File

@ -1,63 +0,0 @@
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
const StyleLintPlugin = require('stylelint-webpack-plugin')
const packageJson = require('./package.json')
const appName = packageJson.name
module.exports = {
entry: {
main: path.join(__dirname, 'src', 'main.js'),
admin: path.join(__dirname, 'src', 'admin.js'),
'service-worker': path.join(__dirname, 'src', 'service-worker.js')
},
output: {
path: path.resolve(__dirname, './js'),
publicPath: '/js/',
filename: `${appName}.[name].js`,
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: /\.(js|vue)$/,
use: 'eslint-loader',
exclude: /node_modules/,
enforce: 'pre',
},
{
test: /\.vue$/,
loader: 'vue-loader',
exclude: /node_modules/,
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [['@babel/preset-env', {
targets: '> 0.25%, not dead',
useBuiltIns: 'usage',
modules: false,
}]],
},
},
},
],
},
plugins: [
new VueLoaderPlugin(),
new StyleLintPlugin(),
],
resolve: {
extensions: ['*', '.js', '.vue'],
},
}

View File

@ -1,7 +0,0 @@
const merge = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'development',
devtool: '#cheap-source-map'
})

12
webpack.js Normal file
View File

@ -0,0 +1,12 @@
const { merge } = require('webpack-merge')
const path = require('path')
const webpackConfig = require('@nextcloud/webpack-vue-config')
const config = {
entry: {
admin: path.join(__dirname, 'src', 'admin.js'),
'service-worker': path.join(__dirname, 'src', 'service-worker.js'),
},
}
module.exports = merge(config, webpackConfig)

View File

@ -1,7 +0,0 @@
const merge = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'production',
devtool: '#source-map'
})