generated from thinkode/modelRepository
24-project-life (#28)
Fix peripherals states and implements plug and reload feature. Graphics improvements. Stability improvements. Reviewed-on: #28
This commit was merged in pull request #28.
This commit is contained in:
@@ -7,66 +7,50 @@
|
||||
import Settings from './components/Settings/Settings.svelte';
|
||||
import Devices from './components/Devices/Devices.svelte';
|
||||
import Show from './components/Show/Show.svelte';
|
||||
import DropdownList from "./components/General/DropdownList.svelte";
|
||||
import RoundDropdownList from "./components/General/RoundDropdownList.svelte";
|
||||
import GeneralConsole from './components/Console/GeneralConsole.svelte';
|
||||
import RoundIconButton from './components/General/RoundIconButton.svelte';
|
||||
import { generateToast, showInformation, needProjectSave, peripherals } from './stores';
|
||||
import { SaveProject } from '../wailsjs/go/main/App.js';
|
||||
import { construct_svelte_component } from 'svelte/internal';
|
||||
import { EventsOn } from '../wailsjs/runtime'
|
||||
import { CreateProject } from "../wailsjs/go/main/App";
|
||||
import { generateToast, showInformation, needProjectSave, projectsList } from './stores.js';
|
||||
import { GetProjects, CreateProject, OpenProjectFromDisk, SaveProject } from '../wailsjs/go/main/App.js';
|
||||
import { WindowSetTitle } from "../wailsjs/runtime/runtime"
|
||||
import { get } from "svelte/store"
|
||||
import ToastNotification from './components/General/ToastNotification.svelte';
|
||||
import { onMount, onDestroy } from 'svelte'
|
||||
import { destroyRuntimeEvents, initRuntimeEvents } from './runtime-events.js'
|
||||
|
||||
// Handle the event when a new peripheral is detected
|
||||
EventsOn('PERIPHERAL_ARRIVAL', function(peripheralInfo){
|
||||
// When a new peripheral is detected, add it to the map and:
|
||||
// - Pass the isDetected key to true
|
||||
// - Set the isSaved key to the last value
|
||||
let peripheralsList = get(peripherals)
|
||||
let lastSavedProperty = peripheralsList[peripheralInfo.SerialNumber]?.isSaved
|
||||
peripheralInfo.isDetected = true
|
||||
peripheralInfo.isSaved = (lastSavedProperty === true) ? true : false
|
||||
peripherals.update((peripherals) => {
|
||||
peripherals[peripheralInfo.SerialNumber] = peripheralInfo
|
||||
return {...peripherals}
|
||||
})
|
||||
console.log("Hardware has been added to the system");
|
||||
generateToast('info', 'bxs-hdd', $_("peripheralArrivalToast") + ' <b>' + peripheralInfo.Name + '</b>')
|
||||
})
|
||||
|
||||
// Handle the event when a peripheral is removed from the system
|
||||
EventsOn('PERIPHERAL_REMOVAL', function(peripheralInfo){
|
||||
console.log("Hardware has been removed from the system");
|
||||
// When a peripheral is disconnected, pass its isDetected key to false
|
||||
// If the isSaved key is set to false, we can completely remove the peripheral from the list
|
||||
let peripheralsList = get(peripherals)
|
||||
let lastSavedProperty = peripheralsList[peripheralInfo.SerialNumber]?.isSaved
|
||||
let needToDelete = (lastSavedProperty !== true) ? true : false
|
||||
peripherals.update((storedPeripherals) => {
|
||||
if (needToDelete){
|
||||
delete storedPeripherals[peripheralInfo.SerialNumber];
|
||||
return { ...storedPeripherals };
|
||||
}
|
||||
storedPeripherals[peripheralInfo.SerialNumber].isDetected = false
|
||||
return {...storedPeripherals}
|
||||
function initializeNewProject(){
|
||||
// Instanciate a new project
|
||||
CreateProject().then(() => {
|
||||
// Project created, we set the needSave flag to true (not already saved)
|
||||
needProjectSave.set(true)
|
||||
}).catch((error) => {
|
||||
console.error(`Unable to create the project: ${error}`)
|
||||
generateToast('danger', 'bx-error', $_("projectCreateErrorToast"))
|
||||
})
|
||||
generateToast('warning', 'bxs-hdd', $_("peripheralRemovalToast") + ' <b>' + peripheralInfo.Name + '</b>')
|
||||
}
|
||||
|
||||
// Initialize runtime events at startup
|
||||
onMount(() => {
|
||||
initRuntimeEvents()
|
||||
|
||||
// Handle window shortcuts
|
||||
document.addEventListener('keydown', function(event) {
|
||||
// Check the CTRL+S keys
|
||||
if ((event.ctrlKey || event.metaKey) && event.key === 's') {
|
||||
// Avoid the natural behaviour
|
||||
event.preventDefault();
|
||||
// Save the current project
|
||||
saveProject()
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize a new project
|
||||
initializeNewProject()
|
||||
})
|
||||
|
||||
// Handle the event when a peripheral status is updated
|
||||
EventsOn('PERIPHERAL_STATUS', function(peripheral, status){
|
||||
console.log("Hardware status has been updated to " + status);
|
||||
// When a peripheral status is updated, update it in the store
|
||||
peripherals.update((storedPeripherals) => {
|
||||
return {
|
||||
...storedPeripherals,
|
||||
[peripheral.SerialNumber]: {
|
||||
...storedPeripherals[peripheral.SerialNumber],
|
||||
isSaved: true,
|
||||
Status: status,
|
||||
},
|
||||
}})
|
||||
// Destroy runtime events at shutdown
|
||||
onDestroy(() => {
|
||||
destroyRuntimeEvents()
|
||||
})
|
||||
|
||||
// Set the window title
|
||||
@@ -92,23 +76,41 @@
|
||||
})
|
||||
}
|
||||
|
||||
// Handle window shortcuts
|
||||
document.addEventListener('keydown', function(event) {
|
||||
// Check the CTRL+S keys
|
||||
if ((event.ctrlKey || event.metaKey) && event.key === 's') {
|
||||
// Avoid the natural behaviour
|
||||
event.preventDefault();
|
||||
// Save the current project
|
||||
saveProject()
|
||||
}
|
||||
});
|
||||
// Open the selected project
|
||||
function openSelectedProject(event){
|
||||
let selectedOption = event.detail.key
|
||||
// Open the selected project
|
||||
OpenProjectFromDisk(selectedOption).then(() => {
|
||||
// Project opened, we set the needSave flag to false (already saved)
|
||||
needProjectSave.set(false)
|
||||
}).catch((error) => {
|
||||
console.error(`Unable to open the project: ${error}`)
|
||||
generateToast('danger', 'bx-error', $_("projectOpenErrorToast"))
|
||||
})
|
||||
}
|
||||
|
||||
// Refresh the projects list
|
||||
let choices = new Map()
|
||||
function loadProjectsList(){
|
||||
GetProjects().then((projects) => {
|
||||
choices = new Map(projects.map(item => [item.Save, item.Name]));
|
||||
$projectsList = projects
|
||||
}).catch((error) => {
|
||||
console.error(`Unable to get the projects list: ${error}`)
|
||||
generateToast('danger', 'bx-error', $_("projectsLoadErrorToast"))
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<header>
|
||||
<!-- Project buttons -->
|
||||
<RoundIconButton on:mouseup={initializeNewProject} icon='bxs-plus-square' width="2.5em" tooltip={$_("newProjectTooltip")}/>
|
||||
<RoundDropdownList on:click={loadProjectsList} on:selected={openSelectedProject} choices={choices} icon='bxs-folder-open' width="2.5em" tooltip={$_("openProjectTooltip")}/>
|
||||
|
||||
<NavigationBar on:navigationChanged="{onNavigationChanged}"/>
|
||||
{#if $needProjectSave}
|
||||
<RoundIconButton on:mouseup={saveProject} icon="bx-save" width="2.5em" tooltip={$_("saveButtonTooltip")}></RoundIconButton>
|
||||
<RoundIconButton on:mouseup={saveProject} icon="bx-save" width="2.5em" tooltip={$_("saveButtonTooltip")}/>
|
||||
{/if}
|
||||
<Clock/>
|
||||
</header>
|
||||
|
||||
152
frontend/src/components/General/RoundDropdownList.svelte
Normal file
152
frontend/src/components/General/RoundDropdownList.svelte
Normal file
@@ -0,0 +1,152 @@
|
||||
<!-- Create a round icon button -->
|
||||
|
||||
<script>
|
||||
import { createEventDispatcher, onDestroy } from 'svelte';
|
||||
import {colors} from '../../stores.js';
|
||||
import Tooltip from './Tooltip.svelte';
|
||||
import { _ } from 'svelte-i18n'
|
||||
|
||||
export let icon = "bxs-heart" // The icon wanted
|
||||
export let width = "10em" // The button width
|
||||
export let active = false // If the button is active or not
|
||||
export let tooltip = "Default tooltip" // The description shown in the tooltip
|
||||
export let operationalStatus = undefined// The optional button status
|
||||
export let okStatusLabel = "" // The label shown when the button is OK
|
||||
export let nokStatusLabel = "" // The label shown when the button is NOK
|
||||
export let choices = new Map()
|
||||
export let style = '';
|
||||
|
||||
let tooltipMessage = tooltip
|
||||
|
||||
// Default values for background and foreground
|
||||
$: background = $colors.first
|
||||
$: foreground = $colors.first
|
||||
|
||||
// Change the background when the selected prop changed
|
||||
$: {
|
||||
if (active === true) {
|
||||
background = $colors.third
|
||||
foreground = $colors.fourth
|
||||
} else {
|
||||
background = $colors.fourth
|
||||
foreground = $colors.second
|
||||
}
|
||||
}
|
||||
|
||||
// Show the operational status if specified
|
||||
// undefined => no status displayed
|
||||
// operationalStatus = true => OK color displayed
|
||||
// operationalStatus = false => NOK color displayed
|
||||
$: statusColor = $colors.nok
|
||||
$: {
|
||||
if (operationalStatus === true){
|
||||
statusColor = $colors.ok
|
||||
tooltipMessage = tooltip + " " + okStatusLabel
|
||||
} else {
|
||||
statusColor = $colors.nok
|
||||
tooltipMessage = tooltip + " " + nokStatusLabel
|
||||
}
|
||||
}
|
||||
|
||||
// Emit a click event when the button is clicked
|
||||
const dispatch = createEventDispatcher();
|
||||
function handleclick(key){
|
||||
// Deactivate the list visibility
|
||||
hideList()
|
||||
dispatch('selected', key)
|
||||
}
|
||||
|
||||
// Show the option list
|
||||
let listShowing = false
|
||||
function toggleList(){
|
||||
if (!listShowing) {
|
||||
dispatch('click')
|
||||
}
|
||||
listShowing = !listShowing
|
||||
}
|
||||
function hideList(){
|
||||
listShowing = false
|
||||
}
|
||||
|
||||
let tooltipPosition = {top: 0, left: 0}
|
||||
|
||||
// Show a tooltip on mouse hover
|
||||
let tooltipShowing = false
|
||||
let buttonRef
|
||||
function toggleTooltip(active){
|
||||
const rect = buttonRef.getBoundingClientRect();
|
||||
tooltipPosition = {
|
||||
top: rect.bottom + 5, // Ajouter une marge en bas
|
||||
left: rect.left, // Centrer horizontalement
|
||||
};
|
||||
tooltipShowing = active
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<button bind:this={buttonRef}
|
||||
style="width:{width}; height:{width}; border-radius:{width}; background-color:{background}; color:{foreground};"
|
||||
on:mouseenter={() => { toggleTooltip(true) }}
|
||||
on:mouseleave={() => { toggleTooltip(false) }}
|
||||
on:click={toggleList}>
|
||||
<i class='bx {icon}' style="font-size:100%;"></i>
|
||||
</button>
|
||||
<!-- Showing the badge status if the button has an operational status -->
|
||||
{#if (operationalStatus !== undefined)}
|
||||
<div class="badge"
|
||||
style="width: calc({width} / 3); height: calc({width} / 3); border-radius: calc({width}); background-color:{statusColor}; display:block;">
|
||||
</div>
|
||||
{/if}
|
||||
<Tooltip message={tooltipMessage} show={tooltipShowing} position={tooltipPosition}></Tooltip>
|
||||
<div class="list" style="color: {$colors.white}; display: {listShowing ? "block" : "none"}; border: 2px solid {$colors.second}; background-color: {$colors.first};"
|
||||
on:mouseleave={hideList}>
|
||||
{#each Array.from(choices) as [key, value]}
|
||||
<div class="item" on:click={() => handleclick({key})}>{value}</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.item{
|
||||
border-radius: 0.3em;
|
||||
padding: 0.3em;
|
||||
}
|
||||
.item:hover {
|
||||
background-color: var(--second-color);
|
||||
color: var(--white-color);
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.list {
|
||||
z-index: 200;
|
||||
padding: 0.2em;
|
||||
margin-top: 0.2em;
|
||||
position: absolute;
|
||||
width: auto;
|
||||
cursor: pointer;
|
||||
border-radius: 0.5em;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
max-width: 30em;
|
||||
max-height: 40vh;
|
||||
overflow-y: scroll;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
button{
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
border:none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover{
|
||||
box-shadow: 1px 1px 3px 0px rgba(0, 0, 0, 0.25) inset;
|
||||
}
|
||||
</style>
|
||||
@@ -15,13 +15,14 @@
|
||||
export let signalizable = false;
|
||||
export let signalized = false;
|
||||
export let selected = false;
|
||||
export let status = "disconnected";
|
||||
export let status = "PERIPHERAL_DISCONNECTED";
|
||||
|
||||
// Emit a delete event when the device is being removed
|
||||
const dispatch = createEventDispatcher();
|
||||
function remove(event){
|
||||
dispatch('delete')
|
||||
}
|
||||
|
||||
function add(event){
|
||||
dispatch('add')
|
||||
}
|
||||
@@ -37,11 +38,11 @@
|
||||
</script>
|
||||
|
||||
<div class="card" on:dblclick={dblclick}>
|
||||
<div class="{selected ? "selected" : "unselected"} {status == "connecting" ? "waiting" : ""}" on:mousedown={click} style="color: {(status == "disconnected") ? $colors.first : $colors.white};">
|
||||
<div class="{selected ? "selected" : "unselected"} {status == "PERIPHERAL_CONNECTING" ? "waiting" : ""}" on:mousedown={click} style="color: {(status == "PERIPHERAL_DISCONNECTED") ? $colors.first : $colors.white};">
|
||||
<div style="z-index: 1;">
|
||||
<p>{#if status == "disconnected" }<i class='bx bx-no-signal' style="font-size:100%; color: var(--nok-color);"></i> {/if}{title}</p>
|
||||
<p>{#if status == "PERIPHERAL_DISCONNECTED" }<i class='bx bx-no-signal' style="font-size:100%; color: var(--nok-color);"></i> {/if}{title}</p>
|
||||
<h6 class="subtitle">{type} {location != '' ? "- " : ""}<i>{location}</i></h6>
|
||||
{#if status == "disconnected"}
|
||||
{#if status == "PERIPHERAL_DISCONNECTED"}
|
||||
<h6><b>Disconnected</b></h6>
|
||||
{:else}
|
||||
<h6>{line1}</h6>
|
||||
@@ -50,9 +51,9 @@
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<InfoButton on:click={add} color="{(status == "disconnected") ? $colors.first : $colors.white}" style="margin: 0.2em; display: { addable ? 'flex' : 'none' }" icon='bxs-message-square-add' interactive message={$_("projectHardwareAddTooltip")}/>
|
||||
<InfoButton on:click={remove} color="{(status == "disconnected") ? $colors.first : $colors.white}" style="margin: 0.2em; display: { removable ? 'flex' : 'none' }" icon='bx-trash' interactive message={$_("projectHardwareDeleteTooltip")}/>
|
||||
<InfoButton style="margin: 0.2em; display: { (status == "activated" || status == "deactivated") ? 'flex' : 'none' }" background={ (status == "activated") ? $colors.ok : (status == "deactivated") ? $colors.nok : null} icon='bx-pulse' hide={!signalizable}/>
|
||||
<InfoButton on:click={add} color="{(status == "PERIPHERAL_DISCONNECTED") ? $colors.first : $colors.white}" style="margin: 0.2em; display: { addable ? 'flex' : 'none' }" icon='bxs-message-square-add' interactive message={$_("projectHardwareAddTooltip")}/>
|
||||
<InfoButton on:click={remove} color="{(status == "PERIPHERAL_DISCONNECTED") ? $colors.first : $colors.white}" style="margin: 0.2em; display: { removable ? 'flex' : 'none' }" icon='bx-trash' interactive message={$_("projectHardwareDeleteTooltip")}/>
|
||||
<InfoButton style="margin: 0.2em; display: { (status == "PERIPHERAL_ACTIVATED" || status == "PERIPHERAL_DEACTIVATED") ? 'flex' : 'none' }" background={ (status == "PERIPHERAL_ACTIVATED") ? $colors.ok : (status == "PERIPHERAL_DEACTIVATED") ? $colors.nok : null} icon='bx-pulse' hide={!signalizable}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,20 +11,8 @@
|
||||
// Add the peripheral to the project
|
||||
function addPeripheral(peripheral){
|
||||
// Add the peripheral to the project (backend)
|
||||
AddPeripheral(peripheral).then((serialNumber) => {
|
||||
peripherals.update((storedPeripherals) => {
|
||||
return {
|
||||
...storedPeripherals,
|
||||
[serialNumber]: {
|
||||
...storedPeripherals[serialNumber],
|
||||
Name: peripheral.Name,
|
||||
ProtocolName: peripheral.ProtocolName,
|
||||
SerialNumber: serialNumber,
|
||||
isSaved: true,
|
||||
},
|
||||
}})
|
||||
$needProjectSave = true
|
||||
}).catch((error) => {
|
||||
AddPeripheral(peripheral)
|
||||
.catch((error) => {
|
||||
console.log("Unable to add the peripheral to the project: " + error)
|
||||
generateToast('danger', 'bx-error', $_("addPeripheralErrorToast"))
|
||||
})
|
||||
@@ -33,27 +21,8 @@
|
||||
// Remove the peripheral from the project
|
||||
function removePeripheral(peripheral) {
|
||||
// Delete the peripheral from the project (backend)
|
||||
RemovePeripheral(peripheral.ProtocolName, peripheral.SerialNumber).then(() => {
|
||||
// If the peripheral is not detected, we can delete it form the store
|
||||
// If not, we only pass the isSaved key to false
|
||||
let peripheralsList = get(peripherals)
|
||||
let lastDetectedProperty = peripheralsList[peripheral.SerialNumber]?.isDetected
|
||||
let needToDelete = (lastDetectedProperty !== true) ? true : false
|
||||
peripherals.update((storedPeripherals) => {
|
||||
if (needToDelete){
|
||||
delete storedPeripherals[peripheral.SerialNumber];
|
||||
return { ...storedPeripherals };
|
||||
}
|
||||
storedPeripherals[peripheral.SerialNumber].isSaved = false
|
||||
return { ...storedPeripherals };
|
||||
})
|
||||
$needProjectSave = true
|
||||
// If the peripheral is currently selected, unselect it
|
||||
if (selectedPeripheralSN == peripheral.SerialNumber) {
|
||||
selectedPeripheralSN = null
|
||||
selectedPeripheralSettings = {}
|
||||
}
|
||||
}).catch((error) => {
|
||||
RemovePeripheral(peripheral)
|
||||
.catch((error) => {
|
||||
console.log("Unable to remove the peripheral from the project: " + error)
|
||||
generateToast('danger', 'bx-error', $_("removePeripheralErrorToast"))
|
||||
})
|
||||
@@ -76,7 +45,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Unselect the peripheral if it is disconnect
|
||||
// Unselect the peripheral if it is disconnected
|
||||
$: {
|
||||
Object.entries($peripherals).filter(([serialNumber, peripheral]) => {
|
||||
if (!peripheral.isDetected && peripheral.isSaved && selectedPeripheralSN == serialNumber) {
|
||||
@@ -120,7 +89,7 @@
|
||||
if(!peripheral.isSaved)
|
||||
addPeripheral(peripheral)
|
||||
}}
|
||||
status="connected" title={peripheral.Name} type={peripheral.ProtocolName} location={peripheral.Location ? peripheral.Location : ""} line1={"S/N: " + peripheral.SerialNumber} addable={!peripheral.isSaved}/>
|
||||
status="PERIPHERAL_CONNECTED" title={peripheral.Name} type={peripheral.ProtocolName} location={peripheral.Location ? peripheral.Location : ""} line1={"S/N: " + peripheral.SerialNumber} addable={!peripheral.isSaved}/>
|
||||
{/if}
|
||||
{/each}
|
||||
<p style="color: var(--first-color);"><i class='bx bxs-network-chart' ></i> {$_("projectHardwareOthersLabel")}</p>
|
||||
@@ -134,7 +103,7 @@
|
||||
{#if savedPeripheralNumber > 0}
|
||||
{#each Object.entries($peripherals) as [serialNumber, peripheral]}
|
||||
{#if peripheral.isSaved}
|
||||
<DeviceCard status="{peripheral.Status}" on:delete={() => removePeripheral(peripheral)} on:dblclick={() => removePeripheral(peripheral)} on:click={() => selectPeripheral(peripheral)}
|
||||
<DeviceCard status="{peripheral.status}" on:delete={() => removePeripheral(peripheral)} on:dblclick={() => removePeripheral(peripheral)} on:click={() => selectPeripheral(peripheral)}
|
||||
title={peripheral.Name} type={peripheral.ProtocolName} location={peripheral.Location ? peripheral.Location : ""} line1={peripheral.SerialNumber ? "S/N: " + peripheral.SerialNumber : ""} selected={serialNumber == selectedPeripheralSN} removable signalizable/>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
@@ -1,109 +1,16 @@
|
||||
<script lang=ts>
|
||||
import { generateToast, projectsList, showInformation, needProjectSave, peripherals } from '../../stores.js';
|
||||
import RoundedButton from "../General/RoundedButton.svelte";
|
||||
import ProjectPropertiesContent from "./ProjectPropertiesContent.svelte";
|
||||
import DropdownList from "../General/DropdownList.svelte";
|
||||
import InputsOutputsContent from "./InputsOutputsContent.svelte";
|
||||
import Tab from "../General/Tab.svelte";
|
||||
import { CreateProject, GetProjects, OpenProjectFromDisk } from "../../../wailsjs/go/main/App";
|
||||
import { _ } from 'svelte-i18n'
|
||||
import {colors} from '../../stores.js';
|
||||
import { get } from "svelte/store"
|
||||
import { EventsOn } from '../../../wailsjs/runtime'
|
||||
|
||||
const tabs = [
|
||||
{ title: $_("projectPropertiesTab"), icon: 'bxs-info-circle', tooltip: $_("projectPropertiesTooltip"), component: ProjectPropertiesContent },
|
||||
{ title: $_("projectInputOutputTab"), icon: 'bxs-plug', tooltip: $_("projectInputOutputTooltip"), component: InputsOutputsContent },
|
||||
];
|
||||
|
||||
// Refresh the projects list
|
||||
let choices = new Map()
|
||||
function loadProjectsList(){
|
||||
GetProjects().then((projects) => {
|
||||
choices = new Map(projects.map(item => [item.Save, item.Name]));
|
||||
$projectsList = projects
|
||||
}).catch((error) => {
|
||||
console.error(`Unable to get the projects list: ${error}`)
|
||||
generateToast('danger', 'bx-error', $_("projectsLoadErrorToast"))
|
||||
})
|
||||
}
|
||||
|
||||
// Unsave peripherals from the store and remove the disconnected peripherals
|
||||
function unsavePeripherals(){
|
||||
peripherals.update((storedPeripherals) => {
|
||||
// Set all the isSaved keys to false and delete the disconnected peripherals
|
||||
for (let peripheralID in storedPeripherals) {
|
||||
storedPeripherals[peripheralID].isSaved = false
|
||||
if (!storedPeripherals[peripheralID].isDetected) {
|
||||
delete storedPeripherals[peripheralID]
|
||||
}
|
||||
}
|
||||
return {...storedPeripherals}
|
||||
})
|
||||
}
|
||||
|
||||
// Load the saved peripherals into the store
|
||||
function loadPeripherals(peripheralsInfo){
|
||||
peripherals.update((storedPeripherals) => {
|
||||
// Add the saved peripherals of the project
|
||||
// If already exists pass the isSaved key to true, if not create the peripheral and set it to disconnected
|
||||
for (let peripheralID in peripheralsInfo){
|
||||
// Add the peripheral to the list of peripherals, with the last isDetected key and the isSaved key to true
|
||||
let lastDetectedKey = storedPeripherals[peripheralID]?.isDetected
|
||||
storedPeripherals[peripheralID] = peripheralsInfo[peripheralID]
|
||||
storedPeripherals[peripheralID].isDetected = (lastDetectedKey === true) ? true : false
|
||||
storedPeripherals[peripheralID].isSaved = true
|
||||
}
|
||||
return {...storedPeripherals}
|
||||
})
|
||||
}
|
||||
|
||||
// Handle the event when a new project need to be loaded
|
||||
EventsOn('LOAD_PROJECT', function(projectInfo){
|
||||
// Store project information
|
||||
showInformation.set(projectInfo.ShowInfo)
|
||||
|
||||
// Remove the saved peripherals of the current project
|
||||
unsavePeripherals()
|
||||
|
||||
// Load new project peripherals
|
||||
loadPeripherals(projectInfo.PeripheralsInfo)
|
||||
|
||||
console.log("Project has been opened");
|
||||
generateToast('info', 'bx-folder-open', $_("projectOpenedToast") + ' <b>' + projectInfo.ShowInfo.Name + '</b>')
|
||||
})
|
||||
|
||||
// Open the selected project
|
||||
function openSelectedProject(event){
|
||||
let selectedOption = event.detail.key
|
||||
// Open the selected project
|
||||
OpenProjectFromDisk(selectedOption).then(() => {
|
||||
// Project opened, we set the needSave flag to false (already saved)
|
||||
needProjectSave.set(false)
|
||||
}).catch((error) => {
|
||||
console.error(`Unable to open the project: ${error}`)
|
||||
generateToast('danger', 'bx-error', $_("projectOpenErrorToast"))
|
||||
})
|
||||
}
|
||||
|
||||
function initializeNewProject(){
|
||||
// Instanciate a new project
|
||||
CreateProject().then(() => {
|
||||
// Project created, we set the needSave flag to true (not already saved)
|
||||
needProjectSave.set(true)
|
||||
}).catch((error) => {
|
||||
console.error(`Unable to create the project: ${error}`)
|
||||
generateToast('danger', 'bx-error', $_("projectCreateErrorToast"))
|
||||
})
|
||||
}
|
||||
|
||||
// Instantiate a new project
|
||||
initializeNewProject()
|
||||
</script>
|
||||
|
||||
<!-- Project buttons -->
|
||||
<RoundedButton on:click={initializeNewProject} text={$_("newProjectString")} icon='bxs-plus-square' tooltip={$_("newProjectTooltip")}/>
|
||||
<DropdownList icon='bxs-folder-open' text={$_("openProjectString")} choices={choices} tooltip={$_("openProjectTooltip")} on:click={loadProjectsList} on:selected={openSelectedProject}/>
|
||||
<!-- Project tabcontrol -->
|
||||
<Tab { tabs } maxHeight='73vh'/>
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import App from './App.svelte';
|
||||
|
||||
import { WindowSetTitle } from "../wailsjs/runtime/runtime"
|
||||
import { _ } from 'svelte-i18n'
|
||||
|
||||
import {showInformation, needProjectSave} from './stores.js';
|
||||
import {messages, showInformation, needProjectSave} from './stores.js';
|
||||
|
||||
// Load dictionaries
|
||||
import { addMessages, init } from 'svelte-i18n';
|
||||
|
||||
169
frontend/src/runtime-events.js
Normal file
169
frontend/src/runtime-events.js
Normal file
@@ -0,0 +1,169 @@
|
||||
import { EventsOn, EventsOff } from "../wailsjs/runtime/runtime.js"
|
||||
import { peripherals, generateToast, needProjectSave, showInformation } from './stores'
|
||||
import { get } from "svelte/store"
|
||||
import { _ } from 'svelte-i18n'
|
||||
|
||||
// New peripheral has been added to the system
|
||||
function peripheralArrival (peripheralInfo){
|
||||
// If not exists, add it to the map
|
||||
// isDetected key to true
|
||||
|
||||
peripherals.update((storedPeripherals) => {
|
||||
return {
|
||||
...storedPeripherals,
|
||||
[peripheralInfo.SerialNumber]: {
|
||||
...storedPeripherals[peripheralInfo.SerialNumber],
|
||||
Name: peripheralInfo.Name,
|
||||
ProtocolName: peripheralInfo.ProtocolName,
|
||||
SerialNumber: peripheralInfo.SerialNumber,
|
||||
Settings: peripheralInfo.Settings,
|
||||
isDetected: true,
|
||||
},
|
||||
}})
|
||||
console.log("Hardware has been added to the system");
|
||||
generateToast('info', 'bxs-hdd', get(_)("peripheralArrivalToast") + ' <b>' + peripheralInfo.Name + '</b>')
|
||||
}
|
||||
|
||||
// Peripheral is removed from the system
|
||||
function peripheralRemoval (peripheralInfo){
|
||||
// If not exists, add it to the map
|
||||
// isDetected key to false
|
||||
|
||||
peripherals.update((storedPeripherals) => {
|
||||
return {
|
||||
...storedPeripherals,
|
||||
[peripheralInfo.SerialNumber]: {
|
||||
...storedPeripherals[peripheralInfo.SerialNumber],
|
||||
Name: peripheralInfo.Name,
|
||||
ProtocolName: peripheralInfo.ProtocolName,
|
||||
SerialNumber: peripheralInfo.SerialNumber,
|
||||
Settings: peripheralInfo.Settings,
|
||||
isDetected: false,
|
||||
status: "PERIPHERAL_DISCONNECTED",
|
||||
},
|
||||
}})
|
||||
console.log("Hardware has been removed from the system");
|
||||
generateToast('warning', 'bxs-hdd', get(_)("peripheralRemovalToast") + ' <b>' + peripheralInfo.Name + '</b>')
|
||||
}
|
||||
|
||||
// Update peripheral status
|
||||
function peripheralUpdateStatus(peripheralInfo, status){
|
||||
// If not exists, add it to the map
|
||||
// change status key
|
||||
|
||||
peripherals.update((storedPeripherals) => {
|
||||
console.log(status)
|
||||
return {
|
||||
...storedPeripherals,
|
||||
[peripheralInfo.SerialNumber]: {
|
||||
...storedPeripherals[peripheralInfo.SerialNumber],
|
||||
Name: peripheralInfo.Name,
|
||||
ProtocolName: peripheralInfo.ProtocolName,
|
||||
SerialNumber: peripheralInfo.SerialNumber,
|
||||
Settings: peripheralInfo.Settings,
|
||||
status: status,
|
||||
},
|
||||
}})
|
||||
|
||||
console.log("Hardware status has been updated to " + status);
|
||||
}
|
||||
|
||||
// Load the peripheral in the project
|
||||
function loadPeripheral (peripheralInfo) {
|
||||
// If not exists, add it to the map
|
||||
// isSaved key to true
|
||||
|
||||
peripherals.update((storedPeripherals) => {
|
||||
return {
|
||||
...storedPeripherals,
|
||||
[peripheralInfo.SerialNumber]: {
|
||||
...storedPeripherals[peripheralInfo.SerialNumber],
|
||||
Name: peripheralInfo.Name,
|
||||
ProtocolName: peripheralInfo.ProtocolName,
|
||||
SerialNumber: peripheralInfo.SerialNumber,
|
||||
Settings: peripheralInfo.Settings,
|
||||
isSaved: true,
|
||||
},
|
||||
}})
|
||||
console.log("Hardware has been added to the project");
|
||||
//TODO: Lors d'un chargement/déchargement natif au démarrage, il ne doit pas y avoir de nécessité de sauvegarder
|
||||
needProjectSave.set(true)
|
||||
}
|
||||
|
||||
function loadProject (showInfo){
|
||||
// Store project information
|
||||
showInformation.set(showInfo)
|
||||
|
||||
console.log("Project has been opened");
|
||||
generateToast('info', 'bx-folder-open', get(_)("projectOpenedToast") + ' <b>' + showInfo.Name + '</b>')
|
||||
}
|
||||
|
||||
// Unload the hardware from the project
|
||||
function unloadPeripheral (peripheralInfo) {
|
||||
// If not exists, add it to the map
|
||||
// isSaved key to false
|
||||
|
||||
peripherals.update((storedPeripherals) => {
|
||||
return {
|
||||
...storedPeripherals,
|
||||
[peripheralInfo.SerialNumber]: {
|
||||
...storedPeripherals[peripheralInfo.SerialNumber],
|
||||
Name: peripheralInfo.Name,
|
||||
ProtocolName: peripheralInfo.ProtocolName,
|
||||
SerialNumber: peripheralInfo.SerialNumber,
|
||||
Settings: peripheralInfo.Settings,
|
||||
isSaved: false,
|
||||
},
|
||||
}})
|
||||
console.log("Hardware has been removed from the project");
|
||||
//TODO: Lors d'un chargement/déchargement natif au démarrage, il ne doit pas y avoir de nécessité de sauvegarder
|
||||
needProjectSave.set(true)
|
||||
}
|
||||
|
||||
let initialized = false
|
||||
|
||||
export function initRuntimeEvents(){
|
||||
if (initialized) return
|
||||
initialized = true
|
||||
|
||||
// Handle the event when a new peripheral is detected
|
||||
EventsOn('PERIPHERAL_ARRIVAL', peripheralArrival)
|
||||
|
||||
// Handle the event when a peripheral is removed from the system
|
||||
EventsOn('PERIPHERAL_REMOVAL', peripheralRemoval)
|
||||
|
||||
// Handle the event when a peripheral status is updated
|
||||
EventsOn('PERIPHERAL_STATUS', peripheralUpdateStatus)
|
||||
|
||||
// Handle the event when a new project need to be loaded
|
||||
EventsOn('LOAD_PROJECT', loadProject)
|
||||
|
||||
// Handle a peripheral loaded in the project
|
||||
EventsOn('LOAD_PERIPHERAL', loadPeripheral)
|
||||
|
||||
// Handle a peripheral unloaded from the project
|
||||
EventsOn('UNLOAD_PERIPHERAL', unloadPeripheral)
|
||||
}
|
||||
|
||||
export function destroyRuntimeEvents(){
|
||||
if (!initialized) return
|
||||
initialized = false
|
||||
|
||||
// Handle the event when a new peripheral is detected
|
||||
EventsOff('PERIPHERAL_ARRIVAL')
|
||||
|
||||
// Handle the event when a peripheral is removed from the system
|
||||
EventsOff('PERIPHERAL_REMOVAL')
|
||||
|
||||
// Handle the event when a peripheral status is updated
|
||||
EventsOff('PERIPHERAL_STATUS')
|
||||
|
||||
// Handle the event when a new project need to be loaded
|
||||
EventsOff('LOAD_PROJECT')
|
||||
|
||||
// Handle a peripheral loaded in the project
|
||||
EventsOff('LOAD_PERIPHERAL')
|
||||
|
||||
// Handle a peripheral unloaded from the project
|
||||
EventsOff('UNLOAD_PERIPHERAL')
|
||||
}
|
||||
@@ -10,13 +10,12 @@ export let showInformation = writable({})
|
||||
// Toasts notifications
|
||||
export let messages = writable([])
|
||||
export function generateToast(type, icon, text){
|
||||
messages.update((value) => {
|
||||
value.push( { id: Date.now(), type: type, icon: icon, text: text } )
|
||||
return value.slice(-5)
|
||||
})
|
||||
messages.update((value) => {
|
||||
value.push( { id: Date.now(), type: type, icon: icon, text: text } )
|
||||
return value.slice(-5)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Application colors
|
||||
export const colors = writable({
|
||||
first: "#1B262C",
|
||||
@@ -35,4 +34,15 @@ export const secondSize = writable("14px")
|
||||
export const thirdSize = writable("20px")
|
||||
|
||||
// List of current hardware
|
||||
export let peripherals = writable({})
|
||||
export let peripherals = writable({})
|
||||
|
||||
// Peripheral structure :
|
||||
|
||||
// Name string `yaml:"name"` // Name of the peripheral
|
||||
// SerialNumber string `yaml:"sn"` // S/N of the peripheral
|
||||
// ProtocolName string `yaml:"protocol"` // Protocol name of the peripheral
|
||||
// Settings map[string]interface{} `yaml:"settings"` // Peripheral settings
|
||||
|
||||
// isSaved // if the peripheral is saved in the project
|
||||
// isDetected // if the peripheral is detected by the system
|
||||
// status // the status of connection
|
||||
Reference in New Issue
Block a user