Initial Commit

This commit is contained in:
Jabir 2023-11-01 22:20:34 +01:00
commit d56291e561
29 changed files with 4407 additions and 0 deletions

13
.eslintignore Normal file
View file

@ -0,0 +1,13 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock

14
.eslintrc.cjs Normal file
View file

@ -0,0 +1,14 @@
module.exports = {
root: true,
extends: ['eslint:recommended', 'plugin:svelte/recommended'],
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020,
extraFileExtensions: ['.svelte']
},
env: {
browser: true,
es2017: true,
node: true
}
};

11
.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.idea

8
.idea/.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View file

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

8
.idea/modules.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/printer-manager-fe.iml" filepath="$PROJECT_DIR$/.idea/printer-manager-fe.iml" />
</modules>
</component>
</project>

19
.idea/php.xml Normal file
View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

1
.npmrc Normal file
View file

@ -0,0 +1 @@
engine-strict=true

38
README.md Normal file
View file

@ -0,0 +1,38 @@
# create-svelte
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```bash
# create a new project in the current directory
npm create svelte@latest
# create a new project in my-app
npm create svelte@latest my-app
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```bash
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.

3410
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

28
package.json Normal file
View file

@ -0,0 +1,28 @@
{
"name": "printer-manager-fe",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint ."
},
"devDependencies": {
"@sveltejs/adapter-auto": "^2.0.0",
"@sveltejs/kit": "^1.20.4",
"autoprefixer": "^10.4.16",
"eslint": "^8.28.0",
"eslint-plugin-svelte": "^2.30.0",
"flowbite": "^1.8.1",
"flowbite-svelte": "^0.44.18",
"postcss": "^8.4.31",
"svelte": "^4.0.5",
"tailwindcss": "^3.3.3",
"vite": "^4.4.2"
},
"type": "module",
"dependencies": {
"axios": "^1.5.1"
}
}

6
postcss.config.js Normal file
View file

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

13
src/app.css Normal file
View file

@ -0,0 +1,13 @@
@import url('https://fonts.googleapis.com/css2?family=Sometype+Mono:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
background-color: #121212;
font-family: 'Sometype Mono', monospace;
/*font-family: 'Roboto', sans-serif;*/
}

13
src/app.html Normal file
View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v4.0.8/css/line.css">
<meta name="viewport" content="width=device-width" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>

View file

@ -0,0 +1,8 @@
<div>
<i class="uil uil-{name}"/>
</div>
<script>
export let name = 'home';
</script>

View file

@ -0,0 +1,16 @@
<div>
{#if isLoading}
<div class="mx-auto justify-center flex text-center my-16">
<Loader loading="{true}"/>
</div>
{:else}
<slot/>
{/if}
</div>
<script>
import Loader from './Loader.svelte';
export let isLoading = false;
</script>

View file

@ -0,0 +1,22 @@
<div>
{#if loading}
<div>
<div role="status">
<svg aria-hidden="true"
class="w-8 h-8 mr-2 text-gray-400 animate-spin dark:text-gray-600 fill-primary-700"
viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
fill="currentColor"/>
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
fill="currentFill"/>
</svg>
<span class="sr-only">Loading...</span>
</div>
</div>
{/if}
</div>
<script>
export let loading = false
</script>

127
src/helpers/backend.js Normal file
View file

@ -0,0 +1,127 @@
import axios from "axios";
axios.defaults.baseURL = "http://localhost:8000"
axios.defaults.headers.post["Content-Type"] = "application/json";
axios.interceptors.request.use((request) => {
return request;
});
axios.interceptors.response.use((response) => {
return response;
}, function (error) {
if (!error.response) {
//unable to reach server
return Promise.reject(error);
}
if (error.response.status >= 500 && error.response.status <= 599) {
// server error
return Promise.reject(error);
}
//Invalid key logout!
if (error.response.status === 401) {
return Promise.reject(error);
}
if (error.response.status === 403) {
return Promise.reject(error);
// no permission
}
if (error.response.status === 422) {
console.log('validation error', error);
}
if (error.response.status === 404) {
console.log('not found');
}
return Promise.reject(error);
});
// const setAuthorization = (access_token) => {
// if (access_token) {
// axios.defaults.headers.common["Authorization"] = "Bearer " + access_token;
// }
// };
export function getValueByDot(obj, target) {
const arr = target.split('.');
for (let i = 0; i < arr.length; i++) {
if (obj)
obj = obj[arr[i]];
}
return obj;
}
export function buildUrl(url) {
return "/api"+ url;
// setAuthorization(user?.access_token);
}
export async function getData(url, params) {
let response;
let paramKeys = [];
url = buildUrl(url);
if (params) {
Object.keys(params).map(key => {
if (params[key] !== undefined && params[key] !== null) {
paramKeys.push(key + '=' + params[key])
}
return paramKeys;
});
const queryString = paramKeys && paramKeys.length ? paramKeys.join('&') : "";
url = url + '?' + queryString;
}
// const cachedData = cache.get(url);
// if(cachedData){
// return cachedData;
// }
response = axios.get(url);
// cache.rememberResponse(url, response, 1);
return response;
}
export async function postData(url, data, params) {
let paramKeys = [];
url = buildUrl(url)
if (params) {
Object.keys(params).map(key => {
if (params[key]) {
paramKeys.push(key + '=' + params[key])
}
return paramKeys;
});
const queryString = paramKeys && paramKeys.length ? paramKeys.join('&') : "";
url = url + '?' + queryString;
}
console.log({url, data})
return await axios.post(url, data);
}
export async function putData(url, data) {
return axios.put(buildUrl(url), data);
}
export async function deleteData(url) {
return axios.delete(buildUrl(url));
}
export function handleResponse(response) {
if (response.status === 200 || response.status === 201) {
return response.data?.data || response.data;
}
return response.data?.data || response.data;
}

1
src/lib/index.js Normal file
View file

@ -0,0 +1 @@
// place files you want to import through the `$lib` alias in this folder.

21
src/routes/+layout.svelte Normal file
View file

@ -0,0 +1,21 @@
<!-- src/routes/__layout.svelte -->
<script>
import "../app.css";
let isDarkMode = false;
function toggleDarkMode() {
isDarkMode = !isDarkMode;
// Add or remove the 'dark-mode' class from the <html> or <body> element
if (isDarkMode) {
document.documentElement.classList.add('dark-mode');
} else {
document.documentElement.classList.remove('dark-mode');
}
}
</script>
<main>
<slot/>
</main>

139
src/routes/+page.svelte Normal file
View file

@ -0,0 +1,139 @@
<div class="max-w-7xl mx-auto px-8">
<h4 class="text-primary-700 text-xl font-bold mt-16 ">
Welcome {user.name}
</h4>
<h4 class="text-primary-700 font-bold mt-4 ">
<span>Select a printer to continue</span>
</h4>
<LoadableContent isLoading="{loadingPrinters}">
<div class="mx-auto">
<div class="mt-4">
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
{#each printers as printer}
<div class="bg-dark-light p-4 rounded-md w-full">
<div class="text-lg font-bold text-center text-white">
<div class="flex justify-center items-center flex-col">
<p>{printer.name}</p>
<div class="mt-1">
<div class="flex flex-col gap-1 text-stone-300 items-center text-sm">
<Badge color="{getPrinterLogs(printer).color}" rounded
class="px-2.5 py-0.5">
<Indicator color="{getPrinterLogs(printer).color}" size="xs"
class="mr-1"/> {printer?.logs?.state?.text ?? 'unkown'}
</Badge>
</div>
{#if printer?.logs?.temperature}
<div class="flex gap-2 justify-center mt-3">
{#each Object.entries(printer?.logs?.temperature) as [key, temperature]}
<div class="flex justify-center text-xs bg-blue-200 text-blue-500 py-0.5 px-2 rounded-full">
{key}
{temperature?.actual}°C
</div>
{/each}
</div>
{#if printer?.logs?.display_logs}
<div class="mt-4 text-left text-xs">
<pre class="text-gray-400">{JSON.stringify(printer.logs, null, 2)}</pre>
</div>
{/if}
{/if}
</div>
</div>
<div class="flex justify-center gap-4 mt-4">
<Button color="primary" size="xs" href="/printers/{printer.id}">Select</Button>
</div>
</div>
</div>
{/each}
</div>
</div>
</div>
</LoadableContent>
</div>
<script>
import {Button, Indicator, Badge} from 'flowbite-svelte';
import LoadableContent from "../components/loadable-content.svelte";
import Icon from "../components/icon.svelte";
import {onDestroy, onMount} from "svelte";
import printerService from "../services/printer/printer.service.js";
import printerDriverService from "../services/printer/printer-driver.service.js";
onMount(() => {
fetchPrinters()
})
let printers = []
let loadingPrinters = true
const user = {name: 'John Doe'}
let clear
$: {
clearInterval(clear)
clear = setInterval(getAllPrinterStatus, 2000)
}
onDestroy(() => {
clearInterval(clear);
});
async function fetchPrinters() {
loadingPrinters = true
await printerService.index().then((response) => {
printers = response.data.data
getAllPrinterStatus()
loadingPrinters = false
}).catch((error) => {
console.log(error)
loadingPrinters = false
})
}
async function getAllPrinterStatus() {
console.log('FOMR HIEROOO')
printers.forEach((printer) => {
getPrinterStatus(printer)
})
}
async function getPrinterStatus(printer) {
await printerDriverService.getStatus(printer).then(res => {
printer = {...printer, logs: res, display_logs: false}; // Using spread operator to create a new object
const index = printers.findIndex(p => p.name === printer.name);
if (index !== -1) {
printers[index] = printer;
}
})
}
function getPrinterColor(state) {
if (state?.paused || state?.printing || state?.pausing) {
return 'yellow'
}
if (state?.operational || state?.ready) {
return 'green'
}
if (state?.cancelling || state?.error) {
return 'red'
}
return 'gray'
}
function getPrinterLogs(printer) {
const color = getPrinterColor(printer?.logs?.state?.flags)
return {
color: color,
}
}
</script>

View file

@ -0,0 +1,326 @@
<div class="max-w-7xl mx-auto px-8">
<div class="flex justify-between items-center mt-16">
<h4 class="text-primary-700 text-xl font-bold">
Printing as <span class="font-bold">{user.name}</span>
<p class="text-xs text-gray-500">{user.user_id}</p>
</h4>
<Button color="primary" size="xs" href="/">
<Icon name="arrow-left"/>
All Printers
</Button>
</div>
<LoadableContent isLoading="{loading}">
<div class="mx-auto">
<div class="mt-4">
<div class="grid grid-cols-1 sm:grid-cols-3 h-full gap-4">
<div class="col-span-1 space-y-4">
<div class="bg-dark-light p-4 rounded-md w-full">
<div class="text-lg font-bold text-center text-white">
<div class="flex justify-center items-center flex-col">
<p>{printer.name}</p>
<div class="mt-1">
<div class="flex flex-col gap-1 text-stone-300 items-center text-sm">
<Badge color="{getPrinterLogs(printer).color}" rounded
class="px-2.5 py-0.5">
<Indicator color="{getPrinterLogs(printer).color}" size="xs"
class="mr-1"/> {printer?.logs?.state?.text ?? 'unkown'}
</Badge>
</div>
{#if printer?.logs?.temperature}
<div class="flex gap-2 justify-center mt-3">
{#each Object.entries(printer?.logs?.temperature) as [key, temperature]}
<div class="flex justify-center text-xs bg-blue-200 text-blue-500 py-0.5 px-2 rounded-full">
{key}
{temperature?.actual}°C
</div>
{/each}
</div>
{#if printer?.logs?.display_logs}
<div class="mt-4 text-left text-xs">
<pre class="text-gray-400">{JSON.stringify(printer.logs, null, 2)}</pre>
</div>
{/if}
{/if}
</div>
</div>
</div>
</div>
<div class="bg-dark-light p-4 rounded-md w-full">
<div class="text-lg font-bold text-center text-white">
<div class="flex justify-center items-center flex-col">
<p>Queue Status</p>
<div class="mt-1">
<div class="flex flex-col gap-1 text-stone-300 items-center text-sm">
<!-- <Badge color="{getPrinterLogs(printer).color}" rounded-->
<!-- class="px-2.5 py-0.5">-->
<!-- <Indicator color="{getPrinterLogs(printer).color}" size="xs"-->
<!-- class="mr-1"/> {printer?.logs?.state?.text ?? 'unkown'}-->
<!-- </Badge>-->
{printerData?.queueData?.queue_state}
</div>
{#if printerData?.queueData?.queued_jobs?.length}
<div class="flex gap-2 flex-col mt-3">
{#each printerData?.queueData?.queued_jobs as queuedJob}
<div class="flex justify-center flex-col text-xs bg-gray-700 p-2 rounded-lg">
<p>{queuedJob.filename}</p>
<p class="text-[9px]">{queuedJob.job_id}</p>
<div class="text-[9px]">
<p>Added At: {formatDate(queuedJob.time_added)}</p>
<p>In queue: {formatTimeAgo(queuedJob.time_added)}</p>
</div>
<button on:click={deleteJobFromQueue(queuedJob.job_id)}>
<Icon name="trash" />
</button>
</div>
{/each}
</div>
<div class="flex justify-center gap-4 mt-8">
<Button color="red" size="xs" on:click={clearPrinterQueue}>
<Icon name="times"/>
<span class="ml-1">Clear queue</span>
</Button>
<Button color="green" size="xs" href="/">
<Icon name="play"/>
<span class="ml-1">Start queue</span>
</Button>
</div>
{/if}
</div>
</div>
</div>
</div>
</div>
<div class="col-span-2 h-auto">
<div class="bg-dark-light p-4 rounded-md w-full">
<div class="flex justify-between items-center">
<div class="text-primary-600">
Files
</div>
<div>
<Button color="primary" size="xs" href="/">
<Icon name="upload"/>
<span class="ml-1">Upload file</span>
</Button>
</div>
</div>
<div class="mt-">
{#if printerData?.files?.length}
<TableSearch color="gray" placeholder="Search by file name" hoverable={true}
bind:inputValue={searchTerm}>
<TableHead>
<TableHeadCell>Filename</TableHeadCell>
<TableHeadCell></TableHeadCell>
</TableHead>
<TableBody class="divide-y">
{#each filteredItems as file}
<TableBodyRow>
<TableBodyCell class="w-[20px]">
<div>
{file.path}
<p class="text-gray-400 text-xs">{formatBytes(file.size)}
- {formatDate(file.modified)}</p>
</div>
</TableBodyCell>
<TableBodyCell>
<Button color="primary" size="xs"
on:click={putInQueue(file.path)}>
<Icon name="print"/>
</Button>
</TableBodyCell>
</TableBodyRow>
{/each}
</TableBody>
</TableSearch>
{/if}
</div>
</div>
</div>
</div>
</div>
</div>
</LoadableContent>
</div>
<script>
import {
Table,
TableBody,
TableBodyCell,
TableBodyRow,
TableHead,
TableHeadCell,
Checkbox,
TableSearch
} from 'flowbite-svelte';
import {Button, Indicator, Badge} from 'flowbite-svelte';
import LoadableContent from "../../../components/loadable-content.svelte";
import Icon from "../../../components/icon.svelte";
import {onDestroy, onMount} from "svelte";
import printerService from "../../../services/printer/printer.service.js";
import printerDriverService from "../../../services/printer/printer-driver.service.js";
import {page} from '$app/stores';
const id = $page.params.id;
onMount(() => {
fetchPrinter(id)
})
let printer = {}
let printerData = {}
let loading = true
let searchTerm = '';
$: filteredItems = printerData?.files?.filter((item) => item.path.toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1);
const user = {name: 'John Doe', user_id: 'dnh-jabir-from-pmanager'}
let clear
$: {
clearInterval(clear)
clear = setInterval(getPrinterStatus, 10000)
}
onDestroy(() => {
clearInterval(clear);
});
function formatBytes(bytes, decimals = 2) {
if (!+bytes) return '0 Bytes'
const k = 1024
const dm = decimals < 0 ? 0 : decimals
const sizes = ['Bytes', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
}
async function putInQueue(file) {
await printerDriverService.postPrinterQueue(printer, file).then((response) => {
getPrinterQueue()
}).catch((error) => {
console.log(error)
loading = false
})
}
async function clearPrinterQueue(){
await printerDriverService.clearQueue(printer).then((response) => {
getPrinterQueue()
}).catch((error) => {
console.log(error)
loading = false
})
}
async function deleteJobFromQueue(jobId){
await printerDriverService.deleteJob(printer, jobId).then((response) => {
getPrinterQueue()
}).catch((error) => {
console.log(error)
loading = false
})
}
function formatDate(date) {
return new Date(date * 1000).toLocaleDateString('en-GB', {
day: 'numeric',
month: 'short',
year: 'numeric',
hour: 'numeric',
minute: 'numeric',
})
}
function formatTimeAgo(date) {
const currentTime = new Date();
const previousTime = new Date(date * 1000);
const timeDifference = Math.abs(currentTime - previousTime);
const minutes = Math.floor(timeDifference / 60000);
const hours = Math.floor(timeDifference / 3600000);
const days = Math.floor(timeDifference / 86400000);
if (minutes < 1) {
return 'just now';
} else if (minutes < 60) {
return `${minutes} ${minutes === 1 ? 'minute' : 'minutes'} ago`;
} else if (hours < 24) {
return `${hours} ${hours === 1 ? 'hour' : 'hours'} ago`;
} else {
return `${days} ${days === 1 ? 'day' : 'days'} ago`;
}
}
async function fetchPrinter(id) {
loading = true
await printerService.fetch(id).then((response) => {
printer = response.data.data
getPrinterStatus()
loading = false
}).then(() => {
getPrinterFiles()
getPrinterQueue()
}).catch((error) => {
console.log(error)
loading = false
})
}
async function getPrinterStatus() {
console.log('nu from hier XD')
await printerDriverService.getStatus(printer).then(res => {
printer = {...printer, logs: res, display_logs: false};
})
}
async function getPrinterFiles() {
await printerDriverService.getFiles(printer).then(res => {
printerData = {...printerData, files: res?.result};
})
}
async function getPrinterQueue() {
await printerDriverService.getPrinterQueue(printer).then(res => {
printerData = {...printerData, queueData: res?.result};
console.log(printerData)
})
}
function getPrinterColor(state) {
if (state?.paused || state?.printing || state?.pausing) {
return 'yellow'
}
if (state?.operational || state?.ready) {
return 'green'
}
if (state?.cancelling || state?.error) {
return 'red'
}
return 'gray'
}
function getPrinterLogs(printer) {
const color = getPrinterColor(printer?.logs?.state?.flags)
return {
color: color,
}
}
</script>

View file

@ -0,0 +1,93 @@
import {deleteData} from "../../helpers/backend.js";
export default {
async getStatus(printer) {
if (printer.driver === 'moonraker') {
return request(`http://${printer.config.host}:${printer.config.port}/api/printer`).then(res => {
return res
})
}
},
async getFiles(printer) {
if (printer.driver === 'moonraker') {
return request(`http://${printer.config.host}:${printer.config.port}/server/files/list`).then(res => {
return res
})
}
},
async getPrinterQueue(printer) {
if (printer.driver === 'moonraker') {
return request(`http://${printer.config.host}:${printer.config.port}/server/job_queue/status`).then(res => {
return res
})
}
},
async postPrinterQueue(printer, filename) {
if (printer.driver === 'moonraker') {
//post
return post(`http://${printer.config.host}:${printer.config.port}/server/job_queue/job?filenames=${filename}`).then(res => {
return res
})
}
},
async deleteJob(printer, jobId) {
if (printer.driver === 'moonraker') {
//post
return deleteMethod(`http://${printer.config.host}:${printer.config.port}/server/job_queue/job?job_ids=${jobId}`).then(res => {
return res
})
}
},
async clearQueue(printer) {
if (printer.driver === 'moonraker') {
//post
return deleteMethod(`http://${printer.config.host}:${printer.config.port}/server/job_queue/job`).then(res => {
return res
})
}
}
}
function post(url, data) {
return fetch(url, {
method: 'POST',
// body: JSON.stringify(data),
// headers: {
// 'Content-Type': 'application/json'
// }
})
.then(response => response.json())
.then(data => data)
.catch(error => {
console.log(error, 'xddddaaa');
});
}
function deleteMethod(url, data) {
return fetch(url, {
method: 'detele',
// body: JSON.stringify(data),
// headers: {
// 'Content-Type': 'application/json'
// }
})
.then(response => response.json())
.then(data => data)
.catch(error => {
console.log(error, 'xddddaaa');
});
}
function request(url, options) {
return fetch(url, options)
.then(response => response.json())
.then(data => data)
.catch(error => {
console.log(error, 'xddddaaa');
});
}

View file

@ -0,0 +1,10 @@
import {getData} from "../../helpers/backend.js";
export default {
async index(params) {
return getData(`/printers`, params);
},
async fetch(id) {
return getData(`/printers/${id}`);
}
}

BIN
static/favicon.png Normal file

Binary file not shown.

After

(image error) Size: 1.5 KiB

10
svelte.config.js Normal file
View file

@ -0,0 +1,10 @@
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/kit/vite';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter()
},
preprocess: vitePreprocess()
};
export default config;

32
tailwind.config.js Normal file
View file

@ -0,0 +1,32 @@
const colors = require('tailwindcss/colors')
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{html,js,svelte,ts}', './node_modules/flowbite-svelte/**/*.{html,js,svelte,ts}'],
plugins: [require('flowbite/plugin')],
theme: {
extend: {
colors: {
'dark-primary': '#121212',
'dark-light': '#282828',
// 'primary': '#0284c7',
gray: colors.gray,
primary: {
'50': '#f0fafb',
'100': '#daf1f3',
'200': '#b9e4e8',
'300': '#89cfd7',
'400': '#5bb6c2',
'500': '#3696a4',
'600': '#307a8a',
'700': '#2c6472',
'800': '#2b535f',
'900': '#284751',
'950': '#162e36',
}
}
}
},
};

6
vite.config.js Normal file
View file

@ -0,0 +1,6 @@
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [sveltekit()]
});