Skip to content

Commit

Permalink
feat: browse poll drafts from poll editor and shared items
Browse files Browse the repository at this point in the history
Signed-off-by: Maksim Sukharev <[email protected]>
  • Loading branch information
Antreesy committed Oct 14, 2024
1 parent 935aae4 commit 1dd81b4
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@

<template>
<!-- Poll card -->
<a v-if="!showAsButton"
<div v-if="draft" class="poll-card" @click="openDraft">
<span class="poll-card__header">
<PollIcon :size="20" />
<span>{{ name }}</span>
</span>
<span class="poll-card__footer">
{{ pollFooterText }}
</span>
</div>
<a v-else-if="!showAsButton"
v-intersection-observer="getPollData"
:aria-label="t('spreed', 'Poll')"
class="poll-card"
Expand Down Expand Up @@ -34,7 +43,7 @@ import { vIntersectionObserver as IntersectionObserver } from '@vueuse/component

import PollIcon from 'vue-material-design-icons/Poll.vue'

import { t } from '@nextcloud/l10n'
import { t, n } from '@nextcloud/l10n'

import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'

Expand Down Expand Up @@ -73,8 +82,15 @@ export default {
type: Boolean,
default: false,
},

draft: {
type: Boolean,
default: false,
},
},

emits: ['click'],

setup() {
return {
pollsStore: usePollsStore(),
Expand All @@ -83,14 +99,18 @@ export default {

computed: {
poll() {
return this.pollsStore.getPoll(this.token, this.id)
return !this.draft
? this.pollsStore.getPoll(this.token, this.id)
: this.pollsStore.drafts[this.token][this.id]
},

pollFooterText() {
if (this.poll?.status === POLL.STATUS.OPEN) {
return this.poll?.votedSelf.length > 0
? t('spreed', 'Open poll • You voted already')
: t('spreed', 'Open poll • Click to vote')
} else if (this.draft) {
return n('spreed', 'Poll draft • %n option', 'Poll draft • %n options', this.poll?.options?.length)
} else {
return this.poll?.status === POLL.STATUS.CLOSED
? t('spreed', 'Poll • Ended')
Expand All @@ -101,6 +121,7 @@ export default {

methods: {
t,
n,
getPollData() {
if (!this.poll) {
this.pollsStore.getPollData({
Expand All @@ -110,6 +131,10 @@ export default {
}
},

openDraft() {
this.$emit('click', this.id)
},

openPoll() {
this.pollsStore.setActivePoll({
token: this.token,
Expand Down
13 changes: 13 additions & 0 deletions src/components/NewMessage/NewMessage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@
:token="token"
@close="togglePollEditor" />

<PollDraftHandler v-if="showPollDraftHandler"
:token="token"
@close="togglePollDraftHandler" />

<!-- New file creation dialog -->
<NewMessageNewFileDialog v-if="showNewFileDialog !== -1"
:token="token"
Expand Down Expand Up @@ -194,6 +198,7 @@ import NewMessageAudioRecorder from './NewMessageAudioRecorder.vue'
import NewMessageNewFileDialog from './NewMessageNewFileDialog.vue'
import NewMessagePollEditor from './NewMessagePollEditor.vue'
import NewMessageTypingIndicator from './NewMessageTypingIndicator.vue'
import PollDraftHandler from '../PollViewer/PollDraftHandler.vue'
import Quote from '../Quote.vue'

import { useIsDarkTheme } from '../../composables/useIsDarkTheme.ts'
Expand Down Expand Up @@ -226,6 +231,7 @@ export default {
NewMessageAudioRecorder,
NewMessageNewFileDialog,
NewMessagePollEditor,
PollDraftHandler,
NewMessageTypingIndicator,
Quote,
// Icons
Expand Down Expand Up @@ -301,6 +307,7 @@ export default {
// True when the audio recorder component is recording
isRecordingAudio: false,
showPollEditor: false,
showPollDraftHandler: false,
showNewFileDialog: -1,
showFilePicker: false,
// Check empty template by default
Expand Down Expand Up @@ -538,6 +545,7 @@ export default {
EventBus.on('upload-discard', this.handleUploadSideEffects)
EventBus.on('retry-message', this.handleRetryMessage)
EventBus.on('smart-picker-open', this.handleOpenTributeMenu)
EventBus.on('poll-drafts-open', this.togglePollDraftHandler)

if (!this.$store.getters.areFileTemplatesInitialised) {
this.$store.dispatch('getFileTemplates')
Expand All @@ -550,6 +558,7 @@ export default {
EventBus.off('upload-discard', this.handleUploadSideEffects)
EventBus.off('retry-message', this.handleRetryMessage)
EventBus.off('smart-picker-open', this.handleOpenTributeMenu)
EventBus.off('poll-drafts-open', this.togglePollDraftHandler)
},

methods: {
Expand Down Expand Up @@ -892,6 +901,10 @@ export default {
this.showPollEditor = !this.showPollEditor
},

togglePollDraftHandler() {
this.showPollDraftHandler = !this.showPollDraftHandler
},

async autoComplete(search, callback) {
const response = await searchPossibleMentions(this.token, search)
if (!response) {
Expand Down
26 changes: 25 additions & 1 deletion src/components/NewMessage/NewMessagePollEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,17 @@
<p class="poll-editor__caption">
{{ t('spreed', 'Question') }}
</p>
<NcTextField :value.sync="pollForm.question" :label="t('spreed', 'Ask a question')" v-on="$listeners" />
<div class="poll-editor__wrapper">
<NcTextField :value.sync="pollForm.question" :label="t('spreed', 'Ask a question')" v-on="$listeners" />
<NcActions v-if="supportPollDrafts" force-menu>
<NcActionButton v-if="isModerator" close-after-click @click="openPollDraftHandler">
<template #icon>
<IconFileEdit :size="20" />
</template>
{{ t('spreed', 'Browse poll drafts') }}
</NcActionButton>
</NcActions>
</div>

<!-- Poll options -->
<p class="poll-editor__caption">
Expand Down Expand Up @@ -93,6 +103,7 @@ import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
import { useStore } from '../../composables/useStore.js'
import { POLL } from '../../constants.js'
import { hasTalkFeature } from '../../services/CapabilitiesManager.ts'
import { EventBus } from '../../services/EventBus.js'
import { usePollsStore } from '../../stores/polls.ts'
import type { createPollParams } from '../../types/index.ts'

Expand Down Expand Up @@ -181,10 +192,23 @@ async function createPollDraft() {
showSuccess(t('spreed', 'Poll draft has been saved'))
}
}

/**
* Open a PollDraftHandler dialog
*/
function openPollDraftHandler() {
EventBus.emit('poll-drafts-open')
}
</script>

<style lang="scss" scoped>
.poll-editor {
&__wrapper {
display: flex;
align-items: flex-end;
gap: 4px;
}

&__caption {
margin: calc(var(--default-grid-baseline) * 2) 0 var(--default-grid-baseline);
font-weight: bold;
Expand Down
84 changes: 84 additions & 0 deletions src/components/PollViewer/PollDraftHandler.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<!--
- SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->

<template>
<NcDialog class="drafts"
:name="t('spreed', 'Poll drafts')"
size="large"
close-on-click-outside
v-on="$listeners"
@update:open="emit('close')">
<EmptyView v-if="!pollDrafts.length"
class="drafts__empty"
:name="t('spreed', 'No poll drafts')"
:description="t('spreed', 'There is no poll drafts yet saved for this conversation')">
<template #icon>
<IconPoll />
</template>
</EmptyView>
<div v-else class="drafts__wrapper">
<Poll v-for="item in pollDrafts"
:id="item.id.toString()"
:key="item.id"
:token="token"
:name="item.question"
draft />
</div>
</NcDialog>
</template>

<script setup lang="ts">
import { computed } from 'vue'

import IconPoll from 'vue-material-design-icons/Poll.vue'

import { t } from '@nextcloud/l10n'

import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'

import EmptyView from '../EmptyView.vue'
import Poll from '../MessagesList/MessagesGroup/Message/MessagePart/Poll.vue'

import { useStore } from '../../composables/useStore.js'
import { hasTalkFeature } from '../../services/CapabilitiesManager.ts'
import { usePollsStore } from '../../stores/polls.ts'

const props = defineProps<{
token: string,
}>()
const emit = defineEmits<{
(event: 'close'): void,
}>()

const supportPollDrafts = hasTalkFeature(props.token, 'talk-polls-drafts')
const store = useStore()
const pollsStore = usePollsStore()
/**
* Receive poll drafts for the current conversation as owner/moderator
*/
const isModerator = computed(() => (store.getters as unknown).isModerator)
if (supportPollDrafts && isModerator.value) {
pollsStore.getPollDrafts(props.token)
}
const pollDrafts = computed(() => supportPollDrafts ? pollsStore.getDrafts(props.token) : [])
</script>

<style lang="scss" scoped>
.drafts {
:deep(.dialog__content) {
min-height: 200px;
}

&__wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: var(--default-grid-baseline);
}

&__empty {
margin: 0 !important;
}
}
</style>
24 changes: 24 additions & 0 deletions src/components/RightSidebar/SharedItems/SharedItemsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
<LoadingComponent v-if="loading" class="shared-items-tab__loading" />

<template v-else>
<NcButton v-if="supportPollDrafts && isModerator"
wide
@click="openPollDraftHandler">
<template #icon>
<IconPoll :size="20" />
</template>
{{ t('spreed', 'Browse poll drafts') }}
</NcButton>
<!-- Shared items grouped by type -->
<template v-for="type in sharedItemsOrder">
<div v-if="sharedItems[type]" :key="type">
Expand Down Expand Up @@ -68,6 +76,7 @@
<script>
import DotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue'
import FolderMultipleImage from 'vue-material-design-icons/FolderMultipleImage.vue'
import IconPoll from 'vue-material-design-icons/Poll.vue'

import { loadState } from '@nextcloud/initial-state'
import { t } from '@nextcloud/l10n'
Expand All @@ -88,6 +97,8 @@ import {
sharedItemsWithPreviewLimit,
sharedItemTitle,
} from './sharedItemsConstants.js'
import { hasTalkFeature } from '../../../services/CapabilitiesManager.ts'
import { EventBus } from '../../../services/EventBus.js'
import { useSharedItemsStore } from '../../../stores/sharedItems.js'
import { useSidebarStore } from '../../../stores/sidebar.js'

Expand All @@ -98,6 +109,7 @@ export default {
components: {
DotsHorizontal,
FolderMultipleImage,
IconPoll,
LoadingComponent,
NcAppNavigationCaption,
NcButton,
Expand Down Expand Up @@ -148,6 +160,14 @@ export default {
return this.$store.getters.conversation(this.token)
},

supportPollDrafts() {
return hasTalkFeature(this.token, 'talk-polls-drafts')
},

isModerator() {
return this.$store.getters.isModerator
},

loading() {
return !this.sharedItemsStore.overviewLoaded[this.token]
},
Expand Down Expand Up @@ -194,6 +214,10 @@ export default {
limit(type) {
return this.sharedItemsWithPreviewLimit.includes(type) ? 2 : 6
},

openPollDraftHandler() {
EventBus.emit('poll-drafts-open')
}
},
}
</script>
Expand Down

0 comments on commit 1dd81b4

Please sign in to comment.