Merge branch 'master' into loginLinkPublicVote

This commit is contained in:
René Gieling 2020-03-02 18:37:35 +01:00 коммит произвёл GitHub
Родитель 3a6e8b1c02 882067f893
Коммит c3787d71e0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
19 изменённых файлов: 228 добавлений и 263 удалений

Просмотреть файл

@ -1,9 +1,10 @@
module.exports = {
plugins: ['@babel/plugin-syntax-dynamic-import'],
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: 3,
targets: {
browsers: ['last 2 versions', 'ie >= 11']
}
@ -11,4 +12,3 @@ module.exports = {
]
]
}

Просмотреть файл

@ -3,9 +3,8 @@ module.exports = {
env: {
browser: true,
es6: true,
'nextcloud/nextcloud': true,
node: true,
jest: true
jest: true,
},
globals: {
t: true,
@ -14,32 +13,32 @@ module.exports = {
OCA: true,
Vue: true,
VueRouter: true,
moment:true
moment:true,
},
parserOptions: {
parser: 'babel-eslint',
ecmaVersion: 6
ecmaVersion: 6,
},
extends: [
'plugin:@nextcloud/recommended',
'eslint:recommended',
'plugin:nextcloud/recommended',
'plugin:node/recommended',
'plugin:vue/essential',
'plugin:vue/recommended',
'standard'
'standard',
],
plugins: [
'vue',
'node',
'nextcloud'
],
rules: {
"@nextcloud/no-deprecations": "warn",
"@nextcloud/no-removed-apis": "error",
'node/no-missing-import': ['error', {
'allowModules': [],
'tryExtensions': ['.js', '.vue']
}],
'nextcloud/no-deprecations': 'warn',
'nextcloud/no-removed-apis': 'error',
// 'comma-dangle': ['error', 'always-multiline'],
// space before function ()
'space-before-function-paren': ['error', 'never'],
// curly braces always space

Просмотреть файл

@ -45,6 +45,7 @@ return [
['name' => 'vote#get', 'url' => '/votes/get/{pollId}', 'verb' => 'GET'],
['name' => 'vote#set', 'url' => '/vote/set/', 'verb' => 'POST'],
['name' => 'vote#write', 'url' => '/vote/write/', 'verb' => 'POST'],
['name' => 'vote#delete', 'url' => '/votes/delete/', 'verb' => 'POST'],
['name' => 'option#get', 'url' => '/options/get/{pollId}', 'verb' => 'GET'],
['name' => 'option#add', 'url' => '/option/add/', 'verb' => 'POST'],

Просмотреть файл

@ -74,8 +74,10 @@ OC.L10N.register(
"Configuration" : "Configuratie",
"Options" : "Opties",
"Shares" : "Shares",
"As an admin you may edit this poll" : "Als beheerder mag je de peiling bewerken",
"Description" : "Beschrijving",
"Poll configurations" : "Peilingconfiguratie",
"Allow admins to edit this poll" : "Sta beheerders toe de peiling te bewerken",
"Allow \"maybe\" vote" : "Sta een Misschien stem toe",
"Anonymous poll" : "Anonieme peiling",
"Expiration date" : "Vervaldatum",
@ -89,6 +91,7 @@ OC.L10N.register(
"Available Options" : "Beschikbare opties",
"Delete option" : "Verwijder optie",
"Week" : "Week",
"Minute" : "Minuut",
"Hour" : "Uur",
"Day" : "Dag",
"Month" : "Maand",
@ -98,6 +101,8 @@ OC.L10N.register(
"Enter option text" : "Voer een optietekst in",
"Invitations" : "Uitnodigingen",
"Invited users will get informed immediately via eMail!" : "Uitgenodigde gebruikers worden onmiddellijk op de hoogte gebracht via e-mail!",
"Copy link to clipboard" : "Kopiëren link naar klembord",
"Remove share" : "Verwijderen share",
"Public shares" : "Openbare deellinks",
"Public link (" : "Openbare link (",
"Add a public link" : "Toevoegen openbare link",
@ -109,7 +114,9 @@ OC.L10N.register(
"Error while adding share" : "Fout bij toevoegen deellink",
"Receive notification email on activity" : "Ontvang email melding bij activiteit",
"Your personal link to this poll: %n" : "Je persoonlijke link naar deze peiling: %n",
"Enter your name" : "Geef je naam in",
"Enter your name!" : "Geef je naam op!",
"To participate, you need to enter a valid username with at least 3 characters. " : "Om mee te doen, moet je een geldige gebruikersnaam hebben van minimaal 3 tekens.",
"Enter your name" : "Geef je naam op",
"Username is not valid. Please enter at least 3 characters." : "Gebruikersnaam is niet geldig. Gebruik aub. minstens 3 tekens.",
"This username is not valid, i.e. because it is already in use." : "Gebruikersnaam is niet geldig, want deze is reeds in gebruik.",
"OK" : "OK",
@ -117,9 +124,12 @@ OC.L10N.register(
"This username can not be chosen." : "Deze gebruikersnaam kan niet worden gekozen.",
"Error saving username" : "Fout bij opslaan gebruikersnaam",
"The poll does not exist" : "De peiling bestaat niet",
"Enter a poll or start a new one." : "Doe mee met een peiling of start een nieuwe.",
"Goto Nextcloud" : "Ga naar Nextcloud",
"Switch view" : "Omschakelen weergave",
"Toggle Sidebar" : "Omschakelen Zijbalk",
"There are no vote options, add some in the options section of the right side bar." : "Er zijn geen peilingsopties, voeg een paar toe in de opties sectie in de rechter zijbalk.",
"There are no vote options. Maybe the owner did not provide some until now." : "Er zijn geen peilingsopties. Misschien heeft de eigenaar nog geen opties toegevoegd.",
"Public access" : "Openbare toegang",
"Hidden poll" : "Verborgen peiling",
"Error deleting poll." : "Fout bij verwijderen peiling.",

Просмотреть файл

@ -72,8 +72,10 @@
"Configuration" : "Configuratie",
"Options" : "Opties",
"Shares" : "Shares",
"As an admin you may edit this poll" : "Als beheerder mag je de peiling bewerken",
"Description" : "Beschrijving",
"Poll configurations" : "Peilingconfiguratie",
"Allow admins to edit this poll" : "Sta beheerders toe de peiling te bewerken",
"Allow \"maybe\" vote" : "Sta een Misschien stem toe",
"Anonymous poll" : "Anonieme peiling",
"Expiration date" : "Vervaldatum",
@ -87,6 +89,7 @@
"Available Options" : "Beschikbare opties",
"Delete option" : "Verwijder optie",
"Week" : "Week",
"Minute" : "Minuut",
"Hour" : "Uur",
"Day" : "Dag",
"Month" : "Maand",
@ -96,6 +99,8 @@
"Enter option text" : "Voer een optietekst in",
"Invitations" : "Uitnodigingen",
"Invited users will get informed immediately via eMail!" : "Uitgenodigde gebruikers worden onmiddellijk op de hoogte gebracht via e-mail!",
"Copy link to clipboard" : "Kopiëren link naar klembord",
"Remove share" : "Verwijderen share",
"Public shares" : "Openbare deellinks",
"Public link (" : "Openbare link (",
"Add a public link" : "Toevoegen openbare link",
@ -107,7 +112,9 @@
"Error while adding share" : "Fout bij toevoegen deellink",
"Receive notification email on activity" : "Ontvang email melding bij activiteit",
"Your personal link to this poll: %n" : "Je persoonlijke link naar deze peiling: %n",
"Enter your name" : "Geef je naam in",
"Enter your name!" : "Geef je naam op!",
"To participate, you need to enter a valid username with at least 3 characters. " : "Om mee te doen, moet je een geldige gebruikersnaam hebben van minimaal 3 tekens.",
"Enter your name" : "Geef je naam op",
"Username is not valid. Please enter at least 3 characters." : "Gebruikersnaam is niet geldig. Gebruik aub. minstens 3 tekens.",
"This username is not valid, i.e. because it is already in use." : "Gebruikersnaam is niet geldig, want deze is reeds in gebruik.",
"OK" : "OK",
@ -115,9 +122,12 @@
"This username can not be chosen." : "Deze gebruikersnaam kan niet worden gekozen.",
"Error saving username" : "Fout bij opslaan gebruikersnaam",
"The poll does not exist" : "De peiling bestaat niet",
"Enter a poll or start a new one." : "Doe mee met een peiling of start een nieuwe.",
"Goto Nextcloud" : "Ga naar Nextcloud",
"Switch view" : "Omschakelen weergave",
"Toggle Sidebar" : "Omschakelen Zijbalk",
"There are no vote options, add some in the options section of the right side bar." : "Er zijn geen peilingsopties, voeg een paar toe in de opties sectie in de rechter zijbalk.",
"There are no vote options. Maybe the owner did not provide some until now." : "Er zijn geen peilingsopties. Misschien heeft de eigenaar nog geen opties toegevoegd.",
"Public access" : "Openbare toegang",
"Hidden poll" : "Verborgen peiling",
"Error deleting poll." : "Fout bij verwijderen peiling.",

Просмотреть файл

@ -135,6 +135,7 @@ class VoteController extends Controller {
*/
public function set($pollId, $option, $userId, $setTo) {
$this->logger->alert('Deleting vote no. ' . $option);
try {
$vote = $this->mapper->findSingleVote($pollId, $option['pollOptionText'], $userId);
$vote->setVoteAnswer($setTo);
@ -158,6 +159,39 @@ class VoteController extends Controller {
}
}
/**
* delete
* @NoAdminRequired
* @param integer $voteId
* @param string $userId
* @param integer $pollId
* @return DataResponse
*/
public function delete($voteId = 0, $userId = '', $pollId = 0) {
$this->logger->alert('Deleting vote no. ' . $voteId);
try {
if ($voteId) {
$vote = $this->mapper->delete($voteId);
$this->logger->alert('Deleting vote no. ' . $voteId);
return new DataResponse(null, Http::STATUS_OK);
} elseif ($pollId && $userId) {
$votes = $this->mapper->deleteByPollAndUser($pollId, $userId);
$this->logger->alert('Deleting votes from ' . $userId . ' in poll ' . $pollId);
return new DataResponse(null, Http::STATUS_OK);
} elseif ($pollId) {
$votes = $this->mapper->deleteByPoll($pollId);
$this->logger->alert('Deleting all votes in poll ' . $pollId);
return new DataResponse(null, Http::STATUS_OK);
} else {
return DataResponse(null, Http::STATUS_NOT_FOUND);
}
} catch (DoesNotExistException $e) {
return DataResponse(null, Http::STATUS_NOT_FOUND);
}
}
/**
* Public functions
*/

Просмотреть файл

@ -388,26 +388,6 @@ class Acl implements JsonSerializable {
return $this;
}
/**
* @NoAdminRequired
* @return string
*/
public function getAccessLevel(): string {
if ($this->getIsOwner()) {
return 'owner';
} elseif ($this->poll->getAccess() === 'public') {
return 'public';
} elseif ($this->poll->getAccess() === 'registered' && \OC::$server->getUserSession()->getUser()->getUID() === $this->userId) {
return 'registered';
} elseif ($this->poll->getAccess() === 'hidden' && $this->getisOwner()) {
return 'hidden';
} elseif ($this->getIsAdmin()) {
return 'admin';
} else {
return 'none';
}
}
/**
* @return array
*/
@ -430,8 +410,7 @@ class Acl implements JsonSerializable {
'groupShare' => $this->getGroupShare(),
'personalShare' => $this->getPersonalShare(),
'publicShare' => $this->getPublicShare(),
'foundByToken' => $this->getFoundByToken(),
'accessLevel' => $this->getAccessLevel()
'foundByToken' => $this->getFoundByToken()
];
}
}

Просмотреть файл

@ -35,23 +35,14 @@
"stylelint:fix": "stylelint src --fix"
},
"dependencies": {
"@babel/runtime": "^7.8.3",
"@nextcloud/axios": "^1.3.1",
"@nextcloud/router": "^1.0.0",
"@nextcloud/vue": "^1.3.0",
"acorn": "^7.1.0",
"acorn-jsx": "^5.1.0",
"babel-plugin-transform-async-to-generator": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-latest": "^6.24.1",
"fibers": "^4.0.2",
"core-js": "^3.6.4",
"lodash": "^4.17.15",
"moment": "^2.23.0",
"v-click-outside": "^3.0.0",
"v-tooltip": "^3.0.0-alpha.11",
"vue": "^2.6.11",
"vue-click-outside": "^1.0.7",
"vue-clipboard2": "^0.3.1",
"vue-router": "^3.1.5",
"vuedraggable": "^2.23.2",
@ -66,37 +57,33 @@
"node": ">=10.0.0"
},
"devDependencies": {
"@babel/core": "^7.8.3",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/preset-env": "^7.8.3",
"@babel/core": "^7.8.6",
"@babel/preset-env": "^7.8.6",
"@nextcloud/eslint-plugin": "^1.1.0",
"babel-eslint": "^10.0.2",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"babel-preset-env": "^1.7.0",
"cross-env": "^7.0.0",
"css-loader": "^3.4.2",
"eslint": "^6.8.0",
"eslint-config-standard": "^14.1.0",
"eslint-loader": "^3.0.3",
"eslint-plugin-import": "^2.20.0",
"eslint-plugin-nextcloud": "^0.3.0",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"eslint-plugin-vue": "^6.1.2",
"file-loader": "^5.0.2",
"node-sass": "^4.13.1",
"prettier-eslint": "^9.0.1",
"raw-loader": "^4.0.0",
"sass-loader": "^8.0.2",
"stylelint": "^13.2.0",
"stylelint-config-recommended-scss": "^4.2.0",
"stylelint-scss": "^3.14.2",
"vue-loader": "^15.7.2",
"vue-style-loader": "^4.1.1",
"vue-template-compiler": "^2.6.10",
"terser-webpack-plugin": "^2.3.5",
"vue-loader": "^15.9.0",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.6.11",
"webpack": "^4.41.5",
"webpack-cli": "^3.3.10",
"webpack-cli": "^3.3.11",
"webpack-merge": "^4.1.5"
}
}

Просмотреть файл

@ -25,7 +25,7 @@
<div v-if="description" class="description">
{{ description }}
</div>
<Avatar :disable-menu="true" :user="userId"
<Avatar :disable-menu="disableMenu" :menu-position="menuPosition" :user="userId"
:is-guest="!Boolean(OC.currentUser)"
:display-name="displayName"
@ -35,6 +35,7 @@
<div v-if="!hideNames" class="user-name">
{{ displayName }}
</div>
<slot />
</div>
</template>
@ -53,6 +54,14 @@ export default {
type: Boolean,
default: false
},
disableMenu: {
type: Boolean,
default: false
},
menuPosition: {
type: String,
default: 'left'
},
userId: {
type: String,
default: undefined

Просмотреть файл

@ -1,172 +0,0 @@
<!--
- @copyright Copyright (c) 2018 René Gieling <github@dartcafe.de>
-
- @author René Gieling <github@dartcafe.de>
-
- @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>
<h2> {{ t('polls', 'Share with') }}</h2>
<Multiselect id="ajax"
v-model="shares"
:options="users"
:multiple="true"
:user-select="true"
:tag-width="80"
:clear-on-select="false"
:preserve-search="true"
:options-limit="20"
:loading="isLoading"
:internal-search="false"
:searchable="true"
:preselect-first="true"
:placeholder="placeholder"
label="displayName"
track-by="user"
@search-change="loadUsersAsync"
@close="updateShares">
<template slot="selection" slot-scope="{ values, search, isOpen }">
<span v-if="values.length &amp;&amp; !isOpen" class="multiselect__single">
{{ values.length }} users selected
</span>
</template>
</Multiselect>
<TransitionGroup :css="false" tag="ul" class="shared-list">
<li v-for="(item, index) in sortedShares" :key="item.displayName" :data-index="index">
<UserDiv :user-id="item.user" :display-name="item.displayName" :type="item.type"
:hide-names="hideNames" />
<div class="options">
<a class="icon icon-delete svg delete-poll" @click="removeShare(index, item)" />
</div>
</li>
</TransitionGroup>
</div>
</template>
<script>
import { Multiselect } from '@nextcloud/vue'
export default {
name: 'ShareDiv',
components: {
Multiselect
},
props: {
placeholder: {
type: String,
default: ''
},
activeShares: {
type: Array,
default: function() {
return []
}
},
hideNames: {
type: Boolean,
default: false
}
},
data() {
return {
shares: [],
users: [],
isLoading: false,
siteUsersListOptions: {
getUsers: true,
getGroups: true,
query: ''
}
}
},
computed: {
sortedShares() {
return this.shares.slice(0).sort(this.sortByDisplayname)
}
},
watch: {
activeShares(value) {
this.shares = value.slice(0)
}
},
methods: {
removeShare(index, item) {
this.$emit('remove-share', item)
},
updateShares() {
this.$emit('update-shares', this.shares)
},
loadUsersAsync(query) {
this.isLoading = false
this.siteUsersListOptions.query = query
this.$http.post(OC.generateUrl('apps/polls/siteusers/get/'), this.siteUsersListOptions)
.then((response) => {
this.users = response.data.siteusers
this.isLoading = false
}, (error) => {
console.error(error.response)
})
},
sortByDisplayname(a, b) {
if (a.displayName.toLowerCase() < b.displayName.toLowerCase()) return -1
if (a.displayName.toLowerCase() > b.displayName.toLowerCase()) return 1
return 0
}
}
}
</script>
<style lang="scss">
.shared-list {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
padding-top: 8px;
> li {
display: flex;
}
}
.options {
display: flex;
position: relative;
top: -12px;
left: -13px;
}
.multiselect {
width: 100% !important;
max-width: 100% !important;
}
</style>

Просмотреть файл

@ -26,8 +26,7 @@
{{ t('polls', 'Your personal link to this poll: %n', 1, personalLink) }}
<a class="icon icon-clippy" @click="copyLink()" />
</div>
<Modal v-show="!isValidUser &!expired & modal" class="modal"
:can-close="false">
<Modal v-show="!isValidUser &!expired & modal" :can-close="false">
<div class="modal__content">
<h2>{{ t('polls', 'Enter your name!') }}</h2>
<p>{{ t('polls', 'To participate, you need to enter a valid username with at least 3 characters.') }}</p>

Просмотреть файл

@ -22,8 +22,8 @@
<template lang="html">
<div class="vote-table">
<div class="header">
<div class="sticky" />
<div class="vote-table__header">
<div class="vote-table__user-column" />
<VoteTableHeader v-for="(option) in sortedOptions"
:key="option.id"
@ -33,16 +33,37 @@
<div v-for="(participant) in participants" :key="participant.userId" :class="{currentuser: (participant.userId === currentUser) }">
<UserDiv :key="participant.userId"
class="sticky"
class="vote-table__user-column"
:disable-menu="true"
:class="{currentuser: (participant.userId === currentUser) }"
:user-id="participant.userId"
:display-name="participant.displayName" />
:display-name="participant.displayName">
<Actions v-if="acl.allowEdit" class="action">
<ActionButton icon="icon-delete"
@click="confirmDelete(participant.userId)">
{{ t('polls', 'Delete votes') }}
</ActionButton>
</Actions>
</UserDiv>
<VoteTableItem v-for="(option) in sortedOptions"
:key="option.id"
:user-id="participant.userId"
:option="option"
@voteClick="setVote(option, participant.userId)" />
</div>
<Modal v-if="modal">
<div class="modal__content">
<h2>{{ t('polls', 'Do you want to remove {username} from poll?', { username: userToRemove }) }}</h2>
<div class="modal__buttons">
<ButtonDiv :title="t('polls', 'No')"
@click="modal = false" />
<ButtonDiv :primary="true" :title="t('polls', 'Yes')"
@click="removeUser()" />
</div>
</div>
</Modal>
</div>
</template>
@ -50,14 +71,25 @@
import VoteTableItem from './VoteTableItem'
import VoteTableHeader from './VoteTableHeader'
import { mapState, mapGetters } from 'vuex'
import { Actions, ActionButton, Modal } from '@nextcloud/vue'
export default {
name: 'VoteTable',
components: {
Actions,
ActionButton,
Modal,
VoteTableHeader,
VoteTableItem
},
data() {
return {
modal: false,
userToRemove: ''
}
},
computed: {
...mapState({
poll: state => state.poll,
@ -75,6 +107,19 @@ export default {
},
methods: {
removeUser() {
this.$store.dispatch('deleteVotes', {
userId: this.userToRemove
})
this.modal = false
this.userToRemove = ''
},
confirmDelete(userId) {
this.userToRemove = userId
this.modal = true
},
setVote(option, userId) {
this.$store
.dispatch('setVoteAsync', {
@ -94,16 +139,34 @@ export default {
</script>
<style lang="scss" scoped>
.user-row.sticky,
.header > .sticky {
.user-row.vote-table__user-column,
.vote-table__header > .vote-table__user-column {
position: sticky;
left: 0;
background-color: var(--color-main-background);
width: 170px;
width: 230px;
flex: 0 0 auto;
}
.header {
.modal__content {
padding: 14px;
display: flex;
flex-direction: column;
color: var(--color-main-text);
input {
width: 100%;
}
}
.modal__buttons {
display: flex;
justify-content: end;
.button {
margin-left: 10px;
margin-right: 0;
}
}
.vote-table__header {
height: 150px;
}
@ -139,7 +202,7 @@ export default {
flex: 1;
}
&.header {
&.vote-table__header {
order: 1;
}
@ -172,12 +235,6 @@ export default {
margin: 0;
}
// &.currentuser {
// display: flex;
// > .user-row.currentuser {
// display: none;
// }
// }
}
&> .currentuser {
@ -188,7 +245,7 @@ export default {
}
}
&> .header, {
&> .vote-table__header, {
height: initial;
padding-left: initial;
display: flex;

Просмотреть файл

@ -36,7 +36,6 @@ import { Tooltip } from '@nextcloud/vue'
import UserDiv from './components/Base/UserDiv'
import ButtonDiv from './components/Base/ButtonDiv'
import LoadingOverlay from './components/Base/LoadingOverlay'
/* eslint-disable-next-line camelcase, no-undef */
__webpack_nonce__ = btoa(OC.requestToken)
@ -57,7 +56,6 @@ Vue.prototype.OCA = OCA
Vue.component('UserDiv', UserDiv)
Vue.component('ButtonDiv', ButtonDiv)
Vue.component('LoadingOverlay', LoadingOverlay)
Vue.directive('tooltip', Tooltip)
Vue.use(ClickOutside)

Просмотреть файл

@ -67,13 +67,13 @@ const getters = {
return (state.expire > 0 && moment.unix(state.expire).diff() < 0)
},
accessType: (state, getters, rootState) => {
if (rootState.acl.accessLevel === 'public') {
accessType: (state) => {
if (state.access === 'public') {
return t('polls', 'Public access')
} else if (rootState.acl.accessLevel === 'hidden') {
} else if (state.access === 'hidden') {
return t('polls', 'Hidden poll')
} else {
return rootState.acl.accessLevel
return state.access
}
},

Просмотреть файл

@ -40,6 +40,10 @@ const mutations = {
Object.assign(state, payload)
},
deleteVotes(state, payload) {
state.list = state.list.filter(vote => vote.userId !== payload.userId)
},
setVote(state, payload) {
const index = state.list.findIndex(vote =>
parseInt(vote.pollId) === payload.pollId
@ -172,6 +176,22 @@ const actions = {
})
},
deleteVotes(context, payload) {
const endPoint = 'apps/polls/votes/delete/'
return axios.post(OC.generateUrl(endPoint), {
pollId: context.rootState.poll.id,
voteId: 0,
userId: payload.userId
})
.then(() => {
context.commit('deleteVotes', payload)
OC.Notification.showTemporary(t('polls', 'User {userId} removed', payload), { type: 'success' })
}, (error) => {
console.error('Error deleting votes', { error: error.response }, { payload: payload })
throw error
})
},
setVoteAsync(context, payload) {
let endPoint = 'apps/polls/vote/set/'

Просмотреть файл

@ -51,12 +51,14 @@ import { AppContent } from '@nextcloud/vue'
import PollListItem from '../components/PollList/PollListItem'
import { mapGetters } from 'vuex'
import sortBy from 'lodash/sortBy'
import LoadingOverlay from '../components/Base/LoadingOverlay'
export default {
name: 'PollList',
components: {
AppContent,
LoadingOverlay,
PollListItem
},

Просмотреть файл

@ -11,12 +11,15 @@ module.exports = {
},
module: {
rules: [
// {
// enforce: 'pre',
// test: /\.(js|vue)$/,
// loader: 'eslint-loader',
// exclude: /node_modules/
// },
{
enforce: 'pre',
test: /\.(js|vue)$/,
loader: 'eslint-loader',
exclude: /node_modules/,
options: {
quiet: true
}
},
{
test: /\.css$/,
use: [
@ -34,7 +37,12 @@ module.exports = {
},
{
test: /\.vue$/,
loader: 'vue-loader'
loader: 'vue-loader',
options: {
compilerOptions: {
whitespace: 'condense'
}
}
},
{
test: /\.js$/,

Просмотреть файл

@ -1,12 +1,25 @@
const merge = require('webpack-merge')
const common = require('./webpack.common.js')
const TerserPlugin = require('terser-webpack-plugin')
module.exports = merge(common, {
mode: 'development',
devtool: 'source-map',
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
devtool: 'source-map'
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
cache: true,
extractComments: false,
terserOptions: {
ecma: 6
}
})
]
}
})

Просмотреть файл

@ -1,7 +1,18 @@
const merge = require('webpack-merge')
const common = require('./webpack.common.js')
const TerserPlugin = require('terser-webpack-plugin')
module.exports = merge(common, {
mode: 'production',
devtool: 'source-map'
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
cache: true,
terserOptions: {
ecma: 6
}
})
]
}
})