Ordered form inputs

This commit is contained in:
rxdn 2022-06-03 23:06:04 +01:00
parent 785b5bb2ca
commit 3a6deeba91
5 changed files with 154 additions and 7 deletions

View File

@ -0,0 +1,77 @@
package forms
import (
dbclient "github.com/TicketsBot/GoPanel/database"
"github.com/TicketsBot/GoPanel/utils"
"github.com/TicketsBot/database"
"github.com/gin-gonic/gin"
"strconv"
)
func SwapInput(ctx *gin.Context) {
guildId := ctx.Keys["guildid"].(uint64)
formId, err := strconv.Atoi(ctx.Param("form_id"))
if err != nil {
ctx.JSON(400, utils.ErrorStr("Invalid form ID"))
return
}
inputId, err := strconv.Atoi(ctx.Param("input_id"))
if err != nil {
ctx.JSON(400, utils.ErrorStr("Invalid form ID"))
return
}
form, ok, err := dbclient.Client.Forms.Get(formId)
if err != nil {
ctx.JSON(500, utils.ErrorJson(err))
return
}
if !ok {
ctx.JSON(404, utils.ErrorStr("Form not found"))
return
}
if form.GuildId != guildId {
ctx.JSON(403, utils.ErrorStr("Form does not belong to this guild"))
return
}
input, ok, err := dbclient.Client.FormInput.Get(inputId)
if err != nil {
ctx.JSON(500, utils.ErrorJson(err))
return
}
if !ok {
ctx.JSON(404, utils.ErrorStr("Input not found"))
return
}
if input.FormId != formId {
ctx.JSON(403, utils.ErrorStr("Input does not belong to this form"))
return
}
var direction database.InputSwapDirection
{
directionRaw := ctx.Param("direction")
if directionRaw == "up" {
direction = database.SwapDirectionUp
} else if directionRaw == "down" {
direction = database.SwapDirectionDown
} else {
ctx.JSON(400, utils.ErrorStr("Invalid swap direction"))
return
}
}
if err := dbclient.Client.FormInput.SwapDirection(inputId, formId, direction); err != nil {
ctx.JSON(500, utils.ErrorJson(err))
return
}
ctx.JSON(200, utils.SuccessResponse)
}

View File

@ -110,6 +110,7 @@ func StartServer() {
guildAuthApiAdmin.DELETE("/forms/:form_id", api_forms.DeleteForm)
guildAuthApiAdmin.POST("/forms/:form_id", api_forms.CreateInput)
guildAuthApiAdmin.PATCH("/forms/:form_id/:input_id", api_forms.UpdateInput)
guildAuthApiAdmin.PATCH("/forms/:form_id/:input_id/:direction", api_forms.SwapInput)
guildAuthApiAdmin.DELETE("/forms/:form_id/:input_id", api_forms.DeleteInput)
// Should be a GET, but easier to take a body for development purposes

View File

@ -1,10 +1,22 @@
<form on:submit|preventDefault={forwardCreate} class="input-form">
<div class="row">
<div class="sub-row" style="flex: 1">
<Input col4={true} label="Label" bind:value={data.label} placeholder="Name of the field" />
<Input col3={true} label="Label" bind:value={data.label} placeholder="Name of the field" />
</div>
<div class="sub-row buttons-row">
{#if windowWidth > 950}
{#if withDirectionButtons}
<form on:submit|preventDefault={() => forwardMove("down")} class="button-form">
<Button disabled={index >= formLength - 1}>
<i class="fas fa-chevron-down"></i>
</Button>
</form>
<form on:submit|preventDefault={() => forwardMove("up")} class="button-form">
<Button disabled={index === 0}>
<i class="fas fa-chevron-up"></i>
</Button>
</form>
{/if}
{#if withSaveButton}
<form on:submit|preventDefault={forwardSave} class="button-form">
<Button icon="fas fa-save">Save</Button>
@ -36,6 +48,18 @@
{#if windowWidth <= 950}
<div class="row">
{#if withDirectionButtons}
<div class="col-2">
<form on:submit|preventDefault={() => forwardMove("down")} class="button-form">
<Button icon="fas fa-chevron-down" disabled={index >= formLength - 1} />
</form>
</div>
<div class="col-2">
<form on:submit|preventDefault={() => forwardMove("up")} class="button-form">
<Button icon="fas fa-chevron-up" disabled={index === 0} />
</form>
</div>
{/if}
{#if withSaveButton}
<form on:submit|preventDefault={forwardSave} class="button-form">
<Button icon="fas fa-save">Save</Button>
@ -71,6 +95,10 @@
export let withCreateButton = false;
export let withSaveButton = false;
export let withDeleteButton = false;
export let withDirectionButtons = false;
export let index;
export let formLength;
export let data = {};
@ -87,6 +115,10 @@
function forwardDelete() {
dispatch('delete', {});
}
function forwardMove(direction) {
dispatch('move', {direction: direction});
}
</script>
<style>
@ -118,7 +150,7 @@
padding-bottom: 0.5em;
}
.buttons-row > form:first-of-type {
.buttons-row > :not(:last-child) {
margin-right: 10px;
}

View File

@ -40,10 +40,15 @@
<div class="manage">
{#if activeFormId !== null}
{#each forms.find(form => form.form_id === activeFormId).inputs as input}
<FormInputRow data={input} formId={activeFormId} withSaveButton={true} withDeleteButton={true}
{#each forms.find(form => form.form_id === activeFormId).inputs as input, i (input)}
<div animate:flip="{{duration: 500}}">
<FormInputRow data={input} formId={activeFormId}
withSaveButton={true} withDeleteButton={true} withDirectionButtons={true}
index={i} {formLength}
on:save={(e) => editInput(activeFormId, input.id, e.detail)}
on:delete={() => deleteInput(activeFormId, input.id)}/>
on:delete={() => deleteInput(activeFormId, input.id)}
on:move={(e) => changePosition(activeFormId, input.id, e.detail.direction)} />
</div>
{/each}
{/if}
@ -70,6 +75,7 @@
import Input from "../components/form/Input.svelte";
import Dropdown from "../components/form/Dropdown.svelte";
import FormInputRow from "../components/manage/FormInputRow.svelte";
import { flip } from "svelte/animate";
export let currentRoute;
let guildId = currentRoute.namedParams.id;
@ -82,6 +88,8 @@
$: activeFormTitle = activeFormId !== null ? forms.find(f => f.form_id === activeFormId).title : 'Unknown';
let inputCreationData = {};
$: formLength = activeFormId !== null ? forms.find(f => f.form_id === activeFormId).inputs.length : 0;
$: windowWidth = 0;
function getForm(formId) {
@ -146,7 +154,6 @@
async function editInput(formId, inputId, data) {
let mapped = {...data, style: parseInt(data.style)};
console.log(mapped);
const res = await axios.patch(`${API_URL}/api/${guildId}/forms/${formId}/${inputId}`, mapped);
if (res.status !== 200) {
@ -176,6 +183,32 @@
notifySuccess('Form input deleted successfully');
}
async function changePosition(formId, inputId, direction) {
const res = await axios.patch(`${API_URL}/api/${guildId}/forms/${formId}/${inputId}/${direction}`);
if (res.status !== 200) {
notifyError(res.data.error);
return;
}
if (res.data.success) {
//let form = getForm(formId);
let form = forms.find(form => form.form_id === activeFormId);
let idx = form.inputs.findIndex((input) => input.id === inputId);
let inputs = form.inputs;
if (direction === "up") {
[inputs[idx-1], inputs[idx]] = [inputs[idx], inputs[idx-1]]
} else if (direction === "down") {
[inputs[idx+1], inputs[idx]] = [form.inputs[idx], form.inputs[idx+1]]
}
console.log(getForm(formId).inputs)
forms = forms;
//await loadForms();
}
}
async function loadForms() {
const res = await axios.get(`${API_URL}/api/${guildId}/forms`);
if (res.status !== 200) {

4
go.mod
View File

@ -82,3 +82,7 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect
nhooyr.io/websocket v1.8.4 // indirect
)
replace (
github.com/TicketsBot/database => "../database"
)