fix some accessibility issues with non focusable elements
This commit is contained in:
@@ -13,6 +13,46 @@ import (
|
||||
"github.com/go-viper/mapstructure/v2"
|
||||
)
|
||||
|
||||
type VMPath struct {
|
||||
Node string
|
||||
Type string
|
||||
VMID string
|
||||
}
|
||||
|
||||
// imported types from fabric
|
||||
|
||||
type InstanceConfig struct {
|
||||
Type fabric.InstanceType `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Proctype string `json:"cpu"`
|
||||
Cores uint64 `json:"cores"`
|
||||
Memory uint64 `json:"memory"`
|
||||
Swap uint64 `json:"swap"`
|
||||
Volumes map[string]*fabric.Volume `json:"volumes"`
|
||||
Nets map[string]*fabric.Net `json:"nets"`
|
||||
Devices map[string]*fabric.Device `json:"devices"`
|
||||
Boot fabric.BootOrder `json:"boot"`
|
||||
// overrides
|
||||
ProctypeSelect common.Select
|
||||
}
|
||||
|
||||
type GlobalConfig struct {
|
||||
CPU struct {
|
||||
Whitelist bool
|
||||
}
|
||||
}
|
||||
|
||||
type UserConfig struct {
|
||||
CPU struct {
|
||||
Global []CPUConfig
|
||||
Nodes map[string][]CPUConfig
|
||||
}
|
||||
}
|
||||
|
||||
type CPUConfig struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func HandleGETConfig(c *gin.Context) {
|
||||
auth, err := common.GetAuth(c)
|
||||
if err == nil {
|
||||
@@ -155,29 +195,6 @@ func ExtractVMPath(c *gin.Context) (VMPath, error) {
|
||||
return vm_path, nil
|
||||
}
|
||||
|
||||
type VMPath struct {
|
||||
Node string
|
||||
Type string
|
||||
VMID string
|
||||
}
|
||||
|
||||
// imported types from fabric
|
||||
|
||||
type InstanceConfig struct {
|
||||
Type fabric.InstanceType `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Proctype string `json:"cpu"`
|
||||
Cores uint64 `json:"cores"`
|
||||
Memory uint64 `json:"memory"`
|
||||
Swap uint64 `json:"swap"`
|
||||
Volumes map[string]*fabric.Volume `json:"volumes"`
|
||||
Nets map[string]*fabric.Net `json:"nets"`
|
||||
Devices map[string]*fabric.Device `json:"devices"`
|
||||
Boot fabric.BootOrder `json:"boot"`
|
||||
// overrides
|
||||
ProctypeSelect common.Select
|
||||
}
|
||||
|
||||
func GetInstanceConfig(vm VMPath, auth common.Auth) (InstanceConfig, error) {
|
||||
config := InstanceConfig{}
|
||||
path := fmt.Sprintf("/cluster/%s/%s/%s", vm.Node, vm.Type, vm.VMID)
|
||||
@@ -208,23 +225,6 @@ func GetInstanceConfig(vm VMPath, auth common.Auth) (InstanceConfig, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type GlobalConfig struct {
|
||||
CPU struct {
|
||||
Whitelist bool
|
||||
}
|
||||
}
|
||||
|
||||
type UserConfig struct {
|
||||
CPU struct {
|
||||
Global []CPUConfig
|
||||
Nodes map[string][]CPUConfig
|
||||
}
|
||||
}
|
||||
|
||||
type CPUConfig struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func GetCPUTypes(vm VMPath, auth common.Auth) (common.Select, error) {
|
||||
cputypes := common.Select{
|
||||
ID: "proctype",
|
||||
|
@@ -10,6 +10,39 @@ import (
|
||||
"github.com/go-viper/mapstructure/v2"
|
||||
)
|
||||
|
||||
// used in constructing instance cards in index
|
||||
type Node struct {
|
||||
Node string `json:"node"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// used in constructing instance cards in index
|
||||
type InstanceCard struct {
|
||||
VMID uint
|
||||
Name string
|
||||
Type string
|
||||
Status string
|
||||
Node string
|
||||
NodeStatus string
|
||||
ConfigPath string
|
||||
ConsolePath string
|
||||
}
|
||||
|
||||
// used in retriving cluster tasks
|
||||
type Task struct {
|
||||
Type string
|
||||
Node string
|
||||
User string
|
||||
ID string
|
||||
VMID uint
|
||||
Status string
|
||||
EndTime uint
|
||||
}
|
||||
|
||||
type InstanceStatus struct {
|
||||
Status string
|
||||
}
|
||||
|
||||
func HandleGETIndex(c *gin.Context) {
|
||||
auth, err := common.GetAuth(c)
|
||||
if err == nil { // user should be authed, try to return index with population
|
||||
@@ -45,39 +78,6 @@ func HandleGETInstancesFragment(c *gin.Context) {
|
||||
|
||||
}
|
||||
|
||||
// used in constructing instance cards in index
|
||||
type Node struct {
|
||||
Node string `json:"node"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// used in constructing instance cards in index
|
||||
type InstanceCard struct {
|
||||
VMID uint
|
||||
Name string
|
||||
Type string
|
||||
Status string
|
||||
Node string
|
||||
NodeStatus string
|
||||
ConfigPath string
|
||||
ConsolePath string
|
||||
}
|
||||
|
||||
// used in retriving cluster tasks
|
||||
type Task struct {
|
||||
Type string
|
||||
Node string
|
||||
User string
|
||||
ID string
|
||||
VMID uint
|
||||
Status string
|
||||
EndTime uint
|
||||
}
|
||||
|
||||
type InstanceStatus struct {
|
||||
Status string
|
||||
}
|
||||
|
||||
func GetClusterResources(auth common.Auth) (map[uint]InstanceCard, map[string]Node, error) {
|
||||
ctx := common.RequestContext{
|
||||
Cookies: map[string]string{
|
||||
|
@@ -35,7 +35,7 @@
|
||||
<h2>Instances</h2>
|
||||
<div class="w3-card w3-padding">
|
||||
<div class="flex row nowrap" style="margin-top: 1em; justify-content: space-between;">
|
||||
<form id="vm-search" role="search" class="flex row nowrap">
|
||||
<form id="vm-search" role="search" class="flex row nowrap" tabindex="0">
|
||||
<svg role="img" aria-label="Search Instances"><use href="images/common/search.svg#symb"></use></svg>
|
||||
<input type="search" id="search" class="w3-input w3-border" style="height: 1lh; max-width: fit-content;" aria-label="search instances by name">
|
||||
</form>
|
||||
|
@@ -122,11 +122,24 @@ class InstanceCard extends HTMLElement {
|
||||
const powerButton = this.shadowRoot.querySelector("#power-btn");
|
||||
if (powerButton.classList.contains("clickable")) {
|
||||
powerButton.onclick = this.handlePowerButton.bind(this);
|
||||
powerButton.onkeydown = (event) => {
|
||||
console.log(event.key, event.key === "Enter")
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault()
|
||||
this.handlePowerButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const deleteButton = this.shadowRoot.querySelector("#delete-btn");
|
||||
if (deleteButton.classList.contains("clickable")) {
|
||||
deleteButton.onclick = this.handleDeleteButton.bind(this);
|
||||
deleteButton.onkeydown = (event) => {
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault()
|
||||
this.handleDeleteButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -237,51 +237,42 @@
|
||||
{{end}}
|
||||
|
||||
{{define "boot"}}
|
||||
<draggable-container id="enabled" data-group="boot">
|
||||
<template shadowrootmode="open">
|
||||
{{template "boot-style"}}
|
||||
<label>Enabled</label>
|
||||
<div id="wrapper" style="padding-bottom: 1em;">
|
||||
{{range .Enabled}}
|
||||
{{template "boot-target" .}}
|
||||
{{end}}
|
||||
</div>
|
||||
</template>
|
||||
</draggable-container>
|
||||
{{template "boot-container" Map "ID" "enabled" "Name" "Enabled" "Targets" .Enabled}}
|
||||
<hr style="padding: 0; margin: 0;">
|
||||
<draggable-container id="disabled" data-group="boot">
|
||||
<template shadowrootmode="open">
|
||||
{{template "boot-style"}}
|
||||
<label>Disabled</label>
|
||||
<div id="wrapper" style="padding-bottom: 1em;">
|
||||
{{range .Disabled}}
|
||||
{{template "boot-target" .}}
|
||||
{{end}}
|
||||
</div>
|
||||
</template>
|
||||
</draggable-container>
|
||||
{{template "boot-container" Map "ID" "disabled" "Name" "Disabled" "Targets" .Disabled}}
|
||||
{{end}}
|
||||
|
||||
{{define "boot-style"}}
|
||||
<style>
|
||||
div.draggable-item.ghost {
|
||||
border: 1px dashed var(--main-text-color);
|
||||
border-radius: 5px;
|
||||
margin: -1px;
|
||||
}
|
||||
div.draggable-item {
|
||||
cursor: grab;
|
||||
}
|
||||
div.draggable-item svg {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
}
|
||||
* {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
{{define "boot-container"}}
|
||||
<draggable-container id="{{.ID}}" data-group="boot">
|
||||
<template shadowrootmode="open">
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
div.draggable-item.ghost {
|
||||
border: 1px dashed var(--main-text-color);
|
||||
border-radius: 5px;
|
||||
margin: -1px;
|
||||
}
|
||||
div.draggable-item {
|
||||
cursor: grab;
|
||||
}
|
||||
div.draggable-item svg {
|
||||
height: 1em;
|
||||
width: 1em;
|
||||
}
|
||||
#wrapper {
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
</style>
|
||||
<label>{{.Name}}</label>
|
||||
<div id="wrapper">
|
||||
{{range .Targets}}
|
||||
{{template "boot-target" .}}
|
||||
{{end}}
|
||||
</div>
|
||||
</template>
|
||||
</draggable-container>
|
||||
{{end}}
|
||||
|
||||
{{define "boot-target"}}
|
||||
|
@@ -39,24 +39,24 @@
|
||||
</div>
|
||||
<div class="w3-col l2 m2 s6 flex row nowrap" style="height: 1lh;">
|
||||
{{if and (eq .NodeStatus "online") (eq .Status "running")}}
|
||||
<svg id="power-btn" class="clickable" aria-label="shutdown instance"><use href="images/actions/instance/stop.svg#symb"></svg>
|
||||
<svg id="configure-btn" aria-label=""><use href="images/actions/instance/config-inactive.svg#symb"></svg>
|
||||
<svg id="power-btn" class="clickable" aria-label="shutdown instance" role="button" tabindex=0><use href="images/actions/instance/stop.svg#symb"></svg>
|
||||
<svg id="configure-btn" aria-disabled="true" role="none"><use href="images/actions/instance/config-inactive.svg#symb"></svg>
|
||||
<a href="{{.ConsolePath}}" target="_blank">
|
||||
<svg id="console-btn" class="clickable" aria-label="open console"><use href="images/actions/instance/console-active.svg#symb"></svg>
|
||||
</a>
|
||||
<svg id="delete-btn" aria-label=""><use href="images/actions/instance/delete-inactive.svg#symb"></svg>
|
||||
<svg id="delete-btn" aria-disabled="true" role="none"><use href="images/actions/instance/delete-inactive.svg#symb"></svg>
|
||||
{{else if and (eq .NodeStatus "online") (eq .Status "stopped")}}
|
||||
<svg id="power-btn" class="clickable" aria-label="start instance"><use href="images/actions/instance/start.svg#symb"></svg>
|
||||
<svg id="power-btn" class="clickable" aria-label="start instance" role="button" tabindex=0><use href="images/actions/instance/start.svg#symb"></svg>
|
||||
<a href="{{.ConfigPath}}">
|
||||
<svg id="configure-btn" class="clickable" aria-label="change configuration"><use href="images/actions/instance/config-active.svg#symb"></svg>
|
||||
</a>
|
||||
<svg id="console-btn" aria-label=""><use href="images/actions/instance/console-inactive.svg#symb"></svg>
|
||||
<svg id="delete-btn" class="clickable" aria-label="delete instance"><use href="images/actions/instance/delete-active.svg#symb"></svg>
|
||||
<svg id="console-btn" aria-disabled="true" role="none"><use href="images/actions/instance/console-inactive.svg#symb"></svg>
|
||||
<svg id="delete-btn" class="clickable" aria-label="delete instance" role="button" tabindex=0><use href="images/actions/instance/delete-active.svg#symb"></svg>
|
||||
{{else if and (eq .NodeStatus "online") (eq .Status "loading")}}
|
||||
<svg id="power-btn" aria-label=""><use href="images/actions/instance/loading.svg#symb"></svg>
|
||||
<svg id="configure-btn" aria-label=""><use href="images/actions/instance/config-inactive.svg#symb"></svg>
|
||||
<svg id="console-btn" aria-label=""><use href="images/actions/instance/console-inactive.svg#symb"></svg>
|
||||
<svg id="delete-btn" aria-label=""><use href="images/actions/instance/delete-inactive.svg#symb"></svg>
|
||||
<svg id="power-btn" aria-disabled="true" role="none"><use href="images/actions/instance/loading.svg#symb"></svg>
|
||||
<svg id="configure-btn" aria-disabled="true" role="none"><use href="images/actions/instance/config-inactive.svg#symb"></svg>
|
||||
<svg id="console-btn" aria-disabled="true" role="none"><use href="images/actions/instance/console-inactive.svg#symb"></svg>
|
||||
<svg id="delete-btn" aria-disabled="true" role="none"><use href="images/actions/instance/delete-inactive.svg#symb"></svg>
|
||||
{{else}}
|
||||
{{end}}
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user