Colour customisation

This commit is contained in:
rxdn 2021-11-09 15:40:47 +00:00
parent 5dc3cfa8b3
commit 677f405826
11 changed files with 273 additions and 28 deletions

View File

@ -0,0 +1,33 @@
package customisation
import (
dbclient "github.com/TicketsBot/GoPanel/database"
"github.com/TicketsBot/GoPanel/utils"
"github.com/TicketsBot/worker/bot/customisation"
"github.com/gin-gonic/gin"
)
// GetColours TODO: Don't depend on worker
func GetColours(ctx *gin.Context) {
guildId := ctx.Keys["guildid"].(uint64)
// TODO: Don't duplicate
raw, err := dbclient.Client.CustomColours.GetAll(guildId)
if err != nil {
ctx.JSON(500, utils.ErrorJson(err))
return
}
colours := make(map[customisation.Colour]utils.HexColour)
for id, hex := range raw {
colours[customisation.Colour(id)] = utils.HexColour(hex)
}
for id, hex := range customisation.DefaultColours {
if _, ok := colours[id]; !ok {
colours[id] = utils.HexColour(hex)
}
}
ctx.JSON(200, colours)
}

View File

@ -0,0 +1,54 @@
package customisation
import (
"context"
"fmt"
dbclient "github.com/TicketsBot/GoPanel/database"
"github.com/TicketsBot/GoPanel/utils"
"github.com/TicketsBot/worker/bot/customisation"
"github.com/gin-gonic/gin"
"golang.org/x/sync/errgroup"
)
// UpdateColours TODO: Don't depend on worker
func UpdateColours(ctx *gin.Context) {
guildId := ctx.Keys["guildid"].(uint64)
var data map[customisation.Colour]utils.HexColour
if err := ctx.BindJSON(&data); err != nil {
ctx.JSON(400, utils.ErrorJson(err))
return
}
if len(data) > len(customisation.DefaultColours) {
ctx.JSON(400, utils.ErrorStr("Invalid colour"))
return
}
for colourCode, hex := range customisation.DefaultColours {
if _, ok := data[colourCode]; !ok {
data[colourCode] = utils.HexColour(hex)
}
}
// TODO: Single query
group, _ := errgroup.WithContext(context.Background())
for colourCode, hex := range data {
colourCode := colourCode
hex := hex
fmt.Printf("%d: %d\n", colourCode, hex)
group.Go(func() error {
fmt.Printf("%d: %d\n", colourCode, hex.Int())
return dbclient.Client.CustomColours.Set(guildId, colourCode.Int16(), hex.Int())
})
}
if err := group.Wait(); err != nil {
ctx.JSON(500, utils.ErrorJson(err))
return
}
ctx.JSON(200, utils.SuccessResponse)
}

View File

@ -4,6 +4,7 @@ import (
"github.com/TicketsBot/GoPanel/app/http/endpoints/api"
api_autoclose "github.com/TicketsBot/GoPanel/app/http/endpoints/api/autoclose"
api_blacklist "github.com/TicketsBot/GoPanel/app/http/endpoints/api/blacklist"
api_customisation "github.com/TicketsBot/GoPanel/app/http/endpoints/api/customisation"
api_panels "github.com/TicketsBot/GoPanel/app/http/endpoints/api/panel"
api_settings "github.com/TicketsBot/GoPanel/app/http/endpoints/api/settings"
api_tags "github.com/TicketsBot/GoPanel/app/http/endpoints/api/tags"
@ -127,6 +128,9 @@ func StartServer() {
guildAuthApiAdmin.GET("/autoclose", api_autoclose.GetAutoClose)
guildAuthApiAdmin.POST("/autoclose", api_autoclose.PostAutoClose)
guildAuthApiAdmin.GET("/customisation/colours", api_customisation.GetColours)
guildAuthApiAdmin.POST("/customisation/colours", api_customisation.UpdateColours)
guildAuthApiAdmin.GET("/team", api_team.GetTeams)
guildAuthApiAdmin.GET("/team/:teamid", rl(middleware.RateLimitTypeUser, 10, time.Second*30), api_team.GetMembers)
guildAuthApiAdmin.POST("/team", rl(middleware.RateLimitTypeUser, 10, time.Minute), api_team.CreateTeam)

View File

@ -0,0 +1,16 @@
<div class="badge">
<slot></slot>
</div>
<style>
.badge {
display: flex;
align-items: center;
background-color: #3472f7;
border-radius: 2px;
font-size: 14px;
padding: 0 4px;
margin-left: 4px;
}
</style>

View File

@ -3,7 +3,7 @@
<div class="parent">
<label class="form-label">{label}</label>
{#if badge !== undefined}
<div class="badge" style="margin-left: 4px">{badge}</div>
<Badge>{badge}</Badge>
{/if}
</div>
</div>
@ -27,6 +27,8 @@
</div>
<script>
import Badge from "../Badge.svelte";
export let label;
export let badge;
export let disabled = false; // note: bind:disabled isn't valid
@ -104,14 +106,4 @@
margin: 0 0 0.5em 0;
height: 40px;
}
:global(.badge) {
display: flex;
align-items: center;
background-color: #3472f7;
border-radius: 2px;
font-size: 14px;
padding: 0 4px;
}
</style>

View File

@ -13,6 +13,7 @@
<NavElement icon="fas fa-ticket-alt" link="/manage/{guildId}/tickets" on:click={closeDropdown}>Tickets</NavElement>
<NavElement icon="fas fa-ban" link="/manage/{guildId}/blacklist" on:click={closeDropdown}>Blacklist</NavElement>
<NavElement icon="fas fa-tags" link="/manage/{guildId}/tags" on:click={closeDropdown}>Tags</NavElement>
<NavElement icon="fas fa-paint-brush" link="/manage/{guildId}/appearance" on:click={closeDropdown}>Customise Appearance</NavElement>
</div>
</div>
<div>
@ -64,7 +65,7 @@
display: none;
}
@media only screen and (max-width: 950px) {
@media only screen and (max-width: 1154px) {
.nav-section {
display: none;
}

View File

@ -19,6 +19,7 @@ import Tags from './views/Tags.svelte'
import Teams from './views/Teams.svelte'
import Tickets from './views/Tickets.svelte'
import TicketView from './views/TicketView.svelte'
import Appearance from './views/Appearance.svelte';
export const routes = [
{name: '/', component: Index, layout: IndexLayout},
@ -33,6 +34,7 @@ export const routes = [
nestedRoutes: [
{name: 'index', component: Error404, layout: ErrorLayout},
{name: 'settings', component: Settings, layout: ManageLayout},
{name: 'appearance', component: Appearance, layout: ManageLayout},
{
name: 'transcripts',
nestedRoutes: [

View File

@ -0,0 +1,116 @@
<div class="parent">
<div class="content">
<Card footer={false}>
<span slot="title">Looking for whitelabel?</span>
<div slot="body" class="body-wrapper">
<p>If you're looking for whitelabel settings (customising bot name and avatar), this is managed on a separate
page, <Navigate to="/whitelabel" styles="link row">available here</Navigate>.
</p>
</div>
</Card>
<Card footer={false}>
<span slot="title">Colour Scheme</span>
<div slot="body" class="body-wrapper">
<form class="settings-form" on:submit|preventDefault={updateColours}>
<div class="row">
<Colour col3={true} label="Success" bind:value={colours["0"]} />
<Colour col3={true} label="Failure" bind:value={colours["1"]} />
</div>
<div class="row">
<Button icon="fas fa-paper-plane">Submit</Button>
</div>
</form>
</div>
</Card>
</div>
</div>
<script>
import Card from "../components/Card.svelte";
import {notifyError, notifySuccess, withLoadingScreen} from '../js/util'
import axios from "axios";
import {API_URL} from "../js/constants";
import {setDefaultHeaders} from '../includes/Auth.svelte'
import {Navigate} from "svelte-router-spa";
import Colour from "../components/form/Colour.svelte";
import Button from "../components/Button.svelte";
export let currentRoute;
let guildId = currentRoute.namedParams.id;
let colours = {};
async function updateColours() {
const res = await axios.post(`${API_URL}/api/${guildId}/customisation/colours`, colours);
if (res.status !== 200) {
notifyError(res.data.error);
return;
}
notifySuccess(`Your colour scheme has been saved`);
}
async function loadColours() {
const res = await axios.get(`${API_URL}/api/${guildId}/customisation/colours`);
if (res.status !== 200) {
notifyError(res.data.error);
return;
}
colours = res.data;
}
withLoadingScreen(async () => {
setDefaultHeaders();
await loadColours();
});
</script>
<style>
.parent {
display: flex;
justify-content: center;
width: 100%;
height: 100%;
}
.content {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 96%;
height: 100%;
margin-top: 30px;
}
.body-wrapper {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.row {
display: flex;
flex-direction: row;
width: 100%;
height: 100%;
margin-bottom: 2%;
}
.col {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
margin-bottom: 2%;
}
@media only screen and (max-width: 950px) {
.row {
flex-direction: column;
}
}
</style>

4
go.mod
View File

@ -6,8 +6,8 @@ require (
github.com/BurntSushi/toml v0.3.1
github.com/TicketsBot/archiverclient v0.0.0-20210220155137-a562b2f1bbbb
github.com/TicketsBot/common v0.0.0-20210910205523-7ce93fba6fa5
github.com/TicketsBot/database v0.0.0-20211102194216-65aaa0ce6ce9
github.com/TicketsBot/worker v0.0.0-20211102194549-f7058a7791fa
github.com/TicketsBot/database v0.0.0-20211109153802-24100e383d78
github.com/TicketsBot/worker v0.0.0-20211108224403-97ac8e44b789
github.com/apex/log v1.1.2
github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect
github.com/getsentry/sentry-go v0.11.0

20
go.sum
View File

@ -13,20 +13,15 @@ github.com/TicketsBot/common v0.0.0-20210910205523-7ce93fba6fa5 h1:IfNrgUB35hs+M
github.com/TicketsBot/common v0.0.0-20210910205523-7ce93fba6fa5/go.mod h1:SVwX6gKkxRCMbp+qwJIgvQiy/Ut0fUddexEqRB/NTzc=
github.com/TicketsBot/database v0.0.0-20200516170158-fd8a949aec2c/go.mod h1:eky4tBL+IZ0svPgTT0N/9i6j7ygHDQH3784DW+HgfcA=
github.com/TicketsBot/database v0.0.0-20210902172951-4e1f8ced84b7/go.mod h1:A4T2uQFIWC/ttCYpfgv7AkPjR09mMRgzG13lgoV/+aI=
github.com/TicketsBot/database v0.0.0-20210906215136-2d0c54bd1109/go.mod h1:A4T2uQFIWC/ttCYpfgv7AkPjR09mMRgzG13lgoV/+aI=
github.com/TicketsBot/database v0.0.0-20211030123522-eeed94443867 h1:2tYF3avpUUY1voXuzcY2gQHggnk17M+1btblS7Zkygk=
github.com/TicketsBot/database v0.0.0-20211030123522-eeed94443867/go.mod h1:72oWvH/Gq1iKeXCZhVRZn1JFbNVC5iAgERZWTrEarEo=
github.com/TicketsBot/database v0.0.0-20211030133445-3b8906e1b64a h1:nn8rmdIXR4jY3JsE+pyf6Ff0LOAYvHjx8F8E+InWaRk=
github.com/TicketsBot/database v0.0.0-20211030133445-3b8906e1b64a/go.mod h1:72oWvH/Gq1iKeXCZhVRZn1JFbNVC5iAgERZWTrEarEo=
github.com/TicketsBot/database v0.0.0-20211102194216-65aaa0ce6ce9 h1:x4xs4IynlfDwpPTTcVbYjt5h1VmL9AeUW9ZFY31dyP0=
github.com/TicketsBot/database v0.0.0-20211102194216-65aaa0ce6ce9/go.mod h1:72oWvH/Gq1iKeXCZhVRZn1JFbNVC5iAgERZWTrEarEo=
github.com/TicketsBot/database v0.0.0-20211108142700-c406ab0fc1bb h1:hDN153ofF4rmAnA9Rs/j3b/+xazi3QFzQqXSJ6HNgZI=
github.com/TicketsBot/database v0.0.0-20211108142700-c406ab0fc1bb/go.mod h1:72oWvH/Gq1iKeXCZhVRZn1JFbNVC5iAgERZWTrEarEo=
github.com/TicketsBot/database v0.0.0-20211109153802-24100e383d78 h1:zzjOyxCdXN1fGDL2Na6Q82EDU96Cfd1vnlafeY1utUQ=
github.com/TicketsBot/database v0.0.0-20211109153802-24100e383d78/go.mod h1:72oWvH/Gq1iKeXCZhVRZn1JFbNVC5iAgERZWTrEarEo=
github.com/TicketsBot/logarchiver v0.0.0-20200423221245-a3f92edf8c14/go.mod h1:whts8TRxrAF4WuDuEAMllkWA/inKem0NhDEFeyuoOvE=
github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261 h1:NHD5GB6cjlkpZFjC76Yli2S63/J2nhr8MuE6KlYJpQM=
github.com/TicketsBot/ttlcache v1.6.1-0.20200405150101-acc18e37b261/go.mod h1:2zPxDAN2TAPpxUPjxszjs3QFKreKrQh5al/R3cMXmYk=
github.com/TicketsBot/worker v0.0.0-20210910205947-89f7bd5ccf67 h1:ZZt7+rCmj+za01PVkgaflrJecLVi2laly1Gjz81YMlk=
github.com/TicketsBot/worker v0.0.0-20210910205947-89f7bd5ccf67/go.mod h1:n6gqs84FS2GxcVJrA2uznGf6WC5qXVfeEF2fr181TNY=
github.com/TicketsBot/worker v0.0.0-20211102194549-f7058a7791fa h1:/4Fp1qNYG6Svsjv4swrfUlOipKpdWD3fdiPhrlqe4r4=
github.com/TicketsBot/worker v0.0.0-20211102194549-f7058a7791fa/go.mod h1:ZX0b2l/SHb6OI3avFkh/0ztqdaqcENjHcMZF12T73AA=
github.com/TicketsBot/worker v0.0.0-20211108224403-97ac8e44b789 h1:wmHfOWVDT875v91YHs2yorQjwWEuR0z411lwFxI3sZY=
github.com/TicketsBot/worker v0.0.0-20211108224403-97ac8e44b789/go.mod h1:BjXxj6Og1fuup+kxbjIiQ7E3l9oitL7vRF3y4tYN16o=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/apex/log v1.1.2 h1:bnDuVoi+o98wOdVqfEzNDlY0tcmBia7r4YkjS9EqGYk=
github.com/apex/log v1.1.2/go.mod h1:SyfRweFO+TlkIJ3DVizTSeI1xk7jOIIqOnUPZQTTsww=
@ -361,9 +356,6 @@ github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThC
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/rxdn/gdl v0.0.0-20200522202912-4ae241eb98c1/go.mod h1:2gPBB++1s9Zh11AGM/y84KpmqTyLCnjGwEnt6xRRKL4=
github.com/rxdn/gdl v0.0.0-20210527173953-25dde613ff0a/go.mod h1:jvcb1N6AdaGx3/e8MoLedO6qSo/+UdA5GGHOA8cnAeU=
github.com/rxdn/gdl v0.0.0-20210906182609-337cb3c44a4c/go.mod h1:rENs8TxMsoYSJRssegNS/+fy18NCI9EUdCJX8R83PlY=
github.com/rxdn/gdl v0.0.0-20210921120128-02188fdcfd88 h1:DpLqFmCtCAREiRK5nq4SYJGOQV3G6qTTz7H4C4Wb1kU=
github.com/rxdn/gdl v0.0.0-20210921120128-02188fdcfd88/go.mod h1:rENs8TxMsoYSJRssegNS/+fy18NCI9EUdCJX8R83PlY=
github.com/rxdn/gdl v0.0.0-20211030160619-a8772c268ca4 h1:vHSTqcCCZZwlj6trBUj3tqys5hnKbBf9J6mtuG7DvgM=
github.com/rxdn/gdl v0.0.0-20211030160619-a8772c268ca4/go.mod h1:rENs8TxMsoYSJRssegNS/+fy18NCI9EUdCJX8R83PlY=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=

35
utils/hexcode.go Normal file
View File

@ -0,0 +1,35 @@
package utils
import (
"fmt"
"strconv"
"strings"
)
type HexColour int
func (h HexColour) Int() int {
return int(h)
}
func (h HexColour) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`"#%06x"`, h)), nil
}
func (h *HexColour) UnmarshalJSON(data []byte) error {
str := strings.TrimPrefix(string(data), `"`)
str = strings.TrimPrefix(str, "#")
str = strings.TrimSuffix(str, `"`)
i, err := strconv.ParseInt(str, 16, 32)
if err != nil {
return err
}
if i < 0 || i > 0xFFFFFF {
return fmt.Errorf("invalid hex colour: %s", str)
}
*h = HexColour(i)
return nil
}