add basic data table with create form
This commit is contained in:
parent
dd421c0655
commit
cead02abe8
@ -1,7 +1,10 @@
|
||||
# ICE Management
|
||||
# ICE Production
|
||||
|
||||
ICE - Ice Cream Emporium
|
||||
|
||||
* [Icons](https://carbon-icons-svelte.onrender.com/)
|
||||
* [Carbon components](https://carbon-components-svelte.onrender.com/)
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer).
|
||||
|
@ -20,6 +20,7 @@
|
||||
"@types/node": "^18.7.10",
|
||||
"@unocss/transformer-directives": "^0.50.4",
|
||||
"carbon-components-svelte": "^0.73.3",
|
||||
"carbon-icons-svelte": "^11.4.0",
|
||||
"svelte": "^3.54.0",
|
||||
"svelte-check": "^3.0.0",
|
||||
"svelte-preprocess": "^5.0.0",
|
||||
|
6
lab2/pnpm-lock.yaml
generated
6
lab2/pnpm-lock.yaml
generated
@ -8,6 +8,7 @@ specifiers:
|
||||
'@types/node': ^18.7.10
|
||||
'@unocss/transformer-directives': ^0.50.4
|
||||
carbon-components-svelte: ^0.73.3
|
||||
carbon-icons-svelte: ^11.4.0
|
||||
svelte: ^3.54.0
|
||||
svelte-check: ^3.0.0
|
||||
svelte-preprocess: ^5.0.0
|
||||
@ -27,6 +28,7 @@ devDependencies:
|
||||
'@types/node': 18.15.0
|
||||
'@unocss/transformer-directives': 0.50.4
|
||||
carbon-components-svelte: 0.73.3
|
||||
carbon-icons-svelte: 11.4.0
|
||||
svelte: 3.56.0
|
||||
svelte-check: 3.1.2_svelte@3.56.0
|
||||
svelte-preprocess: 5.0.1_rx3ssngbibhj4vpczagsdyy47u
|
||||
@ -713,6 +715,10 @@ packages:
|
||||
flatpickr: 4.6.9
|
||||
dev: true
|
||||
|
||||
/carbon-icons-svelte/11.4.0:
|
||||
resolution: {integrity: sha512-p/llZde2kP2BI9SOqM+QFKGfQnYrW+4dVxF1rAYriEADXDsjt9EYlh+KpQ5qf4JpXAq+e2+TB/r/lIG1xdUbAQ==}
|
||||
dev: true
|
||||
|
||||
/chokidar/3.5.3:
|
||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
|
2
lab2/src-tauri/Cargo.lock
generated
2
lab2/src-tauri/Cargo.lock
generated
@ -1403,7 +1403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
|
||||
|
||||
[[package]]
|
||||
name = "ice-management"
|
||||
name = "ice-production"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
|
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "ice-management"
|
||||
name = "ice-production"
|
||||
version = "0.0.0"
|
||||
description = "ICE DB management"
|
||||
authors = ["Roka Puzonas"]
|
||||
|
@ -27,7 +27,7 @@
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
],
|
||||
"identifier": "me.rokaspuz.ice-management",
|
||||
"identifier": "me.rokaspuz.ice-production",
|
||||
"targets": "msi"
|
||||
},
|
||||
"security": {
|
||||
|
@ -1,29 +1,29 @@
|
||||
<script lang="ts">
|
||||
import Greet from './lib/Greet.svelte'
|
||||
import { Content } from "carbon-components-svelte";
|
||||
|
||||
import Router, {location} from "svelte-spa-router"
|
||||
import { Header, Content, SideNav, SideNavItems, SideNavLink } from "carbon-components-svelte";
|
||||
import User from "carbon-icons-svelte/lib/User.svelte";
|
||||
|
||||
import { Header, HeaderNav, HeaderNavItem } from "carbon-components-svelte";
|
||||
import Home from './routes/Home.svelte'
|
||||
import Managers from './routes/Managers.svelte'
|
||||
import Factories from './routes/Factories.svelte'
|
||||
import FactoriesManagers from './routes/Factories-Managers.svelte'
|
||||
|
||||
let isSideNavOpen = false;
|
||||
</script>
|
||||
|
||||
<Header href="/#/" company="ICE" platformName="Management">
|
||||
<HeaderNav>
|
||||
<HeaderNavItem href="/#/factories" text="Factories" />
|
||||
<HeaderNavItem href="/#/managers" text="Managers" />
|
||||
</HeaderNav>
|
||||
</Header>
|
||||
<Header href="/#/" company="ICE" platformName="Production" />
|
||||
<SideNav bind:isOpen={isSideNavOpen} rail>
|
||||
<SideNavItems>
|
||||
<SideNavLink
|
||||
icon={User}
|
||||
text="Factories & Managers"
|
||||
href="/#/factories-managers"
|
||||
isSelected={$location == "/factories-managers"}
|
||||
/>
|
||||
</SideNavItems>
|
||||
</SideNav>
|
||||
|
||||
<Content>
|
||||
<Router routes={{
|
||||
"/": Home,
|
||||
"/managers": Managers,
|
||||
"/factories": Factories,
|
||||
"/factories-managers": FactoriesManagers,
|
||||
}} />
|
||||
|
||||
<hr>
|
||||
{$location}
|
||||
</Content>
|
||||
|
64
lab2/src/lib/FactoryForm.svelte
Normal file
64
lab2/src/lib/FactoryForm.svelte
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { Form, TextInput, NumberInput } from "carbon-components-svelte";
|
||||
|
||||
export const factory = {
|
||||
name: "",
|
||||
location: "",
|
||||
floorSize: 1
|
||||
}
|
||||
|
||||
// Name validation
|
||||
let showNameInvalid = false;
|
||||
function validateName() {
|
||||
showNameInvalid = factory.name === ""
|
||||
}
|
||||
|
||||
// Location validation
|
||||
let showLocationInvalid = false;
|
||||
function validateLocation() {
|
||||
showLocationInvalid = factory.location === ""
|
||||
}
|
||||
|
||||
// Exports
|
||||
export const validate = () => {
|
||||
validateName()
|
||||
validateLocation()
|
||||
return !showLocationInvalid && !showNameInvalid && factory.floorSize >= 1
|
||||
};
|
||||
|
||||
export const reset = () => {
|
||||
factory.name = ""
|
||||
factory.location = ""
|
||||
factory.floorSize = 1
|
||||
showNameInvalid = false
|
||||
showLocationInvalid = false
|
||||
};
|
||||
</script>
|
||||
|
||||
<Form class="flex flex-col gap-1rem" title="Factory">
|
||||
<TextInput
|
||||
bind:value={factory.name}
|
||||
invalidText={"Name can't be empty"}
|
||||
bind:invalid={showNameInvalid}
|
||||
on:input={validateName}
|
||||
required
|
||||
labelText="Name"
|
||||
/>
|
||||
<TextInput
|
||||
bind:value={factory.location}
|
||||
invalidText={"Location can't be empty"}
|
||||
bind:invalid={showLocationInvalid}
|
||||
on:input={validateLocation}
|
||||
required
|
||||
labelText="Location"
|
||||
/>
|
||||
<NumberInput
|
||||
bind:value={factory.floorSize}
|
||||
required
|
||||
hideSteppers
|
||||
min={1}
|
||||
invalidText="Floor size must be at least 1m²"
|
||||
label="Floor size (m²)"
|
||||
/>
|
||||
</Form>
|
@ -1,21 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { invoke } from "@tauri-apps/api/tauri"
|
||||
|
||||
let name = "";
|
||||
let greetMsg = ""
|
||||
|
||||
async function greet(){
|
||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
greetMsg = await invoke("greet", { name })
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div class="row">
|
||||
<input id="greet-input" placeholder="Enter a name..." bind:value={name} />
|
||||
<button on:click={greet}>
|
||||
Greet
|
||||
</button>
|
||||
</div>
|
||||
<p>{greetMsg}</p>
|
||||
</div>
|
84
lab2/src/lib/ManagerForm.svelte
Normal file
84
lab2/src/lib/ManagerForm.svelte
Normal file
@ -0,0 +1,84 @@
|
||||
<script lang="ts">
|
||||
import { Form, TextInput } from "carbon-components-svelte";
|
||||
|
||||
export let manager = {
|
||||
firstName: "",
|
||||
surname: "",
|
||||
phoneNumber: "",
|
||||
title: "",
|
||||
email: ""
|
||||
}
|
||||
|
||||
// First name validation
|
||||
let showFirstNameInvalid = false;
|
||||
function validateFirstName() {
|
||||
showFirstNameInvalid = manager.firstName === ""
|
||||
}
|
||||
|
||||
// Surname validation
|
||||
let showSurnameInvalid = false;
|
||||
function validateSurname() {
|
||||
showSurnameInvalid = manager.surname === ""
|
||||
}
|
||||
|
||||
// Title validation
|
||||
let showTitleInvalid = false;
|
||||
function validateTitle() {
|
||||
showTitleInvalid = manager.title === ""
|
||||
}
|
||||
|
||||
// Exports
|
||||
export const validate = () => {
|
||||
validateFirstName()
|
||||
validateSurname()
|
||||
validateTitle()
|
||||
return !showFirstNameInvalid && !showSurnameInvalid && !showTitleInvalid
|
||||
};
|
||||
|
||||
export const reset = () => {
|
||||
manager.firstName = ""
|
||||
manager.surname = ""
|
||||
manager.phoneNumber = ""
|
||||
manager.title = ""
|
||||
manager.email = ""
|
||||
showFirstNameInvalid = false
|
||||
showSurnameInvalid = false
|
||||
showTitleInvalid = false
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<Form class="flex flex-col gap-1rem" title="Manager">
|
||||
<TextInput
|
||||
bind:value={manager.firstName}
|
||||
invalidText={"First name can't be empty"}
|
||||
bind:invalid={showFirstNameInvalid}
|
||||
on:input={validateFirstName}
|
||||
required
|
||||
labelText="First name"
|
||||
/>
|
||||
<TextInput
|
||||
bind:value={manager.surname}
|
||||
invalidText={"Surname can't be empty"}
|
||||
bind:invalid={showSurnameInvalid}
|
||||
on:input={validateSurname}
|
||||
required
|
||||
labelText="Surname"
|
||||
/>
|
||||
<TextInput
|
||||
bind:value={manager.title}
|
||||
invalidText={"Title can't be empty"}
|
||||
bind:invalid={showTitleInvalid}
|
||||
on:input={validateTitle}
|
||||
required
|
||||
labelText="Title"
|
||||
/>
|
||||
<TextInput
|
||||
bind:value={manager.phoneNumber}
|
||||
labelText="Phone number"
|
||||
/>
|
||||
<TextInput
|
||||
bind:value={manager.email}
|
||||
labelText="Email"
|
||||
/>
|
||||
</Form>
|
129
lab2/src/routes/Factories-Managers.svelte
Normal file
129
lab2/src/routes/Factories-Managers.svelte
Normal file
@ -0,0 +1,129 @@
|
||||
<script>
|
||||
import {
|
||||
DataTable,
|
||||
Toolbar,
|
||||
ToolbarContent,
|
||||
ToolbarBatchActions,
|
||||
Button,
|
||||
ToolbarSearch,
|
||||
Pagination,
|
||||
Modal,
|
||||
} from "carbon-components-svelte";
|
||||
import TrashCan from "carbon-icons-svelte/lib/TrashCan.svelte";
|
||||
import Edit from "carbon-icons-svelte/lib/Edit.svelte";
|
||||
import ManagerForm from "../lib/ManagerForm.svelte";
|
||||
import FactoryForm from "../lib/FactoryForm.svelte";
|
||||
|
||||
let rows = [
|
||||
{ id: "a", name: "Load Balancer 3", port: 3000, rule: "Round robin" },
|
||||
{ id: "b", name: "Load Balancer 1", port: 443, rule: "Round robin" },
|
||||
{ id: "c", name: "Load Balancer 2", port: 80, rule: "DNS delegation" },
|
||||
{ id: "d", name: "Load Balancer 6", port: 3000, rule: "Round robin" },
|
||||
{ id: "e", name: "Load Balancer 4", port: 443, rule: "Round robin" },
|
||||
{ id: "f", name: "Load Balancer 5", port: 80, rule: "DNS delegation" },
|
||||
];
|
||||
|
||||
let activeDelete = false
|
||||
let activeUpdate = false
|
||||
let selectedRowIds = []
|
||||
let filteredRowIds = []
|
||||
|
||||
let resetFactoryForm, validateFactoryForm;
|
||||
let resetManagerForm, validateManagerForm;
|
||||
let showCreateModal = false;
|
||||
$: if (showCreateModal) {
|
||||
resetFactoryForm()
|
||||
resetManagerForm()
|
||||
}
|
||||
|
||||
let headers = [
|
||||
{ key: "name", value: "Name" },
|
||||
{ key: "port", value: "Port" },
|
||||
{ key: "rule", value: "Rule" },
|
||||
{ key: "update-btn", empty: true, width: "5rem" },
|
||||
]
|
||||
</script>
|
||||
|
||||
<DataTable
|
||||
zebra
|
||||
selectable={activeDelete}
|
||||
batchSelection={activeDelete}
|
||||
sortable
|
||||
bind:selectedRowIds
|
||||
{headers}
|
||||
{rows}
|
||||
>
|
||||
<Toolbar>
|
||||
<ToolbarBatchActions
|
||||
bind:active={activeDelete}
|
||||
on:cancel={(e) => {
|
||||
e.preventDefault();
|
||||
activeDelete = false;
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
icon={TrashCan}
|
||||
disabled={selectedRowIds.length === 0}
|
||||
on:click={() => {
|
||||
rows = rows.filter((row) => !selectedRowIds.includes(row.id));
|
||||
selectedRowIds = [];
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
</ToolbarBatchActions>
|
||||
<ToolbarContent>
|
||||
<ToolbarSearch
|
||||
persistent
|
||||
shouldFilterRows
|
||||
bind:filteredRowIds
|
||||
/>
|
||||
<Button on:click={() => showCreateModal = true}>Create</Button>
|
||||
<Button on:click={() => (activeDelete = true)}>Delete</Button>
|
||||
</ToolbarContent>
|
||||
</Toolbar>
|
||||
<svelte:fragment slot="cell" let:cell>
|
||||
{#if cell.key === "update-btn"}
|
||||
<Button kind="ghost" size="field" iconDescription={"Edit"} icon={Edit} />
|
||||
{:else}
|
||||
{cell.value}
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</DataTable>
|
||||
|
||||
<Modal
|
||||
bind:open={showCreateModal}
|
||||
modalHeading="Create factory & manager"
|
||||
primaryButtonText="Confirm"
|
||||
secondaryButtonText="Cancel"
|
||||
on:open
|
||||
on:close={() => showCreateModal = false}
|
||||
on:click:button--secondary={() => showCreateModal = false}
|
||||
on:submit={() => {
|
||||
let isFactoryValid = validateFactoryForm()
|
||||
let isManagerValid = validateManagerForm()
|
||||
if (!(isFactoryValid && isManagerValid)) {
|
||||
return false
|
||||
}
|
||||
|
||||
showCreateModal = false
|
||||
return true
|
||||
}}
|
||||
>
|
||||
<div class="flex flex-row gap-1rem">
|
||||
<div class="flex-grow">
|
||||
<p>Factory</p>
|
||||
<FactoryForm
|
||||
bind:validate={validateFactoryForm}
|
||||
bind:reset={resetFactoryForm}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-grow-2">
|
||||
<p>Manager</p>
|
||||
<ManagerForm
|
||||
bind:validate={validateManagerForm}
|
||||
bind:reset={resetManagerForm}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
@ -1 +0,0 @@
|
||||
Factories
|
@ -1,34 +0,0 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
Form,
|
||||
Button,
|
||||
TextInput
|
||||
} from "carbon-components-svelte";
|
||||
import { invoke } from '@tauri-apps/api/tauri';
|
||||
|
||||
let firstName = ""
|
||||
let surname = ""
|
||||
let phoneNumber = ""
|
||||
let title = ""
|
||||
let email = ""
|
||||
|
||||
let onSubmit = async (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
const result = await invoke('add_manager', {
|
||||
firstName, surname, phoneNumber, title, email
|
||||
})
|
||||
console.log("submit")
|
||||
console.log(result)
|
||||
}
|
||||
</script>
|
||||
|
||||
<Form on:submit={onSubmit} class="flex flex-col gap-1rem">
|
||||
<TextInput bind:value={firstName} required labelText="First name" />
|
||||
<TextInput bind:value={surname} required labelText="Surname" />
|
||||
<TextInput bind:value={phoneNumber} labelText="Phone number" />
|
||||
<TextInput bind:value={title} required labelText="Title" />
|
||||
<TextInput bind:value={email} labelText="Email" />
|
||||
|
||||
<Button type="submit">Submit</Button>
|
||||
</Form>
|
@ -3,6 +3,7 @@ import { svelte } from "@sveltejs/vite-plugin-svelte";
|
||||
import sveltePreprocess from "svelte-preprocess";
|
||||
import transformerDirective from '@unocss/transformer-directives'
|
||||
import Unocss from 'unocss/vite'
|
||||
import { resolve } from 'path'
|
||||
|
||||
const mobile =
|
||||
process.env.TAURI_PLATFORM === "android" ||
|
||||
|
Loading…
Reference in New Issue
Block a user