Custom naming schemes
This commit is contained in:
parent
b8d2bf03ff
commit
d5f8e58b3a
@ -23,6 +23,11 @@ import (
|
||||
|
||||
const freePanelLimit = 3
|
||||
|
||||
var (
|
||||
placeholderPattern = regexp.MustCompile(`%(\w+)%`)
|
||||
channelNamePattern = regexp.MustCompile(`^[\w\d-_]+$`)
|
||||
)
|
||||
|
||||
type panelBody struct {
|
||||
ChannelId uint64 `json:"channel_id,string"`
|
||||
MessageId uint64 `json:"message_id,string"`
|
||||
@ -40,6 +45,7 @@ type panelBody struct {
|
||||
ButtonStyle component.ButtonStyle `json:"button_style,string"`
|
||||
ButtonLabel string `json:"button_label"`
|
||||
FormId *int `json:"form_id"`
|
||||
NamingScheme *string `json:"naming_scheme"`
|
||||
}
|
||||
|
||||
func (p *panelBody) IntoPanelMessageData(customId string, isPremium bool) panelMessageData {
|
||||
@ -153,6 +159,7 @@ func CreatePanel(ctx *gin.Context) {
|
||||
ButtonStyle: int(data.ButtonStyle),
|
||||
ButtonLabel: data.ButtonLabel,
|
||||
FormId: data.FormId,
|
||||
NamingScheme: data.NamingScheme,
|
||||
}
|
||||
|
||||
panelId, err := dbclient.Client.Panel.Create(panel)
|
||||
@ -305,6 +312,11 @@ func (p *panelBody) doValidations(ctx *gin.Context, guildId uint64) bool {
|
||||
}
|
||||
}
|
||||
|
||||
if !p.verifyNamingScheme() {
|
||||
ctx.JSON(400, utils.ErrorStr("Invalid naming scheme: ensure that the naming scheme is less than 100 characters and the placeholders you have used are valid"))
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@ -459,6 +471,47 @@ func (p *panelBody) verifyTeams(guildId uint64) (bool, error) {
|
||||
return dbclient.Client.SupportTeam.AllTeamsExistForGuild(guildId, p.Teams)
|
||||
}
|
||||
|
||||
func (p *panelBody) verifyNamingScheme() bool {
|
||||
if p.NamingScheme == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(*p.NamingScheme) == 0 {
|
||||
p.NamingScheme = nil
|
||||
return true
|
||||
}
|
||||
|
||||
// Substitute out {} users may use by mistake, spaces for dashes and convert to lowercase
|
||||
p.NamingScheme = utils.Ptr(strings.ReplaceAll(*p.NamingScheme, "{", "%"))
|
||||
p.NamingScheme = utils.Ptr(strings.ReplaceAll(*p.NamingScheme, "}", "%"))
|
||||
p.NamingScheme = utils.Ptr(strings.ReplaceAll(*p.NamingScheme, " ", "-"))
|
||||
p.NamingScheme = utils.Ptr(strings.ToLower(*p.NamingScheme))
|
||||
|
||||
if len(*p.NamingScheme) > 100 {
|
||||
return false
|
||||
}
|
||||
|
||||
// We must remove all placeholders from the string to check whether the rest of the string is legal
|
||||
noPlaceholders := *p.NamingScheme
|
||||
|
||||
// Validate placeholders used
|
||||
validPlaceholders := []string{"id", "username"}
|
||||
for _, match := range placeholderPattern.FindAllStringSubmatch(*p.NamingScheme, -1) {
|
||||
if len(match) < 2 { // Infallible
|
||||
return false
|
||||
}
|
||||
|
||||
placeholder := match[1]
|
||||
if !utils.Contains(validPlaceholders, placeholder) {
|
||||
return false
|
||||
}
|
||||
|
||||
noPlaceholders = strings.Replace(noPlaceholders, match[0], "", -1) // match[0] = "%placeholder%"
|
||||
}
|
||||
|
||||
return channelNamePattern.MatchString(noPlaceholders)
|
||||
}
|
||||
|
||||
func getRoleHashSet(guildId uint64) (*collections.Set[uint64], error) {
|
||||
ctx, err := botcontext.ContextForGuild(guildId)
|
||||
if err != nil {
|
||||
|
@ -17,6 +17,7 @@ func ListPanels(ctx *gin.Context) {
|
||||
Emoji types.Emoji `json:"emote"`
|
||||
Mentions []string `json:"mentions"`
|
||||
Teams []int `json:"teams"`
|
||||
UseServerDefaultNamingScheme bool `json:"use_server_default_naming_scheme"`
|
||||
}
|
||||
|
||||
guildId := ctx.Keys["guildid"].(uint64)
|
||||
@ -79,6 +80,7 @@ func ListPanels(ctx *gin.Context) {
|
||||
Emoji: types.NewEmoji(p.EmojiName, p.EmojiId),
|
||||
Mentions: mentions,
|
||||
Teams: teamIds,
|
||||
UseServerDefaultNamingScheme: p.NamingScheme == nil,
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -125,6 +125,7 @@ func UpdatePanel(ctx *gin.Context) {
|
||||
ButtonStyle: int(data.ButtonStyle),
|
||||
ButtonLabel: data.ButtonLabel,
|
||||
FormId: data.FormId,
|
||||
NamingScheme: data.NamingScheme,
|
||||
}
|
||||
|
||||
if err = dbclient.Client.Panel.Update(panel); err != nil {
|
||||
|
86
frontend/package-lock.json
generated
86
frontend/package-lock.json
generated
@ -12,7 +12,8 @@
|
||||
"sirv-cli": "^1.0.0",
|
||||
"svelte-emoji-selector": "^1.0.1",
|
||||
"svelte-router-spa": "^6.0.2",
|
||||
"svelte-select": "^3.17.0"
|
||||
"svelte-select": "^3.17.0",
|
||||
"svelte-tooltip": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.14.6",
|
||||
@ -3176,6 +3177,51 @@
|
||||
"integrity": "sha512-2gzDDMDhM+ImDaLEZVlnlHVY1340Y368tT4Qk5IwLnCeRJ4zV3cVwliVGacoHy7iCDukcGXzKwDzG/hTTcaljg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/svelte-tooltip": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-tooltip/-/svelte-tooltip-1.2.0.tgz",
|
||||
"integrity": "sha512-FmaiNoCGkXBqF5AAscv+NdLtVIhywpqcaKw7mP1IksLJPMW3QaOPB8G23CHPQWde0J3A0NdCDQ3DI2isWGsDbg==",
|
||||
"dependencies": {
|
||||
"sirv-cli": "^0.4.4"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-tooltip/node_modules/@polka/url": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-0.5.0.tgz",
|
||||
"integrity": "sha512-oZLYFEAzUKyi3SKnXvj32ZCEGH6RDnao7COuCVhDydMS9NrCSVXhM79VaKyP5+Zc33m0QXEd2DN3UkU7OsHcfw=="
|
||||
},
|
||||
"node_modules/svelte-tooltip/node_modules/sirv": {
|
||||
"version": "0.4.6",
|
||||
"resolved": "https://registry.npmjs.org/sirv/-/sirv-0.4.6.tgz",
|
||||
"integrity": "sha512-rYpOXlNbpHiY4nVXxuDf4mXPvKz1reZGap/LkWp9TvcZ84qD/nPBjjH/6GZsgIjVMbOslnY8YYULAyP8jMn1GQ==",
|
||||
"dependencies": {
|
||||
"@polka/url": "^0.5.0",
|
||||
"mime": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/svelte-tooltip/node_modules/sirv-cli": {
|
||||
"version": "0.4.6",
|
||||
"resolved": "https://registry.npmjs.org/sirv-cli/-/sirv-cli-0.4.6.tgz",
|
||||
"integrity": "sha512-/Vj85/kBvPL+n9ibgX6FicLE8VjidC1BhlX67PYPBfbBAphzR6i0k0HtU5c2arejfU3uzq8l3SYPCwl1x7z6Ww==",
|
||||
"dependencies": {
|
||||
"console-clear": "^1.1.0",
|
||||
"get-port": "^3.2.0",
|
||||
"kleur": "^3.0.0",
|
||||
"local-access": "^1.0.1",
|
||||
"sade": "^1.4.0",
|
||||
"sirv": "^0.4.6",
|
||||
"tinydate": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"sirv": "index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.7.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.7.0.tgz",
|
||||
@ -5606,6 +5652,44 @@
|
||||
"integrity": "sha512-2gzDDMDhM+ImDaLEZVlnlHVY1340Y368tT4Qk5IwLnCeRJ4zV3cVwliVGacoHy7iCDukcGXzKwDzG/hTTcaljg==",
|
||||
"dev": true
|
||||
},
|
||||
"svelte-tooltip": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/svelte-tooltip/-/svelte-tooltip-1.2.0.tgz",
|
||||
"integrity": "sha512-FmaiNoCGkXBqF5AAscv+NdLtVIhywpqcaKw7mP1IksLJPMW3QaOPB8G23CHPQWde0J3A0NdCDQ3DI2isWGsDbg==",
|
||||
"requires": {
|
||||
"sirv-cli": "^0.4.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@polka/url": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-0.5.0.tgz",
|
||||
"integrity": "sha512-oZLYFEAzUKyi3SKnXvj32ZCEGH6RDnao7COuCVhDydMS9NrCSVXhM79VaKyP5+Zc33m0QXEd2DN3UkU7OsHcfw=="
|
||||
},
|
||||
"sirv": {
|
||||
"version": "0.4.6",
|
||||
"resolved": "https://registry.npmjs.org/sirv/-/sirv-0.4.6.tgz",
|
||||
"integrity": "sha512-rYpOXlNbpHiY4nVXxuDf4mXPvKz1reZGap/LkWp9TvcZ84qD/nPBjjH/6GZsgIjVMbOslnY8YYULAyP8jMn1GQ==",
|
||||
"requires": {
|
||||
"@polka/url": "^0.5.0",
|
||||
"mime": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"sirv-cli": {
|
||||
"version": "0.4.6",
|
||||
"resolved": "https://registry.npmjs.org/sirv-cli/-/sirv-cli-0.4.6.tgz",
|
||||
"integrity": "sha512-/Vj85/kBvPL+n9ibgX6FicLE8VjidC1BhlX67PYPBfbBAphzR6i0k0HtU5c2arejfU3uzq8l3SYPCwl1x7z6Ww==",
|
||||
"requires": {
|
||||
"console-clear": "^1.1.0",
|
||||
"get-port": "^3.2.0",
|
||||
"kleur": "^3.0.0",
|
||||
"local-access": "^1.0.1",
|
||||
"sade": "^1.4.0",
|
||||
"sirv": "^0.4.6",
|
||||
"tinydate": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "5.7.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.7.0.tgz",
|
||||
|
@ -28,6 +28,7 @@
|
||||
"sirv-cli": "^1.0.0",
|
||||
"svelte-emoji-selector": "^1.0.1",
|
||||
"svelte-router-spa": "^6.0.2",
|
||||
"svelte-select": "^3.17.0"
|
||||
"svelte-select": "^3.17.0",
|
||||
"svelte-tooltip": "^1.2.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,39 @@
|
||||
<div class:col-1={col1} class:col-2={col2} class:col-3={col3} class:col-4={col4}>
|
||||
{#if label !== undefined}
|
||||
<label for="input" class="form-label">{label}</label>
|
||||
<div class="label-wrapper">
|
||||
<label for="input" class="form-label">
|
||||
{label}
|
||||
</label>
|
||||
{#if tooltipText !== undefined}
|
||||
<div style="margin-bottom: 5px">
|
||||
<Tooltip tip={tooltipText} top color="#121212">
|
||||
{#if tooltipLink !== undefined}
|
||||
<a href={tooltipLink} target="_blank">
|
||||
<i class="fas fa-circle-info form-label tooltip-icon"></i>
|
||||
</a>
|
||||
{:else}
|
||||
<i class="fas fa-circle-info form-label tooltip-icon"></i>
|
||||
{/if}
|
||||
</Tooltip>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
<input id="input" class="form-input" placeholder="{placeholder}" disabled="{disabled}" on:input on:change
|
||||
bind:value={value}>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import Tooltip from 'svelte-tooltip';
|
||||
|
||||
export let value;
|
||||
export let label;
|
||||
export let placeholder;
|
||||
export let disabled = false;
|
||||
|
||||
export let tooltipText = undefined;
|
||||
export let tooltipLink = undefined;
|
||||
|
||||
export let col1 = false;
|
||||
export let col2 = false;
|
||||
export let col3 = false;
|
||||
@ -22,4 +44,15 @@
|
||||
input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.label-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.tooltip-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
@ -41,8 +41,6 @@
|
||||
on:toggle={handleEmojiTypeChange} />
|
||||
</div>
|
||||
{#if data.use_custom_emoji}
|
||||
<!--bind:selectedValue={selectedMentions}
|
||||
on:select={updateMentions}-->
|
||||
<div class="multiselect-super">
|
||||
<Select items={emojis}
|
||||
Item={EmojiItem}
|
||||
@ -106,6 +104,29 @@
|
||||
<Input col2={true} label="Large Image URL" bind:value={data.image_url} placeholder="https://example.com/image.png" />
|
||||
<Input col2={true} label="Small Image URL" bind:value={data.thumbnail_url} placeholder="https://example.com/image.png" />
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<label for="naming-scheme-wrapper" class="form-label">Naming Scheme</label>
|
||||
<div class="row" id="naming-scheme-wrapper">
|
||||
<div>
|
||||
<label class="form-label">Use Server Default</label>
|
||||
<Toggle hideLabel
|
||||
toggledColor="#66bb6a"
|
||||
untoggledColor="#ccc"
|
||||
bind:toggled={data.use_server_default_naming_scheme} />
|
||||
</div>
|
||||
<div class="col-fill">
|
||||
{#if !data.use_server_default_naming_scheme}
|
||||
<Input label="Naming Scheme"
|
||||
bind:value={data.naming_scheme}
|
||||
placeholder="ticket-%id%"
|
||||
tooltipText="Click here for the full placeholder list"
|
||||
tooltipLink="https://docs.ticketsbot.net" />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -126,6 +147,7 @@
|
||||
import Dropdown from "../form/Dropdown.svelte";
|
||||
import Checkbox from "../form/Checkbox.svelte";
|
||||
import Toggle from "svelte-toggle";
|
||||
import Slider from "../form/Slider.svelte";
|
||||
|
||||
export let guildId;
|
||||
export let seedDefault = true;
|
||||
@ -247,8 +269,7 @@
|
||||
.forEach((mention) => selectedMentions.push(mention));
|
||||
}
|
||||
|
||||
$: data.emote = data.emote;
|
||||
console.log(data.emote)
|
||||
data.emote = data.emote;
|
||||
|
||||
tempColour = intToColour(data.colour);
|
||||
}
|
||||
@ -271,7 +292,8 @@
|
||||
button_style: "1",
|
||||
form_id: "null",
|
||||
channel_id: channels.find((c) => c.type === 0).id,
|
||||
category_id: channels.find((c) => c.type === 4).id
|
||||
category_id: channels.find((c) => c.type === 4).id,
|
||||
use_server_default_naming_scheme: true,
|
||||
};
|
||||
} else {
|
||||
applyOverrides();
|
||||
@ -295,6 +317,12 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.col-fill {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
:global(.col-1-3) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -359,6 +387,10 @@
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#naming-scheme-wrapper {
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
:global(.multiselect-super) {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
@ -13,7 +13,7 @@
|
||||
<!--<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700" rel="stylesheet">-->
|
||||
|
||||
<!-- Icons -->
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.1.1/css/all.css">
|
||||
|
||||
<!-- GA -->
|
||||
<script async src='https://www.google-analytics.com/analytics.js'
|
||||
|
@ -38,7 +38,7 @@
|
||||
export let currentRoute;
|
||||
export let params = {};
|
||||
|
||||
let guildId = currentRoute.namedParams.id
|
||||
let guildId = currentRoute.namedParams.id;
|
||||
|
||||
import Head from '../includes/Head.svelte'
|
||||
import LoadingScreen from '../includes/LoadingScreen.svelte'
|
||||
|
4
go.mod
4
go.mod
@ -81,3 +81,7 @@ require (
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
nhooyr.io/websocket v1.8.4 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/TicketsBot/database => "../database"
|
||||
)
|
||||
|
@ -4,9 +4,9 @@ import (
|
||||
"github.com/rxdn/gdl/objects/channel/message"
|
||||
)
|
||||
|
||||
func ContainsString(slice []string, target string) bool {
|
||||
func Contains[T comparable](slice []T, value T) bool {
|
||||
for _, elem := range slice {
|
||||
if elem == target {
|
||||
if elem == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user