mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-11-09 00:30:02 +00:00
844 lines
30 KiB
HTML
844 lines
30 KiB
HTML
|
<html>
|
||
|
|
||
|
<title>Twitch-Bot: Config-Editor</title>
|
||
|
<link rel="stylesheet" href="editor/bundle.css">
|
||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/css/all.min.css">
|
||
|
|
||
|
<style>
|
||
|
[v-cloak] {
|
||
|
display: none;
|
||
|
}
|
||
|
.btn-twitch {
|
||
|
background-color: #6441a5;
|
||
|
}
|
||
|
</style>
|
||
|
|
||
|
<div id="app" v-cloak>
|
||
|
<b-navbar toggleable="lg" type="dark" variant="primary" class="mb-3">
|
||
|
<b-navbar-brand href="#"><i class="fas fa-fw fa-robot mr-1"></i> Twitch-Bot</b-navbar-brand>
|
||
|
|
||
|
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
|
||
|
|
||
|
<b-collapse id="nav-collapse" is-nav>
|
||
|
<b-navbar-nav v-if="authToken">
|
||
|
<b-nav-item :active="editMode === 'general'" @click="editMode = 'general'">
|
||
|
<i class="fas fa-fw fa-cog mr-1"></i>
|
||
|
General
|
||
|
</b-nav-item>
|
||
|
<b-nav-item :active="editMode === 'automessages'" @click="editMode = 'automessages'">
|
||
|
<i class="fas fa-fw fa-envelope-open-text mr-1"></i>
|
||
|
Auto-Messages
|
||
|
<b-badge pill>{{ autoMessages.length }}
|
||
|
</b-badge></b-nav-item>
|
||
|
<b-nav-item :active="editMode === 'rules'" @click="editMode = 'rules'">
|
||
|
<i class="fas fa-fw fa-inbox mr-1"></i>
|
||
|
Rules
|
||
|
<b-badge pill>{{ rules.length }}</b-badge>
|
||
|
</b-nav-item>
|
||
|
</b-navbar-nav>
|
||
|
|
||
|
<b-navbar-nav class="ml-auto">
|
||
|
<b-nav-text>
|
||
|
<span v-if="configNotifySocketConnected">
|
||
|
<i
|
||
|
class="fas fa-fw fa-ethernet mr-1 text-success"
|
||
|
title="Connected to Bot"
|
||
|
v-b-tooltip.hover
|
||
|
></i>
|
||
|
</span>
|
||
|
<span v-else>
|
||
|
<i
|
||
|
class="fas fa-fw fa-ethernet mr-1 text-danger"
|
||
|
title="Disconnected from Bot"
|
||
|
v-b-tooltip.hover
|
||
|
></i>
|
||
|
</span>
|
||
|
</b-nav-text>
|
||
|
</b-navbar-nav>
|
||
|
</b-collapse>
|
||
|
|
||
|
</b-navbar>
|
||
|
|
||
|
<b-container>
|
||
|
<!-- Error display -->
|
||
|
<b-row v-if="error">
|
||
|
<b-col>
|
||
|
<b-alert
|
||
|
dismissible
|
||
|
@dismissed="error = null"
|
||
|
show
|
||
|
variant="danger"
|
||
|
>
|
||
|
<i class="fas fa-fw fa-exclamation-circle mr-1"></i> {{ error }}
|
||
|
</b-alert>
|
||
|
</b-col>
|
||
|
</b-row>
|
||
|
|
||
|
<!-- Working display -->
|
||
|
<b-row v-if="changePending">
|
||
|
<b-col>
|
||
|
<b-alert
|
||
|
show
|
||
|
variant="info"
|
||
|
>
|
||
|
<i class="fas fa-fw fa-spinner fa-pulse mr-1"></i>
|
||
|
Your change was submitted and is pending, please wait for config to be updated!
|
||
|
</b-alert>
|
||
|
</b-col>
|
||
|
</b-row>
|
||
|
|
||
|
<!-- Logged-out state -->
|
||
|
<b-row
|
||
|
v-if="!authToken"
|
||
|
>
|
||
|
|
||
|
<b-col
|
||
|
class="text-center"
|
||
|
>
|
||
|
<b-button
|
||
|
:disabled="!vars.TwitchClientID"
|
||
|
:href="authURL"
|
||
|
variant="twitch"
|
||
|
>
|
||
|
<i class="fab fa-fw fa-twitch mr-1"></i> Login with Twitch
|
||
|
</b-button>
|
||
|
</b-col>
|
||
|
|
||
|
</b-row>
|
||
|
|
||
|
<!-- Logged-in state -->
|
||
|
<template v-else>
|
||
|
|
||
|
<b-row v-if="editMode === 'general'">
|
||
|
<b-col>
|
||
|
<b-card-group columns>
|
||
|
|
||
|
<b-card no-body>
|
||
|
<b-card-header>
|
||
|
<i class="fas fa-fw fa-hashtag mr-1"></i> Channels
|
||
|
</b-card-header>
|
||
|
<b-list-group flush>
|
||
|
<b-list-group-item
|
||
|
class="d-flex align-items-center align-middle"
|
||
|
:key="channel"
|
||
|
v-for="channel in sortedChannels"
|
||
|
>
|
||
|
<span class="mr-auto">
|
||
|
<i class="fas fa-fw fa-hashtag mr-1"></i>
|
||
|
{{ channel }}
|
||
|
</span>
|
||
|
<b-button
|
||
|
@click="removeChannel(channel)"
|
||
|
size="sm"
|
||
|
variant="danger"
|
||
|
>
|
||
|
<i class="fas fa-fw fa-minus"></i>
|
||
|
</b-button>
|
||
|
</b-list-group-item>
|
||
|
|
||
|
<b-list-group-item>
|
||
|
<b-input-group>
|
||
|
<b-form-input @keyup.enter="addChannel" v-model="models.addChannel"></b-form-input>
|
||
|
<b-input-group-append>
|
||
|
<b-button @click="addChannel" variant="success"><i class="fas fa-fw fa-plus mr-1"></i> Add</b-button>
|
||
|
</b-input-group-append>
|
||
|
</b-input-group>
|
||
|
</b-list-group-item>
|
||
|
</b-list-group>
|
||
|
</b-card>
|
||
|
|
||
|
<b-card no-body>
|
||
|
<b-card-header>
|
||
|
<i class="fas fa-fw fa-users mr-1"></i> Bot-Editors
|
||
|
</b-card-header>
|
||
|
<b-list-group flush>
|
||
|
<b-list-group-item
|
||
|
class="d-flex align-items-center align-middle"
|
||
|
:key="editor"
|
||
|
v-for="editor in sortedEditors"
|
||
|
>
|
||
|
<b-avatar class="mr-3" :src="userProfiles[editor]?.profile_image_url"></b-avatar>
|
||
|
<span class="mr-auto">{{ userProfiles[editor] ? userProfiles[editor].display_name : editor }}</span>
|
||
|
<b-button
|
||
|
@click="removeEditor(editor)"
|
||
|
size="sm"
|
||
|
variant="danger"
|
||
|
>
|
||
|
<i class="fas fa-fw fa-minus"></i>
|
||
|
</b-button>
|
||
|
</b-list-group-item>
|
||
|
|
||
|
<b-list-group-item>
|
||
|
<b-input-group>
|
||
|
<b-form-input @keyup.enter="addEditor" v-model="models.addEditor"></b-form-input>
|
||
|
<b-input-group-append>
|
||
|
<b-button @click="addEditor" variant="success"><i class="fas fa-fw fa-plus mr-1"></i> Add</b-button>
|
||
|
</b-input-group-append>
|
||
|
</b-input-group>
|
||
|
</b-list-group-item>
|
||
|
</b-list-group>
|
||
|
</b-card>
|
||
|
|
||
|
</b-card-group>
|
||
|
</b-col>
|
||
|
</b-row>
|
||
|
|
||
|
<b-row v-else-if="editMode === 'automessages'">
|
||
|
<b-col>
|
||
|
<b-table
|
||
|
:busy="!autoMessages"
|
||
|
:fields="autoMessageFields"
|
||
|
hover
|
||
|
:items="autoMessages"
|
||
|
key="autoMessagesTable"
|
||
|
striped
|
||
|
>
|
||
|
<template #cell(actions)="data">
|
||
|
<b-button-group size="sm">
|
||
|
<b-button @click="editAutoMessage(data.item)"><i class="fas fa-fw fa-pen"></i></b-button>
|
||
|
<b-button @click="deleteAutoMessage(data.item.uuid)" variant="danger"><i class="fas fa-fw fa-minus"></i></b-button>
|
||
|
</b-button-group>
|
||
|
</template>
|
||
|
|
||
|
<template #cell(channel)="data">
|
||
|
<i class="fas fa-fw fa-hashtag mr-1"></i>
|
||
|
{{ data.value }}
|
||
|
</template>
|
||
|
|
||
|
<template #cell(cron)="data">
|
||
|
<code>{{ data.value }}</code>
|
||
|
</template>
|
||
|
|
||
|
<template #head(actions)="data">
|
||
|
<b-button-group size="sm">
|
||
|
<b-button @click="newAutoMessage" variant="success"><i class="fas fa-fw fa-plus"></i></b-button>
|
||
|
</b-button-group>
|
||
|
</template>
|
||
|
</b-table>
|
||
|
</b-col>
|
||
|
</b-row>
|
||
|
|
||
|
<b-row v-else-if="editMode === 'rules'">
|
||
|
<b-col>
|
||
|
<b-table
|
||
|
:busy="!rules"
|
||
|
:fields="rulesFields"
|
||
|
hover
|
||
|
:items="rules"
|
||
|
key="rulesTable"
|
||
|
striped
|
||
|
>
|
||
|
<template #cell(_actions)="data">
|
||
|
<b-button-group size="sm">
|
||
|
<b-button @click="editRule(data.item)"><i class="fas fa-fw fa-pen"></i></b-button>
|
||
|
<b-button @click="deleteRule(data.item.uuid)" variant="danger"><i class="fas fa-fw fa-minus"></i></b-button>
|
||
|
</b-button-group>
|
||
|
</template>
|
||
|
|
||
|
<template #cell(_match)="data">
|
||
|
<b-badge
|
||
|
class="m-1 text-truncate text-left col-12"
|
||
|
style="max-width: 250px;"
|
||
|
v-for="badge in formatRuleMatch(data.item)"
|
||
|
>
|
||
|
<strong>{{ badge.key }}</strong> <code class="ml-2">{{ badge.value }}</code>
|
||
|
</b-badge>
|
||
|
</template>
|
||
|
|
||
|
<template #cell(_description)="data">
|
||
|
<template v-if="data.item.description">{{ data.item.description }}<br></template>
|
||
|
<b-badge
|
||
|
class="mt-1 mr-1"
|
||
|
v-for="badge in formatRuleActions(data.item)"
|
||
|
>
|
||
|
{{ badge }}
|
||
|
</b-badge>
|
||
|
</template>
|
||
|
|
||
|
<template #head(_actions)="data">
|
||
|
<b-button-group size="sm">
|
||
|
<b-button @click="newRule" variant="success"><i class="fas fa-fw fa-plus"></i></b-button>
|
||
|
</b-button-group>
|
||
|
</template>
|
||
|
</b-table>
|
||
|
</b-col>
|
||
|
</b-row>
|
||
|
|
||
|
</template>
|
||
|
|
||
|
<!-- Auto-Message Editor -->
|
||
|
<b-modal
|
||
|
@hidden="showAutoMessageEditModal=false"
|
||
|
hide-header-close
|
||
|
@ok="saveAutoMessage"
|
||
|
:ok-disabled="!validateAutoMessage"
|
||
|
ok-title="Save"
|
||
|
size="lg"
|
||
|
:visible="showAutoMessageEditModal"
|
||
|
title="Edit Auto-Message"
|
||
|
v-if="showAutoMessageEditModal"
|
||
|
>
|
||
|
<b-row>
|
||
|
<b-col cols="8">
|
||
|
|
||
|
<b-form-group
|
||
|
label="Channel"
|
||
|
label-for="formAutoMessageChannel"
|
||
|
>
|
||
|
<b-input-group
|
||
|
prepend="#"
|
||
|
>
|
||
|
<b-form-input
|
||
|
id="formAutoMessageChannel"
|
||
|
:state="validateAutoMessageChannel"
|
||
|
type="text"
|
||
|
required
|
||
|
v-model="models.autoMessage.channel"
|
||
|
></b-form-input>
|
||
|
</b-input-group>
|
||
|
</b-form-group>
|
||
|
|
||
|
<hr>
|
||
|
|
||
|
<b-form-group
|
||
|
:description="`${models.autoMessage.message?.length || 0} / ${validateAutoMessageMessageLength}`"
|
||
|
label="Message"
|
||
|
label-for="formAutoMessageMessage"
|
||
|
>
|
||
|
<b-form-textarea
|
||
|
id="formAutoMessageMessage"
|
||
|
max-rows="6"
|
||
|
required
|
||
|
rows="3"
|
||
|
:state="models.autoMessage.message?.length <= validateAutoMessageMessageLength"
|
||
|
v-model="models.autoMessage.message"
|
||
|
></b-form-textarea>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group>
|
||
|
<b-form-checkbox
|
||
|
switch
|
||
|
v-model="models.autoMessage.use_action"
|
||
|
>
|
||
|
Send message as action (<code>/me</code>)
|
||
|
</b-form-checkbox>
|
||
|
</b-form-group>
|
||
|
|
||
|
<hr>
|
||
|
|
||
|
<b-form-group
|
||
|
label="Sending Mode"
|
||
|
label-for="formAutoMessageSendMode"
|
||
|
>
|
||
|
<b-form-select
|
||
|
id="formAutoMessageSendMode"
|
||
|
:options="autoMessageSendModes"
|
||
|
v-model="models.autoMessage.sendMode"
|
||
|
></b-form-select>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group
|
||
|
label="Send at"
|
||
|
label-for="formAutoMessageCron"
|
||
|
v-if="models.autoMessage.sendMode === 'cron'"
|
||
|
>
|
||
|
<b-form-input
|
||
|
id="formAutoMessageCron"
|
||
|
v-model="models.autoMessage.cron"
|
||
|
:state="validateAutoMessageCron"
|
||
|
type="text"
|
||
|
></b-form-input>
|
||
|
|
||
|
<div slot="description">
|
||
|
<code>@every [time]</code> or Cron syntax
|
||
|
</div>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group
|
||
|
label="Send every"
|
||
|
label-for="formAutoMessageNLines"
|
||
|
v-if="models.autoMessage.sendMode === 'lines'"
|
||
|
>
|
||
|
<b-input-group
|
||
|
append="Lines"
|
||
|
>
|
||
|
<b-form-input
|
||
|
id="formAutoMessageNLines"
|
||
|
v-model="models.autoMessage.message_interval"
|
||
|
type="number"
|
||
|
></b-form-input>
|
||
|
</b-input-group>
|
||
|
</b-form-group>
|
||
|
|
||
|
<hr>
|
||
|
|
||
|
<b-form-group>
|
||
|
<b-form-checkbox
|
||
|
switch
|
||
|
v-model="models.autoMessage.only_on_live"
|
||
|
>
|
||
|
Send only when channel is live
|
||
|
</b-form-checkbox>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group
|
||
|
label="Disable on Template"
|
||
|
label-for="formAutoMessageDisableOnTemplate"
|
||
|
>
|
||
|
<div slot="description">
|
||
|
Template expression resulting in <code>true</code> to disable the rule or <code>false</code> to enable it
|
||
|
</div>
|
||
|
<b-form-textarea
|
||
|
id="formAutoMessageDisableOnTemplate"
|
||
|
max-rows="6"
|
||
|
required
|
||
|
rows="1"
|
||
|
v-model="models.autoMessage.disable_on_template"
|
||
|
></b-form-textarea>
|
||
|
</b-form-group>
|
||
|
|
||
|
</b-col>
|
||
|
|
||
|
<b-col cols="4">
|
||
|
<h6>Getting Help</h6>
|
||
|
<p>
|
||
|
For information about available template functions and variables to use in the <strong>Message</strong> see the <a href="https://github.com/Luzifer/twitch-bot/wiki#templating" target="_blank">Templating</a> section of the Wiki.
|
||
|
</p>
|
||
|
<p>
|
||
|
For information about the <strong>Cron</strong> syntax have a look at the <a href="https://cron.help/" target="_blank">cron.help</a> site. Aditionally you can use <code>@every [time]</code> syntax. The <code>[time]</code> part is in format <code>1h30m20s</code>. You can leave out every segment but need to specify the unit of every segment. So for example <code>@every 1h</code> or <code>@every 10m</code> would be a valid specification.
|
||
|
</p>
|
||
|
</b-col>
|
||
|
</b-row>
|
||
|
|
||
|
</b-modal>
|
||
|
|
||
|
<!-- Rule Editor -->
|
||
|
<b-modal
|
||
|
@hidden="showRuleEditModal=false"
|
||
|
hide-header-close
|
||
|
@ok="saveRule"
|
||
|
:ok-disabled="!validateRule"
|
||
|
ok-title="Save"
|
||
|
scrollable
|
||
|
size="xl"
|
||
|
:visible="showRuleEditModal"
|
||
|
title="Edit Rule"
|
||
|
v-if="showRuleEditModal"
|
||
|
>
|
||
|
<b-row>
|
||
|
<b-col cols="6">
|
||
|
|
||
|
<b-form-group
|
||
|
description="Human readable description for the rules list"
|
||
|
label="Description"
|
||
|
label-for="formRuleDescription"
|
||
|
>
|
||
|
<b-form-input
|
||
|
id="formRuleDescription"
|
||
|
type="text"
|
||
|
v-model="models.rule.description"
|
||
|
></b-form-input>
|
||
|
</b-form-group>
|
||
|
|
||
|
<hr>
|
||
|
|
||
|
<b-tabs content-class="mt-3">
|
||
|
<b-tab>
|
||
|
<div slot="title">
|
||
|
Matcher <b-badge>{{ countRuleMatchers }}</b-badge>
|
||
|
</div>
|
||
|
|
||
|
<b-form-group
|
||
|
description="Channel with leading hash: #mychannel - matches all channels if none are given"
|
||
|
label="Match Channels"
|
||
|
label-for="formRuleMatchChannels"
|
||
|
>
|
||
|
<b-form-tags
|
||
|
id="formRuleMatchChannels"
|
||
|
no-add-on-enter
|
||
|
placeholder="Enter channels separated by space or comma"
|
||
|
remove-on-delete
|
||
|
separator=" ,"
|
||
|
:tag-validator="(tag) => Boolean(tag.match(/^#[a-zA-Z0-9_]{4,25}$/))"
|
||
|
v-model="models.rule.match_channels"
|
||
|
></b-form-tags>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group
|
||
|
description="Matches no events if not set"
|
||
|
label="Match Event"
|
||
|
label-for="formRuleMatchEvent"
|
||
|
>
|
||
|
<b-form-select
|
||
|
id="formRuleMatchEvent"
|
||
|
:options="availableEvents"
|
||
|
v-model="models.rule.match_event"
|
||
|
></b-form-select>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group
|
||
|
description="Regular expression to match the message, matches all messages when not set"
|
||
|
label="Match Message"
|
||
|
label-for="formRuleMatchMessage"
|
||
|
>
|
||
|
<b-form-input
|
||
|
id="formRuleMatchMessage"
|
||
|
:state="models.rule.match_message__validation"
|
||
|
type="text"
|
||
|
v-model="models.rule.match_message"
|
||
|
></b-form-input>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group
|
||
|
description="Matches all users if none are given"
|
||
|
label="Match Users"
|
||
|
label-for="formRuleMatchUsers"
|
||
|
>
|
||
|
<b-form-tags
|
||
|
id="formRuleMatchUsers"
|
||
|
no-add-on-enter
|
||
|
placeholder="Enter usernames separated by space or comma"
|
||
|
remove-on-delete
|
||
|
separator=" ,"
|
||
|
:tag-validator="(tag) => Boolean(tag.match(/^[a-z0-9_]{4,25}$/))"
|
||
|
v-model="models.rule.match_users"
|
||
|
></b-form-tags>
|
||
|
</b-form-group>
|
||
|
|
||
|
</b-tab>
|
||
|
<b-tab>
|
||
|
<div slot="title">
|
||
|
Cooldown <b-badge>{{ countRuleCooldowns }}</b-badge>
|
||
|
</div>
|
||
|
|
||
|
<b-row>
|
||
|
<b-col>
|
||
|
<b-form-group
|
||
|
label="Rule Cooldown"
|
||
|
label-for="formRuleRuleCooldown"
|
||
|
>
|
||
|
<b-form-input
|
||
|
id="formRuleRuleCooldown"
|
||
|
placeholder="No Cooldown"
|
||
|
:state="validateDuration(models.rule.cooldown, false)"
|
||
|
type="text"
|
||
|
v-model="models.rule.cooldown"
|
||
|
></b-form-input>
|
||
|
</b-form-group>
|
||
|
</b-col>
|
||
|
<b-col>
|
||
|
<b-form-group
|
||
|
label="Channel Cooldown"
|
||
|
label-for="formRuleChannelCooldown"
|
||
|
>
|
||
|
<b-form-input
|
||
|
id="formRuleChannelCooldown"
|
||
|
placeholder="No Cooldown"
|
||
|
:state="validateDuration(models.rule.channel_cooldown, false)"
|
||
|
type="text"
|
||
|
v-model="models.rule.channel_cooldown"
|
||
|
></b-form-input>
|
||
|
</b-form-group>
|
||
|
</b-col>
|
||
|
<b-col>
|
||
|
<b-form-group
|
||
|
label="User Cooldown"
|
||
|
label-for="formRuleUserCooldown"
|
||
|
>
|
||
|
<b-form-input
|
||
|
id="formRuleUserCooldown"
|
||
|
placeholder="No Cooldown"
|
||
|
:state="validateDuration(models.rule.user_cooldown, false)"
|
||
|
type="text"
|
||
|
v-model="models.rule.user_cooldown"
|
||
|
></b-form-input>
|
||
|
</b-form-group>
|
||
|
</b-row>
|
||
|
|
||
|
<b-form-group
|
||
|
:description="`Available badges: ${vars.IRCBadges?.join(', ')}`"
|
||
|
label="Skip Cooldown for"
|
||
|
label-for="formRuleSkipCooldown"
|
||
|
>
|
||
|
<b-form-tags
|
||
|
id="formRuleSkipCooldown"
|
||
|
no-add-on-enter
|
||
|
placeholder="Enter badges separated by space or comma"
|
||
|
remove-on-delete
|
||
|
separator=" ,"
|
||
|
:tag-validator="validateTwitchBadge"
|
||
|
v-model="models.rule.skip_cooldown_for"
|
||
|
></b-form-tags>
|
||
|
</b-form-group>
|
||
|
|
||
|
</b-tab>
|
||
|
<b-tab>
|
||
|
<div slot="title">
|
||
|
Conditions <b-badge>{{ countRuleConditions }}</b-badge>
|
||
|
</div>
|
||
|
|
||
|
<p>Disable rule…</p>
|
||
|
<b-row>
|
||
|
<b-col>
|
||
|
<b-form-group>
|
||
|
<b-form-checkbox
|
||
|
switch
|
||
|
v-model="models.rule.disable"
|
||
|
>
|
||
|
completely
|
||
|
</b-form-checkbox>
|
||
|
</b-form-group>
|
||
|
</b-col>
|
||
|
<b-col>
|
||
|
<b-form-group>
|
||
|
<b-form-checkbox
|
||
|
switch
|
||
|
v-model="models.rule.disable_on_offline"
|
||
|
>
|
||
|
when channel is offline
|
||
|
</b-form-checkbox>
|
||
|
</b-form-group>
|
||
|
</b-col>
|
||
|
<b-col>
|
||
|
<b-form-group>
|
||
|
<b-form-checkbox
|
||
|
switch
|
||
|
v-model="models.rule.disable_on_permit"
|
||
|
>
|
||
|
when user has permit
|
||
|
</b-form-checkbox>
|
||
|
</b-form-group>
|
||
|
</b-col>
|
||
|
</b-row>
|
||
|
|
||
|
<b-form-group
|
||
|
:description="`Available badges: ${vars.IRCBadges?.join(', ')}`"
|
||
|
label="Disable Rule for"
|
||
|
label-for="formRuleDisableOn"
|
||
|
>
|
||
|
<b-form-tags
|
||
|
id="formRuleDisableOn"
|
||
|
no-add-on-enter
|
||
|
placeholder="Enter badges separated by space or comma"
|
||
|
remove-on-delete
|
||
|
separator=" ,"
|
||
|
:tag-validator="validateTwitchBadge"
|
||
|
v-model="models.rule.disable_on"
|
||
|
></b-form-tags>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group
|
||
|
:description="`Available badges: ${vars.IRCBadges?.join(', ')}`"
|
||
|
label="Enable Rule for"
|
||
|
label-for="formRuleEnableOn"
|
||
|
>
|
||
|
<b-form-tags
|
||
|
id="formRuleEnableOn"
|
||
|
no-add-on-enter
|
||
|
placeholder="Enter badges separated by space or comma"
|
||
|
remove-on-delete
|
||
|
separator=" ,"
|
||
|
:tag-validator="validateTwitchBadge"
|
||
|
v-model="models.rule.enable_on"
|
||
|
></b-form-tags>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group
|
||
|
label="Disable on Template"
|
||
|
label-for="formRuleDisableOnTemplate"
|
||
|
>
|
||
|
<div slot="description">
|
||
|
Template expression resulting in <code>true</code> to disable the rule or <code>false</code> to enable it
|
||
|
</div>
|
||
|
<b-form-textarea
|
||
|
id="formRuleDisableOnTemplate"
|
||
|
max-rows="6"
|
||
|
required
|
||
|
rows="1"
|
||
|
v-model="models.rule.disable_on_template"
|
||
|
></b-form-textarea>
|
||
|
</b-form-group>
|
||
|
|
||
|
</b-tab>
|
||
|
</b-tabs>
|
||
|
|
||
|
</b-col>
|
||
|
|
||
|
<b-col cols="6">
|
||
|
|
||
|
<div class="accordion" role="tablist">
|
||
|
<b-card
|
||
|
:key="`${models.rule.uuid}-action-${idx}`"
|
||
|
no-body
|
||
|
class="mb-1"
|
||
|
v-for="(action, idx) in models.rule.actions"
|
||
|
>
|
||
|
<b-card-header header-tag="header" class="p-1 d-flex" role="tab">
|
||
|
<b-button-group class="flex-fill">
|
||
|
<b-button
|
||
|
block
|
||
|
v-b-toggle="`${models.rule.uuid}-action-${idx}`"
|
||
|
variant="primary"
|
||
|
>
|
||
|
{{ getActionDefinitionByType(action.type).name }}
|
||
|
<i class="fas fa-fw fa-exclamation-triangle text-danger" v-if="actionHasValidationError(idx)"></i>
|
||
|
</b-button>
|
||
|
<b-button
|
||
|
@click="moveAction(idx, -1)"
|
||
|
:disabled="idx === 0"
|
||
|
variant="secondary"
|
||
|
><i class="fas fa-fw fa-chevron-up"></i></b-button>
|
||
|
<b-button
|
||
|
@click="moveAction(idx, +1)"
|
||
|
:disabled="idx === models.rule.actions.length - 1"
|
||
|
variant="secondary"
|
||
|
><i class="fas fa-fw fa-chevron-down"></i></b-button>
|
||
|
<b-button
|
||
|
@click="removeAction(idx)"
|
||
|
variant="danger"
|
||
|
><i class="fas fa-fw fa-trash"></i></b-button>
|
||
|
</b-button-group>
|
||
|
</b-card-header>
|
||
|
<b-collapse
|
||
|
:id="`${models.rule.uuid}-action-${idx}`"
|
||
|
accordion="my-accordion"
|
||
|
role="tabpanel"
|
||
|
>
|
||
|
<b-card-body v-if="getActionDefinitionByType(action.type).fields?.length > 0">
|
||
|
<template
|
||
|
v-for="field in getActionDefinitionByType(action.type).fields"
|
||
|
>
|
||
|
<b-form-group
|
||
|
v-if="field.type === 'bool'"
|
||
|
>
|
||
|
<div slot="description">
|
||
|
<i
|
||
|
class="fas fa-fw fa-code mr-1 text-success"
|
||
|
title="Supports Templating"
|
||
|
v-if="field.support_template"
|
||
|
></i>
|
||
|
{{ field.description }}
|
||
|
</div>
|
||
|
|
||
|
<b-form-checkbox
|
||
|
switch
|
||
|
v-model="models.rule.actions[idx].attributes[field.key]"
|
||
|
>
|
||
|
{{ field.name }}
|
||
|
</b-form-checkbox>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group
|
||
|
:label="field.name"
|
||
|
:label-for="`${models.rule.uuid}-action-${idx}-${field.key}`"
|
||
|
v-else-if="field.type === 'stringslice'"
|
||
|
>
|
||
|
<div slot="description">
|
||
|
<i
|
||
|
class="fas fa-fw fa-code mr-1 text-success"
|
||
|
title="Supports Templating"
|
||
|
v-if="field.support_template"
|
||
|
></i>
|
||
|
{{ field.description }}
|
||
|
</div>
|
||
|
|
||
|
<b-form-tags
|
||
|
:id="`${models.rule.uuid}-action-${idx}-${field.key}`"
|
||
|
:state="validateActionArgument(idx, field.key)"
|
||
|
placeholder="Enter elements and press enter to add the element"
|
||
|
remove-on-delete
|
||
|
v-model="models.rule.actions[idx].attributes[field.key]"
|
||
|
></b-form-tags>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group
|
||
|
:label="field.name"
|
||
|
:label-for="`${models.rule.uuid}-action-${idx}-${field.key}`"
|
||
|
v-else-if="field.type === 'string' && field.long"
|
||
|
>
|
||
|
<div slot="description">
|
||
|
<i
|
||
|
class="fas fa-fw fa-code mr-1 text-success"
|
||
|
title="Supports Templating"
|
||
|
v-if="field.support_template"
|
||
|
></i>
|
||
|
{{ field.description }}
|
||
|
</div>
|
||
|
|
||
|
<b-form-textarea
|
||
|
:id="`${models.rule.uuid}-action-${idx}-${field.key}`"
|
||
|
max-rows="6"
|
||
|
:required="!field.optional"
|
||
|
rows="3"
|
||
|
:state="validateActionArgument(idx, field.key)"
|
||
|
v-model="models.rule.actions[idx].attributes[field.key]"
|
||
|
></b-form-textarea>
|
||
|
</b-form-group>
|
||
|
|
||
|
<b-form-group
|
||
|
:label="field.name"
|
||
|
:label-for="`${models.rule.uuid}-action-${idx}-${field.key}`"
|
||
|
v-else
|
||
|
>
|
||
|
<div slot="description">
|
||
|
<i
|
||
|
class="fas fa-fw fa-code mr-1 text-success"
|
||
|
title="Supports Templating"
|
||
|
v-if="field.support_template"
|
||
|
></i>
|
||
|
{{ field.description }}
|
||
|
</div>
|
||
|
|
||
|
<b-form-input
|
||
|
:id="`${models.rule.uuid}-action-${idx}-${field.key}`"
|
||
|
:placeholder="field.default"
|
||
|
:required="!field.optional"
|
||
|
:state="validateActionArgument(idx, field.key)"
|
||
|
type="text"
|
||
|
v-model="models.rule.actions[idx].attributes[field.key]"
|
||
|
></b-form-input>
|
||
|
</b-form-group>
|
||
|
|
||
|
</template>
|
||
|
</b-card-body>
|
||
|
<b-card-body v-else>
|
||
|
This action has no attributes.
|
||
|
</b-card-body>
|
||
|
</b-collapse>
|
||
|
</b-card>
|
||
|
|
||
|
<hr>
|
||
|
|
||
|
<b-form-group
|
||
|
label="Add Action"
|
||
|
label-for="ruleAddAction"
|
||
|
>
|
||
|
<b-input-group>
|
||
|
<b-form-select
|
||
|
id="ruleAddAction"
|
||
|
:options="availableActionsForAdd"
|
||
|
v-model="models.addAction"
|
||
|
></b-form-select>
|
||
|
<b-input-group-append>
|
||
|
<b-button
|
||
|
@click="addAction"
|
||
|
:disabled="!models.addAction"
|
||
|
variant="success"
|
||
|
><i class="fas fa-fw fa-plus mr-1"></i> Add</b-button>
|
||
|
</b-input-group-append>
|
||
|
</b-input-group>
|
||
|
</b-form-group>
|
||
|
<div>
|
||
|
|
||
|
</b-col>
|
||
|
</b-row>
|
||
|
|
||
|
</b-modal>
|
||
|
|
||
|
</b-container>
|
||
|
</div>
|
||
|
|
||
|
<script src="editor/bundle.js"></script>
|
||
|
<script src="editor/app.js"></script>
|
||
|
</html>
|