fix some accessibility issues with non focusable elements
This commit is contained in:
@@ -13,6 +13,46 @@ import (
|
|||||||
"github.com/go-viper/mapstructure/v2"
|
"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) {
|
func HandleGETConfig(c *gin.Context) {
|
||||||
auth, err := common.GetAuth(c)
|
auth, err := common.GetAuth(c)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -155,29 +195,6 @@ func ExtractVMPath(c *gin.Context) (VMPath, error) {
|
|||||||
return vm_path, nil
|
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) {
|
func GetInstanceConfig(vm VMPath, auth common.Auth) (InstanceConfig, error) {
|
||||||
config := InstanceConfig{}
|
config := InstanceConfig{}
|
||||||
path := fmt.Sprintf("/cluster/%s/%s/%s", vm.Node, vm.Type, vm.VMID)
|
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
|
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) {
|
func GetCPUTypes(vm VMPath, auth common.Auth) (common.Select, error) {
|
||||||
cputypes := common.Select{
|
cputypes := common.Select{
|
||||||
ID: "proctype",
|
ID: "proctype",
|
||||||
|
@@ -10,6 +10,39 @@ import (
|
|||||||
"github.com/go-viper/mapstructure/v2"
|
"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) {
|
func HandleGETIndex(c *gin.Context) {
|
||||||
auth, err := common.GetAuth(c)
|
auth, err := common.GetAuth(c)
|
||||||
if err == nil { // user should be authed, try to return index with population
|
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) {
|
func GetClusterResources(auth common.Auth) (map[uint]InstanceCard, map[string]Node, error) {
|
||||||
ctx := common.RequestContext{
|
ctx := common.RequestContext{
|
||||||
Cookies: map[string]string{
|
Cookies: map[string]string{
|
||||||
|
@@ -35,7 +35,7 @@
|
|||||||
<h2>Instances</h2>
|
<h2>Instances</h2>
|
||||||
<div class="w3-card w3-padding">
|
<div class="w3-card w3-padding">
|
||||||
<div class="flex row nowrap" style="margin-top: 1em; justify-content: space-between;">
|
<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>
|
<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">
|
<input type="search" id="search" class="w3-input w3-border" style="height: 1lh; max-width: fit-content;" aria-label="search instances by name">
|
||||||
</form>
|
</form>
|
||||||
|
@@ -122,11 +122,24 @@ class InstanceCard extends HTMLElement {
|
|||||||
const powerButton = this.shadowRoot.querySelector("#power-btn");
|
const powerButton = this.shadowRoot.querySelector("#power-btn");
|
||||||
if (powerButton.classList.contains("clickable")) {
|
if (powerButton.classList.contains("clickable")) {
|
||||||
powerButton.onclick = this.handlePowerButton.bind(this);
|
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");
|
const deleteButton = this.shadowRoot.querySelector("#delete-btn");
|
||||||
if (deleteButton.classList.contains("clickable")) {
|
if (deleteButton.classList.contains("clickable")) {
|
||||||
deleteButton.onclick = this.handleDeleteButton.bind(this);
|
deleteButton.onclick = this.handleDeleteButton.bind(this);
|
||||||
|
deleteButton.onkeydown = (event) => {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
event.preventDefault()
|
||||||
|
this.handleDeleteButton()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -237,51 +237,42 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "boot"}}
|
{{define "boot"}}
|
||||||
<draggable-container id="enabled" data-group="boot">
|
{{template "boot-container" Map "ID" "enabled" "Name" "Enabled" "Targets" .Enabled}}
|
||||||
<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>
|
|
||||||
<hr style="padding: 0; margin: 0;">
|
<hr style="padding: 0; margin: 0;">
|
||||||
<draggable-container id="disabled" data-group="boot">
|
{{template "boot-container" Map "ID" "disabled" "Name" "Disabled" "Targets" .Disabled}}
|
||||||
<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>
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "boot-style"}}
|
{{define "boot-container"}}
|
||||||
<style>
|
<draggable-container id="{{.ID}}" data-group="boot">
|
||||||
div.draggable-item.ghost {
|
<template shadowrootmode="open">
|
||||||
border: 1px dashed var(--main-text-color);
|
<style>
|
||||||
border-radius: 5px;
|
* {
|
||||||
margin: -1px;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
div.draggable-item {
|
div.draggable-item.ghost {
|
||||||
cursor: grab;
|
border: 1px dashed var(--main-text-color);
|
||||||
}
|
border-radius: 5px;
|
||||||
div.draggable-item svg {
|
margin: -1px;
|
||||||
height: 1em;
|
}
|
||||||
width: 1em;
|
div.draggable-item {
|
||||||
}
|
cursor: grab;
|
||||||
* {
|
}
|
||||||
-webkit-box-sizing: border-box;
|
div.draggable-item svg {
|
||||||
-moz-box-sizing: border-box;
|
height: 1em;
|
||||||
box-sizing: border-box;
|
width: 1em;
|
||||||
}
|
}
|
||||||
</style>
|
#wrapper {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<label>{{.Name}}</label>
|
||||||
|
<div id="wrapper">
|
||||||
|
{{range .Targets}}
|
||||||
|
{{template "boot-target" .}}
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</draggable-container>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{define "boot-target"}}
|
{{define "boot-target"}}
|
||||||
|
@@ -39,24 +39,24 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="w3-col l2 m2 s6 flex row nowrap" style="height: 1lh;">
|
<div class="w3-col l2 m2 s6 flex row nowrap" style="height: 1lh;">
|
||||||
{{if and (eq .NodeStatus "online") (eq .Status "running")}}
|
{{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="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-label=""><use href="images/actions/instance/config-inactive.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">
|
<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>
|
<svg id="console-btn" class="clickable" aria-label="open console"><use href="images/actions/instance/console-active.svg#symb"></svg>
|
||||||
</a>
|
</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")}}
|
{{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}}">
|
<a href="{{.ConfigPath}}">
|
||||||
<svg id="configure-btn" class="clickable" aria-label="change configuration"><use href="images/actions/instance/config-active.svg#symb"></svg>
|
<svg id="configure-btn" class="clickable" aria-label="change configuration"><use href="images/actions/instance/config-active.svg#symb"></svg>
|
||||||
</a>
|
</a>
|
||||||
<svg id="console-btn" aria-label=""><use href="images/actions/instance/console-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" class="clickable" aria-label="delete instance"><use href="images/actions/instance/delete-active.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")}}
|
{{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="power-btn" aria-disabled="true" role="none"><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="configure-btn" aria-disabled="true" role="none"><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="console-btn" aria-disabled="true" role="none"><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="delete-btn" aria-disabled="true" role="none"><use href="images/actions/instance/delete-inactive.svg#symb"></svg>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user