diff --git a/config.go b/config.go index d98f201..c68adb6 100644 --- a/config.go +++ b/config.go @@ -48,7 +48,7 @@ func readConfig() (config Config, err error) { return } -func (cfg *Config) UpdateDevice(currentName string, deviceToUpdate Device) (dev Device, err error) { +func (cfg *Config) UpdateDevice(currentName string, deviceToUpdate Device) (dev Device, err error) {// {{{ i := slices.IndexFunc(cfg.Devices, func(d Device) bool { return strings.TrimSpace(strings.ToLower(d.Name)) == strings.TrimSpace(strings.ToLower(currentName)) @@ -104,4 +104,14 @@ func (cfg *Config) UpdateDevice(currentName string, deviceToUpdate Device) (dev err = os.WriteFile(cfg.filename, j, 0600) return -} +}// }}} +func (cfg *Config) DeleteDevice(devname string) (err error) {// {{{ + cfg.Devices = slices.DeleteFunc(cfg.Devices, func(d Device) bool { + return strings.TrimSpace(strings.ToLower(d.Name)) == strings.TrimSpace(strings.ToLower(devname)) + }) + + j, _ := json.Marshal(cfg) + err = os.WriteFile(cfg.filename, j, 0600) + + return +}// }}} diff --git a/static/css/index.css b/static/css/index.css index 407ae3a..41f0b4c 100644 --- a/static/css/index.css +++ b/static/css/index.css @@ -35,6 +35,7 @@ html { *:after { box-sizing: inherit; } + *:focus { outline: none; } @@ -150,6 +151,7 @@ button { &.show { border-right: var(--header-border); + &>* { display: initial; } @@ -478,31 +480,58 @@ button { #device-dialog { display: grid; grid-template-columns: min-content min-content; - align-items: top; + align-items: start; grid-gap: 16px; .devices { display: flex; - flex-direction:column; + flex-direction: column; gap: 8px; align-items: flex-start; + min-height: 256px; + height: 75vh; .header { + width: 100%; + display: grid; + grid-template-columns: 1fr min-content; + margin-bottom: 8px; + font-weight: bold; - } - .device { - border: 1px solid #aaa; - background-color: #f0f0f0; - padding: 8px 16px; - border-radius: 8px; - cursor: pointer; - user-select: none; - - &.selected { - background-color: var(--header-background); + .filter { + grid-column: 1 / -1; + margin-top: 8px; + margin-bottom: 8px; } } + + .device-list { + overflow-y: auto; + min-width: 256px; + justify-items: start; + + .device { + border: 1px solid #aaa; + background-color: #f0f0f0; + padding: 8px 16px; + border-radius: 8px; + cursor: pointer; + user-select: none; + white-space: nowrap; + margin-bottom: 16px; + margin-right: 16px; + + &.selected { + background-color: var(--header-background); + } + + &.filtered { + display: none; + } + } + } + } .fields { diff --git a/static/js/dns.mjs b/static/js/dns.mjs index 707b6ed..5cfcc23 100644 --- a/static/js/dns.mjs +++ b/static/js/dns.mjs @@ -26,7 +26,8 @@ export class Application { }) _mbus.subscribe('device_selected', event => this.connectDevice(event.detail.devName)) - _mbus.subscribe('search', ()=>this.search()) + _mbus.subscribe('device_deleted', event => this.deleteDevice(event.detail.devName)) + _mbus.subscribe('search', () => this.search()) }// }}} // resetDeviceState removes the device state such as the records, records tree and search field. @@ -96,6 +97,15 @@ export class Application { } }// }}} + // deleteDevice removes it from the list and resets app state if it was connected. + deleteDevice(devName) {// {{{ + this.devices.delete(devName) + if (this.currentDevice.name() == devName) { + this.resetDeviceState() + this.settings.set('last_device', '') + } + }// }}} + // filteredRecords takes the current search value and only returns records matching it. filteredRecords() {// {{{ const searchFor = this.searchWidget.value() @@ -420,6 +430,8 @@ class DeviceSelectWidget { this.div = null this.elDeviceSelect = null this.currentlySelected = null + + _mbus.subscribe('device_deleted', event => this.deleteDevice(event.detail.devName)) }// }}} setDevices(devices) {// {{{ this.devices = devices @@ -436,7 +448,7 @@ class DeviceSelectWidget { this.elDeviceSelect = this.div.querySelector('select') this.elDeviceSelect.addEventListener('change', () => this.notifyDeviceSelect()) - this.div.querySelector('img').addEventListener('click', ()=>new DeviceDialog(this.devices).render()) + this.div.querySelector('img').addEventListener('click', () => new DeviceDialog(this.devices).render()) } this.restockDeviceSelect() return this.div @@ -467,6 +479,10 @@ class DeviceSelectWidget { this.elDeviceSelect.value = devname this.notifyDeviceSelect() }// }}} + deleteDevice(devName) {// {{{ + this.devices.delete(devName) + this.restockDeviceSelect() + }// }}} } class Folder { @@ -1012,7 +1028,14 @@ class DeviceDialog { this.dlg.id = 'device-dialog' this.dlg.innerHTML = `