Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/polls.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordartcafe <github@dartcafe.de>2019-12-10 09:32:58 +0300
committerdartcafe <github@dartcafe.de>2019-12-10 09:32:58 +0300
commit41930996829421bbf5e26aeb25c93d9214d35e9c (patch)
tree217e7fe3ed394256a324ed7bcbf81c89f0a0c19e /src/js/components/SideBar
parent7363c382904c6ea909010a4939e4ecd40dfdb5eb (diff)
- moved src back in right place
Diffstat (limited to 'src/js/components/SideBar')
-rw-r--r--src/js/components/SideBar/CommentAdd.vue99
-rw-r--r--src/js/components/SideBar/SideBar.vue109
-rw-r--r--src/js/components/SideBar/SideBarTabComments.vue98
-rw-r--r--src/js/components/SideBar/SideBarTabConfiguration.vue344
-rw-r--r--src/js/components/SideBar/SideBarTabDateOptions.vue173
-rw-r--r--src/js/components/SideBar/SideBarTabInformation.vue58
-rw-r--r--src/js/components/SideBar/SideBarTabShare.vue211
-rw-r--r--src/js/components/SideBar/SideBarTabTextOptions.vue164
8 files changed, 1256 insertions, 0 deletions
diff --git a/src/js/components/SideBar/CommentAdd.vue b/src/js/components/SideBar/CommentAdd.vue
new file mode 100644
index 00000000..2d7f054a
--- /dev/null
+++ b/src/js/components/SideBar/CommentAdd.vue
@@ -0,0 +1,99 @@
+<!--
+ - @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 lang="html">
+ <div class="newCommentRow comment new-comment">
+ <user-div :user-id="currentUser" />
+
+ <form class="commentAdd" name="send_comment">
+ <input v-model="comment" class="message" data-placeholder="New Comment ...">
+ <input v-show="!loading" class="submitComment icon-confirm" @click="writeComment">
+ <span v-show="loading" class="icon-loading-small" style="float:right;" />
+ </form>
+ </div>
+</template>
+
+<script>
+export default {
+ name: 'AddComment',
+ data() {
+ return {
+ comment: ''
+ }
+ },
+
+ computed: {
+ currentUser() {
+ return OC.getCurrentUser().uid
+ }
+ },
+
+ methods: {
+ writeComment() {
+ this.$store.dispatch('writeCommentPromise', this.comment)
+ .then(response => {
+ OC.Notification.showTemporary(t('polls', 'Your comment was added'), { type: 'success' })
+ })
+ .catch(error => {
+ this.writingVote = false
+ console.error('Error while saving comment - Error: ', error.response)
+ OC.Notification.showTemporary(t('polls', 'Error while saving comment'), { type: 'error' })
+ })
+
+ }
+ }
+}
+</script>
+
+<style lang="scss" scoped>
+ .comment {
+ margin-bottom: 30px;
+ }
+
+ .commentAdd {
+ display: flex;
+ }
+
+ .message {
+ margin-left: 40px;
+ flex: 1;
+ &:empty:before {
+ content: attr(data-placeholder);
+ color: grey;
+ }
+ }
+ .submitComment {
+ align-self: last baseline;
+ width: 30px;
+ margin: 0;
+ padding: 7px 9px;
+ background-color: transparent;
+ border: none;
+ opacity: 0.3;
+ cursor: pointer;
+ }
+
+ .icon-loading-small {
+ float: left;
+ margin-top: 10px;
+ }
+</style>
diff --git a/src/js/components/SideBar/SideBar.vue b/src/js/components/SideBar/SideBar.vue
new file mode 100644
index 00000000..30931f01
--- /dev/null
+++ b/src/js/components/SideBar/SideBar.vue
@@ -0,0 +1,109 @@
+<!--
+ - @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>
+ <AppSidebar :active="initialTab" :title="t('polls', 'Details')" @close="$emit('closeSideBar')">
+ <UserDiv slot="primary-actions" :user-id="event.owner" :description="t('polls', 'Owner')" />
+
+ <AppSidebarTab :name="t('polls', 'Comments')" icon="icon-comment">
+ <SideBarTabComments />
+ </AppSidebarTab>
+
+ <AppSidebarTab v-if="acl.allowEdit && event.type === 'datePoll'" :name="t('polls', 'Date options')" icon="icon-calendar">
+ <SideBarTabDateOptions />
+ </AppSidebarTab>
+
+ <AppSidebarTab v-if="acl.allowEdit && event.type === 'textPoll'" :name="t('polls', 'Text options')" icon="icon-toggle-filelist">
+ <SideBarTabTextOptions />
+ </AppSidebarTab>
+
+ <AppSidebarTab v-if="acl.allowEdit" :name="t('polls', 'Configuration')" icon="icon-settings">
+ <SideBarTabConfiguration @deletePoll="$emit('deletePoll')" />
+ </AppSidebarTab>
+
+ <AppSidebarTab v-if="acl.allowEdit" :name="t('polls', 'Shares')" icon="icon-share">
+ <SideBarTabShare />
+ </AppSidebarTab>
+ </AppSidebar>
+</template>
+
+<script>
+import { AppSidebar, AppSidebarTab } from '@nextcloud/vue'
+
+import SideBarTabConfiguration from './SideBarTabConfiguration'
+import SideBarTabDateOptions from './SideBarTabDateOptions'
+import SideBarTabTextOptions from './SideBarTabTextOptions'
+import SideBarTabComments from './SideBarTabComments'
+import SideBarTabShare from './SideBarTabShare'
+import { mapState } from 'vuex'
+
+export default {
+ name: 'SideBar',
+ components: {
+ SideBarTabConfiguration,
+ SideBarTabComments,
+ SideBarTabDateOptions,
+ SideBarTabTextOptions,
+ SideBarTabShare,
+ AppSidebar,
+ AppSidebarTab
+ },
+
+ data() {
+ return {
+ initialTab: 'comments'
+ }
+ },
+
+ computed: {
+ ...mapState({
+ event: state => state.event,
+ acl: state => state.acl
+ })
+ }
+
+}
+
+</script>
+
+<style scoped lang="scss">
+
+ ul {
+ & > li {
+ margin-bottom: 30px;
+ & > .comment-item {
+ display: flex;
+ align-items: center;
+
+ & > .date {
+ right: 0;
+ top: 5px;
+ opacity: 0.5;
+ }
+ }
+ & > .message {
+ margin-left: 44px;
+ flex: 1 1;
+ }
+ }
+ }
+</style>
diff --git a/src/js/components/SideBar/SideBarTabComments.vue b/src/js/components/SideBar/SideBarTabComments.vue
new file mode 100644
index 00000000..1d4c9fb4
--- /dev/null
+++ b/src/js/components/SideBar/SideBarTabComments.vue
@@ -0,0 +1,98 @@
+<!--
+ - @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>
+ <CommentAdd />
+ <transition-group v-if="countComments" name="fade" class="comments"
+ tag="ul">
+ <li v-for="(comment) in sortedComments" :key="comment.id">
+ <div class="comment-item">
+ <user-div :user-id="comment.userId" />
+ <div class="date">
+ {{ realtiveDate(comment.date) }}
+ </div>
+ </div>
+ <div class="message wordwrap comment-content">
+ {{ comment.comment }}
+ </div>
+ </li>
+ </transition-group>
+ <div v-else class="emptycontent">
+ <div class="icon-comment" />
+ <p> {{ t('polls', 'No comments yet. Be the first.') }}</p>
+ </div>
+ </div>
+</template>
+
+<script>
+import moment from 'moment'
+import CommentAdd from './CommentAdd'
+import { mapState, mapGetters } from 'vuex'
+
+export default {
+ name: 'SideBarTabComments',
+ components: {
+ CommentAdd
+ },
+
+ computed: {
+ ...mapState({
+ comments: state => state.comments
+ }),
+ ...mapGetters([
+ 'countComments',
+ 'sortedComments'
+ ])
+ },
+
+ methods: {
+ realtiveDate(date) {
+ return t('core', moment.utc(date).fromNow())
+ }
+
+ }
+}
+</script>
+
+<style scoped lang="scss">
+
+ ul {
+ & > li {
+ margin-bottom: 30px;
+ & > .comment-item {
+ display: flex;
+ align-items: center;
+
+ & > .date {
+ right: 0;
+ top: 5px;
+ opacity: 0.5;
+ }
+ }
+ & > .message {
+ margin-left: 44px;
+ flex: 1 1;
+ }
+ }
+ }
+</style>
diff --git a/src/js/components/SideBar/SideBarTabConfiguration.vue b/src/js/components/SideBar/SideBarTabConfiguration.vue
new file mode 100644
index 00000000..1e135af1
--- /dev/null
+++ b/src/js/components/SideBar/SideBarTabConfiguration.vue
@@ -0,0 +1,344 @@
+<!--
+ - @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>
+ <div class="configBox">
+ <label v-if="writingPoll" class="icon-loading-small title">
+ {{ t('polls', 'Saving') }}
+ </label>
+ <label v-else class="icon-checkmark title">
+ {{ t('polls', 'Saved') }}
+ </label>
+ </div>
+
+ <div v-if="acl.allowEdit" class="configBox">
+ <label class="icon-sound title">
+ {{ t('polls', 'Title') }}
+ </label>
+ <input v-model="eventTitle" :class="{ error: titleEmpty }" type="text">
+ </div>
+
+ <div v-if="acl.allowEdit" class="configBox">
+ <label class="icon-edit title">
+ {{ t('polls', 'Description') }}
+ </label>
+ <textarea v-model="eventDescription" />
+ <!-- <textarea v-if="acl.allowEdit" :value="event.description" @input="updateDescription" /> -->
+ </div>
+
+ <div class="configBox">
+ <label class="title icon-category-customization">
+ {{ t('polls', 'Poll configurations') }}
+ </label>
+
+ <input id="allowMaybe"
+ v-model="eventAllowMaybe"
+ :disabled="!acl.allowEdit"
+ type="checkbox"
+ class="checkbox">
+ <label for="allowMaybe" class="title">
+ {{ t('polls', 'Allow "maybe" vote') }}
+ </label>
+
+ <input id="anonymous" v-model="eventIsAnonymous"
+ :disabled="!acl.allowEdit"
+ type="checkbox"
+ class="checkbox">
+ <label for="anonymous" class="title">
+ {{ t('polls', 'Anonymous poll') }}
+ </label>
+
+ <input v-show="event.isAnonymous"
+ id="trueAnonymous"
+ v-model="eventFullAnonymous"
+ :disabled="!acl.allowEdit"
+ type="checkbox"
+ class="checkbox">
+ <label v-show="event.isAnonymous" class="title" for="trueAnonymous">
+ {{ t('polls', 'Hide user names for admin') }}
+ </label>
+
+ <input id="expiration"
+ v-model="eventExpiration"
+ :disabled="!acl.allowEdit"
+ type="checkbox"
+ class="checkbox">
+ <label class="title" for="expirtion">
+ {{ t('polls', 'Expires') }}
+ </label>
+
+ <date-picker v-show="event.expire"
+ v-model="eventExpiration"
+ v-bind="expirationDatePicker"
+ :disabled="!acl.allowEdit"
+ :time-picker-options="{ start: '00:00', step: '00:05', end: '23:55' }"
+ style="width:170px" />
+ </div>
+
+ <div class="configBox">
+ <label class="title icon-category-auth">
+ {{ t('polls', 'Access') }}
+ </label>
+
+ <input id="hidden"
+ v-model="eventAccess"
+ :disabled="!acl.allowEdit"
+ type="radio"
+ value="hidden"
+ class="radio">
+ <label for="hidden" class="title">
+ <div class="title icon-category-security" />
+ <span>{{ t('polls', 'Hidden to other users') }}</span>
+ </label>
+
+ <input id="public"
+ v-model="eventAccess"
+ :disabled="!acl.allowEdit"
+ type="radio"
+ value="public"
+ class="radio">
+ <label for="public" class="title">
+ <div class="title icon-link" />
+ <span>{{ t('polls', 'Visible to other users') }}</span>
+ </label>
+ </div>
+
+ <button class="button btn primary" @click="$emit('deletePoll')">
+ <span>{{ t('polls', 'Delete this poll') }}</span>
+ </button>
+ </div>
+</template>
+
+<script>
+import debounce from 'lodash/debounce'
+import { mapState, mapMutations, mapActions, mapGetters } from 'vuex'
+
+export default {
+ name: 'SideBarTab',
+
+ data() {
+ return {
+ writingPoll: false,
+ sidebar: false,
+ titleEmpty: false
+ }
+ },
+
+ computed: {
+ ...mapState({
+ event: state => state.event,
+ acl: state => state.acl
+ }),
+
+ ...mapGetters([
+ 'languageCodeShort'
+ ]),
+
+ // Add bindings
+ eventDescription: {
+ get() {
+ return this.event.description
+ },
+ set(value) {
+ this.writeValueDebounced({ 'description': value })
+ }
+ },
+
+ eventTitle: {
+ get() {
+ return this.event.title
+ },
+ set(value) {
+ this.writeValueDebounced({ 'title': value })
+ }
+ },
+
+ eventAccess: {
+ get() {
+ return this.event.access
+ },
+ set(value) {
+ this.writeValue({ 'access': value })
+ }
+ },
+
+ eventExpiration: {
+ get() {
+ return this.event.expire
+ },
+ set(value) {
+ this.writeValue({ 'expire': value })
+ }
+ },
+
+ eventFullAnonymous: {
+ get() {
+ return this.event.fullAnonymous
+ },
+ set(value) {
+ this.writeValue({ 'fullAnonymous': value })
+ }
+ },
+
+ eventIsAnonymous: {
+ get() {
+ return this.event.isAnonymous
+ },
+ set(value) {
+ this.writeValue({ 'isAnonymous': value })
+ }
+ },
+
+ eventAllowMaybe: {
+ get() {
+ return this.event.allowMaybe
+ },
+ set(value) {
+ this.writeValue({ 'allowMaybe': value })
+ }
+ },
+
+ // eventExpiration: {
+ // get() {
+ // return this.$store.state.event.expiration
+ // },
+ // set(value) {
+ // this.writeValue({ 'expiration': value })
+ // }
+ // },
+
+ expirationDatePicker() {
+ return {
+ editable: true,
+ minuteStep: 1,
+ type: 'datetime',
+ format: this.dateTimeFormat,
+ lang: this.langShort,
+ placeholder: t('polls', 'Expiration date'),
+ timePickerOptions: {
+ start: '00:00',
+ step: '00:30',
+ end: '23:30'
+ }
+ }
+ },
+
+ optionDatePicker() {
+ return {
+ editable: false,
+ minuteStep: 1,
+ type: 'datetime',
+ format: this.dateTimeFormat,
+ lang: this.languageCodeShort,
+ placeholder: t('polls', 'Click to add a date'),
+ timePickerOptions: {
+ start: '00:00',
+ step: '00:30',
+ end: '23:30'
+ }
+ }
+ },
+
+ protect: function() {
+ return this.poll.mode === 'vote'
+ },
+
+ saveButtonTitle: function() {
+ if (this.writingPoll) {
+ return t('polls', 'Writing poll')
+ } else if (this.acl.allowEdit) {
+ return t('polls', 'Update poll')
+ } else {
+ return t('polls', 'Create new poll')
+ }
+ }
+ },
+ methods: {
+
+ ...mapMutations([ 'setEventProperty' ]),
+ ...mapActions([ 'writeEventPromise' ]),
+
+ writeValueDebounced: debounce(function(e) {
+ this.writeValue(e)
+ }, 1500),
+
+ writeValue(e) {
+ this.$store.commit('setEventProperty', e)
+ this.writingPoll = true
+ this.writePoll()
+ },
+
+ writePoll() {
+ if (this.titleEmpty) {
+ OC.Notification.showTemporary(t('polls', 'Title must not be empty!'), { type: 'success' })
+ } else {
+ this.writeEventPromise()
+ this.writingPoll = false
+ OC.Notification.showTemporary(t('polls', '%n successfully saved', 1, this.event.title), { type: 'success' })
+ }
+ },
+
+ write() {
+ if (this.acl.allowEdit) {
+ this.writePoll()
+ }
+
+ }
+ }
+}
+</script>
+
+<style lang="scss">
+ .configBox {
+ display: flex;
+ flex-direction: column;
+ padding: 8px;
+ & > * {
+ padding-left: 21px;
+ }
+
+ & > input {
+ margin-left: 24px;
+ width: auto;
+
+ }
+
+ & > textarea {
+ margin-left: 24px;
+ width: auto;
+ padding: 7px 6px;
+ }
+
+ & > .title {
+ display: flex;
+ background-position: 0 2px;
+ padding-left: 24px;
+ opacity: 0.7;
+ font-weight: bold;
+ margin-bottom: 4px;
+ & > span {
+ padding-left: 4px;
+ }
+ }
+ }
+</style>
diff --git a/src/js/components/SideBar/SideBarTabDateOptions.vue b/src/js/components/SideBar/SideBarTabDateOptions.vue
new file mode 100644
index 00000000..c99b129b
--- /dev/null
+++ b/src/js/components/SideBar/SideBarTabDateOptions.vue
@@ -0,0 +1,173 @@
+<!--
+ - @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>
+ <div class="configBox">
+ <label class="title icon-calendar">
+ {{ t('polls', 'Add a date option') }}
+ </label>
+ <DatePicker v-bind="optionDatePicker" style="width:100%" confirm
+ @change="addOption($event)" />
+ </div>
+
+ <div class="configBox">
+ <label class="title icon-history">
+ {{ t('polls', 'Shift all date options') }}
+ </label>
+ <div>
+ <div class="selectUnit">
+ <input v-model="move.step">
+ <Multiselect v-model="move.unit" :options="move.units" />
+ </div>
+ </div>
+ <div>
+ <button class="button btn primary" @click="shiftDates(move)">
+ <span>{{ t('polls', 'Shift') }}</span>
+ </button>
+ </div>
+ </div>
+
+ <ul class="configBox poll-table">
+ <label class="title icon-calendar">
+ {{ t('polls', 'Available Options') }}
+ </label>
+ <DatePollItem v-for="(option) in sortedOptions"
+ :key="option.id"
+ :option="option"
+ @remove="removeOption(option)" />
+ </ul>
+ </div>
+</template>
+
+<script>
+import { Multiselect } from '@nextcloud/vue'
+import moment from 'moment'
+import { mapGetters, mapState } from 'vuex'
+import DatePollItem from '../Create/CreateDateItem'
+
+export default {
+ name: 'SideBarTabDateOptions',
+
+ components: {
+ Multiselect,
+ DatePollItem
+
+ },
+
+ data() {
+ return {
+ move: {
+ step: 1,
+ unit: 'week',
+ units: ['minute', 'hour', 'day', 'week', 'month', 'year']
+ }
+ }
+ },
+
+ computed: {
+ ...mapState({
+ options: state => state.options
+ }),
+
+ ...mapGetters([ 'languageCodeShort', 'sortedOptions' ]),
+
+ optionDatePicker() {
+ return {
+ editable: false,
+ minuteStep: 1,
+ type: 'datetime',
+ format: this.dateTimeFormat,
+ lang: this.languageCodeShort,
+ placeholder: t('polls', 'Click to add a date'),
+ timePickerOptions: {
+ start: '00:00',
+ step: '00:30',
+ end: '23:30'
+ }
+ }
+ }
+ },
+
+ methods: {
+
+ addOption(pollOptionText) {
+ this.$store.dispatch('addOptionAsync', { pollOptionText: pollOptionText })
+ },
+
+ shiftDates(payload) {
+ let store = this.$store
+ this.options.list.forEach(function(existingOption) {
+ let option = Object.assign({}, existingOption)
+ option.pollOptionText = moment(option.pollOptionText).add(payload.step, payload.unit).format('YYYY-MM-DD HH:mm:ss')
+ option.timestamp = moment.utc(option.pollOptionText).unix()
+ store.dispatch('updateOptionAsync', { option: option })
+ })
+ },
+
+ removeOption(option) {
+ this.$store.dispatch('removeOptionAsync', { option: option })
+ }
+
+ }
+
+}
+</script>
+
+<style lang="scss">
+ .configBox {
+ display: flex;
+ flex-direction: column;
+ padding: 8px;
+ & > * {
+ padding-left: 21px;
+ }
+
+ & > input {
+ margin-left: 24px;
+ width: auto;
+
+ }
+
+ & > textarea {
+ margin-left: 24px;
+ width: auto;
+ padding: 7px 6px;
+ }
+
+ & > .title {
+ display: flex;
+ background-position: 0 2px;
+ padding-left: 24px;
+ opacity: 0.7;
+ font-weight: bold;
+ margin-bottom: 4px;
+ & > span {
+ padding-left: 4px;
+ }
+ }
+ &.poll-table > li {
+ border-bottom-color: rgb(72, 72, 72);
+ margin-left: 18px;
+ }
+ }
+</style>
diff --git a/src/js/components/SideBar/SideBarTabInformation.vue b/src/js/components/SideBar/SideBarTabInformation.vue
new file mode 100644
index 00000000..edffcaaf
--- /dev/null
+++ b/src/js/components/SideBar/SideBarTabInformation.vue
@@ -0,0 +1,58 @@
+<!--
+ - @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>
+ <user-div :user-id="event.owner" :description="t('polls', 'Owner')" />
+ <div>{{ accessType }}</div>
+ <h3> {{ t('polls', 'Created') }} </h3>
+ <div>{{ timeSpanCreated }}</div>
+ <h3> {{ t('polls', 'Expires') }} </h3>
+ <div>{{ timeSpanExpiration }}</div>
+ <div>{{ countCommentsHint }}</div>
+ </div>
+</template>
+
+<script>
+import { mapState, mapGetters } from 'vuex'
+
+export default {
+ name: 'SideBarTabInformationTab',
+ computed: {
+ ...mapState({
+ event: state => state.event
+ }),
+
+ ...mapGetters([
+ 'accessType',
+ 'countComments',
+ 'timeSpanCreated',
+ 'timeSpanExpiration'
+ ]),
+
+ countCommentsHint: function() {
+ return n('polls', 'There is %n comment', 'There are %n comments', this.countComments)
+ }
+ }
+}
+
+</script>
diff --git a/src/js/components/SideBar/SideBarTabShare.vue b/src/js/components/SideBar/SideBarTabShare.vue
new file mode 100644
index 00000000..080be7db
--- /dev/null
+++ b/src/js/components/SideBar/SideBarTabShare.vue
@@ -0,0 +1,211 @@
+<!--
+ - @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>
+ <h3>{{ t('polls','Invitations') }}</h3>
+ <TransitionGroup :css="false" tag="ul" class="shared-list">
+ <li v-for="(share) in invitationShares" :key="share.id">
+ <UserDiv :user-id="resolveShareUser(share)" :type="share.type" :icon="true" />
+ <div class="options">
+ <a class="icon icon-clippy" @click="copyLink( { url: OC.generateUrl('apps/polls/s/') + share.token } )" />
+ <a class="icon icon-delete svg delete-poll" @click="removeShare(share)" />
+ </div>
+ </li>
+ </TransitionGroup>
+
+ <Multiselect id="ajax"
+ :options="users"
+ :multiple="false"
+ :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"
+ @select="addShare"
+ @search-change="loadUsersAsync">
+ <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>
+
+ <h3>{{ t('polls','Public shares') }}</h3>
+ <TransitionGroup :css="false" tag="ul" class="shared-list">
+ <li v-for="(share) in publicShares" :key="share.id">
+ <div class="user-row user">
+ <div class="avatar icon-public" />
+ <div class="user-name">
+ {{ t('polls', 'Share Link') }}
+ </div>
+ </div>
+ <div class="options">
+ <a class="icon icon-clippy" @click="copyLink( { url: OC.generateUrl('apps/polls/s/') + share.token } )" />
+ <a class="icon icon-delete" @click="removeShare(share)" />
+ </div>
+ </li>
+ </TransitionGroup>
+ <div class="user-row user" @click="addShare({type: 'public', user: ''})">
+ <div class="avatar icon-add" />
+ <div class="user-name">
+ {{ t('polls', 'Add a public link') }}
+ </div>
+ </div>
+ </div>
+</template>
+
+<script>
+import { Multiselect } from '@nextcloud/vue'
+import { mapGetters } from 'vuex'
+
+export default {
+ name: 'SideBarTabShare',
+
+ components: {
+ Multiselect
+ },
+
+ data() {
+ return {
+ users: [],
+ invitations: [],
+ invitation: {},
+ isLoading: false,
+ siteUsersListOptions: {
+ getUsers: true,
+ getGroups: true,
+ query: ''
+ }
+ }
+ },
+
+ computed: {
+ ...mapGetters([
+ 'countShares',
+ 'sortedShares',
+ 'invitationShares',
+ 'publicShares'
+ ])
+ },
+
+ methods: {
+ loadUsersAsync(query) {
+ this.isLoading = false
+ this.siteUsersListOptions.query = query
+ this.$http.post(OC.generateUrl('apps/polls/get/siteusers'), this.siteUsersListOptions)
+ .then((response) => {
+ this.users = response.data.siteusers
+ this.isLoading = false
+ }, (error) => {
+ console.error(error.response)
+ })
+ },
+
+ copyLink(payload) {
+ this.$copyText(window.location.origin + payload.url).then(
+ function(e) {
+ OC.Notification.showTemporary(t('polls', 'Link copied to clipboard'), { type: 'success' })
+ },
+ function(e) {
+ OC.Notification.showTemporary(t('polls', 'Error while copying link to clipboard'), { type: 'error' })
+ }
+ )
+ },
+
+ resolveShareUser(share) {
+ if (share.userId !== '' && share.userId !== null) {
+ return share.userId
+ } else if (share.type === 'mail') {
+ return share.userEmail
+ } else {
+ return t('polls', 'Unknown user')
+ }
+
+ },
+
+ removeShare(share) {
+ this.$store.dispatch('removeShareAsync', { share: share })
+ },
+
+ addShare(payload) {
+ this.$store.dispatch('writeSharePromise', {
+ 'share': {
+ 'type': payload.type,
+ 'userId': payload.user,
+ 'pollId': '0',
+ 'userEmail': '',
+ 'token': ''
+ }
+ })
+ // .then(response => {
+ // OC.Notification.showTemporary(t('polls', 'You added %n.', 1, payload.user), { type: 'success' })
+ // })
+ .catch(error => {
+ console.error('Error while adding share comment - Error: ', error)
+ OC.Notification.showTemporary(t('polls', 'Error while adding share'), { type: 'error' })
+ })
+ }
+ }
+}
+</script>
+
+<style lang="scss">
+ .shared-list {
+ display: flex;
+ flex-wrap: wrap;
+ flex-direction: column;
+ justify-content: flex-start;
+ padding-top: 8px;
+
+ > li {
+ display: flex;
+ align-items: stretch;
+ margin: 4px 0;
+ }
+ }
+
+ .options {
+ display: flex;
+
+ .icon:not(.hidden) {
+ padding: 14px;
+ height: 44px;
+ width: 44px;
+ opacity: .5;
+ display: block;
+ cursor: pointer;
+ }
+ }
+
+ .multiselect {
+ width: 100% !important;
+ max-width: 100% !important;
+ }
+</style>
diff --git a/src/js/components/SideBar/SideBarTabTextOptions.vue b/src/js/components/SideBar/SideBarTabTextOptions.vue
new file mode 100644
index 00000000..002d5d62
--- /dev/null
+++ b/src/js/components/SideBar/SideBarTabTextOptions.vue
@@ -0,0 +1,164 @@
+<!--
+ - @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>
+ <div class="configBox">
+ <label class="title icon-toggle-filelist">
+ {{ t('polls', 'Add a new text option') }}
+ </label>
+ <input v-model="newPollText" :placeholder=" t('polls', 'Enter option text and press Enter') " @keyup.enter="addOption(newPollText)">
+ </div>
+
+ <ul class="configBox poll-table">
+ <label class="title icon-calendar">
+ {{ t('polls', 'Available Options') }}
+ </label>
+ <TextPollItem v-for="(option) in sortedOptions" :key="option.id" :option="option"
+ @remove="removeOption(option)" />
+ </ul>
+ </div>
+</template>
+
+<script>
+import { mapGetters, mapState } from 'vuex'
+import TextPollItem from '../Create/TextPollItem'
+export default {
+ name: 'SideBarTabTextOptions',
+
+ components: {
+ TextPollItem
+ },
+
+ data() {
+ return {
+ newPollText: ''
+ }
+ },
+
+ computed: {
+ ...mapState({
+ options: state => state.options
+ }),
+
+ ...mapGetters(['languageCodeShort', 'sortedOptions'])
+ },
+
+ methods: {
+
+ addOption(pollOptionText) {
+ if (pollOptionText !== '') {
+ this.$store.dispatch('addOptionAsync', {
+ pollOptionText: pollOptionText
+ })
+ this.newPollText = ''
+ }
+ },
+
+ removeOption(option) {
+ this.$store.dispatch('removeOptionAsync', {
+ option: option
+ })
+ }
+
+ }
+
+}
+</script>
+
+<style lang="scss">
+.configBox {
+ display: flex;
+ flex-direction: column;
+ padding: 8px;
+ & > * {
+ padding-left: 21px;
+ }
+
+ & > input {
+ margin-left: 24px;
+ width: auto;
+
+ }
+
+ & > textarea {
+ margin-left: 24px;
+ width: auto;
+ padding: 7px 6px;
+ }
+
+ & > .title {
+ display: flex;
+ background-position: 0 2px;
+ padding-left: 24px;
+ opacity: 0.7;
+ font-weight: bold;
+ margin-bottom: 4px;
+ & > span {
+ padding-left: 4px;
+ }
+ }
+
+ &.poll-table > li {
+ border-bottom-color: rgb(72, 72, 72);
+ margin-left: 18px;
+ }
+
+}
+
+.poll-table {
+ > li {
+ display: flex;
+ align-items: center;
+ padding-left: 8px;
+ padding-right: 8px;
+ line-height: 2em;
+ min-height: 4em;
+ border-bottom: 1px solid var(--color-border);
+ overflow: hidden;
+ white-space: nowrap;
+
+ &:active,
+ &:hover {
+ transition: var(--background-dark) 0.3s ease;
+ background-color: var(--color-background-dark); //$hover-color;
+ }
+
+ > div {
+ display: flex;
+ flex: 1;
+ font-size: 1.2em;
+ opacity: 0.7;
+ white-space: normal;
+ padding-right: 4px;
+ &.avatar {
+ flex: 0;
+ }
+ }
+
+ > div:nth-last-child(1) {
+ justify-content: center;
+ flex: 0 0;
+ }
+ }
+}
+</style>