replaced flowbite-svelte with yesvelte UI library

This commit is contained in:
Dave Lane 2024-10-04 16:59:49 +13:00
parent 1ce925a95d
commit 6e191c16e6
9 changed files with 5094 additions and 4843 deletions

View file

@ -55,6 +55,15 @@ and then run
npm i dotenv npm i dotenv
npm i --save-dev @sveltejs/enhanced-img npm i --save-dev @sveltejs/enhanced-img
### pnpm installs
pnpm add -g pnpm
source /home/${USER}/.bashrc
pnpm setup
pnpm add -g pnpm
pnpm i -D flowbite-svelte flowbite
### To build a new image ### To build a new image
docker-compose build docker-compose build

2028
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -17,12 +17,10 @@
"@sveltejs/kit": "^2.0.0", "@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0",
"@types/eslint": "^9.6.0", "@types/eslint": "^9.6.0",
"autoprefixer": "^10.4.20",
"eslint": "^9.0.0", "eslint": "^9.0.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.36.0", "eslint-plugin-svelte": "^2.36.0",
"flowbite": "^2.5.1",
"flowbite-svelte": "^0.46.18",
"flowbite-svelte-icons": "^1.6.1",
"globals": "^15.0.0", "globals": "^15.0.0",
"prettier": "^3.1.1", "prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.1.2", "prettier-plugin-svelte": "^3.1.2",
@ -34,6 +32,7 @@
"dependencies": { "dependencies": {
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"sass": "^1.77.8", "sass": "^1.77.8",
"svelte-preprocess": "^6.0.2" "svelte-preprocess": "^6.0.2",
"yesvelte": "next"
} }
} }

View file

@ -10,7 +10,7 @@ body {
min-height: 100%; min-height: 100%;
padding: 1em; padding: 1em;
width: 100%; width: 100%;
font-size: 1.2em; font-size: 1.3em;
border: double 3px #ddd; border: double 3px #ddd;
border-top: none; border-top: none;
border-bottom: none; border-bottom: none;
@ -23,5 +23,10 @@ a {
color: #4054ad; color: #4054ad;
font-weight: bold; font-weight: bold;
} }
a:hover { color: #1b2c44; } a:hover {
a:visited { color: #437fad; } color: #000;
text-decoration: underline;
}
a:visited {
color: #437fad;
}

View file

@ -7,7 +7,7 @@
export let context = 'none'; export let context = 'none';
export let filterValues; export let filterValues;
export let histogram; // an array with key = filter value, val = number of technologies export let histogram; // an array with key = filter value, val = number of technologies
export let colours = []; // an array of colour values with export const colours = []; // an array of colour values with
//console.log('Filterable contextFilter: ', filterValues); //console.log('Filterable contextFilter: ', filterValues);
let activeFiltersString = 'None'; let activeFiltersString = 'None';
@ -76,7 +76,7 @@
filterText = filterVerbage(isActive); filterText = filterVerbage(isActive);
} }
console.log('histogram: ', histogram); //console.log('histogram: ', histogram);
</script> </script>
<slot name="title"><h2>Test Array</h2></slot> <slot name="title"><h2>Test Array</h2></slot>
@ -139,14 +139,13 @@
word-break: normal; word-break: normal;
margin: 1.5em 1em 2em 0; margin: 1.5em 1em 2em 0;
} }
.filter:hover { /* .filter:hover {
box-shadow: 6px 6px 5px #aaa; box-shadow: 6px 6px 5px #aaa;
border-color: #222; border-color: #222;
} }
.active { .active {
background-color: lightblue; background-color: lightblue;
/*border-color: blue;*/ } */
}
/* instance-specific styles */ /* instance-specific styles */
.filter { .filter {
@ -160,8 +159,8 @@
box-shadow: 3px 3px 3px #6a6d6a; box-shadow: 3px 3px 3px #6a6d6a;
color: #222; color: #222;
} }
.filter:hover { box-shadow: 4px 4px 3px #727372; color: #000; } .filter:hover { box-shadow: 6px 6px 5px #aaa; color: #000; }
.filter:hover.active { color: #fff;} .filter:active { box-shadow: 0px 0px 3px #727372; color: #fff;}
.filter.categories.active { .filter.categories.active {
background-color: #9aa34d; background-color: #9aa34d;
color: #eee; color: #eee;

View file

@ -2,6 +2,9 @@
// a 'technology' object // a 'technology' object
export let technology; export let technology;
export let affiliate_colours; export let affiliate_colours;
import { Button, Modal, ModalBody, ModalFooter, Popover } from 'yesvelte';
let showModal = false;
const formatter = new Intl.ListFormat('en', { const formatter = new Intl.ListFormat('en', {
style: 'long', style: 'long',
@ -33,15 +36,16 @@
} }
</script> </script>
<div class="tile technology"> <div on:click={() => (showModal = !showModal)} class="tile technology">
<div class="links"> <div class="links">
<span class="website"><a href="{technology.website}" title="Project site for {technology.name}">P</a></span>
{#if technology.repository}<span class="repository"><a {#if technology.repository}<span class="repository"><a
href={technology.repository} title="The source code repository for {technology.name}">R</a></span>{/if} href={technology.repository} title="The source code repository for {technology.name}">R</a></span>{/if}
{#if technology.wikipedia}<span class="wikipedia"><a {#if technology.wikipedia}<span class="wikipedia"><a
href={technology.wikipedia} href={technology.wikipedia}
title="Wikipedia Page for {technology.name}">W</a></span>{/if} title="Wikipedia Page for {technology.name}">W</a></span>{/if}
</div> </div>
<h2><a href={technology.website}>{technology.name}</a></h2> <h2>{technology.name}</h2>
<p class="description">{technology.description}{#if technology.extended_description}<span <p class="description">{technology.description}{#if technology.extended_description}<span
title={technology.extended_description}>i</span>{/if} title={technology.extended_description}>i</span>{/if}
</p> </p>
@ -66,6 +70,12 @@
{/if} {/if}
</div> </div>
<Modal title="{technology.name}" bind:showModal>
<ModalBody>
Modal stuff...
</ModalBody>
</Modal>
<style> <style>
.tile { .tile {
display: inline-block; display: inline-block;
@ -76,7 +86,7 @@
overflow: hidden; overflow: hidden;
box-sizing: border-box; box-sizing: border-box;
box-shadow: 5px 5px 3px #6a6d6a; box-shadow: 5px 5px 3px #6a6d6a;
border: solid 3px #516855; border: solid 3px #3a8ea5;
border-radius: 15px; border-radius: 15px;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
@ -96,6 +106,10 @@
.tile:hover { .tile:hover {
box-shadow: 10px 10px 6px #727372; box-shadow: 10px 10px 6px #727372;
} }
.tile:active {
box-shadow: 0 0 0;
border-color: #000;
}
.tile p.description { .tile p.description {
height: 200px; height: 200px;
overflow: scroll; overflow: scroll;
@ -156,15 +170,15 @@
vertical-align: middle; vertical-align: middle;
} }
.circle { .circle {
height: 20px; height: 26px;
width: 20px; width: 26px;
background-color: #555; background-color: #555;
border-radius: 50%; border-radius: 50%;
display: inline-block; display: inline-block;
} }
.square { .square {
height: 20px; height: 26px;
width: 20px; width: 26px;
background-color: #555; background-color: #555;
display: inline-block; display: inline-block;
} }

View file

@ -1,7 +1,21 @@
<script> <script>
import '../app.css'; import '../app.css';
import tabler from 'yesvelte/css/tabler.min.css?url';
import daisyui from 'yesvelte/css/daisyui.min.css?url';
// you can change theme of your project from here.
let theme = 'tabler';
// let theme = 'daisyui';
</script> </script>
<svelte:head>
{#if theme === 'tabler'}
<link rel="stylesheet" href={tabler} />
{:else}
<link rel="stylesheet" href={daisyui} />
{/if}
</svelte:head>
<nav> <nav>
<a href="/">Web Services</a> <a href="/">Web Services</a>
<a href="/about">About</a> <a href="/about">About</a>
@ -18,15 +32,15 @@
<style> <style>
/* global styles are in ../app.css */ /* global styles are in ../app.css */
nav { nav { margin: auto; }
margin: auto; nav a { margin-right: 20px; }
} nav a:hover {
nav a { color: #000;
margin-right: 20px; text-decoration: underline;
} }
footer { footer {
display: inline-grid; display: inline-grid;
margin: 4em, auto, 0, auto; margin: 4em auto 0 auto;
grid-template-columns: 2fr 3fr 1fr; grid-template-columns: 2fr 3fr 1fr;
} }
footer div { footer div {

View file

@ -8,9 +8,10 @@
// the filters // the filters
import { setFilter, getFilter } from '$lib/components/filter.js'; import { setFilter, getFilter } from '$lib/components/filter.js';
import { Accordions, Accordion, AccordionBody } from 'yesvelte';
import Filterable from '$lib/components/Filterable.svelte'; import Filterable from '$lib/components/Filterable.svelte';
// collapsible sections // collapsible sections
import CollapsibleSection from '$lib/components/CollapsibleSection.svelte'; //import CollapsibleSection from '$lib/components/CollapsibleSection.svelte';
import TechnologyTile from '$lib/components/TechnologyTile.svelte'; import TechnologyTile from '$lib/components/TechnologyTile.svelte';
let tabindex = 0; // a counter which facilitates keyboard navigation. let tabindex = 0; // a counter which facilitates keyboard navigation.
@ -180,8 +181,8 @@
let host_array = {}; let host_array = {};
let i = 0; let i = 0;
console.log('hosts:', hosts); //console.log('hosts:', hosts);
console.log('host_list:', host_list); //console.log('host_list:', host_list);
for (let index in host_list) { for (let index in host_list) {
console.log(host_list[index]); console.log(host_list[index]);
@ -204,7 +205,7 @@
let i = 0; let i = 0;
//console.log('affiliates:', affiliates); //console.log('affiliates:', affiliates);
console.log('affiliate_list:', affiliate_list); //console.log('affiliate_list:', affiliate_list);
for (let index in affiliate_list) { for (let index in affiliate_list) {
//console.log('affiliate:', affiliate); //console.log('affiliate:', affiliate);
@ -256,7 +257,7 @@
let arr = tech[field] let arr = tech[field]
const intersection = inCommon(arr, list); const intersection = inCommon(arr, list);
if (intersection && intersection.constructor === Array) { if (intersection && intersection.constructor === Array) {
console.log('intersection length: ', intersection.length); //console.log('intersection length: ', intersection.length);
if (intersection.length > 0) { if (intersection.length > 0) {
included.push(tech); included.push(tech);
} }
@ -275,7 +276,7 @@
let arr = [tech[field]]; let arr = [tech[field]];
const intersection = inCommon(arr, list); const intersection = inCommon(arr, list);
if (intersection && intersection.constructor === Array) { if (intersection && intersection.constructor === Array) {
console.log('intersection length: ', intersection.length); //console.log('intersection length: ', intersection.length);
if (intersection.length > 0) { if (intersection.length > 0) {
included.push(tech); included.push(tech);
} }
@ -318,14 +319,14 @@
$hostFilter = getSortedFilter(results.instance_lists.host_list); $hostFilter = getSortedFilter(results.instance_lists.host_list);
const hosts = results.hosts; const hosts = results.hosts;
console.log('host_data: ', results.hosts); //console.log('host_data: ', results.hosts);
const affiliates = results.affiliates; const affiliates = results.affiliates;
console.log('affiliate_data: ', results.affiliates); //console.log('affiliate_data: ', results.affiliates);
const host_colours = hostColours($hostFilter, colours, hosts); const host_colours = hostColours($hostFilter, colours, hosts);
console.log('host_colours:', host_colours); //console.log('host_colours:', host_colours);
colours.sort(); colours.sort();
const affiliate_colours = affiliateColours($affiliateFilter, colours, affiliates); const affiliate_colours = affiliateColours($affiliateFilter, colours, affiliates);
console.log('affiliate_colours:',affiliate_colours); //console.log('affiliate_colours:',affiliate_colours);
let filteredTechnologies; let filteredTechnologies;
let technologies; let technologies;
@ -379,17 +380,22 @@
<p>To manage the servers and keep them up-to-date, I use SSH to establish secure encrypted connections to them (via key-based authentication). I run updates of the hosts manually, and update individual services when required (urgently if updates are security-related). Some of the Docker containers I run I have built myself, in other cases I use those supplied by the communities developing the service.</p> <p>To manage the servers and keep them up-to-date, I use SSH to establish secure encrypted connections to them (via key-based authentication). I run updates of the hosts manually, and update individual services when required (urgently if updates are security-related). Some of the Docker containers I run I have built myself, in other cases I use those supplied by the communities developing the service.</p>
<p>One huge advantage of the Docker Compose pattern is that I can rapidly move services between different hosts, or even replicate services very rapidly for development or staging purposes. Using them has revolutionised my hosting processes.</p> <p>One huge advantage of the Docker Compose pattern is that I can rapidly move services between different hosts, or even replicate services very rapidly for development or staging purposes. Using them has revolutionised my hosting processes.</p>
</div> </div>
<CollapsibleSection headerText={'Filters'}> <Accordions>
<div class="filters"> <Accordion title="Filters">
<CollapsibleSection headerText={'Software Catergory Filter'}> <AccordionBody>
<Accordions>
<Accordion title="Software Catergory Filter">
<AccordionBody>
<div class="filter-group categories"> <div class="filter-group categories">
<Filterable filterValues={categoryFilter} <Filterable filterValues={categoryFilter}
histogram={results.tech_lists.category_list} context={'categories'}> histogram={results.tech_lists.category_list} context={'categories'}>
<h2 slot="title">Categories</h2> <h2 slot="title">Categories</h2>
</Filterable> </Filterable>
</div> </div>
</CollapsibleSection> </AccordionBody>
<CollapsibleSection headerText={'Software Analogue Filter'}> </Accordion>
<Accordion title="Software Analogue Filter">
<AccordionBody>
<div class="filter-group analogues"> <div class="filter-group analogues">
<Filterable filterValues={analogueFilter} <Filterable filterValues={analogueFilter}
tabindex={tabindex} tabindex={tabindex}
@ -397,8 +403,10 @@
<h2 slot="title">Analogues</h2> <h2 slot="title">Analogues</h2>
</Filterable> </Filterable>
</div> </div>
</CollapsibleSection> </AccordionBody>
<CollapsibleSection headerText={'License Filter'}> </Accordion>
<Accordion title="License Filter">
<AccordionBody>
<div class="filter-group licenses"> <div class="filter-group licenses">
<Filterable filterValues={licenseFilter} <Filterable filterValues={licenseFilter}
tabindex={tabindex} tabindex={tabindex}
@ -406,8 +414,10 @@
<h2 slot="title">Open Source & Copyleft Licenses</h2> <h2 slot="title">Open Source & Copyleft Licenses</h2>
</Filterable> </Filterable>
</div> </div>
</CollapsibleSection> </AccordionBody>
<CollapsibleSection headerText={'Service Status Filter'}> </Accordion>
<Accordion title="Service Status Filter">
<AccordionBody>
<div class="filter-group statuses"> <div class="filter-group statuses">
<Filterable filterValues={statusFilter} <Filterable filterValues={statusFilter}
tabindex={tabindex} tabindex={tabindex}
@ -415,8 +425,10 @@
<h2 slot="title">Statuses</h2> <h2 slot="title">Statuses</h2>
</Filterable> </Filterable>
</div> </div>
</CollapsibleSection> </AccordionBody>
<CollapsibleSection headerText={'Service Affiliates Filter'}> </Accordion>
<Accordion title="Service Affiliates Filter">
<AccordionBody>
<div class="filter-group affilates"> <div class="filter-group affilates">
<Filterable filterValues={affiliateFilter} <Filterable filterValues={affiliateFilter}
tabindex={tabindex} tabindex={tabindex}
@ -424,8 +436,10 @@
context={'affiliates'}><h2 slot="title">Affiliates</h2> context={'affiliates'}><h2 slot="title">Affiliates</h2>
</Filterable> </Filterable>
</div> </div>
</CollapsibleSection> </AccordionBody>
<CollapsibleSection headerText={'Service Host filter'}> </Accordion>
<Accordion title="Service Host Filter">
<AccordionBody>
<div class="filter-group hosts"> <div class="filter-group hosts">
<Filterable filterValues={hostFilter} <Filterable filterValues={hostFilter}
tabindex={tabindex} tabindex={tabindex}
@ -433,9 +447,12 @@
<h2 slot="title">Hosts</h2> <h2 slot="title">Hosts</h2>
</Filterable> </Filterable>
</div> </div>
</CollapsibleSection> </AccordionBody>
</div> </Accordion>
</CollapsibleSection> </Accordions>
</AccordionBody>
</Accordion>
</Accordions>
<div class="tiles"> <div class="tiles">
{#each filteredTechnologies as technology} {#each filteredTechnologies as technology}
<TechnologyTile technology={technology} affiliate_colours={affiliate_colours} /> <TechnologyTile technology={technology} affiliate_colours={affiliate_colours} />
@ -476,6 +493,19 @@
} }
.summary .label { color: #666; } .summary .label { color: #666; }
.summary .number { color: #000; } .summary .number { color: #000; }
/* .accordion-item {
width: 30em;
display: flex;
text-align: left;
}
.accordion-item h2 {
display: inline;
}
.accordion-item svg {
width: 12px;
display: block;
vertical-align: middle;
}*/
@media screen and (max-width: 600px) { @media screen and (max-width: 600px) {
.summary { .summary {
float: none; float: none;

View file

@ -1,6 +1,5 @@
//import adapter from '@sveltejs/adapter-auto'; //import adapter from '@sveltejs/adapter-auto';
import adapter from '@sveltejs/adapter-node'; // ref https://medium.com/@loic.joachim/dockerize-sveltekit-with-node-adapter-62c5dc6fc15a import adapter from '@sveltejs/adapter-node'; // ref https://medium.com/@loic.joachim/dockerize-sveltekit-with-node-adapter-62c5dc6fc15a
import sveltePreprocess from 'svelte-preprocess'; import sveltePreprocess from 'svelte-preprocess';
/** @type {import('@sveltejs/kit').Config} */ /** @type {import('@sveltejs/kit').Config} */