create new bot flow
This commit is contained in:
parent
99987f8444
commit
90dfc3dec4
4 changed files with 140 additions and 4 deletions
|
@ -134,17 +134,25 @@ pub struct BotParams {
|
|||
name: String,
|
||||
}
|
||||
|
||||
// TODO: can we unify this with save_bot?
|
||||
pub async fn create_bot(
|
||||
conn: DatabaseConnection,
|
||||
user: User,
|
||||
params: Json<BotParams>,
|
||||
) -> (StatusCode, Json<Bot>) {
|
||||
) -> Result<(StatusCode, Json<Bot>), SaveBotError> {
|
||||
validate_bot_name(¶ms.name)?;
|
||||
let existing_bot = bots::find_bot_by_name(¶ms.name, &conn)
|
||||
.optional()
|
||||
.expect("could not run query");
|
||||
if existing_bot.is_some() {
|
||||
return Err(SaveBotError::BotNameTaken);
|
||||
}
|
||||
let bot_params = bots::NewBot {
|
||||
owner_id: Some(user.id),
|
||||
name: ¶ms.name,
|
||||
};
|
||||
let bot = bots::create_bot(&bot_params, &conn).unwrap();
|
||||
(StatusCode::CREATED, Json(bot))
|
||||
Ok((StatusCode::CREATED, Json(bot)))
|
||||
}
|
||||
|
||||
// TODO: handle errors
|
||||
|
|
98
web/pw-server/src/routes/bots/new.svelte
Normal file
98
web/pw-server/src/routes/bots/new.svelte
Normal file
|
@ -0,0 +1,98 @@
|
|||
<script lang="ts">
|
||||
import { goto } from "$app/navigation";
|
||||
import { get_session_token } from "$lib/auth";
|
||||
import { currentUser } from "$lib/stores/current_user";
|
||||
import { onMount } from "svelte";
|
||||
let botName: string | undefined = undefined;
|
||||
let saveErrors: string[] = [];
|
||||
|
||||
onMount(() => {
|
||||
// ensure user is logged in
|
||||
if (!$currentUser) {
|
||||
goto("/login");
|
||||
}
|
||||
});
|
||||
|
||||
async function createBot() {
|
||||
saveErrors = [];
|
||||
|
||||
let response = await fetch("/api/bots", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${get_session_token()}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: botName,
|
||||
}),
|
||||
});
|
||||
|
||||
let responseData = await response.json();
|
||||
if (response.ok) {
|
||||
let bot = responseData;
|
||||
goto(`/bots/${bot["name"]}`);
|
||||
} else {
|
||||
const error = responseData["error"];
|
||||
if (error["type"] === "validation_failed") {
|
||||
saveErrors = error["validation_errors"];
|
||||
} else if (error["type"] === "bot_name_taken") {
|
||||
saveErrors = ["Bot name is already taken"];
|
||||
} else {
|
||||
// unexpected error
|
||||
throw responseData;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<div class="create-bot-form">
|
||||
<h4>Create new bot</h4>
|
||||
<input type="text" class="bot-name-input" placeholder="bot name" bind:value={botName} />
|
||||
{#if saveErrors.length > 0}
|
||||
<ul>
|
||||
{#each saveErrors as errorText}
|
||||
<li class="error-text">{errorText}</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
<button class="submit-button save-button" on:click={createBot}>Save</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
width: 400px;
|
||||
max-width: 80%;
|
||||
margin: 50px auto;
|
||||
}
|
||||
|
||||
.create-bot-form h4 {
|
||||
margin-bottom: 0.3em;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
padding: 6px 16px;
|
||||
border-radius: 4px;
|
||||
border: 0;
|
||||
font-size: 18pt;
|
||||
display: block;
|
||||
margin: 10px auto;
|
||||
background-color: lightgreen;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bot-name-input {
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
padding: 8px 16px;
|
||||
box-sizing: border-box;
|
||||
margin: 10px 0;
|
||||
border: 1px solid rgb(216, 219, 223);
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
|
@ -1,6 +1,5 @@
|
|||
<script lang="ts" context="module">
|
||||
import { get_session_token } from "$lib/auth";
|
||||
import { mount_component } from "svelte/internal";
|
||||
|
||||
export async function load({ page }) {
|
||||
const token = get_session_token();
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { currentUser } from "$lib/stores/current_user";
|
||||
|
||||
export let userName: string;
|
||||
export let bots: object[];
|
||||
</script>
|
||||
|
@ -25,7 +27,13 @@
|
|||
<div class="header">
|
||||
<h1 class="user-name">{userName}</h1>
|
||||
</div>
|
||||
<h2>Bots</h2>
|
||||
|
||||
<div class="bot-list-header">
|
||||
<h2 class="bot-list-header-title">Bots</h2>
|
||||
{#if $currentUser && $currentUser.username == userName}
|
||||
<a href="/bots/new" class="btn-new-bot"> New bot </a>
|
||||
{/if}
|
||||
</div>
|
||||
<ul class="bot-list">
|
||||
{#each bots as bot}
|
||||
<li class="bot">
|
||||
|
@ -51,6 +59,29 @@
|
|||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.bot-list-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.bot-list-header-title {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.btn-new-bot {
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
border: 0;
|
||||
display: block;
|
||||
color: white;
|
||||
background-color: rgb(40, 167, 69);
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
font-size: 11pt;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bot-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
|
Loading…
Reference in a new issue