Implement collections integration

Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
Julius Härtl
2019-03-05 14:34:19 +01:00
parent 9149a01949
commit e2be00a18d
15 changed files with 982 additions and 158 deletions

10
css/collections.css Normal file
View File

@@ -0,0 +1,10 @@
.icon-deck {
background-image: url('../img/deck-dark.svg');
}
.resource-type-deck img {
opacity: 0.4 !important;
}
.resource-type-deck:hover img {
opacity: 0.7 !important;
}

View File

@@ -21,8 +21,11 @@
*/
import app from '../app/App.js';
import Vue from 'vue';
import CollaborationView from '../views/CollaborationView';
/* global oc_defaults OC OCP OCA */
app.controller('BoardController', function ($rootScope, $scope, $stateParams, StatusService, BoardService, StackService, CardService, LabelService, $state, $transitions, $filter, FileService) {
app.controller('BoardController', function ($rootScope, $scope, $element, $stateParams, StatusService, BoardService, StackService, CardService, LabelService, $state, $transitions, $filter, FileService) {
$scope.sidebar = $rootScope.sidebar;
@@ -148,6 +151,31 @@ app.controller('BoardController', function ($rootScope, $scope, $stateParams, St
}
});
const ComponentVM = new Vue({
render: h => h(CollaborationView),
data: {
model: BoardService.getCurrent()
},
});
$scope.mountCollections = () => {
console.log('mountCollections');
const MountingPoint = document.getElementById('collaborationResources');
if (MountingPoint) {
console.log(MountingPoint);
ComponentVM.model = BoardService.getCurrent();
ComponentVM.$mount(MountingPoint);
}
};
$scope.$$postDigest($scope.mountCollections);
$scope.$watch(function () {
return BoardService.getCurrent();
}, function() {
ComponentVM.model = BoardService.getCurrent();
if ($scope.sidebar.show) {
$scope.$$postDigest($scope.mountCollections);
}
});
$scope.toggleCompactMode = function() {
$rootScope.compactMode = !$rootScope.compactMode;
localStorage.setItem('deck.compactMode', JSON.stringify($rootScope.compactMode));

67
js/init-collections.js Normal file
View File

@@ -0,0 +1,67 @@
/*
* @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
'use strict';
/* global __webpack_nonce__ OC */
__webpack_nonce__ = btoa(OC.requestToken); // eslint-disable-line no-native-reassign
__webpack_public_path__ = OC.linkTo('deck', 'js/build/');
import Vue from 'vue';
import BoardSelector from './views/BoardSelector';
import './../css/collections.css';
(function(OCP) {
Vue.prototype.$ = $
Vue.prototype.t = t
Vue.prototype.n = n
Vue.prototype.OC = OC
OCP.Collaboration.registerType('deck', {
action: () => {
return new Promise((resolve, reject) => {
const container = document.createElement('div');
container.id = 'deck-board-select';
const body = document.getElementById('body-user');
body.append(container);
const ComponentVM = new Vue({
render: h => h(BoardSelector),
});
ComponentVM.$mount(container);
ComponentVM.$root.$on('close', () => {
ComponentVM.$el.remove();
ComponentVM.$destroy();
reject();
});
ComponentVM.$root.$on('select', (id) => {
resolve(id);
ComponentVM.$el.remove();
ComponentVM.$destroy();
});
});
},
typeString: t('deck', 'board'),
typeIconClass: 'icon-deck'
});
})(window.OCP);

View File

@@ -2,6 +2,7 @@
/* global __webpack_nonce__ OC */
__webpack_nonce__ = btoa(OC.requestToken); // eslint-disable-line no-native-reassign
__webpack_public_path__ = OC.linkTo('deck', 'js/build/');
// used for building a vendor stylesheet
import 'ng-sortable/dist/ng-sortable.css';

529
js/package-lock.json generated
View File

@@ -682,6 +682,15 @@
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-dynamic-import": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz",
"integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0"
}
},
"@babel/plugin-syntax-json-strings": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz",
@@ -1171,6 +1180,73 @@
"resolved": "https://registry.npmjs.org/@uirouter/core/-/core-5.0.23.tgz",
"integrity": "sha512-rwFOH++z/KY8y+h0IOpQ5uC8Nim6E0EBCQrIjhVCr+XKYXgpK+VdtuOLFdogvbJ3AAi5Z7ei00qdEr7Did5CAg=="
},
"@vue/component-compiler-utils": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-2.6.0.tgz",
"integrity": "sha512-IHjxt7LsOFYc0DkTncB7OXJL7UzwOLPPQCfEUNyxL2qt+tF12THV+EO33O1G2Uk4feMSWua3iD39Itszx0f0bw==",
"dev": true,
"requires": {
"consolidate": "^0.15.1",
"hash-sum": "^1.0.2",
"lru-cache": "^4.1.2",
"merge-source-map": "^1.1.0",
"postcss": "^7.0.14",
"postcss-selector-parser": "^5.0.0",
"prettier": "1.16.3",
"source-map": "~0.6.1",
"vue-template-es2015-compiler": "^1.9.0"
},
"dependencies": {
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"postcss": {
"version": "7.0.14",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz",
"integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==",
"dev": true,
"requires": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
"supports-color": "^6.1.0"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
"supports-color": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"@webassemblyjs/ast": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
@@ -1575,6 +1651,15 @@
"integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=",
"dev": true
},
"axios": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
"requires": {
"follow-redirects": "^1.3.0",
"is-buffer": "^1.1.5"
}
},
"babel-loader": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.5.tgz",
@@ -2045,8 +2130,24 @@
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"charenc": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
"integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc="
},
"chokidar": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz",
@@ -2239,6 +2340,15 @@
"date-now": "^0.1.4"
}
},
"consolidate": {
"version": "0.15.1",
"resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz",
"integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==",
"dev": true,
"requires": {
"bluebird": "^3.1.1"
}
},
"constants-browserify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
@@ -2379,6 +2489,11 @@
"which": "^1.2.9"
}
},
"crypt": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
"integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs="
},
"crypto-browserify": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
@@ -2423,12 +2538,6 @@
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
"dev": true
},
"camelcase": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz",
"integrity": "sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==",
"dev": true
},
"json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
@@ -2493,6 +2602,12 @@
"integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
"dev": true
},
"de-indent": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
"integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=",
"dev": true
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -3051,6 +3166,11 @@
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
"dev": true
},
"fecha": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
"integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg=="
},
"figgy-pudding": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
@@ -3166,7 +3286,6 @@
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz",
"integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==",
"dev": true,
"requires": {
"debug": "^3.2.6"
},
@@ -3175,7 +3294,6 @@
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
@@ -3183,8 +3301,7 @@
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}
}
},
@@ -3243,9 +3360,9 @@
"dev": true
},
"fsevents": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz",
"integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==",
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz",
"integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==",
"dev": true,
"optional": true,
"requires": {
@@ -3272,7 +3389,7 @@
"optional": true
},
"are-we-there-yet": {
"version": "1.1.4",
"version": "1.1.5",
"bundled": true,
"dev": true,
"optional": true,
@@ -3298,7 +3415,7 @@
}
},
"chownr": {
"version": "1.0.1",
"version": "1.1.1",
"bundled": true,
"dev": true,
"optional": true
@@ -3337,7 +3454,7 @@
}
},
"deep-extend": {
"version": "0.5.1",
"version": "0.6.0",
"bundled": true,
"dev": true,
"optional": true
@@ -3386,7 +3503,7 @@
}
},
"glob": {
"version": "7.1.2",
"version": "7.1.3",
"bundled": true,
"dev": true,
"optional": true,
@@ -3406,12 +3523,12 @@
"optional": true
},
"iconv-lite": {
"version": "0.4.21",
"version": "0.4.24",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safer-buffer": "^2.1.0"
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ignore-walk": {
@@ -3476,17 +3593,17 @@
"optional": true
},
"minipass": {
"version": "2.2.4",
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
}
},
"minizlib": {
"version": "1.1.0",
"version": "1.2.1",
"bundled": true,
"dev": true,
"optional": true,
@@ -3510,7 +3627,7 @@
"optional": true
},
"needle": {
"version": "2.2.0",
"version": "2.2.4",
"bundled": true,
"dev": true,
"optional": true,
@@ -3521,18 +3638,18 @@
}
},
"node-pre-gyp": {
"version": "0.10.0",
"version": "0.10.3",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"detect-libc": "^1.0.2",
"mkdirp": "^0.5.1",
"needle": "^2.2.0",
"needle": "^2.2.1",
"nopt": "^4.0.1",
"npm-packlist": "^1.1.6",
"npmlog": "^4.0.2",
"rc": "^1.1.7",
"rc": "^1.2.7",
"rimraf": "^2.6.1",
"semver": "^5.3.0",
"tar": "^4"
@@ -3549,13 +3666,13 @@
}
},
"npm-bundled": {
"version": "1.0.3",
"version": "1.0.5",
"bundled": true,
"dev": true,
"optional": true
},
"npm-packlist": {
"version": "1.1.10",
"version": "1.2.0",
"bundled": true,
"dev": true,
"optional": true,
@@ -3632,12 +3749,12 @@
"optional": true
},
"rc": {
"version": "1.2.7",
"version": "1.2.8",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"deep-extend": "^0.5.1",
"deep-extend": "^0.6.0",
"ini": "~1.3.0",
"minimist": "^1.2.0",
"strip-json-comments": "~2.0.1"
@@ -3667,16 +3784,16 @@
}
},
"rimraf": {
"version": "2.6.2",
"version": "2.6.3",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"glob": "^7.0.5"
"glob": "^7.1.3"
}
},
"safe-buffer": {
"version": "5.1.1",
"version": "5.1.2",
"bundled": true,
"dev": true,
"optional": true
@@ -3694,7 +3811,7 @@
"optional": true
},
"semver": {
"version": "5.5.0",
"version": "5.6.0",
"bundled": true,
"dev": true,
"optional": true
@@ -3747,17 +3864,17 @@
"optional": true
},
"tar": {
"version": "4.4.1",
"version": "4.4.8",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"chownr": "^1.0.1",
"chownr": "^1.1.1",
"fs-minipass": "^1.2.5",
"minipass": "^2.2.4",
"minizlib": "^1.1.0",
"minipass": "^2.3.4",
"minizlib": "^1.1.1",
"mkdirp": "^0.5.0",
"safe-buffer": "^5.1.1",
"safe-buffer": "^5.1.2",
"yallist": "^3.0.2"
}
},
@@ -3768,12 +3885,12 @@
"optional": true
},
"wide-align": {
"version": "1.1.2",
"version": "1.1.3",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"string-width": "^1.0.2"
"string-width": "^1.0.2 || 2"
}
},
"wrappy": {
@@ -3783,7 +3900,7 @@
"optional": true
},
"yallist": {
"version": "3.0.2",
"version": "3.0.3",
"bundled": true,
"dev": true,
"optional": true
@@ -3888,6 +4005,11 @@
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
"dev": true
},
"hammerjs": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
"integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
@@ -4002,6 +4124,12 @@
"safe-buffer": "^5.0.1"
}
},
"hash-sum": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
"integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
"dev": true
},
"hash.js": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
@@ -4012,6 +4140,12 @@
"minimalistic-assert": "^1.0.1"
}
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true
},
"hmac-drbg": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
@@ -4189,8 +4323,7 @@
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"is-callable": {
"version": "1.1.4",
@@ -4512,6 +4645,11 @@
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
"dev": true
},
"lodash.merge": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz",
"integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ=="
},
"log4js": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/log4js/-/log4js-4.0.2.tgz",
@@ -4617,6 +4755,16 @@
"resolved": "https://registry.npmjs.org/markdown-it-link-target/-/markdown-it-link-target-1.0.2.tgz",
"integrity": "sha1-0v1FV181FI6cXiNet4ertvlGCmc="
},
"md5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz",
"integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=",
"requires": {
"charenc": "~0.0.1",
"crypt": "~0.0.1",
"is-buffer": "~1.1.1"
}
},
"md5.js": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@@ -4660,6 +4808,23 @@
"readable-stream": "^2.0.1"
}
},
"merge-source-map": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
"integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
"dev": true,
"requires": {
"source-map": "^0.6.1"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@@ -4904,6 +5069,60 @@
"integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==",
"dev": true
},
"nextcloud-axios": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/nextcloud-axios/-/nextcloud-axios-0.1.3.tgz",
"integrity": "sha512-M2eLX0qrP8xy1VEGDhPXGwvV4W4gMnU1ysjnURVen8ehR1qRLdb/JfhJHab6XRsme7vWWMgSTEj+o3ibQ94N6g==",
"requires": {
"axios": "^0.18.0"
}
},
"nextcloud-vue": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/nextcloud-vue/-/nextcloud-vue-0.8.0.tgz",
"integrity": "sha512-6qXcWTgtrbM4W1AjyHSWn0cHOFm/Q39A//OibrY7M332orQnDvCrDoGloUUOW6+vbXJarI+L7t7scL6mkRw4Qg==",
"requires": {
"hammerjs": "^2.0.8",
"md5": "^2.2.1",
"nextcloud-axios": "^0.1.3",
"v-tooltip": "^2.0.0-rc.33",
"vue": "^2.6.7",
"vue-click-outside": "^1.0.7",
"vue-multiselect": "^2.1.3",
"vue2-datepicker": "^2.10.0"
}
},
"nextcloud-vue-collections": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/nextcloud-vue-collections/-/nextcloud-vue-collections-0.2.0.tgz",
"integrity": "sha512-LDbJyUZffu8ZIkkXAMXkfqkUK36GaUiuS4IdgoOLe/z9prV/Iic7uwrDME015FsCv9GmfheOs7cfiU6xBIidGA==",
"requires": {
"nextcloud-axios": "^0.1.2",
"nextcloud-vue": "^0.9.0",
"v-tooltip": "^2.0.0-rc.33",
"vue": "^2.6.6",
"vue-click-outside": "^1.0.7",
"vuex": "^3.1.0"
},
"dependencies": {
"nextcloud-vue": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/nextcloud-vue/-/nextcloud-vue-0.9.2.tgz",
"integrity": "sha512-gw0A+qIEHP+P+iRhb+btSXuS3mkEgTyVr1aaJf8CvNXMlfxJMYMo25jQ+lHc9uRbl9MdGzl3U8gY84kTQffPjw==",
"requires": {
"hammerjs": "^2.0.8",
"md5": "^2.2.1",
"nextcloud-axios": "^0.1.3",
"v-tooltip": "^2.0.0-rc.33",
"vue": "^2.6.7",
"vue-click-outside": "^1.0.7",
"vue-multiselect": "^2.1.3",
"vue-visible": "^1.0.2",
"vue2-datepicker": "^2.10.0"
}
}
}
},
"ng-infinite-scroll": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ng-infinite-scroll/-/ng-infinite-scroll-1.3.0.tgz",
@@ -5127,7 +5346,7 @@
},
"p-is-promise": {
"version": "2.0.0",
"resolved": "http://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz",
"resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz",
"integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==",
"dev": true
},
@@ -5286,6 +5505,11 @@
"find-up": "^3.0.0"
}
},
"popper.js": {
"version": "1.14.7",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.14.7.tgz",
"integrity": "sha512-4q1hNvoUre/8srWsH7hnoSJ5xVmIL4qgz+s4qf2TnJIMyZFUFMGH+9vE7mXynAlHSZ/NdTmmow86muD0myUkVQ=="
},
"posix-character-classes": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@@ -5303,42 +5527,11 @@
"supports-color": "^6.1.0"
},
"dependencies": {
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
"supports-color": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
@@ -5360,6 +5553,19 @@
"postcss": "^7.0.6",
"postcss-selector-parser": "^6.0.0",
"postcss-value-parser": "^3.3.1"
},
"dependencies": {
"postcss-selector-parser": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
"integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==",
"dev": true,
"requires": {
"cssesc": "^3.0.0",
"indexes-of": "^1.0.1",
"uniq": "^1.0.1"
}
}
}
},
"postcss-modules-scope": {
@@ -5370,6 +5576,19 @@
"requires": {
"postcss": "^7.0.6",
"postcss-selector-parser": "^6.0.0"
},
"dependencies": {
"postcss-selector-parser": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
"integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==",
"dev": true,
"requires": {
"cssesc": "^3.0.0",
"indexes-of": "^1.0.1",
"uniq": "^1.0.1"
}
}
}
},
"postcss-modules-values": {
@@ -5383,14 +5602,22 @@
}
},
"postcss-selector-parser": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
"integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz",
"integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==",
"dev": true,
"requires": {
"cssesc": "^3.0.0",
"cssesc": "^2.0.0",
"indexes-of": "^1.0.1",
"uniq": "^1.0.1"
},
"dependencies": {
"cssesc": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz",
"integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==",
"dev": true
}
}
},
"postcss-value-parser": {
@@ -5399,6 +5626,12 @@
"integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
"dev": true
},
"prettier": {
"version": "1.16.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.3.tgz",
"integrity": "sha512-kn/GU6SMRYPxUakNXhpP0EedT/KmaPzr0H5lIsDogrykbaxOpOfAFfk5XA7DZrJyMAv1wlMV3CPcZruGXVVUZw==",
"dev": true
},
"private": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@@ -6298,10 +6531,20 @@
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
"dev": true
},
"style-loader": {
"version": "0.23.1",
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz",
"integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==",
"dev": true,
"requires": {
"loader-utils": "^1.1.0",
"schema-utils": "^1.0.0"
}
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
@@ -6728,6 +6971,17 @@
}
}
},
"url-loader": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz",
"integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==",
"dev": true,
"requires": {
"loader-utils": "^1.1.0",
"mime": "^2.0.3",
"schema-utils": "^1.0.0"
}
},
"use": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz",
@@ -6786,6 +7040,21 @@
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
"dev": true
},
"v-click-outside": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/v-click-outside/-/v-click-outside-2.0.2.tgz",
"integrity": "sha512-4dDekJloLi7WbVUM6IC/Gdv8qYaE+a2LY3sLUkzJc2WBf92kL0VPHGCTxVkTzZjHLVdkcjX0haiLXofrhZfHXA=="
},
"v-tooltip": {
"version": "2.0.0-rc.33",
"resolved": "https://registry.npmjs.org/v-tooltip/-/v-tooltip-2.0.0-rc.33.tgz",
"integrity": "sha1-ePfY6cNCZWIr5lup3HjGfx3AK3M=",
"requires": {
"lodash.merge": "^4.6.0",
"popper.js": "^1.12.9",
"vue-resize": "^0.4.3"
}
},
"v8-compile-cache": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz",
@@ -6807,6 +7076,89 @@
"integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
"dev": true
},
"vue": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/vue/-/vue-2.6.8.tgz",
"integrity": "sha512-+vp9lEC2Kt3yom673pzg1J7T1NVGuGzO9j8Wxno+rQN2WYVBX2pyo/RGQ3fXCLh2Pk76Skw/laAPCuBuEQ4diw=="
},
"vue-click-outside": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/vue-click-outside/-/vue-click-outside-1.0.7.tgz",
"integrity": "sha1-zdKxYF48SUR4TheU6uShKg9wC9Y="
},
"vue-hot-reload-api": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.3.tgz",
"integrity": "sha512-KmvZVtmM26BQOMK1rwUZsrqxEGeKiYSZGA7SNWE6uExx8UX/cj9hq2MRV/wWC3Cq6AoeDGk57rL9YMFRel/q+g==",
"dev": true
},
"vue-loader": {
"version": "15.7.0",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.7.0.tgz",
"integrity": "sha512-x+NZ4RIthQOxcFclEcs8sXGEWqnZHodL2J9Vq+hUz+TDZzBaDIh1j3d9M2IUlTjtrHTZy4uMuRdTi8BGws7jLA==",
"dev": true,
"requires": {
"@vue/component-compiler-utils": "^2.5.1",
"hash-sum": "^1.0.2",
"loader-utils": "^1.1.0",
"vue-hot-reload-api": "^2.3.0",
"vue-style-loader": "^4.1.0"
}
},
"vue-multiselect": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/vue-multiselect/-/vue-multiselect-2.1.4.tgz",
"integrity": "sha512-ryd2Ybl56LE81IxlwbZUo4gAWnUSG45iUGX4KgVwsteitK2R+cOLwJaJescobpIDJnVlVorRUnX5u7my1vBu2w=="
},
"vue-resize": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-0.4.5.tgz",
"integrity": "sha512-bhP7MlgJQ8TIkZJXAfDf78uJO+mEI3CaLABLjv0WNzr4CcGRGPIAItyWYnP6LsPA4Oq0WE+suidNs6dgpO4RHg=="
},
"vue-style-loader": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
"integrity": "sha512-0ip8ge6Gzz/Bk0iHovU9XAUQaFt/G2B61bnWa2tCcqqdgfHs1lF9xXorFbE55Gmy92okFT+8bfmySuUOu13vxQ==",
"dev": true,
"requires": {
"hash-sum": "^1.0.2",
"loader-utils": "^1.0.2"
}
},
"vue-template-compiler": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.8.tgz",
"integrity": "sha512-SwWKANE5ee+oJg+dEJmsdxsxWYICPsNwk68+1AFjOS8l0O/Yz2845afuJtFqf3UjS/vXG7ECsPeHHEAD65Cjng==",
"dev": true,
"requires": {
"de-indent": "^1.0.2",
"he": "^1.1.0"
}
},
"vue-template-es2015-compiler": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz",
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true
},
"vue-visible": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/vue-visible/-/vue-visible-1.0.2.tgz",
"integrity": "sha512-yaX2its9XAJKGuQqf7LsiZHHSkxsIK8rmCOQOvEGEoF41blKRK8qr9my4qYoD6ikdLss4n8tKqYBecmaY0+WJg=="
},
"vue2-datepicker": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/vue2-datepicker/-/vue2-datepicker-2.10.0.tgz",
"integrity": "sha512-WGL7ou0TdBiJQuHVp29BtBw3rSkLrIYwXWU/ELmaLdnAerI0EdGVAu7DvZV2iIxY4lsHyjqocApxdvXTmwLrAw==",
"requires": {
"fecha": "^2.3.3"
}
},
"vuex": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.1.0.tgz",
"integrity": "sha512-mdHeHT/7u4BncpUZMlxNaIdcN/HIt1GsGG5LKByArvYG/v6DvHcOxvDCts+7SRdCoIRGllK8IMZvQtQXLppDYg=="
},
"watchpack": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
@@ -6891,6 +7243,17 @@
"supports-color": "^5.5.0",
"v8-compile-cache": "^2.0.2",
"yargs": "^12.0.5"
},
"dependencies": {
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"webpack-merge": {

View File

@@ -3,7 +3,6 @@
"description": "Frontend for the Nextcloud Deck app",
"repository": "https://github.com/nextcloud/deck",
"version": "1.0.0",
"main": "Gruntfile.js",
"directories": {
"test": "tests"
},
@@ -17,25 +16,37 @@
"babel-polyfill": "^6.26.0",
"markdown-it": "^8.4.2",
"markdown-it-link-target": "^1.0.2",
"nextcloud-axios": "^0.1.3",
"nextcloud-vue": "^0.8.0",
"nextcloud-vue-collections": "^0.2.0",
"ng-infinite-scroll": "^1.3.0",
"ng-sortable": "^1.3.8",
"ui-select": "^0.19.8"
"ui-select": "^0.19.8",
"v-click-outside": "^2.0.2",
"vue": "^2.6.8",
"vuex": "^3.1.0"
},
"devDependencies": {
"@babel/core": "^7.4.0",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/polyfill": "^7.4.0",
"@babel/preset-env": "^7.4.2",
"babel-loader": "^8.0.5",
"css-loader": "^2.1.1",
"karma": "^4.0.1",
"mini-css-extract-plugin": "^0.5.0",
"style-loader": "^0.23.1",
"uglifyjs-webpack-plugin": "^2.1.2",
"url-loader": "^1.1.2",
"vue-loader": "^15.7.0",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.6.8",
"webpack": "^4.29.6",
"webpack-cli": "^3.3.0",
"webpack-merge": "^4.2.1"
},
"scripts": {
"build": "./node_modules/webpack-cli/bin/cli.js --mode production --config webpack.prod.config.js",
"build": "NODE_ENV=production ./node_modules/webpack-cli/bin/cli.js --mode production --config webpack.prod.config.js",
"dev": "./node_modules/webpack-cli/bin/cli.js --mode development --config webpack.dev.config.js",
"watch": "./node_modules/webpack-cli/bin/cli.js --mode development --config webpack.dev.config.js --watch",
"test": "echo \"Warning: no test specified\" && exit 0"

111
js/views/BoardSelector.vue Normal file
View File

@@ -0,0 +1,111 @@
<!--
- @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
-
- @author Julius Härtl <jus@bitgrid.net>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
<template>
<Modal @close="close">
<div id="modal-inner" :class="{ 'icon-loading': loading }">
<h1>Select a board to add to the collection</h1>
<ul v-if="!loading">
<li v-for="board in boards" @click="selectedBoard=board.id" :class="{'selected': (selectedBoard === board.id) }">
<span class="board-bullet" :style="{ 'backgroundColor': '#' + board.color }"></span>
<span>{{ board.title }}</span>
</li>
</ul>
<button v-if="!loading" @click="select" class="primary">Select board</button>
</div>
</Modal>
</template>
<style scoped>
#modal-inner {
width: 90vw;
max-width: 400px;
padding: 20px;
}
ul {
min-height: 100px;
}
li {
padding: 6px;
border: 1px solid transparent;
}
li:hover, li:focus {
background-color: var(--color-background-dark);
}
li.selected {
border: 1px solid var(--color-primary);
}
.board-bullet {
display: inline-block;
width: 12px;
height: 12px;
border: none;
border-radius: 50%;
cursor: pointer;
}
li > span,
.avatar {
vertical-align: middle;
}
</style>
<script>
import { Modal } from 'nextcloud-vue/dist/Components/Modal'
import { Avatar } from 'nextcloud-vue/dist/Components/Avatar'
import axios from 'nextcloud-axios'
export default {
name: 'CollaborationView',
components: {
Modal, Avatar
},
data() {
return {
boards: [],
selectedBoard: null,
loading: true,
}
},
beforeMount() {
this.fetchBoards();
},
methods: {
fetchBoards() {
axios.get(OC.generateUrl('/apps/deck/boards')).then((response) => {
this.boards = response.data
this.loading = false
})
},
close() {
this.$root.$emit('close');
},
select() {
this.$root.$emit('select', this.selectedBoard)
}
},
computed: {
},
}
</script>

View File

@@ -0,0 +1,58 @@
<!--
- @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
-
- @author Julius Härtl <jus@bitgrid.net>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->
<template>
<div>
<collection-list v-if="boardId" type="deck" :id="boardId" :name="boardTitle"></collection-list>
</div>
</template>
<script>
import { CollectionList } from 'nextcloud-vue-collections';
import Vue from 'vue';
import PopoverMenu from 'nextcloud-vue/dist/Components/PopoverMenu'
import vClickOutside from 'v-click-outside'
Vue.component('popover-menu', PopoverMenu);
Vue.use(vClickOutside)
export default {
name: 'CollaborationView',
computed: {
boardId() {
if (this.$root.model && this.$root.model.id) {
return '' + this.$root.model.id;
}
return null;
},
boardTitle() {
if (this.$root.model && this.$root.model.title) {
return '' + this.$root.model.title;
}
return '';
}
},
components: {
CollectionList: CollectionList
}
}
</script>

View File

@@ -1,66 +1,76 @@
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { VueLoaderPlugin } = require('vue-loader');
module.exports = {
node: {
fs: 'empty',
},
entry: {
deck: ['./init.js'],
},
output: {
filename: '[name].js',
path: __dirname + '/build'
},
resolve: {
modules: [path.resolve(__dirname), 'node_modules'],
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['@babel/preset-env'],
}
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
/* separate vendor chunk for node_modules and legacy scripts */
commons: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all'
},
legacy: {
test: /[\\/]legacy[\\/]/,
name: 'vendor',
chunks: 'all'
}
}
}
},
/* use external jQuery from server */
externals: {
'jquery': 'jQuery'
},
plugins: [
new MiniCssExtractPlugin('[name].css'),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
node: {
fs: 'empty',
},
entry: {
deck: ['./init.js'],
collections: ['./init-collections.js']
},
output: {
filename: '[name].js',
path: __dirname + '/build'
},
module: {
rules: [
{
test: /\.css$/,
use: ['vue-style-loader', 'style-loader', 'css-loader']
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-syntax-dynamic-import']
}
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'url-loader',
options: {
name: '[name].[ext]?[hash]'
}
},
]
},
/* use external jQuery from server */
externals: {
'jquery': 'jQuery'
},
resolve: {
alias: {
vue$: 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json'],
modules: [
path.resolve(__dirname),
path.join(__dirname, 'node_modules'),
'node_modules'
]
},
plugins: [
new VueLoaderPlugin(),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
};

View File

@@ -24,6 +24,7 @@
namespace OCA\Deck\AppInfo;
use OCA\Deck\Activity\CommentEventHandler;
use OCA\Deck\Collaboration\Resources\ResourceProvider;
use OCA\Deck\Db\Acl;
use OCA\Deck\Db\AclMapper;
use OCA\Deck\Db\AssignedUsersMapper;
@@ -32,6 +33,8 @@ use OCA\Deck\Middleware\ExceptionMiddleware;
use OCA\Deck\Notification\Notifier;
use OCP\AppFramework\App;
use OCA\Deck\Middleware\SharingMiddleware;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\Collaboration\Resources\IManager;
use OCP\Comments\CommentsEntityEvent;
use OCP\IGroup;
use OCP\IUser;
@@ -100,6 +103,8 @@ class Application extends App {
}
});
$this->registerCollaborationResources();
}
public function registerNavigationEntry() {
@@ -147,4 +152,16 @@ class Application extends App {
return $this->getContainer()->query(CommentEventHandler::class);
});
}
protected function registerCollaborationResources() {
/**
* Register Collaboration ResourceProvider
*/
/** @var IManager $resourceManager */
$resourceManager = $this->getContainer()->query(IManager::class);
$resourceManager->registerResourceProvider(ResourceProvider::class);
\OC::$server->getEventDispatcher()->addListener('\OCP\Collaboration\Resources::loadAdditionalScripts', function () {
\OCP\Util::addScript('deck', 'build/collections');
});
}
}

View File

@@ -0,0 +1,133 @@
<?php
/**
* @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Deck\Collaboration\Resources;
use OCA\Deck\Db\Acl;
use OCA\Deck\Db\Board;
use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Service\PermissionService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\AppFramework\QueryException;
use OCP\Collaboration\Resources\IManager;
use OCP\Collaboration\Resources\IProvider;
use OCP\Collaboration\Resources\IResource;
use OCP\Collaboration\Resources\ResourceException;
use OCP\IUser;
class ResourceProvider implements IProvider {
const RESOURCE_TYPE = 'deck';
private $boardMapper;
private $permissionService;
/** @var array */
protected $nodes = [];
public function __construct(BoardMapper $boardMapper, PermissionService $permissionService) {
$this->boardMapper = $boardMapper;
$this->permissionService = $permissionService;
}
/**
* Get the type of a resource
*
* @param IResource $resource
* @return string
* @since 15.0.0
*/
public function getType(): string {
return self::RESOURCE_TYPE;
}
/**
* Get the rich object data of a resource
*
* @param IResource $resource
* @return array
* @throws \OCP\AppFramework\Db\DoesNotExistException
* @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException
* @since 16.0.0
*/
public function getResourceRichObject(IResource $resource): array {
$board = $this->getBoard($resource);
$link = \OC::$server->getURLGenerator()->linkToRoute('deck.page.index') . '#!/board/' . $resource->getId();
return [
'type' => self::RESOURCE_TYPE,
'id' => $resource->getId(),
'name' => $board->getTitle(),
'link' => $link,
'iconUrl' => \OC::$server->getURLGenerator()->imagePath('deck', 'deck-dark.svg')
];
}
/**
* Can a user/guest access the collection
*
* @param IResource $resource
* @param IUser|null $user
* @return bool
* @since 16.0.0
*/
public function canAccessResource(IResource $resource, ?IUser $user): bool {
if ($resource->getType() !== self::RESOURCE_TYPE || !$user instanceof IUser) {
return false;
}
$board = $this->getBoard($resource);
if ($board === null) {
return false;
}
if ($board->getOwner() === $user->getUID()) {
return true;
}
return $this->permissionService->userCan($board->getAcl(), Acl::PERMISSION_READ, $user->getUID());
}
private function getBoard(IResource $resource) {
try {
return $this->boardMapper->find($resource->getId(), false, true);
} catch (DoesNotExistException $e) {
} catch (MultipleObjectsReturnedException $e) {
return null;
}
}
public function invalidateAccessCache($boardId = null) {
try {
/** @var IManager $resourceManager */
$resourceManager = \OC::$server->query(IManager::class);
} catch (QueryException $e) {
}
if ($boardId !== null) {
$resource = $resourceManager->getResourceForUser(self::RESOURCE_TYPE, (string)$boardId, null);
$resourceManager->invalidateAccessCacheForResource($resource);
} else {
$resourceManager->invalidateAccessCacheForProvider($this);
}
}
}

View File

@@ -25,6 +25,7 @@ namespace OCA\Deck\Service;
use OCA\Deck\Activity\ActivityManager;
use OCA\Deck\Activity\ChangeSet;
use OCA\Deck\Collaboration\Resources\ResourceProvider;
use OCA\Deck\Db\Acl;
use OCA\Deck\Db\AclMapper;
use OCA\Deck\Db\AssignedUsersMapper;
@@ -59,6 +60,7 @@ class BoardService {
private $userId;
private $activityManager;
private $changeHelper;
private $resourceProvider;
public function __construct(
BoardMapper $boardMapper,
@@ -73,6 +75,7 @@ class BoardService {
IGroupManager $groupManager,
ActivityManager $activityManager,
ChangeHelper $changeHelper,
ResourceProvider $resourceProvider,
$userId
) {
$this->boardMapper = $boardMapper;
@@ -87,6 +90,7 @@ class BoardService {
$this->groupManager = $groupManager;
$this->activityManager = $activityManager;
$this->changeHelper = $changeHelper;
$this->resourceProvider = $resourceProvider;
$this->userId = $userId;
}
@@ -459,6 +463,7 @@ class BoardService {
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_BOARD, $newAcl, ActivityManager::SUBJECT_BOARD_SHARE);
$this->boardMapper->mapAcl($newAcl);
$this->changeHelper->boardChanged($boardId);
$this->resourceProvider->invalidateAccessCache($boardId);
return $newAcl;
}
@@ -529,6 +534,7 @@ class BoardService {
}
$this->activityManager->triggerEvent(ActivityManager::DECK_OBJECT_BOARD, $acl, ActivityManager::SUBJECT_BOARD_UNSHARE);
$this->changeHelper->boardChanged($acl->getBoardId());
$this->resourceProvider->invalidateAccessCache($acl->getBoardId());
return $this->aclMapper->delete($acl);
}

View File

@@ -127,7 +127,7 @@ class PermissionService {
* @return bool
* @throws NoPermissionException
*/
public function checkPermission($mapper, $id, $permission) {
public function checkPermission($mapper, $id, $permission, $userId = null) {
$boardId = $id;
if ($mapper instanceof IPermissionMapper) {
$boardId = $mapper->findBoardId($id);
@@ -141,12 +141,12 @@ class PermissionService {
return false;
}
if ($this->userIsBoardOwner($boardId)) {
if ($this->userIsBoardOwner($boardId, $userId)) {
return true;
}
$acls = $this->aclMapper->findAll($boardId);
$result = $this->userCan($acls, $permission);
$result = $this->userCan($acls, $permission, $userId);
if ($result) {
return true;
}
@@ -159,10 +159,13 @@ class PermissionService {
* @param $boardId
* @return bool
*/
public function userIsBoardOwner($boardId) {
public function userIsBoardOwner($boardId, $userId = null) {
if ($userId === null) {
$userId = $this->userId;
}
try {
$board = $this->boardMapper->find($boardId);
return $board && $this->userId === $board->getOwner();
return $board && $userId === $board->getOwner();
} catch (DoesNotExistException $e) {
} catch (MultipleObjectsReturnedException $e) {
return false;
@@ -176,17 +179,20 @@ class PermissionService {
* @param $permission
* @return bool
*/
public function userCan(array $acls, $permission) {
public function userCan(array $acls, $permission, $userId = null) {
if ($userId === null) {
$userId = $this->userId;
}
// check for users
foreach ($acls as $acl) {
if ($acl->getType() === Acl::PERMISSION_TYPE_USER && $acl->getParticipant() === $this->userId) {
if ($acl->getType() === Acl::PERMISSION_TYPE_USER && $acl->getParticipant() === $userId) {
return $acl->getPermission($permission);
}
}
// check for groups
$hasGroupPermission = false;
foreach ($acls as $acl) {
if (!$hasGroupPermission && $acl->getType() === Acl::PERMISSION_TYPE_GROUP && $this->groupManager->isInGroup($this->userId, $acl->getParticipant())) {
if (!$hasGroupPermission && $acl->getType() === Acl::PERMISSION_TYPE_GROUP && $this->groupManager->isInGroup($userId, $acl->getParticipant())) {
$hasGroupPermission = $acl->getPermission($permission);
}
}

View File

@@ -32,8 +32,8 @@ Util::addStyle('activity', 'style');
Util::addStyle('comments', 'comments');
Util::addScript('oc-backbone-webdav');
Util::addStyle('deck', '../js/build/vendor');
Util::addScript('deck', 'build/vendor');
//Util::addStyle('deck', '../js/build/vendor');
//Util::addScript('deck', 'build/vendor');
Util::addStyle('deck', 'style');
Util::addScript('deck', 'build/deck');
@@ -41,6 +41,7 @@ Util::addScript('deck', 'build/deck');
if (\OC_Util::getVersion()[0] < 14) {
Util::addStyle('deck', 'comp-13');
}
\OC::$server->getEventDispatcher()->dispatch('\OCP\Collaboration\Resources::loadAdditionalScripts');
?>
<div

View File

@@ -34,7 +34,7 @@
{{ sharee.participant.displayname }} (<?php p($l->t('Group')); ?>)
</span>
<span class="has-tooltip username" ng-if="sharee.type==OC.Share.SHARE_TYPE_USER">
{{ sharee.participant.displayname }}
{{ sharee.participant.displayname }}
</span>
</ui-select-choices>
<ui-select-no-choice>
@@ -82,6 +82,8 @@
<?php p($l->t('Sharing has been disabled for your account.')); ?>
</li>
</ul>
<h1>Collections</h1>
<div id="collaborationResources"></div>
</div>
<div id="board-detail-labels" class="tab commentsTabView" ng-if="params.tab==1">