Improved sensors list
This commit is contained in:
parent
4b0220027e
commit
b68efea626
|
|
@ -1,33 +1,41 @@
|
|||
.sensors-page {
|
||||
.sensors-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
.sensors-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
|
||||
> button {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
> button {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
section.content {
|
||||
padding: 1rem;
|
||||
|
||||
> .box {
|
||||
max-width: 50rem;
|
||||
padding: 1rem;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.sensors-list {
|
||||
.sensor-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0.25rem 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
overflow: auto;
|
||||
padding: 1rem;
|
||||
|
||||
&.head {
|
||||
opacity: 0.75;
|
||||
font-size: 85%;
|
||||
}
|
||||
@media screen and (max-width: 1500px) {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
}
|
||||
|
||||
.sensor-item {
|
||||
margin: 0.25rem;
|
||||
overflow: auto;
|
||||
padding: 0.5rem;
|
||||
|
||||
> div {
|
||||
flex-grow: 0;
|
||||
|
|
@ -36,30 +44,46 @@
|
|||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
> .id {
|
||||
flex: 0.3;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
> .auth {
|
||||
.auth-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 85%;
|
||||
margin: 0.25rem 0;
|
||||
|
||||
> .name {
|
||||
margin-right: 0.5rem;
|
||||
flex: 1;
|
||||
}
|
||||
.label {
|
||||
width: 2rem;
|
||||
background-color: #666;
|
||||
padding: 0.2rem;
|
||||
border-radius: 0.25rem;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
> .key {
|
||||
display: flex;
|
||||
flex: 1.5;
|
||||
.value {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
||||
button {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
padding: 0.25rem 0.5rem;
|
||||
input {
|
||||
flex: 1;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
padding: 0rem 0.5rem;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
font-size: 120%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .actions {
|
||||
flex: 2;
|
||||
text-align: right;
|
||||
margin-top: 0.5rem;
|
||||
|
||||
button {
|
||||
margin-left: 0.25rem;
|
||||
|
|
@ -69,3 +93,29 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@media screen and (max-width: 768px) {
|
||||
.sensors-page .sensors-list {
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
.sensors-page .sensors-list {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
.sensors-page .sensors-list {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1980px) {
|
||||
.sensors-page .sensors-list {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path></svg>
|
||||
|
After Width: | Height: | Size: 338 B |
|
|
@ -0,0 +1 @@
|
|||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3"></path></svg>
|
||||
|
After Width: | Height: | Size: 354 B |
|
|
@ -0,0 +1,36 @@
|
|||
import { ClipboardCheckIcon, ClipboardCopyIcon } from '@/icons'
|
||||
import { useRef, useState } from 'preact/hooks'
|
||||
|
||||
type Props = {
|
||||
value: string
|
||||
}
|
||||
|
||||
export const InputWithCopy = ({ value }: Props) => {
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
|
||||
const [hasCopied, setHasCopied] = useState(false)
|
||||
|
||||
const handleCopy = () => {
|
||||
const target = inputRef.current
|
||||
|
||||
if (target) {
|
||||
target.select()
|
||||
target.setSelectionRange(0, 99999)
|
||||
|
||||
navigator.clipboard.writeText(target.value)
|
||||
|
||||
setHasCopied(true)
|
||||
|
||||
setTimeout(() => setHasCopied(false), 2000)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<input type="text" value={value} ref={inputRef} readOnly disabled />
|
||||
<button className="icon" onClick={handleCopy}>
|
||||
{hasCopied ? <ClipboardCheckIcon /> : <ClipboardCopyIcon />}
|
||||
</button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
@ -7,3 +7,5 @@ export { ReactComponent as PlusIcon } from '@/assets/icons/plus.svg'
|
|||
export { ReactComponent as EyeIcon } from '@/assets/icons/eye.svg'
|
||||
export { ReactComponent as EyeOffIcon } from '@/assets/icons/eye-off.svg'
|
||||
export { ReactComponent as EditIcon } from '@/assets/icons/edit.svg'
|
||||
export { ReactComponent as ClipboardCopyIcon } from '@/assets/icons/clipboard-copy.svg'
|
||||
export { ReactComponent as ClipboardCheckIcon } from '@/assets/icons/clipboard-check.svg'
|
||||
|
|
|
|||
|
|
@ -24,18 +24,10 @@ export const SensorsPage = () => {
|
|||
}
|
||||
className="sensors-page"
|
||||
>
|
||||
<div className="box">
|
||||
<div className="sensors-list">
|
||||
<div className="sensor-item head">
|
||||
<div className="id">ID</div>
|
||||
<div className="name">Name</div>
|
||||
<div className="key">Key</div>
|
||||
<div className="actions"></div>
|
||||
</div>
|
||||
{sensors.data?.map((i) => (
|
||||
<SensorItem key={i.id} sensor={i} onEdit={setEdited} />
|
||||
))}
|
||||
</div>
|
||||
<div className="sensors-list">
|
||||
{sensors.data?.map((i) => (
|
||||
<SensorItem key={i.id} sensor={i} onEdit={setEdited} />
|
||||
))}
|
||||
</div>
|
||||
{(showNew || edited) && (
|
||||
<SensorFormModal
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { SensorInfo } from '@/api/sensors'
|
||||
import { CancelIcon, EditIcon, EyeIcon, RefreshIcon } from '@/icons'
|
||||
import { useState } from 'preact/hooks'
|
||||
import { InputWithCopy } from '@/components/InputWithCopy'
|
||||
import { CancelIcon, EditIcon } from '@/icons'
|
||||
|
||||
type Props = {
|
||||
sensor: SensorInfo
|
||||
|
|
@ -8,30 +8,29 @@ type Props = {
|
|||
}
|
||||
|
||||
export const SensorItem = ({ sensor, onEdit }: Props) => {
|
||||
const [showPassword, setShowPassword] = useState(false)
|
||||
|
||||
return (
|
||||
<div className="sensor-item">
|
||||
<div className="id">{sensor.id}</div>
|
||||
<div className="box sensor-item">
|
||||
<div className="name">{sensor.name}</div>
|
||||
<div className="key">
|
||||
<input
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
value={sensor.authKey}
|
||||
disabled
|
||||
readOnly
|
||||
/>
|
||||
<button className="icon" onClick={() => setShowPassword((v) => !v)}>
|
||||
<EyeIcon />
|
||||
</button>
|
||||
|
||||
<div className="auth">
|
||||
<div className="auth-value">
|
||||
<div className="label">ID</div>
|
||||
<div className="value">
|
||||
<InputWithCopy value={sensor.id.toString()} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="auth-value">
|
||||
<div className="label">KEY</div>
|
||||
<div className="value">
|
||||
<InputWithCopy value={sensor.authKey} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="actions">
|
||||
<button onClick={() => onEdit(sensor)}>
|
||||
<EditIcon /> Edit
|
||||
</button>
|
||||
<button>
|
||||
<RefreshIcon /> Refresh key
|
||||
</button>
|
||||
|
||||
<button>
|
||||
<CancelIcon /> Delete
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Reference in New Issue