Pick first dashboard if there's any, dashboards are now deletable
This commit is contained in:
parent
4173629693
commit
c7d430805a
|
|
@ -41,3 +41,12 @@ export const updateDashboard = ({
|
||||||
contents: JSON.stringify(body.contents),
|
contents: JSON.stringify(body.contents),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const deleteDashboard = (id: number) =>
|
||||||
|
request<DashboardInfo>(
|
||||||
|
`/api/dashboards/${id}`,
|
||||||
|
{
|
||||||
|
method: 'DELETE',
|
||||||
|
},
|
||||||
|
'void'
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,8 @@ export const DashboardHeader = () => {
|
||||||
<CancelIcon />
|
<CancelIcon />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<DashboardSwitch />
|
||||||
|
|
||||||
<DashboardFilters />
|
<DashboardFilters />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
import {
|
import {
|
||||||
createDashboard,
|
createDashboard,
|
||||||
DashboardInfo,
|
DashboardInfo,
|
||||||
|
deleteDashboard,
|
||||||
updateDashboard,
|
updateDashboard,
|
||||||
} from '@/api/dashboards'
|
} from '@/api/dashboards'
|
||||||
import { Modal } from '@/components/Modal'
|
import { Modal } from '@/components/Modal'
|
||||||
|
import { useConfirmModal } from '@/contexts/ConfirmModalsContext'
|
||||||
|
import { useDashboardContext } from '@/pages/dashboard/contexts/DashboardContext'
|
||||||
import { createDashboardContent } from '@/utils/createDashboardContent'
|
import { createDashboardContent } from '@/utils/createDashboardContent'
|
||||||
import { useForm } from '@/utils/hooks/useForm'
|
import { useForm } from '@/utils/hooks/useForm'
|
||||||
import { useMutation, useQueryClient } from 'react-query'
|
import { useMutation, useQueryClient } from 'react-query'
|
||||||
|
|
@ -13,17 +16,40 @@ type Props = {
|
||||||
onClose: () => void
|
onClose: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DashboardModal = ({ dashboard, onClose }: Props) => {
|
export const DashboardSettings = ({ dashboard, onClose }: Props) => {
|
||||||
|
const { setDashboardId, dashboardId } = useDashboardContext()
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const createMutation = useMutation(createDashboard)
|
const createMutation = useMutation(createDashboard)
|
||||||
const updateMutation = useMutation(updateDashboard)
|
const updateMutation = useMutation(updateDashboard)
|
||||||
|
|
||||||
|
const deleteMutation = useMutation(deleteDashboard, {
|
||||||
|
onSuccess: () => {
|
||||||
|
queryClient.invalidateQueries(['/dashboards'])
|
||||||
|
onClose()
|
||||||
|
|
||||||
|
if (dashboardId === dashboard?.id) {
|
||||||
|
setDashboardId(-1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const isLoading =
|
||||||
|
deleteMutation.isLoading ||
|
||||||
|
updateMutation.isLoading ||
|
||||||
|
createMutation.isLoading
|
||||||
|
|
||||||
|
const deleteConfirm = useConfirmModal({
|
||||||
|
content: `Are you sure you want to delete ${dashboard?.name} dashboard?`,
|
||||||
|
onConfirm: () => !isLoading && deleteMutation.mutate(dashboard?.id ?? 1),
|
||||||
|
})
|
||||||
|
|
||||||
const { handleSubmit, register } = useForm({
|
const { handleSubmit, register } = useForm({
|
||||||
defaultValue: () => ({
|
defaultValue: () => ({
|
||||||
name: dashboard?.name ?? '',
|
name: dashboard?.name ?? '',
|
||||||
}),
|
}),
|
||||||
onSubmit: async (v) => {
|
onSubmit: async (v) => {
|
||||||
if (updateMutation.isLoading || createMutation.isLoading) {
|
if (isLoading) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -54,6 +80,10 @@ export const DashboardModal = ({ dashboard, onClose }: Props) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="actions">
|
<div className="actions">
|
||||||
|
<button className="remove" type="button" onClick={deleteConfirm.show}>
|
||||||
|
Remove
|
||||||
|
</button>
|
||||||
|
|
||||||
<button className="cancel" onClick={onClose} type="button">
|
<button className="cancel" onClick={onClose} type="button">
|
||||||
Cancel
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -3,7 +3,7 @@ import { EditIcon, PlusIcon } from '@/icons'
|
||||||
import { useDashboardContext } from '@/pages/dashboard/contexts/DashboardContext'
|
import { useDashboardContext } from '@/pages/dashboard/contexts/DashboardContext'
|
||||||
import { useState } from 'preact/hooks'
|
import { useState } from 'preact/hooks'
|
||||||
import { useQuery } from 'react-query'
|
import { useQuery } from 'react-query'
|
||||||
import { DashboardModal } from './DashboardModal'
|
import { DashboardSettings } from './DashboardSettings'
|
||||||
|
|
||||||
export const DashboardSwitch = () => {
|
export const DashboardSwitch = () => {
|
||||||
const { dashboardId, setDashboardId, dashboard } = useDashboardContext()
|
const { dashboardId, setDashboardId, dashboard } = useDashboardContext()
|
||||||
|
|
@ -26,16 +26,16 @@ export const DashboardSwitch = () => {
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<button onClick={() => setEdited(dashboard)}>
|
<button onClick={() => setEdited(dashboard)}>
|
||||||
<EditIcon /> Edit
|
<EditIcon />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button onClick={() => setShowNew(true)}>
|
<button onClick={() => setShowNew(true)}>
|
||||||
<PlusIcon /> Add
|
<PlusIcon />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{showNew && <DashboardModal onClose={() => setShowNew(false)} />}
|
{showNew && <DashboardSettings onClose={() => setShowNew(false)} />}
|
||||||
{edited && (
|
{edited && (
|
||||||
<DashboardModal
|
<DashboardSettings
|
||||||
dashboard={edited}
|
dashboard={edited}
|
||||||
onClose={() => setEdited(undefined)}
|
onClose={() => setEdited(undefined)}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
import { DashboardInfo, getDashboard, updateDashboard } from '@/api/dashboards'
|
import {
|
||||||
|
DashboardInfo,
|
||||||
|
getDashboard,
|
||||||
|
getDashboards,
|
||||||
|
updateDashboard,
|
||||||
|
} from '@/api/dashboards'
|
||||||
import { parseDashboard } from '@/utils/dashboard/parseDashboard'
|
import { parseDashboard } from '@/utils/dashboard/parseDashboard'
|
||||||
import { useViewportSize } from '@/utils/hooks/useViewportSize'
|
import { useViewportSize } from '@/utils/hooks/useViewportSize'
|
||||||
import { intervalToRange } from '@/utils/intervalToRange'
|
import { intervalToRange } from '@/utils/intervalToRange'
|
||||||
|
|
@ -40,6 +45,8 @@ export const DashboardContextProvider = ({
|
||||||
const [dashboardId, setDashboardId] = useState(-1)
|
const [dashboardId, setDashboardId] = useState(-1)
|
||||||
const isDashboardSelected = !isNaN(dashboardId) && dashboardId >= 0
|
const isDashboardSelected = !isNaN(dashboardId) && dashboardId >= 0
|
||||||
|
|
||||||
|
const dashboards = useQuery(['/dashboards'], getDashboards)
|
||||||
|
|
||||||
const dashboard = useQuery(
|
const dashboard = useQuery(
|
||||||
['/dashboards', dashboardId],
|
['/dashboards', dashboardId],
|
||||||
() => getDashboard(dashboardId),
|
() => getDashboard(dashboardId),
|
||||||
|
|
@ -77,6 +84,12 @@ export const DashboardContextProvider = ({
|
||||||
setBoxes(dashboardContent?.boxes ?? [])
|
setBoxes(dashboardContent?.boxes ?? [])
|
||||||
}, [dashboardContent])
|
}, [dashboardContent])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (dashboards.data && !dashboards.isFetching && !isDashboardSelected) {
|
||||||
|
setDashboardId(dashboards.data[0]?.id)
|
||||||
|
}
|
||||||
|
}, [dashboards.data, isDashboardSelected])
|
||||||
|
|
||||||
const [filter, setFilter] = useState<FilterValue>(() => {
|
const [filter, setFilter] = useState<FilterValue>(() => {
|
||||||
const range = intervalToRange('week', new Date(), new Date())
|
const range = intervalToRange('week', new Date(), new Date())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ func main() {
|
||||||
loginProtected.POST("/api/dashboards", routes.PostDashboard(server))
|
loginProtected.POST("/api/dashboards", routes.PostDashboard(server))
|
||||||
loginProtected.GET("/api/dashboards/:id", routes.GetDashboardById(server))
|
loginProtected.GET("/api/dashboards/:id", routes.GetDashboardById(server))
|
||||||
loginProtected.PUT("/api/dashboards/:id", routes.PutDashboard(server))
|
loginProtected.PUT("/api/dashboards/:id", routes.PutDashboard(server))
|
||||||
|
loginProtected.DELETE("/api/dashboards/:id", routes.DeleteDashboard(server))
|
||||||
loginProtected.POST("/api/logout", routes.Logout(server))
|
loginProtected.POST("/api/logout", routes.Logout(server))
|
||||||
|
|
||||||
// Routes accessible using auth key
|
// Routes accessible using auth key
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"basic-sensor-receiver/app"
|
"basic-sensor-receiver/app"
|
||||||
|
"database/sql"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
|
@ -42,6 +43,11 @@ func GetDashboardById(s *app.Server) gin.HandlerFunc {
|
||||||
|
|
||||||
item, err := s.Services.Dashboards.GetById(id)
|
item, err := s.Services.Dashboards.GetById(id)
|
||||||
|
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
c.Status(404)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.AbortWithError(500, err)
|
||||||
return
|
return
|
||||||
|
|
@ -97,6 +103,25 @@ func PutDashboard(s *app.Server) gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeleteDashboard(s *app.Server) gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
id, err := getIntParam(c, "id")
|
||||||
|
if err != nil {
|
||||||
|
c.AbortWithError(400, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.Services.Dashboards.Delete(id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
c.AbortWithError(500, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Status(http.StatusOK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getIntParam(c *gin.Context, key string) (int64, error) {
|
func getIntParam(c *gin.Context, key string) (int64, error) {
|
||||||
value := c.Param(key)
|
value := c.Param(key)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,12 @@ func (s *DashboardsService) Update(id int64, name string, contents string) (*Das
|
||||||
return &item, nil
|
return &item, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DashboardsService) Delete(id int64) error {
|
||||||
|
_, err := s.ctx.DB.Exec("DELETE FROM dashboards WHERe id = ?", id)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func (s *DashboardsService) GetById(id int64) (*DashboardItem, error) {
|
func (s *DashboardsService) GetById(id int64) (*DashboardItem, error) {
|
||||||
item := DashboardItem{}
|
item := DashboardItem{}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue