diff --git a/app/http/endpoints/api/panel/panelcreate.go b/app/http/endpoints/api/panel/panelcreate.go index 793e7ab..a45b341 100644 --- a/app/http/endpoints/api/panel/panelcreate.go +++ b/app/http/endpoints/api/panel/panelcreate.go @@ -57,6 +57,7 @@ type panelBody struct { HideCloseButton bool `json:"hide_close_button"` HideCloseWithReasonButton bool `json:"hide_close_with_reason_button"` HideClaimButton bool `json:"hide_claim_button"` + TicketPermissions database.TicketPermissions `json:"ticket_permissions"` } func (p *panelBody) IntoPanelMessageData(customId string, isPremium bool) panelMessageData { @@ -260,6 +261,7 @@ func CreatePanel(c *gin.Context) { HideClaimButton: data.HideClaimButton, } + createOptions := panelCreateOptions{ TeamIds: data.Teams, // Already validated AccessControlRules: data.AccessControlList, // Already validated @@ -294,6 +296,11 @@ func CreatePanel(c *gin.Context) { return } + if err := dbclient.Client.PanelTicketPermissions.Set(c, panelId, data.TicketPermissions); err != nil { + _ = c.AbortWithError(http.StatusInternalServerError, app.NewError(err, "Failed to save panel ticket permissions")) + return + } + audit.Log(audit.LogEntry{ GuildId: audit.Uint64Ptr(guildId), UserId: userId, diff --git a/app/http/endpoints/api/panel/panellist.go b/app/http/endpoints/api/panel/panellist.go index bea310d..5c4960b 100644 --- a/app/http/endpoints/api/panel/panellist.go +++ b/app/http/endpoints/api/panel/panellist.go @@ -25,6 +25,7 @@ func ListPanels(c *gin.Context) { AccessControlList []database.PanelAccessControlRule `json:"access_control_list"` HasSupportHours bool `json:"has_support_hours"` IsCurrentlyActive bool `json:"is_currently_active"` + TicketPermissions database.TicketPermissions `json:"ticket_permissions"` } guildId := c.Keys["guildid"].(uint64) @@ -111,6 +112,11 @@ func ListPanels(c *gin.Context) { accessControlList = make([]database.PanelAccessControlRule, 0) } + ticketPerms, err := dbclient.Client.PanelTicketPermissions.Get(c, p.PanelId) + if err != nil { + return err + } + // Check if panel has support hours configured supportHours, err := dbclient.Client.PanelSupportHours.GetByPanelId(c, p.PanelId) if err != nil { @@ -138,6 +144,7 @@ func ListPanels(c *gin.Context) { AccessControlList: accessControlList, HasSupportHours: hasSupportHours, IsCurrentlyActive: isCurrentlyActive, + TicketPermissions: ticketPerms, } return nil diff --git a/app/http/endpoints/api/panel/panelupdate.go b/app/http/endpoints/api/panel/panelupdate.go index 9bd9512..9859e25 100644 --- a/app/http/endpoints/api/panel/panelupdate.go +++ b/app/http/endpoints/api/panel/panelupdate.go @@ -265,6 +265,7 @@ func UpdatePanel(c *gin.Context) { HideClaimButton: data.HideClaimButton, } + // insert mention data validRoles := utils.ToSet(utils.Map(roles, utils.RoleToId)) @@ -324,6 +325,11 @@ func UpdatePanel(c *gin.Context) { return } + if err := dbclient.Client.PanelTicketPermissions.Set(c, panel.PanelId, data.TicketPermissions); err != nil { + _ = c.AbortWithError(http.StatusInternalServerError, app.NewError(err, "Failed to save panel ticket permissions")) + return + } + // This doesn't need to be done in a transaction // Update multi panels diff --git a/frontend/src/components/manage/PanelCreationForm.svelte b/frontend/src/components/manage/PanelCreationForm.svelte index 4391264..ed7ef10 100644 --- a/frontend/src/components/manage/PanelCreationForm.svelte +++ b/frontend/src/components/manage/PanelCreationForm.svelte @@ -59,6 +59,18 @@ return matches !== null && matches.length === 1 && matches[0] === value; } + $: if (data && !data.ticket_permissions) { + data.ticket_permissions = { + add_reactions: false, + send_tts_messages: false, + embed_links: false, + attach_files: false, + use_external_emojis: false, + use_external_stickers: false, + send_voice_messages: false, + }; + } + // Replace spaces with dashes in naming scheme as the user types $: if ( data.naming_scheme !== undefined && @@ -246,6 +258,15 @@ hide_close_button: false, hide_close_with_reason_button: false, hide_claim_button: false, + ticket_permissions: { + add_reactions: false, + send_tts_messages: false, + embed_links: false, + attach_files: false, + use_external_emojis: false, + use_external_stickers: false, + send_voice_messages: false, + }, welcome_message: { fields: [], colour: "#2ECC71", @@ -618,6 +639,44 @@ + + Ticket Permissions +
+
+ + + + + + + +
+
+
+ Access Control
@@ -685,6 +744,14 @@ margin-bottom: 10px; } + .permissions-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); + column-gap: 8px; + row-gap: 20px; + width: 100%; + } + .incomplete-row { display: flex; flex-direction: row; diff --git a/frontend/src/components/manage/SettingsCard.svelte b/frontend/src/components/manage/SettingsCard.svelte index 0f60173..3e3728f 100644 --- a/frontend/src/components/manage/SettingsCard.svelte +++ b/frontend/src/components/manage/SettingsCard.svelte @@ -558,23 +558,37 @@ tooltip="Define which permissions are given to users in ticket channels" > Ticket Permissions -
- - - +
+
+ + + + + + + +
@@ -628,6 +642,14 @@ height: 100%; } + .permissions-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); + column-gap: 8px; + row-gap: 20px; + width: 100%; + } + .row { display: flex; justify-content: flex-start; diff --git a/go.mod b/go.mod index a968acd..eadcf47 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/BurntSushi/toml v1.2.1 github.com/TicketsBot-cloud/archiverclient v0.0.0-20251015181023-f0b66a074704 github.com/TicketsBot-cloud/common v0.0.0-20260210203202-54154661338e - github.com/TicketsBot-cloud/database v0.0.0-20260308184238-a418ca6b7258 + github.com/TicketsBot-cloud/database v0.0.0-20260308193919-30a698fefa8b github.com/TicketsBot-cloud/gdl v0.0.0-20260306134952-cccb0116fef6 github.com/TicketsBot-cloud/logarchiver v0.0.0-20251018211319-7a7df5cacbdc github.com/TicketsBot-cloud/worker v0.0.0-20260301212853-f5f9e1ebbfc2 diff --git a/go.sum b/go.sum index bf1833d..334a44b 100644 --- a/go.sum +++ b/go.sum @@ -47,8 +47,8 @@ github.com/TicketsBot-cloud/archiverclient v0.0.0-20251015181023-f0b66a074704 h1 github.com/TicketsBot-cloud/archiverclient v0.0.0-20251015181023-f0b66a074704/go.mod h1:Mux1bEPpOHwRw1wo6Fa6qJLJH9Erk9qv1yAIfLi1Wmw= github.com/TicketsBot-cloud/common v0.0.0-20260210203202-54154661338e h1:nFKV7yEm8MWbCP7dtsJ88+agcxDUD0YKIotVHMVvytw= github.com/TicketsBot-cloud/common v0.0.0-20260210203202-54154661338e/go.mod h1:tGrTHFz09OM3eDWF+62hIi9ELpT4igCFi868FKSvKBg= -github.com/TicketsBot-cloud/database v0.0.0-20260308184238-a418ca6b7258 h1:2W95npQA1RLh88C+Fo3Kv3RjBf06hy6OsuLyLJwKeOw= -github.com/TicketsBot-cloud/database v0.0.0-20260308184238-a418ca6b7258/go.mod h1:HQXAgmNSm7/FmBYwcsa6qpZqMrDhbLoEl+AyqFQ+RwY= +github.com/TicketsBot-cloud/database v0.0.0-20260308193919-30a698fefa8b h1:bHkfJWo8T/9TiHuYHxaOz8GAILIiKPugC1k3CzdOq/A= +github.com/TicketsBot-cloud/database v0.0.0-20260308193919-30a698fefa8b/go.mod h1:HQXAgmNSm7/FmBYwcsa6qpZqMrDhbLoEl+AyqFQ+RwY= github.com/TicketsBot-cloud/gdl v0.0.0-20260306134952-cccb0116fef6 h1:ucG0xLPt7xixW7/LvL0hXDBDouDRS1Nf+77qP8iJ/X0= github.com/TicketsBot-cloud/gdl v0.0.0-20260306134952-cccb0116fef6/go.mod h1:CdwBR2egPtxUXjD2CgC9ZwfuB8dz9HPePM8nuG6dt7Y= github.com/TicketsBot-cloud/logarchiver v0.0.0-20251018211319-7a7df5cacbdc h1:qTLNpCvIqM7UwZ6MdWQ9EztcDsIJfHh+VJdG+ULLEaA=