Added modal confirmation dialog
Added comment counter Added voting indicator
This commit is contained in:
Родитель
b0e0e5bc8f
Коммит
9352b93dd7
|
@ -23,8 +23,8 @@
|
|||
|
||||
return [
|
||||
'routes' => [
|
||||
['name' => 'page#list_polls', 'url' => '/', 'verb' => 'GET'],
|
||||
['name' => 'page#index', 'url' => '/list', 'verb' => 'GET'],
|
||||
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
|
||||
['name' => 'page#index_old', 'url' => '/list', 'verb' => 'GET'],
|
||||
['name' => 'page#goto_poll', 'url' => '/poll/{hash}', 'verb' => 'GET'],
|
||||
|
||||
['name' => 'page#create_poll', 'url' => '/new', 'verb' => 'GET'],
|
||||
|
|
|
@ -134,7 +134,7 @@ class PageController extends Controller {
|
|||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function index() {
|
||||
public function indexOld() {
|
||||
$polls = $this->eventMapper->findAllForUserWithInfo($this->userId);
|
||||
$comments = $this->commentMapper->findDistinctByUser($this->userId);
|
||||
$votes = $this->voteMapper->findDistinctByUser($this->userId);
|
||||
|
@ -164,7 +164,7 @@ class PageController extends Controller {
|
|||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function listPolls() {
|
||||
public function index() {
|
||||
return new TemplateResponse('polls', 'polls.tmpl',
|
||||
['urlGenerator' => $this->urlGenerator]);
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
$color-main-background: #fff;
|
||||
$color-border: #ebebeb;
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
#content-wrapper {
|
||||
padding-top: unset;
|
||||
}
|
||||
|
||||
#content {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
display: flex;
|
||||
padding-top: 45px;
|
||||
min-height: 100%;
|
||||
height: unset;
|
||||
width: unset;
|
||||
}
|
||||
|
||||
#app-content {
|
||||
position: initial;
|
||||
height: initial;
|
||||
overflow-y: initial;
|
||||
flex-basis: 100vw;
|
||||
}
|
||||
|
||||
#content[class*="app-"] * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#controls {
|
||||
position: sticky;
|
||||
top: 45px;
|
||||
right: unset;
|
||||
left: unset;
|
||||
display: flex;
|
||||
height: 40px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
z-index: 60;
|
||||
position: webkit-sticky;
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
@import '../css-oc-fixes/oc-container-fix.scss';
|
||||
@import '../../css/createpoll.scss';
|
|
@ -1 +0,0 @@
|
|||
@import '../../css/flex.scss';
|
|
@ -1,3 +0,0 @@
|
|||
@import '../css-oc-fixes/oc-colors-fix.scss';
|
||||
@import '../css-oc-fixes/oc-container-fix.scss';
|
||||
@import '../../css/list.scss';
|
|
@ -1 +0,0 @@
|
|||
@import '../../css/main.scss';
|
|
@ -1 +0,0 @@
|
|||
@import '../../css/public.scss';
|
|
@ -1,2 +0,0 @@
|
|||
@import '../css-oc-fixes/oc-colors-fix.scss';
|
||||
@import '../../css/sidebar.scss';
|
|
@ -1,2 +0,0 @@
|
|||
@import '../css-oc-fixes/oc-container-fix.scss';
|
||||
@import '../../css/vote.scss';
|
|
@ -24,7 +24,11 @@
|
|||
<div>
|
||||
<div class="wrapper group-master">
|
||||
<div class="wrapper group-1">
|
||||
<div class="thumbnail" :class="[poll.event.type, {expired : poll.event.expired}] " />
|
||||
<div v-if="countComments" class="comment-badge">
|
||||
{{ countComments }}
|
||||
</div>
|
||||
<div class="thumbnail" :class="[poll.event.type, {expired : poll.event.expired}] ">
|
||||
</div>
|
||||
<a :href="voteUrl" class="wrapper group-1-1">
|
||||
<div class="flex-column name">
|
||||
{{ poll.event.title }}
|
||||
|
@ -59,8 +63,7 @@
|
|||
{{ timeSpanExpiration }}
|
||||
</div>
|
||||
<div class="flex-column participants">
|
||||
<div class="symbol alt-tooltip partic_voted icon-voted" />
|
||||
<div class="symbol alt-tooltip partic_commented icon-comment-yes" />
|
||||
<div v-if="votedBycurrentUser" class="symbol icon-voted" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -69,7 +72,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
// import moment from 'moment'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -212,6 +215,23 @@ export default {
|
|||
&.expired {
|
||||
background-color: var(--color-error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.icon-voted {
|
||||
background-image: var(--icon-checkmark-49bc49);
|
||||
}
|
||||
.comment-badge {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
width: 26px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
font-size: 0.7rem;
|
||||
color: white;
|
||||
background-image: var(--icon-comment-49bc49);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 26px;
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -27,6 +27,7 @@ import axios from 'nextcloud-axios'
|
|||
import App from './App.vue'
|
||||
import vClickOutside from 'v-click-outside'
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
import Modal from './plugins/plugin.js'
|
||||
|
||||
import { DatetimePicker, PopoverMenu } from 'nextcloud-vue'
|
||||
|
||||
|
@ -48,10 +49,13 @@ Vue.component('ShareDiv', ShareDiv)
|
|||
|
||||
Vue.use(vClickOutside)
|
||||
Vue.use(VueClipboard)
|
||||
Vue.use(Modal)
|
||||
|
||||
Vue.prototype.t = t
|
||||
Vue.prototype.n = n
|
||||
Vue.prototype.$http = axios
|
||||
Vue.prototype.OC = OC
|
||||
Vue.prototype.OCA = OCA
|
||||
|
||||
// CSP config for webpack dynamic chunk loading
|
||||
// eslint-disable-next-line
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
<template>
|
||||
<div class="modal-wrapper" v-if="visible">
|
||||
<div class="modal-header">
|
||||
<h2>{{ title }}</h2>
|
||||
</div>
|
||||
<div class="modal-text">
|
||||
<p>{{ text }}</p>
|
||||
</div>
|
||||
<div class="modal-buttons">
|
||||
<button class="button" @click="hide">{{ t('polls','No') }}</button>
|
||||
<button class="button primary" @click="confirm">{{ t('polls','yes') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
// we must import our Modal plugin instance
|
||||
// because it contains reference to our Eventbus
|
||||
import Modal from './plugin.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
title: '',
|
||||
text: '',
|
||||
onConfirm: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
hide() {
|
||||
this.visible = false;
|
||||
},
|
||||
confirm() {
|
||||
// we must check if this.onConfirm is function
|
||||
if(typeof this.onConfirm === 'function') {
|
||||
// run passed function and then close the modal
|
||||
this.onConfirm();
|
||||
this.hide();
|
||||
} else {
|
||||
// we only close the modal
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
show(params) {
|
||||
// making modal visible
|
||||
this.visible = true;
|
||||
// setting title and text
|
||||
this.title = params.title;
|
||||
this.text = params.text;
|
||||
// setting callback function
|
||||
this.onConfirm = params.onConfirm;
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
// here we need to listen for emited events
|
||||
// we declared those events inside our plugin
|
||||
Modal.EventBus.$on('show', (params) => {
|
||||
this.show(params)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.modal-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
min-width: 300px;
|
||||
max-width: 500px;
|
||||
z-index: 1000;
|
||||
background-color: var(--color-main-background);
|
||||
box-shadow: 10px 10px 30px 1px rgba(0, 0, 0, 0.24);
|
||||
& > * {
|
||||
padding: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
background-color: var(--color-primary);
|
||||
& > * {
|
||||
color: var(--color-primary-text);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
// we need our modal component
|
||||
import ModalDialog from './modalDialog.vue'
|
||||
|
||||
const Modal = {
|
||||
// every plugin for Vue.js needs install method
|
||||
// this method will run after Vue.use(<your-plugin-here>) is executed
|
||||
install(Vue, options) {
|
||||
// We must create new Eventbus
|
||||
// which is just another Vue instance that will be listening for and emiting events from our main instance
|
||||
// this EventBus will be available as Modal.EventBus
|
||||
this.EventBus = new Vue()
|
||||
|
||||
// making our modal component global
|
||||
Vue.component('modal-dialog', ModalDialog)
|
||||
|
||||
// exposing global $modal object with method show()
|
||||
// method show() takes object params as argument
|
||||
// inside this object we can have modal title, text, styles... and also our callback confirm function
|
||||
Vue.prototype.$modal = {
|
||||
show(params) {
|
||||
// if we use this.$modal.show(params) inside our original Vue instance
|
||||
// we will emit 'show' event with parameters 'params'
|
||||
Modal.EventBus.$emit('show', params)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Modal
|
|
@ -1,3 +1,4 @@
|
|||
/* jshint esversion: 6 */
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||
* @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
<template>
|
||||
<div id="app-content">
|
||||
<controls>
|
||||
<router-link :to="{ name: 'create'}" class="button symbol icon-add">
|
||||
<router-link :to="{ name: 'create'}" class="button">
|
||||
<span class="symbol icon-add"></span>
|
||||
<span class="hidden-visually">
|
||||
{{ t('polls', 'New') }}
|
||||
</span>
|
||||
|
@ -57,6 +58,7 @@
|
|||
@deletePoll="removePoll(index, poll.event)"
|
||||
/>
|
||||
</transition-group>
|
||||
<modal-dialog/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -101,22 +103,27 @@ export default {
|
|||
})
|
||||
},
|
||||
|
||||
removePoll: function (index, event) {
|
||||
this.loading = true
|
||||
this.$http.post(OC.generateUrl('apps/polls/remove/poll'), event )
|
||||
.then((response) => {
|
||||
OC.Notification.showTemporary(t('polls', 'Poll "%n" deleted', 1, event.title))
|
||||
this.polls.splice(index, 1)
|
||||
this.loading = false
|
||||
console.log(response.data)
|
||||
removePoll: function(index, event) {
|
||||
const params = {
|
||||
title: t('polls','Delete poll'),
|
||||
text: t('polls', 'Do you want to delete "%n"?', 1, event.title),
|
||||
onConfirm: () => {
|
||||
// this.deletePoll(index, event)
|
||||
this.$http.post(OC.generateUrl('apps/polls/remove/poll'), event)
|
||||
.then((response) => {
|
||||
this.polls.splice(index, 1)
|
||||
OC.Notification.showTemporary(t('polls', 'Poll "%n" deleted', 1, event.title))
|
||||
}, (error) => {
|
||||
OC.Notification.showTemporary(t('polls', 'Error while deleting Poll "%n"', 1, event.title))
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.log(error.response)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
this.$modal.show(params)
|
||||
},
|
||||
|
||||
}, (error) => {
|
||||
/* eslint-disable-next-line no-console */
|
||||
OC.Notification.showTemporary(t('polls', 'Error while deleting Poll "%n"', 1, event.title))
|
||||
console.log(error.response)
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="actions creatable" style="">
|
||||
<a href="<?php p($urlGenerator->linkToRoute('polls.page.polls_app')); ?>" class="button new">
|
||||
<a href="<?php p($urlGenerator->linkToRoute('polls.page.create_poll')); ?>" class="button new">
|
||||
<span class="symbol icon-add"></span><span class="hidden-visually">Neu</span>
|
||||
</a>
|
||||
<input class="stop icon-close" style="display:none" value="" type="button">
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
|
||||
<?php if (User::isLoggedIn()) : ?>
|
||||
<div class="crumb svg crumbhome">
|
||||
<a class="icon-home" href="<?php p($urlGenerator->linkToRoute('polls.page.list_polls')); ?>"> Home </a>
|
||||
<a class="icon-home" href="<?php p($urlGenerator->linkToRoute('polls.page.index')); ?>"> Home </a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче