Add another attempt with python

This commit is contained in:
2022-07-02 22:03:35 +02:00
parent 4ef8cc57b1
commit 8ac2237892
38 changed files with 261 additions and 0 deletions

4
rust_warp_svelte/ui/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
/node_modules/
/public/build/
.DS_Store

View File

@@ -0,0 +1,3 @@
{
"recommendations": ["svelte.svelte-vscode"]
}

View File

@@ -0,0 +1,107 @@
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
---
# svelte app
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
```bash
npx degit sveltejs/template svelte-app
cd svelte-app
```
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
## Get started
Install the dependencies...
```bash
cd svelte-app
npm install
```
...then start [Rollup](https://rollupjs.org):
```bash
npm run dev
```
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense.
## Building and running in production mode
To create an optimised version of the app:
```bash
npm run build
```
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
## Single-page app mode
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
```js
"start": "sirv public --single"
```
## Using TypeScript
This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with:
```bash
node scripts/setupTypeScript.js
```
Or remove the script via:
```bash
rm scripts/setupTypeScript.js
```
If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte).
## Deploying to the web
### With [Vercel](https://vercel.com)
Install `vercel` if you haven't already:
```bash
npm install -g vercel
```
Then, from within your project folder:
```bash
cd public
vercel deploy --name my-project
```
### With [surge](https://surge.sh/)
Install `surge` if you haven't already:
```bash
npm install -g surge
```
Then, from within your project folder:
```bash
npm run build
surge public my-project.surge.sh
```

6580
rust_warp_svelte/ui/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
{
"name": "svelte-app",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public --no-clear",
"check": "svelte-check --tsconfig ./tsconfig.json"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.0.0",
"@rollup/plugin-typescript": "^8.0.0",
"@tsconfig/svelte": "^2.0.0",
"npm": "^8.11.0",
"rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0",
"svelte": "^3.0.0",
"svelte-check": "^2.0.0",
"svelte-preprocess": "^4.0.0",
"tslib": "^2.0.0",
"typescript": "^4.0.0"
},
"dependencies": {
"sirv-cli": "^1.0.0"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,63 @@
html, body {
position: relative;
width: 100%;
height: 100%;
}
body {
color: #333;
margin: 0;
padding: 8px;
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
}
a {
color: rgb(0,100,200);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a:visited {
color: rgb(0,80,160);
}
label {
display: block;
}
input, button, select, textarea {
font-family: inherit;
font-size: inherit;
-webkit-padding: 0.4em 0;
padding: 0.4em;
margin: 0 0 0.5em 0;
box-sizing: border-box;
border: 1px solid #ccc;
border-radius: 2px;
}
input:disabled {
color: #ccc;
}
button {
color: #333;
background-color: #f4f4f4;
outline: none;
}
button:disabled {
color: #999;
}
button:not(:disabled):active {
background-color: #ddd;
}
button:focus {
border-color: #666;
}

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<link rel='stylesheet' href='/global.css'>
<link rel='stylesheet' href='/build/bundle.css'>
<script defer src='/build/bundle.js'></script>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1,83 @@
import svelte from 'rollup-plugin-svelte';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
import sveltePreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';
import css from 'rollup-plugin-css-only';
const production = !process.env.ROLLUP_WATCH;
function serve() {
let server;
function toExit() {
if (server) server.kill(0);
}
return {
writeBundle() {
if (server) return;
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev', '--single'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true
});
process.on('SIGTERM', toExit);
process.on('exit', toExit);
}
};
}
export default {
input: 'src/main.ts',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/build/bundle.js'
},
plugins: [
svelte({
preprocess: sveltePreprocess({ sourceMap: !production }),
compilerOptions: {
// enable run-time checks when not in production
dev: !production
}
}),
// we'll extract any component CSS out into
// a separate file - better for performance
css({ output: 'bundle.css' }),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
browser: true,
dedupe: ['svelte']
}),
commonjs(),
typescript({
sourceMap: !production,
inlineSources: !production
}),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
watch: {
clearScreen: false
}
};

View File

@@ -0,0 +1,79 @@
<svelte:head>
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
</svelte:head>
<script lang="ts">
import Home from "./routes/Home.svelte";
import PackageLists from "./routes/PackageLists.svelte";
import PackageList from "./routes/PackageList.svelte";
import Preparation from "./routes/Preparation.svelte";
import Trips from "./routes/Trips.svelte";
import Trip from "./routes/Trip.svelte";
import NotFound from "./routes/NotFound.svelte";
function normalize(path) {
return path.replace(/\/+$/, '') + "/";
}
let currentRoute;
let data;
function route(path) {
path = normalize(path);
console.log(`Routing path "${path}"`);
data = {}
let urlParts = path.split("/").slice(1, -1);
if (path === "/") {
console.log("=> Home");
currentRoute = Home;
} else if (urlParts[0] == "lists" && urlParts.length == 1) {
console.log("=> PackageLists");
currentRoute = PackageLists;
} else if (urlParts[0] == "trips" && urlParts.length == 1) {
console.log("=> Trips");
currentRoute = Trips;
} else if (urlParts[0] == "trips" && urlParts.length == 2) {
console.log("=> Trip");
currentRoute = Trip;
data = {id: urlParts[1]};
} else if (urlParts[0] == "lists" && urlParts.length == 2) {
console.log("=> PackageList");
currentRoute = PackageList;
data = {id: urlParts[1]};
} else if (urlParts.length == 5
&& urlParts[0] == "lists"
&& urlParts[2] == "items"
&& urlParts[4] == "preparation") {
console.log("=> PackageList");
currentRoute = Preparation;
data = {list_id: urlParts[1], item_id: urlParts[3]};
} else {
console.log("No matching route found");
currentRoute = NotFound;
}
}
window.onload = e => {
route(window.location.pathname);
}
function redirect(path) {
history.pushState({id: path}, "", path);
route(path);
}
window.addEventListener("locationchange", function() {
route(window.location.pathname);
});
window.addEventListener("popstate", event => {
route(window.location.pathname);
});
</script>
<main>
<svelte:component this={currentRoute} redirect={redirect} data={data}/>
</main>

View File

@@ -0,0 +1,10 @@
<script lang="ts">
export let data;
</script>
<div>
{data.name}
</div>
<style>
</style>

View File

@@ -0,0 +1,51 @@
<script lang="ts">
import PackageItem from "./PackageItem.svelte"
import { createEventDispatcher } from 'svelte';
import { fade } from 'svelte/transition';
export let name;
export let items;
export let id;
const dispatch = createEventDispatcher();
let active = false;
let shown_items = [];
let ellipsed = false;
const enter = () => {
active = true
}
const leave = () => {
active = false
}
$: if (items.length <= 4) {
shown_items = items
ellipsed = false
} else {
shown_items = items.slice(0, !active && 3 || items.length)
ellipsed = true
}
function onClick(id) {
dispatch('select', {
id: id
});
}
</script>
<main on:mouseenter={enter} on:mouseleave={leave} on:click={onClick(id)}>
<h2 class="text-lg font-semibold text-center mb-5 mt-3">{name}</h2>
<ul class="list-disc ml-5">
{#each shown_items as item}
<li in:fade|local={{duration: 200}} out:fade|local={{duration: 100, delay: 100}}><PackageItem data={item} /></li>
{/each}
{#if !active && ellipsed}
...
{/if}
</ul>
</main>
<style>
</style>

View File

@@ -0,0 +1,78 @@
<script lang="ts">
export let id;
export let items;
export let redirect;
$: has_counts = items.some(l => l.count > 1);
$: has_preparations = items.some(l => l.preparation.steps.length > 0);
//has_sizes = items.some(l => l.size.type != "None");
let has_sizes = false;
let has_preparations = false;
let has_counts = false;
const navigateToPreparation = (item_id) => {
redirect(`/lists/${id}/items/${item_id}/preparation`);
}
</script>
<div>
<table class="table-auto w-full">
<thead>
<tr class="font-semibold tracking-wider text-left bg-gray-100 uppercase border-b border-gray-400">
<th class="p-3">Name</th>
{#if has_sizes }
<th class="p-3">Size</th>
{/if}
{#if has_counts}
<th class="p-3">Count</th>
{/if}
{#if has_preparations}
<th class="p-3">Preparation Steps</th>
{/if}
</tr>
</thead>
<tbody>
{#each items as item}
<tr class="border">
<td class="p-3">{item.name}</td>
{#if has_sizes }
<td class="p-3">
{#if item.size.type == "None"}
{:else if item.size.type == "Gram"}
{#if item.size.value == 1}
{item.size.value} Gram
{:else}
{item.size.value} Grams
{/if}
{:else if item.size.type == "Pack"}
{#if item.size.value == 1}
{item.size.value} Pack
{:else}
{item.size.value} Packs
{/if}
{:else}
{item.size.value} {item.size.type}
{/if}
</td>
{/if}
{#if has_counts}
<td class="p-3">
{#if item.count > 1}
{item.count}
{/if}
</td>
{/if}
{#if has_preparations}
<td class="p-3">
{#if item.preparation.steps.length > 0}
{item.preparation.steps.length} steps
<button on:click={() => navigateToPreparation(item.id)}>Show preparation steps</button>
{/if}
</td>
{/if}
</tr>
{/each}
</tbody>
</table>
</div>

1
rust_warp_svelte/ui/src/global.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="svelte" />

View File

@@ -0,0 +1,9 @@
import App from './App.svelte';
const app = new App({
target: document.body,
props: {
}
});
export default app;

View File

@@ -0,0 +1,15 @@
<script lang="ts">
export let redirect;
function navigateToPackageLists() {
redirect("/lists/");
}
</script>
<main>
<div>
Welcome to Packager, your helper for your next trip!
</div>
<button on:click={navigateToPackageLists}>Lists</button>
<button on:click={() => redirect("/trips/")}>Trips</button>
</main>

View File

@@ -0,0 +1,10 @@
<script lang="ts">
export let redirect;
</script>
<main>
<div>
404 -- Not Found
</div>
<button on:click={() => redirect("/")}>Back to home</button>
</main>

View File

@@ -0,0 +1,134 @@
<script lang="ts">
import { onMount } from 'svelte';
import PackageListTable from "../components/PackageListTable.svelte"
export let redirect;
export let data;
const resetActiveElement = () => {
activeElement = {
name: "",
count: 1,
preparationsteps: [],
};
};
let activeElement;
resetActiveElement();
export const url = `/lists/${data.id}`
let sidebarActive = true;
const toggleSidebar = () => {
sidebarActive = !sidebarActive;
}
const apply = async () => {
const response = await fetch(`http://localhost:9000/v1/lists/${data.id}/items`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
},
body: JSON.stringify({
name: activeElement.name,
count: activeElement.count,
}),
cache: "no-store",
});
const d = await response.json();
console.log(d);
items = [...items, d];
console.log(items[0]);
console.log(d);
resetActiveElement();
sidebarActive = false;
}
const cancel = () => {
resetActiveElement();
sidebarActive = false;
}
async function getItems(id) {
let response = await fetch(`http://localhost:9000/v1/lists/${id}/items`, {
method: "GET",
headers: {
"Accept": "application/json"
},
cache: "no-store",
});
items = await response.json();
}
async function getList() {
const response = await fetch(`http://localhost:9000/v1/lists/${data.id}`, {
method: "GET",
headers: {
"Accept": "application/json"
},
cache: "no-store",
})
list = await response.json();
}
let list = {name: ""};
let items = [];
onMount(async () => {
await getList();
await getItems(data.id);
});
</script>
<main>
<div>
<h2 class="text-3xl mt-12 mb-20 font-semibold text-center mb-5 mt-3">{list.name}</h2>
<div class="container mx-auto grid grid-cols-12 gap-1 items-start justify-items-stretch">
<div class="col-start-1 col-end-9">
<PackageListTable items={items} id={list.id} {redirect}/>
<button class="p-3 w-full mt-3 border border-gray-200 bg-indigo-300" on:click={toggleSidebar}>Add new item</button>
</div>
<div class="col-start-9 col-end-10"/>
<div class="col-start-10 col-end-13">
{#if sidebarActive}
<div>
<label for="name">Name</label>
<input
class="w-full"
type="text"
id="name"
name="name"
bind:value={activeElement.name}
/>
</div>
<div>
<label for="count">Count</label>
<input
class="w-full"
type="number"
id="count"
name="count"
bind:value={activeElement.count}
/>
</div>
<div>
{#each activeElement.preparationsteps as step}
{step}
{/each}
</div>
<div class="flex flex-row mt-6 justify-between w-full">
<button type="submit" class="p-3 border border-gray-200 bg-green-300" on:click={() => apply()}>Apply</button>
<button class="p-3 border border-gray-200 bg-red-300" on:click={() => cancel()}>Cancel</button>
</div>
{/if}
</div>
</div>
</div>
</main>

View File

@@ -0,0 +1,47 @@
<script lang="ts">
import PackageList from "../components/PackageList.svelte"
export let redirect;
export let data;
export const url = "/lists/"
async function getLists() {
let response = await fetch("http://localhost:9000/v1/lists", {
method: "GET",
headers: {
"Accept": "application/json"
},
cache: "no-store",
});
let lists = await response.json();
return lists;
}
</script>
<main>
<div class="container mx-auto mt-12">
<table class="table-auto w-full">
<thead>
<tr class="font-semibold tracking-wider text-left bg-gray-100 uppercase border-b border-gray-400">
<th class="p-3">Name</th>
<th class="p-3"># Items</th>
</tr>
</thead>
<tbody>
{#await getLists()}
<p>Loading</p>
{:then lists}
{#each lists as list}
<tr class="border" on:click={e => redirect(url + list.id)}>
<td class="p-3">{list.name}</td>
<td class="p-3">{list.items.length}</td>
</tr>
{/each}
{:catch error}
<p>Error: {error}</p>
{/await}
</tbody>
</table>
</div>
</main>

View File

@@ -0,0 +1,41 @@
<script lang="ts">
export let redirect;
export let data;
async function getSteps() {
let response = await fetch(`http://localhost:9000/v1/lists/${data.list_id}/items/${data.item_id}/preparation`, {
method: "GET",
headers: {
"Accept": "application/json"
},
cache: "no-store",
});
let list = await response.json();
return list;
}
</script>
<main>
<table class="table-auto w-full">
<thead>
<tr class="font-semibold tracking-wider text-left bg-gray-100 uppercase border-b border-gray-400">
<th class="p-3">Name</th>
<th class="p-3">Start</th>
</tr>
</thead>
<tbody>
{#await getSteps()}
<p>Loading</p>
{:then steps}
{#each steps as step}
<tr class="border">
<td class="p-3">{step.name}</td>
<td class="p-3">{step.start.days} days before</td>
</tr>
{/each}
{:catch error}
<p>Error: {error}</p>
{/await}
</tbody>
</table>
</main>

View File

@@ -0,0 +1,78 @@
<script lang="ts">
export let redirect;
export let data;
export const url = "/trips/"
async function getTrip() {
let response = await fetch(`http://localhost:9000/v1/trips/${data.id}`, {
method: "GET",
headers: {
"Accept": "application/json"
},
cache: "no-store",
});
let trip = await response.json();
return trip;
}
async function getTripItems() {
let response = await fetch(`http://localhost:9000/v1/trips/${data.id}/items`, {
method: "GET",
headers: {
"Accept": "application/json"
},
cache: "no-store",
});
let items = await response.json();
return items;
}
</script>
<main>
<div class="container mx-auto mt-12">
{#await getTrip()}
<p>Loading</p>
{:then trip}
<h2 class="text-3xl mt-12 mb-20 font-semibold text-center mb-5 mt-3">{trip.name}</h2>
<table>
<tr>
<td>Date</td>
<td>{trip.date}</td>
</tr>
<tr>
<td>Duration</td>
<td>{trip.parameters.days} Days</td>
</tr>
<tr>
<td>Status</td>
<td>{trip.state}</td>
</tr>
</table>
<table class="table-auto w-full">
<thead>
<tr class="font-semibold tracking-wider text-left bg-gray-100 uppercase border-b border-gray-400">
<th class="p-3">Name</th>
<th class="p-3">Status</th>
</tr>
</thead>
<tbody>
{#await getTripItems()}
<p>Loading</p>
{:then items}
{#each items as item}
<tr class="border">
<td class="p-3">{item.packageItem.name}</td>
<td class="p-3">{item.status}</td>
</tr>
{/each}
{:catch error}
{error}
{/await}
</tbody>
</table>
{/await}
</div>
</main>

View File

@@ -0,0 +1,64 @@
<script lang="ts">
export let redirect;
export let data;
export const url = "/trips/"
async function getTrips() {
let response = await fetch("http://localhost:9000/v1/trips", {
method: "GET",
headers: {
"Accept": "application/json"
},
cache: "no-store",
});
let trips = await response.json();
return trips;
}
</script>
<main>
<div class="container mx-auto mt-12">
<h2 class="text-3xl mt-12 mb-20 font-semibold text-center mb-5 mt-3">Trips</h2>
<table class="table-auto w-full">
<thead>
<tr class="font-semibold tracking-wider text-left bg-gray-100 uppercase border-b border-gray-400">
<th class="p-3">Name</th>
<th class="p-3">Date</th>
<th class="p-3">Days</th>
<th class="p-3">State</th>
<th class="p-3">Package Lists</th>
</tr>
</thead>
<tbody>
{#await getTrips()}
<p>Loading</p>
{:then trips}
{#each trips as trip}
<tr class="border" on:click={e => redirect(url + trip.id)}>
<td class="p-3" on:click={() => redirect(`/trips/${trip.id}`)}>{trip.name}</td>
<td class="p-3">{trip.date}</td>
<td class="p-3">{trip.parameters.days}</td>
{#if trip.state == "active"}
<td class="p-3 bg-green-100">{trip.state}</td>
{:else if trip.state == "planned"}
<td class="p-3 bg-blue-100">{trip.state}</td>
{:else}
<td class="p-3">{trip.state}</td>
{/if}
<td class="p-3">
<ul>
{#each trip.packageLists as list}
<li><button on:click={() => redirect(`/lists/${list.id}`)}>{list.name}</button></li>
{/each}
</ul>
</td>
</tr>
{/each}
{:catch error}
<p>Error: {error}</p>
{/await}
</tbody>
</table>
</div>
</main>

View File

@@ -0,0 +1,6 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",
"include": ["src/**/*"],
"exclude": ["node_modules/*", "__sapper__/*", "public/*"]
}