feat: adhere to and display poll limits (#2114)

This commit is contained in:
Tuur Martens 2023-05-21 13:37:33 +02:00 committed by GitHub
parent 1fda33848e
commit 22556984fa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 9 deletions

View file

@ -63,14 +63,25 @@ const { editor } = useTiptap({
onPaste: handlePaste, onPaste: handlePaste,
}) })
function trimPollOptions() {
const indexLastNonEmpty = draft.params.poll!.options.findLastIndex(option => option.trim().length > 0)
const trimmedOptions = draft.params.poll!.options.slice(0, indexLastNonEmpty + 1)
if (currentInstance.value?.configuration
&& trimmedOptions.length >= currentInstance.value?.configuration?.polls.maxOptions)
draft.params.poll!.options = trimmedOptions
else
draft.params.poll!.options = [...trimmedOptions, '']
}
function editPollOptionDraft(event: Event, index: number) { function editPollOptionDraft(event: Event, index: number) {
draft.params.poll!.options[index] = (event.target as HTMLInputElement).value draft.params.poll!.options[index] = (event.target as HTMLInputElement).value
const indexLastNonEmpty = draft.params.poll!.options.findLastIndex(option => option.trim().length > 0) trimPollOptions()
draft.params.poll!.options = [...draft.params.poll!.options.slice(0, indexLastNonEmpty + 1), '']
} }
function deletePollOption(index: number) { function deletePollOption(index: number) {
draft.params.poll!.options.splice(index, 1) draft.params.poll!.options.splice(index, 1)
trimPollOptions()
} }
const expiresInOptions = [ const expiresInOptions = [
@ -326,18 +337,26 @@ onDeactivated(() => {
border="~ base" flex-1 h10 pe-4 rounded-2 w-full flex="~ row" border="~ base" flex-1 h10 pe-4 rounded-2 w-full flex="~ row"
items-center relative focus-within:box-shadow-outline gap-3 items-center relative focus-within:box-shadow-outline gap-3
px-4 py-2 px-4 py-2
:placeholder="$t('polls.option_placeholder')" :placeholder="$t('polls.option_placeholder', { current: index + 1, max: currentInstance?.configuration?.polls.maxOptions })"
class="option-input"
@input="editPollOptionDraft($event, index)" @input="editPollOptionDraft($event, index)"
> >
<CommonTooltip placement="top" :content="$t('polls.remove_option')"> <CommonTooltip placement="top" :content="$t('polls.remove_option')" class="delete-button">
<button <button
btn-action-icon class="hover:bg-red/75" btn-action-icon class="hover:bg-red/75"
:disabled="index === draft.params.poll!.options.length - 1" :disabled="index === draft.params.poll!.options.length - 1 && (index + 1 !== currentInstance?.configuration?.polls.maxOptions || draft.params.poll!.options[index].length === 0)"
@click.prevent="deletePollOption(index)" @click.prevent="deletePollOption(index)"
> >
<div i-ri:delete-bin-line /> <div i-ri:delete-bin-line />
</button> </button>
</CommonTooltip> </CommonTooltip>
<span
v-if="currentInstance?.configuration?.polls.maxCharactersPerOption"
class="char-limit-radial"
aspect-ratio-1
h-10
:style="{ background: `radial-gradient(closest-side, rgba(var(--rgb-bg-base)) 79%, transparent 80% 100%), conic-gradient(${draft.params.poll!.options[index].length / currentInstance?.configuration?.polls.maxCharactersPerOption > 1 ? 'var(--c-danger)' : 'var(--c-primary)'} ${draft.params.poll!.options[index].length / currentInstance?.configuration?.polls.maxCharactersPerOption * 100}%, var(--c-primary-fade) 0)` }"
>{{ draft.params.poll!.options[index].length }}</span>
</div> </div>
</form> </form>
<div <div
@ -488,4 +507,18 @@ onDeactivated(() => {
background-color: var(--c-bg-btn-disabled); background-color: var(--c-bg-btn-disabled);
color: var(--c-text-btn-disabled); color: var(--c-text-btn-disabled);
} }
.option-input:focus + .delete-button {
display: none;
}
.option-input:not(:focus) + .delete-button + .char-limit-radial {
display: none;
}
.char-limit-radial {
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
}
</style> </style>

View file

@ -40,9 +40,16 @@ export function usePublish(options: {
|| (draft.attachments.length === 0 && !draft.params.status) || (draft.attachments.length === 0 && !draft.params.status)
|| failedMessages.length > 0 || failedMessages.length > 0
|| (draft.attachments.length > 0 && draft.params.poll !== null && draft.params.poll !== undefined) || (draft.attachments.length > 0 && draft.params.poll !== null && draft.params.poll !== undefined)
|| (draft.params.poll !== null && draft.params.poll !== undefined && draft.params.poll.options.length <= 1) || ((draft.params.poll !== null && draft.params.poll !== undefined)
|| (draft.params.poll !== null && draft.params.poll !== undefined && ![-1, draft.params.poll.options.length - 1].includes(draft.params.poll.options.findIndex(option => option.trim().length === 0))) && (
|| (draft.params.poll !== null && draft.params.poll !== undefined && new Set(draft.params.poll.options).size !== draft.params.poll.options.length) draft.params.poll.options.length <= 1
|| (![-1, draft.params.poll.options.length - 1].includes(draft.params.poll.options.findIndex(option => option.trim().length === 0)))
|| (new Set(draft.params.poll.options).size !== draft.params.poll.options.length)
|| (currentInstance.value?.configuration?.polls.maxCharactersPerOption !== undefined
&& draft.params.poll.options.find(option => option.length > currentInstance.value!.configuration!.polls.maxCharactersPerOption) !== undefined
)
)
)
}) })
watch(() => draft, () => { watch(() => draft, () => {

View file

@ -314,7 +314,7 @@
"disallow_multiple": "Disallow multiple choice", "disallow_multiple": "Disallow multiple choice",
"expiration": "Poll expiration", "expiration": "Poll expiration",
"hide_votes": "Hide vote totals until the end", "hide_votes": "Hide vote totals until the end",
"option_placeholder": "Poll choice", "option_placeholder": "Poll choice {current}/{max}",
"remove_option": "Remove choice", "remove_option": "Remove choice",
"settings": "Poll options", "settings": "Poll options",
"show_votes": "Always show vote totals" "show_votes": "Always show vote totals"