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
6 changes: 6 additions & 0 deletions src/assets/scss/hacks.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
*/
// some hacks, do alter the display of third parity components

// FIXME: remove this hack after the issue is fixed
// make sure selects are 100% width in config box
.config-box .v-select {
width: 100%;
}

// FIXME: remove this hack after the issue is fixed
// limit the width of the user bubble to prevent it from overflowing
.user-bubble__name {
Expand Down
1 change: 0 additions & 1 deletion src/components/Base/modules/Collapsible.vue
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ const containerClass = computed(() => ({
.collapsible_container {
position: relative;
overflow: auto;
width: 100%;
transition: height 0.3s ease;
padding-inline-end: 8px;

Expand Down
3 changes: 0 additions & 3 deletions src/components/Base/modules/ConfigBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ const { name, info = '', indented = false } = defineProps<Props>()

&__container {
grid-area: container;
& > * {
width: 100%;
}
}

.indented {
Expand Down
85 changes: 45 additions & 40 deletions src/components/PollList/PollItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ const expirationDateTime = computed(() =>
DateTime.fromMillis(poll.configuration.expire * 1000),
)

const createdDateTime = computed(() =>
DateTime.fromMillis(poll.status.created * 1000),
)

const archiveDateTime = computed(() =>
DateTime.fromMillis(poll.status.archivedDate * 1000),
)
Expand Down Expand Up @@ -75,25 +71,48 @@ const expiryClass = computed(() => {
return 'success'
})

const descriptionLine = computed(() => {
if (preferencesStore.user.verbosePollsList) {
if (poll.configuration.description) {
return poll.configuration.description
const pollDetails = computed(() => {
if (noLink || !poll.permissions.view) {
return {
iconComponent: LockPollIcon,
title: t('polls', 'No access'),
description: t('polls', 'No access to this poll of {ownerName}.', {
ownerName: poll.owner.displayName,
}),
}
return t('polls', 'No description provided')
}

if (poll.status.isArchived) {
return t('polls', 'Archived {relativeTime}', {
relativeTime: archiveDateTime.value.toRelative() as string,
})
return {
iconComponent: ArchivedPollIcon,
title: t('polls', 'Archived poll'),
description: t('polls', 'Archived {relativeTime}', {
relativeTime: archiveDateTime.value.toRelative() as string,
}),
}
}
if (poll.configuration.access === 'private') {
return {
iconComponent: PrivatePollIcon,
title: t('polls', 'Private poll'),
description: t(
'polls',
'Private poll, only invited participants have access',
),
}
}
return {
iconComponent: OpenPollIcon,
title: t('polls', 'Openly accessible poll'),
description: t(
'polls',
'Open poll, accessible to all users of this instance and invited participants',
),
}

return t('polls', 'Started {relativeTime} from {ownerName}', {
ownerName: poll.owner.displayName,
relativeTime: createdDateTime.value.toRelative() as string,
})
})

const descriptionLine = computed(
() => poll.configuration.description || pollDetails.value.description,
)
</script>

<template>
Expand All @@ -113,7 +132,7 @@ const descriptionLine = computed(() => {
</div>

<div class="description_line">
<LockPollIcon :size="16" />
<component :is="pollDetails.iconComponent" :size="16" />
<div class="description">
{{
t('polls', 'No access to this poll of {ownerName}.', {
Expand Down Expand Up @@ -143,27 +162,10 @@ const descriptionLine = computed(() => {
</div>

<div class="description_line">
<ArchivedPollIcon
v-if="
!preferencesStore.user.verbosePollsList
&& poll.status.isArchived
"
:title="t('polls', 'Archived poll')"
:size="16" />
<OpenPollIcon
v-else-if="
!preferencesStore.user.verbosePollsList
&& poll.configuration.access === 'open'
"
:title="t('polls', 'Openly accessible poll')"
:size="16" />
<PrivatePollIcon
v-else-if="
!preferencesStore.user.verbosePollsList
&& poll.configuration.access === 'private'
"
:title="t('polls', 'Private poll')"
:size="16" />
<component
:is="pollDetails.iconComponent"
:size="16"
:title="pollDetails.title" />

<span class="description">
{{ descriptionLine }}
Expand Down Expand Up @@ -322,6 +324,9 @@ const descriptionLine = computed(() => {
justify-content: space-between;
}
.description_line {
display: grid;
grid-template-columns: max-content 1fr;
gap: 0.25rem;
opacity: 0.5;
}
.badges {
Expand Down
48 changes: 25 additions & 23 deletions src/components/Settings/AdminSettings/AdminJobs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,28 @@ async function loadJobs() {
Logger.error('Error on fetching jobs list', { error })
}
}

function jobStatus(job: Job) {
if (executedJobs.value.has(job.name)) {
return {
component: JobExecutedIcon,
title: t('polls', '{jobName} has been executed.', { jobName: job.name }),
}
}
if (job.manuallyRunnable) {
return {
component: PlayIcon,
title: t('polls', 'Start {jobName} manually.', { jobName: job.name }),
}
}
return {
component: NotSupportedIcon,
title: t('polls', '{jobName} does not support manually run.', {
jobName: job.name,
}),
}
}

/**
* fetch the jobs list on component mount
*/
Expand Down Expand Up @@ -158,29 +180,9 @@ onMounted(() => {
:aria-label="t('polls', 'Request job execution')"
@click="runJob(job)">
<template #icon>
<JobExecutedIcon
v-if="executedJobs.has(job.name)"
:title="
t('polls', '{jobName} has been executed.', {
jobName: job.name,
})
" />
<PlayIcon
v-else-if="job.manuallyRunnable"
:title="
t('polls', 'Start {jobName} manually.', {
jobName: job.name,
})
" />
<NotSupportedIcon
v-else
:title="
t(
'polls',
'{jobName} does not support manually run.',
{ jobName: job.name },
)
" />
<component
:is="jobStatus(job).component"
:title="jobStatus(job).title" />
</template>
</NcActionButton>
</template>
Expand Down
99 changes: 80 additions & 19 deletions src/components/Shares/ShareItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ import ShareMenu from './ShareMenu.vue'

import type { Share } from '../../stores/shares.types'
import { AvatarTypeIcon } from '../User/UserAvatar.types'
import AdminIcon from 'vue-material-design-icons/ShieldCrownOutline.vue'
import ContactIcon from 'vue-material-design-icons/CardAccountDetailsOutline.vue'
import EmailIcon from 'vue-material-design-icons/EmailOutline.vue'
import ShareIcon from 'vue-material-design-icons/ShareVariantOutline.vue'
import PollGroupIcon from 'vue-material-design-icons/CodeBraces.vue'

const emit = defineEmits(['showQrCode'])

Expand All @@ -27,6 +32,8 @@ const publicShareDescription = computed(() => {
return t('polls', 'Public link: {token}', { token: share.user.id })
})

const typeIconSize = 16

const userDescription = computed(() => {
if (share.groupId && !share.pollId) {
return t('polls', 'Poll group access')
Expand All @@ -53,13 +60,6 @@ const userDescription = computed(() => {
return ''
})

const computedTypeIcon = computed<AvatarTypeIcon>(() => {
if (share.groupId && !share.pollId) {
return 'pollGroupIcon'
}
return true
})

const label = ref({
inputValue: '',
inputProps: {
Expand All @@ -71,6 +71,67 @@ const label = ref({
},
})

const computedTypeIcon = computed<AvatarTypeIcon>(() => {
if (share.groupId && !share.pollId) {
return 'pollGroupIcon'
}
return share.type
})

const typeIconComponent = computed(() => {
switch (computedTypeIcon.value) {
case 'admin':
return AdminIcon
case 'contact':
return ContactIcon
case 'email':
return EmailIcon
case 'external':
return ShareIcon
case 'pollGroupIcon':
return PollGroupIcon
default:
return null
}
})

// const votedIndicator = computed(() => {
// if (share.voted) {
// return {
// class: 'vote-status voted',
// component: VotedIcon,
// name: t('polls', 'Has voted'),
// }
// }
// if (!share.voted) {
// return {
// class: 'vote-status unvoted',
// component: UnvotedIcon,
// name: t('polls', 'Has not voted'),
// }
// }
// return { class: 'vote-status empty', component: null, name: '' }
// })

const votedIndicator = computed(() => {
if (share.groupId || ['public', 'group'].includes(share.type)) {
return { class: 'vote-status empty', component: 'div', name: '' }
}
if (share.voted) {
return {
class: 'vote-status voted',
component: VotedIcon,
name: t('polls', 'Has voted'),
}
}

return {
class: 'vote-status unvoted',
component: UnvotedIcon,
name: t('polls', 'Has not voted'),
}
})

onMounted(() => {
label.value.inputValue = share.label
})
Expand All @@ -82,21 +143,21 @@ onMounted(() => {
:class="{ deleted: share.deleted }"
:user="share.user"
show-email
:type-icon="computedTypeIcon"
:description="userDescription"
:label="share.label">
<template #typeIcon>
<component
:is="typeIconComponent"
v-if="typeIconComponent"
:size="typeIconSize" />
</template>

<template #status>
<div
v-if="share.groupId || ['public', 'group'].includes(share.type)"
class="vote-status empty" />
<VotedIcon
v-else-if="share.voted"
class="vote-status voted"
:name="t('polls', 'Has voted')" />
<UnvotedIcon
v-else
class="vote-status unvoted"
:name="t('polls', 'Has not voted')" />
<component
:is="votedIndicator.component"
v-if="votedIndicator.component"
:class="votedIndicator.class"
:title="votedIndicator.name" />
</template>

<ShareMenu :share="share" @show-qr-code="emit('showQrCode')" />
Expand Down
4 changes: 3 additions & 1 deletion src/components/User/UserAvatar.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

export type AvatarTypeIcon = boolean | 'pollGroupIcon'
import { ShareType } from '@/stores/shares.types'

export type AvatarTypeIcon = ShareType | 'pollGroupIcon'
Loading