parent
4168b2ce41
commit
ffb8ac8ddc
@ -10,21 +10,49 @@ import '../styles/poll.scss'
|
||||
export default class MUCPollView extends CustomElement {
|
||||
static get properties () {
|
||||
return {
|
||||
model: { type: Object, attribute: true }
|
||||
model: { type: Object, attribute: true },
|
||||
collapsed: { type: Boolean, attribute: false },
|
||||
buttonDisabled: { type: Boolean, attribute: false }
|
||||
}
|
||||
}
|
||||
|
||||
async initialize () {
|
||||
this.collapsed = false
|
||||
this.buttonDisabled = false
|
||||
if (!this.model) {
|
||||
return
|
||||
}
|
||||
this.listenTo(this.model, 'change:current_poll', () => this.requestUpdate())
|
||||
this.listenTo(this.model, 'change:current_poll', () => {
|
||||
this.buttonDisabled = false
|
||||
this.requestUpdate()
|
||||
})
|
||||
}
|
||||
|
||||
render () {
|
||||
const currentPoll = this.model?.get('current_poll')
|
||||
return tplPoll(this, currentPoll)
|
||||
}
|
||||
|
||||
toggle () {
|
||||
this.collapsed = !this.collapsed
|
||||
}
|
||||
|
||||
voteFor (choice) {
|
||||
if (this.buttonDisabled) { return }
|
||||
|
||||
const currentPoll = this.model?.get('current_poll')
|
||||
if (!currentPoll) { return }
|
||||
if (currentPoll.over) { return }
|
||||
|
||||
console.info('User has voted for choice: ', choice)
|
||||
// We disable vote buttons until next refresh:
|
||||
this.buttonDisabled = true
|
||||
this.requestUpdate()
|
||||
|
||||
this.model.sendMessage({
|
||||
body: '!' + choice.choice
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
api.elements.define('livechat-converse-muc-poll', MUCPollView)
|
||||
|
@ -45,6 +45,7 @@ converse.plugins.add('livechat-converse-poll', {
|
||||
votes: parseInt(poll.getAttribute('votes') ?? 0),
|
||||
over: poll.hasAttribute('over'),
|
||||
endDate: endDate,
|
||||
time: attrs.time, // this is to be sure that we update the custom element (needed to re-enable buttons)
|
||||
choices: choices.map(c => {
|
||||
return {
|
||||
label: c.textContent,
|
||||
@ -81,9 +82,10 @@ converse.plugins.add('livechat-converse-poll', {
|
||||
}
|
||||
|
||||
console.info('Got a poll message, setting it as the current_poll')
|
||||
this.set('current_poll', attrs.current_poll)
|
||||
// this will be displayed by the livechat-converse-muc-poll custom element,
|
||||
// which is inserted in the DOM by the muc.js template overload.
|
||||
this.set('current_poll', attrs.current_poll)
|
||||
|
||||
if (attrs.current_poll.over) {
|
||||
console.info('The poll is over, displaying the message in the chat')
|
||||
return this.__super__.onMessage(attrs)
|
||||
|
@ -13,12 +13,25 @@
|
||||
border: 1px solid var(--peertube-menu-background);
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
max-height: 150px;
|
||||
overflow-y: scroll;
|
||||
|
||||
.livechat-poll-toggle {
|
||||
background: unset;
|
||||
border: 0;
|
||||
padding-left: 0.25em;
|
||||
padding-right: 0.25em;
|
||||
}
|
||||
|
||||
p.livechat-poll-question {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p.livechat-poll-instructions {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
p.livechat-poll-end {
|
||||
text-align: right;
|
||||
}
|
||||
@ -74,3 +87,28 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body[livechat-viewer-mode="on"] {
|
||||
livechat-converse-muc-poll {
|
||||
/* Dont display the poll before user choose a nickname */
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.livechat-readonly {
|
||||
.conversejs {
|
||||
livechat-converse-muc-poll {
|
||||
/* stylelint-disable-next-line no-descending-specificity */
|
||||
& > div {
|
||||
// In readonly mode, dont impose max-height
|
||||
max-height: initial !important;
|
||||
overflow-y: visible !important;
|
||||
|
||||
&.livechat-poll-over {
|
||||
// stop showing poll when over in readonly mode
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,18 @@ import { html } from 'lit'
|
||||
import { repeat } from 'lit/directives/repeat.js'
|
||||
import { __ } from 'i18n'
|
||||
|
||||
function _tplPollInstructions (el, currentPoll) {
|
||||
if (currentPoll.over) {
|
||||
return html``
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-undef
|
||||
const i18nPollInstructions = __(LOC_poll_vote_instructions)
|
||||
return html`<p class="livechat-poll-instructions">
|
||||
${i18nPollInstructions}
|
||||
</p>`
|
||||
}
|
||||
|
||||
function _tplPollEnd (el, currentPoll) {
|
||||
if (!currentPoll.endDate) {
|
||||
return html``
|
||||
@ -36,13 +48,9 @@ function _tplChoice (el, currentPoll, choice) {
|
||||
<button type="button" class="btn btn-primary btn-sm"
|
||||
@click=${ev => {
|
||||
ev.preventDefault()
|
||||
if (currentPoll.over) { return }
|
||||
|
||||
console.info('User has voted for choice: ', choice)
|
||||
el.model.sendMessage({
|
||||
body: '!' + choice.choice
|
||||
})
|
||||
el.voteFor(choice)
|
||||
}}
|
||||
?disabled=${el.buttonDisabled}
|
||||
>
|
||||
${i18nChoiceN}
|
||||
</button>`
|
||||
@ -72,11 +80,36 @@ export function tplPoll (el, currentPoll) {
|
||||
return html``
|
||||
}
|
||||
|
||||
return html`<div>
|
||||
<p class="livechat-poll-question">${currentPoll.question}</p>
|
||||
<table><tbody>
|
||||
${repeat(currentPoll.choices ?? [], (c) => c.choice, (c) => _tplChoice(el, currentPoll, c))}
|
||||
</tbody></table>
|
||||
${_tplPollEnd(el, currentPoll)}
|
||||
return html`<div class="${currentPoll.over ? 'livechat-poll-over' : ''}">
|
||||
<p class="livechat-poll-question">
|
||||
${el.collapsed
|
||||
? html`
|
||||
<button @click=${el.toggle} class="livechat-poll-toggle">
|
||||
<converse-icon
|
||||
color="var(--muc-toolbar-btn-color)"
|
||||
class="fa fa-angle-right"
|
||||
size="1em"></converse-icon>
|
||||
</button>`
|
||||
: html`
|
||||
<button @click=${el.toggle} class="livechat-poll-toggle">
|
||||
<converse-icon
|
||||
color="var(--muc-toolbar-btn-color)"
|
||||
class="fa fa-angle-down"
|
||||
size="1em"></converse-icon>
|
||||
</button>`
|
||||
}
|
||||
${currentPoll.question}
|
||||
</p>
|
||||
${
|
||||
el.collapsed
|
||||
? ''
|
||||
: html`
|
||||
<table><tbody>
|
||||
${repeat(currentPoll.choices ?? [], (c) => c.choice, (c) => _tplChoice(el, currentPoll, c))}
|
||||
</tbody></table>
|
||||
${_tplPollInstructions(el, currentPoll)}
|
||||
${_tplPollEnd(el, currentPoll)}
|
||||
`
|
||||
}
|
||||
</div>`
|
||||
}
|
||||
|
@ -44,7 +44,8 @@ const locKeys = [
|
||||
'poll_title',
|
||||
'poll_instructions',
|
||||
'poll_end',
|
||||
'poll'
|
||||
'poll',
|
||||
'poll_vote_instructions'
|
||||
]
|
||||
|
||||
module.exports = locKeys
|
||||
|
@ -573,3 +573,5 @@ poll_duration: Poll duration (in minutes)
|
||||
poll_anonymous_results: Anonymous results
|
||||
poll_choice_n: 'Choice {{N}}:'
|
||||
poll_end: 'Poll ends at:'
|
||||
poll_vote_instructions: |
|
||||
To vote, click on your choice or send a message with an exclamation mark followed by your choice number (Example: !1)
|
||||
|
@ -29,3 +29,5 @@ Here are the existing strings and default values:
|
||||
|
||||
* poll_string_over: This poll is now over.
|
||||
* poll_string_vote_instructions: Send a message with an exclamation mark followed by your choice number to vote. Example: !1
|
||||
* poll_string_invalid_choice: This choice is not valid.
|
||||
* poll_string_anonymous_vote_ok: You vote is taken into account. Votes are anonymous, it will not be shown to other participants.
|
||||
|
@ -11,6 +11,9 @@ local poll_start_message = module:require("message").poll_start_message;
|
||||
local poll_end_message = module:require("message").poll_end_message;
|
||||
local schedule_poll_update_message = module:require("message").schedule_poll_update_message;
|
||||
|
||||
local string_poll_invalid_choice = module:get_option_string("poll_string_invalid_choice") or "This choice is not valid.";
|
||||
local string_poll_anonymous_vote_ok = module:get_option_string("poll_string_anonymous_vote_ok") or "You vote is taken into account. Votes are anonymous, it will not be shown to other participants.";
|
||||
|
||||
local scheduled_end = {};
|
||||
|
||||
local function schedule_poll_purge(room_jid)
|
||||
@ -171,7 +174,7 @@ local function handle_groupchat(event)
|
||||
"cancel",
|
||||
-- error_condition = 'not-allowed' (see RFC 6120 Defined Error Conditions https://xmpp.org/rfcs/rfc6120.html#stanzas-error-conditions)
|
||||
"bad-request",
|
||||
"This choice is not valid."
|
||||
string_poll_invalid_choice
|
||||
));
|
||||
return true; -- stop!
|
||||
end
|
||||
@ -205,7 +208,7 @@ local function handle_groupchat(event)
|
||||
"continue",
|
||||
-- error_condition
|
||||
"undefined-condition",
|
||||
"You vote is taken into account. Votes are anonymous, it will not be shown to other participants."
|
||||
string_poll_anonymous_vote_ok
|
||||
));
|
||||
return true; -- stop!
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user