This commit is contained in:
dartcafe 2018-10-14 13:55:51 +02:00
Родитель cfcd1a054f
Коммит 541612d271
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: CCE73CEF3035D3C8
7 изменённых файлов: 298 добавлений и 250 удалений

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@ -116,7 +116,9 @@ class ApiController extends Controller {
'id' => $user->getUID(),
'type' => 'user',
'displayName' => $user->getDisplayName(),
'avatarURL' => ''
'avatarURL' => '',
'lastLogin' => $user->getLastLogin(),
'cloudId' => $user->getCloudId()
];
}
}

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

@ -23,7 +23,7 @@
"axios": "^0.17.1",
"lodash": "^4.17.11",
"moment": "^2.22.1",
"nextcloud-vue": "^0.1.5",
"nextcloud-vue": "^0.2.0",
"velocity-animate": "^1.5.1",
"vue": "^2.5.16",
"vue-js-modal": "^1.3.26"

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

@ -83,7 +83,6 @@
<div class="header">
<div class="pollInformation flex-column">
<user-div :description="t('polls', 'Owner')" :user-id="poll.event.owner"></user-div>
<cloud-div v-bind:options="poll.event"></cloud-div>
</div>
</div>
@ -95,7 +94,7 @@
<div>
<div class="flex-wrap align-centered space-between" v-if="protect">
<span>{{ t('polls', 'Configuration is locked. Changing options may result in unwanted behaviour,but you can unlock it anyway.') }}</span>
<span>{{ t('polls', 'Configuration is locked. Changing options may result in unwanted behaviour, but you can unlock it anyway.') }}</span>
<button @click="protect=false" > {{ t('polls', 'Unlock configuration ') }} </button>
</div>
<div id="configurationsTabView" class="tab configurationsTabView flex-wrap">
@ -145,8 +144,7 @@
:placeholder="t('polls', 'Name of user or group')"
:active-shares="poll.shares"
v-show="poll.event.access === 'select'"
@add-share="addShare"
@remove-share="removeShare"/>
:shares="poll.shares"/>
</div>
</div>
</div>
@ -199,9 +197,8 @@
}
},
system:[],
lang: OC.getLanguage(),
locale: OC.getLocale(),
localeData: moment.localeData(moment.locale(OC.getLocale())),
lang: '',
locale: '',
placeholder: '',
newPollDate: '',
newPollTime: '',
@ -212,35 +209,27 @@
sidebar: false,
titleEmpty: false,
indexPage: '',
longDateFormat: moment.localeData().longDateFormat('L'),
dateTimeFormat: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
expirationDatePicker: {
editable: true,
minuteStep: 1,
type: 'datetime',
format: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
lang: OC.getLanguage().split("-")[0],
placeholder: t('polls', 'Expiration date')
},
optionDatePicker: {
editable: false,
minuteStep: 1,
type: 'datetime',
format: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
lang: OC.getLanguage().split("-")[0],
placeholder: t('polls', 'Click to add a date'),
timePickerOptions: {
start: '00:00',
step: '00:05',
end: '23:55'
}
}
longDateFormat: '',
dateTimeFormat: '',
}
},
created: function() {
this.indexPage = OC.generateUrl('apps/polls/');
this.getSystemValues();
this.lang = OC.getLanguage();
try {
this.locale = OC.getLocale();
} catch (e) {
if (e instanceof TypeError) {
this.locale = this.lang;
} else {
console.log(e)
}
}
moment.locale(this.locale);
this.longDateFormat = moment.localeData().longDateFormat('L');
this.dateTimeFormat = moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT');
var urlArray = window.location.pathname.split( '/' );
if (urlArray[urlArray.length - 1] === 'create') {
@ -258,7 +247,7 @@
computed: {
langShort: function () {
return OC.getLanguage().split("-")[0]
return this.lang.split("-")[0]
},
title: function() {
@ -276,8 +265,39 @@
} else {
return t('polls', 'Create new poll')
}
},
localeData: function () {
return moment.localeData(moment.locale(this.locale))
},
expirationDatePicker: function () {
return {
editable: true,
minuteStep: 1,
type: 'datetime',
lang: this.lang.split("-")[0],
format: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
placeholder: t('polls', 'Expiration date')
}
},
optionDatePicker: function () {
return {
editable: false,
minuteStep: 1,
type: 'datetime',
format: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
lang: this.lang.split("-")[0],
placeholder: t('polls', 'Click to add a date'),
timePickerOptions: {
start: '00:00',
step: '00:05',
end: '23:55'
}
}
}
},
watch: {
@ -312,12 +332,14 @@
},
addNewPollDate: function (newPollDate) {
this.newPollDate = moment(newPollDate);
this.poll.options.pollDates.push({
id: this.nextPollDateId++,
timestamp: moment(newPollDate).unix(),
});
this.poll.options.pollDates = _.sortBy(this.poll.options.pollDates, 'timestamp');
if (newPollDate != null) {
this.newPollDate = moment(newPollDate);
this.poll.options.pollDates.push({
id: this.nextPollDateId++,
timestamp: moment(newPollDate).unix(),
});
this.poll.options.pollDates = _.sortBy(this.poll.options.pollDates, 'timestamp');
}
},
addNewPollText: function () {
@ -378,6 +400,7 @@
}
</script>
<style lang="scss">
#content {
display: flex;
@ -491,10 +514,12 @@
border-bottom: 1px solid var(--color-border);
overflow: hidden;
white-space: nowrap;
&:hover, &:active {
transition: var(--background-dark) 0.3s ease;
background-color: var(--color-loading-light); //$hover-color;
}
> div {
display: flex;
flex-grow: 1;
@ -525,7 +550,10 @@
.autocomplete {
position: relative;
}
.configurationsTabView {
display: flex;
}
#share-list {
.user-list {
max-height: 180px;
@ -539,5 +567,4 @@
width: 99%;
}
}
</style>

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

@ -1,22 +1,18 @@
/* global Vue, oc_userconfig */
<template>
<div class="userRow">
<div v-show="description" class="description">{{description}}</div>
<div class="avatar">
<img :src="avatarURL" :width="size" :height="size">
</div>
<div v-show="nothidden" class="avatar imageplaceholderseed" :data-username="userId" :data-displayname="computedDisplayName" data-seed="Poll users 1">
{{ computedDisplayName.toUpperCase().substr(0,1) }}
</div>
<div class="user">{{ computedDisplayName }}</div>
<div class="user-row" :class="type">
<div v-show="description" class="description">{{description}}</div>
<div class="avatar"><img :src="avatarURL" :width="size" :height="size" :title="computedDisplayName"></div>
<div v-show="!onlyAvatar" class="user-name">{{ computedDisplayName }}</div>
</div>
<div class="avatar imageplaceholderseed"</div>
</template>
<script>
export default {
props: {
onlyAvatar: {
default: false
},
userId: {
type: String,
default: OC.getCurrentUser().uid
@ -81,36 +77,33 @@
}
</script>
<style scoped>
.userRow {
<style lang="scss">
.user-row {
display: flex;
flex-direction: row;
flex-grow: 1;
align-items: center;
margin-left: 0;
margin-top: 0;
}
.description {
opacity: 0.7;
margin-right: 4px;
}
.avatar {
height: 32px;
width: 32px;
}
.user {
margin-left: 8px;
opacity: 0.5;
flex-grow: 1;
}
.imageplaceholderseed {
height: 32px;
width: 32px;
background-color: rgb(185, 185, 185);
color: rgb(255, 255, 255);
font-weight: normal;
text-align: center;
line-height: 32px;
font-size: 17.6px;
> div {
margin: 0 4px 0 4px;
}
.description {
opacity: 0.7;
flex-grow: 0;
}
.avatar {
height: 32px;
width: 32px;
flex-grow: 0;
}
.user-name {
opacity: 0.5;
flex-grow: 1;
}
}
</style>

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

@ -1,36 +1,35 @@
<template>
<div>
<h2> {{ t('polls', 'Share with') }}</h2>
<div class="autocomplete">
<input class="shareWithField"
autocomplete="off"
type="text"
:placeholder="placeholder"
v-model="query"
@input="onInput"
@focus="onInput">
<transition-group v-show="openList" tag="ul" v-bind:css="false" class="user-list suggestion">
<li v-for="(item, index) in sortedSiteusers"
v-bind:key="item.displayName"
v-bind:data-index="index"
class="flex-row"
v-on:click="addShare(index, item)">
<user-div :user-id="item.id" :display-name="item.displayName" :type="item.type"></user-div>
</li>
</transition-group>
</div>
<multiselect
v-model="shares"
:options="users"
:option-height=32
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:preserve-search="true"
label="displayName"
track-by="id"
:preselect-first="true"
:placeholder="placeholder">
<template slot="selection" slot-scope="{ values, search, isOpen }">
<span class="multiselect__single" v-if="values.length &amp;&amp; !isOpen">
{{ values.length }} users selected
</span>
</template>
<template slot="option" slot-scope="props">
<div class="option__desc">
<user-div :user-id="props.option.id" :display-name="props.option.displayName" :type="props.option.type"></user-div>
</div>
</template>
</multiselect>
<transition-group tag="ul" v-bind:css="false" class="shared-list">
<li v-for="(item, index) in sortedShares"
v-bind:key="item.displayName"
v-bind:data-index="index"
class="flex-row">
<user-div :user-id="item.id" :display-name="item.displayName" :type="item.type"></user-div>
<div class="flex-row options">
<a @click="removeShare(index, item)" class="icon icon-delete svg delete-poll"></a>
</div>
v-bind:data-index="index">
<user-div :user-id="item.id" :display-name="item.displayName" :type="item.type" only-avatar="true"></user-div>
</li>
</transition-group>
</div>
@ -38,8 +37,13 @@
<script>
import axios from 'axios';
import { Multiselect } from 'nextcloud-vue';
export default {
components: {
Multiselect
},
props: {
placeholder: {
type: String
@ -52,14 +56,11 @@
data: function () {
return {
query: '',
shares: [],
users: [],
openList: false,
siteUsersLoaded: false,
siteUsersListOptions: {
getUsers: true,
getGroups: true,
skipUsers: [],
skipGroups: []
}
}
},
@ -68,54 +69,20 @@
this.loadSiteUsers();
},
mounted: function() {
document.addEventListener('click', this.handleClickOutside)
},
destroyed: function() {
document.removeEventListener('click', this.handleClickOutside)
},
computed: {
filteredSiteusers: function() {
var vm = this;
return this.users.filter(function (item) {
return item.displayName.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
})
},
sortedSiteusers: function() {
return this.filteredSiteusers.sort(this.sortByDisplayname);
},
sortedShares: function() {
return this.activeShares.sort(this.sortByDisplayname);
return this.shares.sort(this.sortByDisplayname);
}
},
methods: {
addShare: function (index, item){
this.$emit('add-share', item);
this.users.splice(this.users.indexOf(item), 1);
},
removeShare: function (index, item){
this.$emit('remove-share', item);
this.users.push(item);
},
loadSiteUsers: function () {
var vm = this;
vm.siteUsersListOptions.skipUsers = [];
vm.siteUsersListOptions.skipGroups = [];
this.activeShares.forEach(function(item) {
if (item.type === 'group') {
vm.siteUsersListOptions.skipGroups.push(item.id)
} else if (item.type === 'user') {
vm.siteUsersListOptions.skipUsers.push(item.id)
}
});
axios.post(OC.generateUrl('apps/polls/get/siteusers'), this.siteUsersListOptions)
.then((response) => {
this.users = response.data.siteusers;
@ -124,24 +91,75 @@
});
},
onInput: function() {
this.loadSiteUsers();
if (this.query !== '') {
this.openList = true;
}
},
sortByDisplayname: function (a, b) {
if (a.displayName.toLowerCase() < b.displayName.toLowerCase()) return -1;
if (a.displayName.toLowerCase() > b.displayName.toLowerCase()) return 1;
return 0;
},
}
handleClickOutside: function(evt) {
if (!this.$el.contains(evt.target)) {
this.openList = false;
}
}
}
}
</script>
<style lang="scss">
.shared-list {
display: flex;
padding-top: 8px;
flex-grow: 0;
justify-content: flex-start;
> li {
display: flex;
flex-grow: 0;
}
}
div, select {
&.multiselect:not(.multiselect-vue), &.multiselect:not(.multiselect-vue) {
max-width: unset;
}
}
.multiselect {
width: 100%;
.multiselect__content-wrapper li > span {
height: unset;
}
.option__desc {
flex-grow: 1;
}
.multiselect__option--highlight {
background: #41b883;
outline: none;
color: #fff;
&::after {
content: attr(data-select);
background: #41b883;
color: #fff;
}
}
.multiselect__option--selected {
&::after {
content: attr(data-selected);
color: silver;
}
&.multiselect__option--highlight {
background: #ff6a6a;
color: #fff;
&::after {
background: #ff6a6a;
content: attr(data-deselect);
color: #fff;
}
}
}
}
</style>

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

@ -98,11 +98,7 @@
$owner = $poll->getOwner();
$expiry_style = '';
if ($poll->getType() === 0) {
$participated = $_['participations'];
} else {
$participated = $_['participations_text'];
}
$participated = $_['votes'];
$participated_class = 'partic_no';
$participated_title = 'You did not vote';
$participated_count = count($participated);