Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/components/Actions/modules/ActionSendConfirmed.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ import { Confirmations } from '../../../Api/modules/polls.ts'

const route = useRoute()
const showModal = ref(false)
const sendButtonCaption = ref(
t('polls', 'Send information about confirmed options by email'),
)
const sendButtonCaption = ref(t('polls', 'Send confirmation mails'))

const confirmations = ref<Confirmations>({
sentMails: [],
abortedMails: [],
Expand Down
19 changes: 13 additions & 6 deletions src/components/Base/modules/CardDiv.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,18 @@ import NcNoteCard from '@nextcloud/vue/components/NcNoteCard'
padding-inline-end: 8px;
}

.notecard .card-content {
display: flex;
flex-wrap: wrap;
align-items: center;
flex: 1;
column-gap: 8px;
.notecard {
& > * {
display: flex;
flex-direction: column;
}

.card-content {
display: flex;
flex-wrap: wrap;
align-items: center;
flex: 1;
column-gap: 8px;
}
}
</style>
28 changes: 24 additions & 4 deletions src/components/Cards/VoteInfoCards.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,33 @@ const showRegisterCard = computed(
</script>

<template>
<TransitionGroup tag="div">
<CardUnpublishedPoll v-if="showUnpublishedPollCard" :key="0" />
<CardAddProposals v-if="showAddProposalsCard" :key="1" />
<TransitionGroup tag="div" class="vote-info-cards">
<CardLimitedVotes v-if="showLimitCard" :key="2" />
<CardUnpublishedPoll v-if="showUnpublishedPollCard" :key="0" />
<CardClosedPoll v-if="showClosedCard" :key="3" />
<CardSendConfirmations v-if="showSendConfirmationsCard" :key="4" />
<CardLocked v-if="pollStore.currentUserStatus.isLocked" :key="5" />
<CardAddProposals v-if="showAddProposalsCard" :key="1" />
<CardSendConfirmations v-if="showSendConfirmationsCard" :key="4" />
<CardRegister v-if="showRegisterCard" :key="6" />
</TransitionGroup>
</template>

<style lang="scss" scoped>
.vote-info-cards {
margin: auto;
display: flex;
gap: 1rem;
flex-wrap: wrap;
justify-content: center;

& > * {
flex: 1;
}

// remove margin from notecard in favor of flexbox gap
.notecard {
margin: unset;
flex: 1 calc(var(--cap-width) / 2);
}
}
</style>
90 changes: 51 additions & 39 deletions src/components/Cards/modules/CardLimitedVotes.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import { CardDiv } from '../../Base/index.ts'
import ActionDeleteOrphanedVotes from '../../Actions/modules/ActionDeleteOrphanedVotes.vue'
import { t, n } from '@nextcloud/l10n'
import { usePollStore } from '../../../stores/poll.ts'
import { useOptionsStore } from '../../../stores/options.ts'

const pollStore = usePollStore()
const optionsStore = useOptionsStore()

const orphanedVotesText = computed(() =>
n(
'polls',
'%n orphaned vote of a probaly deleted option is possibly blocking your vote limit.',
'%n orphaned votes of probaly deleted options are possibly blocking your vote limit.',
'%n orphaned vote reduces your vote quota.',
'%n orphaned votes reduces your vote quota.',
pollStore.currentUserStatus.orphanedVotes,
),
)
Expand All @@ -29,6 +31,34 @@ const votesLeft = computed(() =>
: 0,
)

const optionsAvailableText = computed(() => {
if (optionsStore.countOptionsLeft === 0) {
return t('polls', 'No more voting options are available.')
}

return n(
'polls',
'%n voting option is available.',
'%n voting options are available.',
optionsStore.countOptionsLeft,
)
})

const votesLeftText = computed(() => {
if (!votesLeft.value) {
return t('polls', 'You have no votes left.')
}
return n(
'polls',
'You have %n vote left out of {maxVotes}.',
'You have %n votes left out of {maxVotes}.',
votesLeft.value,
{
maxVotes: pollStore.configuration.maxVotesPerUser,
},
)
})

const cardType = computed(() =>
pollStore.configuration.maxVotesPerUser && votesLeft.value < 1
? 'error'
Expand All @@ -38,43 +68,19 @@ const cardType = computed(() =>

<template>
<CardDiv :heading="t('polls', 'Limited votes.')" :type="cardType">
<ul>
<li v-if="pollStore.configuration.maxVotesPerOption">
{{
n(
'polls',
'%n vote is allowed per option.',
'%n votes are allowed per option.',
pollStore.configuration.maxVotesPerOption,
)
}}
</li>
<li v-if="pollStore.configuration.maxVotesPerUser">
{{
n(
'polls',
'%n vote is allowed per participant.',
'%n votes are allowed per participant.',
pollStore.configuration.maxVotesPerUser,
)
}}
{{
n(
'polls',
'You have %n vote left.',
'You have %n votes left.',
votesLeft,
)
}}
</li>
<div
v-if="
pollStore.currentUserStatus.orphanedVotes
&& pollStore.configuration.maxVotesPerUser
">
<b>{{ orphanedVotesText }}</b>
</div>
</ul>
<span v-if="pollStore.configuration.maxVotesPerOption">
{{ optionsAvailableText }}
</span>
<span v-if="pollStore.configuration.maxVotesPerUser">
{{ votesLeftText }}
</span>
<div
v-if="
pollStore.currentUserStatus.orphanedVotes
&& pollStore.configuration.maxVotesPerUser
">
<b>{{ orphanedVotesText }}</b>
</div>

<template
v-if="
Expand All @@ -86,3 +92,9 @@ const cardType = computed(() =>
</template>
</CardDiv>
</template>

<style lang="scss" scoped>
span::after {
content: ' ';
}
</style>
2 changes: 1 addition & 1 deletion src/components/Configuration/ConfigOptionLimit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function validateLimit() {
v-model="pollStore.configuration.hideBookedUp"
class="indented"
type="switch"
@change="emit('change')">
@update:model-value="emit('change')">
{{ t('polls', 'Hide not available Options') }}
</NcCheckboxRadioSwitch>
</div>
Expand Down
1 change: 0 additions & 1 deletion src/components/Poll/MarkDownDescription.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ const pollStore = usePollStore()
<style lang="scss">
.markdown-description {
overflow: auto;
max-width: 49rem;

* {
margin: revert;
Expand Down
42 changes: 0 additions & 42 deletions src/components/Subscription/Subscription.vue

This file was deleted.

2 changes: 1 addition & 1 deletion src/helpers/modules/StoreHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const StoreHelper = {
const votesStore = useVotesStore()
const optionsStore = useOptionsStore()

if (Object.hasOwn(data, 'polls')) {
if (Object.hasOwn(data, 'poll')) {
pollStore.$patch(data.poll as Poll)
}
if (Object.hasOwn(data, 'votes')) {
Expand Down
2 changes: 1 addition & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ const Polls = createApp(App)
.directive('focus', {
mounted: (el) => el.focus(),
})
Polls.mount('#content_polls')
Polls.mount('#content')
21 changes: 13 additions & 8 deletions src/polls-reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ import { registerWidget } from '@nextcloud/vue/components/NcRichText'
import Reference from './views/Reference.vue'
import './assets/scss/polls-icon.scss'

registerWidget('polls_reference_widget', async (el, { richObject }) => {
const PollsReference = createApp(Reference, {
richObject,
})
.use(pinia)
.mount(el)
return PollsReference
})
registerWidget(
'polls_reference_widget',
async (el, { richObject }) => {
const PollsReference = createApp(Reference, {
richObject,
})
.use(pinia)
.mount(el)
return PollsReference
},
(el) => el.classList.add('nc-polls-reference-widget'),
{},
)
15 changes: 15 additions & 0 deletions src/stores/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,21 @@ export const useOptionsStore = defineStore('options', {
return state.list.length
},

countAvailable(state): number {
return state.list.filter((option) => !option.locked && !option.deleted)
.length
},

countVotedByCurrentUser(state): number {
return state.list.filter(
(option) => option.votes.currentUser === Answer.Yes,
).length
},

countOptionsLeft(): number {
return this.countAvailable - this.countVotedByCurrentUser
},

rankedOptions(state): Option[] {
return orderBy(
state.list,
Expand Down
2 changes: 1 addition & 1 deletion src/views/Reference.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const expiryClass = richObject?.poll?.expiry
{{ richObject.poll.description }}
</span>
</div>
<div class="widget_footer">
<div v-if="richObject.poll.ownerId" class="widget_footer">
<span>{{ t('polls', 'By:') }}</span>
<NcUserBubble
:user="richObject.poll.ownerId"
Expand Down
12 changes: 10 additions & 2 deletions src/views/Vote.vue
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,16 @@ onUnmounted(() => {
</template>

<style lang="scss">
.vote_main > * {
margin-top: 0.5rem;
.vote_main {
--cap-width: 49rem;
.markdown-description {
margin: auto;
max-width: var(--cap-width);
}

& > * {
margin-top: 0.5rem;
}
}

.vote_head {
Expand Down
2 changes: 1 addition & 1 deletion templates/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
?>
<div id="content_polls" />
<div id="content_polls" />