From c7d430805ae5948edfd83ca80e72de48e45b673a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Z=C3=ADpek?= Date: Sat, 3 Sep 2022 21:59:37 +0200 Subject: [PATCH] Pick first dashboard if there's any, dashboards are now deletable --- client/src/api/dashboards.ts | 9 +++++ .../DashboardHeader/DashboardHeader.tsx | 2 ++ ...shboardModal.tsx => DashboardSettings.tsx} | 34 +++++++++++++++++-- .../components/DashboardSwitch.tsx | 10 +++--- .../dashboard/contexts/DashboardContext.tsx | 15 +++++++- server/main.go | 1 + server/routes/dashboards.go | 25 ++++++++++++++ server/services/dashboards_service.go | 6 ++++ 8 files changed, 94 insertions(+), 8 deletions(-) rename client/src/pages/dashboard/components/DashboardHeader/components/{DashboardModal.tsx => DashboardSettings.tsx} (59%) diff --git a/client/src/api/dashboards.ts b/client/src/api/dashboards.ts index aa87c08..b3468ca 100644 --- a/client/src/api/dashboards.ts +++ b/client/src/api/dashboards.ts @@ -41,3 +41,12 @@ export const updateDashboard = ({ contents: JSON.stringify(body.contents), }), }) + +export const deleteDashboard = (id: number) => + request( + `/api/dashboards/${id}`, + { + method: 'DELETE', + }, + 'void' + ) diff --git a/client/src/pages/dashboard/components/DashboardHeader/DashboardHeader.tsx b/client/src/pages/dashboard/components/DashboardHeader/DashboardHeader.tsx index 2ba3108..05802b5 100644 --- a/client/src/pages/dashboard/components/DashboardHeader/DashboardHeader.tsx +++ b/client/src/pages/dashboard/components/DashboardHeader/DashboardHeader.tsx @@ -66,6 +66,8 @@ export const DashboardHeader = () => { + + diff --git a/client/src/pages/dashboard/components/DashboardHeader/components/DashboardModal.tsx b/client/src/pages/dashboard/components/DashboardHeader/components/DashboardSettings.tsx similarity index 59% rename from client/src/pages/dashboard/components/DashboardHeader/components/DashboardModal.tsx rename to client/src/pages/dashboard/components/DashboardHeader/components/DashboardSettings.tsx index 6142ed7..aaf507f 100644 --- a/client/src/pages/dashboard/components/DashboardHeader/components/DashboardModal.tsx +++ b/client/src/pages/dashboard/components/DashboardHeader/components/DashboardSettings.tsx @@ -1,9 +1,12 @@ import { createDashboard, DashboardInfo, + deleteDashboard, updateDashboard, } from '@/api/dashboards' import { Modal } from '@/components/Modal' +import { useConfirmModal } from '@/contexts/ConfirmModalsContext' +import { useDashboardContext } from '@/pages/dashboard/contexts/DashboardContext' import { createDashboardContent } from '@/utils/createDashboardContent' import { useForm } from '@/utils/hooks/useForm' import { useMutation, useQueryClient } from 'react-query' @@ -13,17 +16,40 @@ type Props = { onClose: () => void } -export const DashboardModal = ({ dashboard, onClose }: Props) => { +export const DashboardSettings = ({ dashboard, onClose }: Props) => { + const { setDashboardId, dashboardId } = useDashboardContext() + const queryClient = useQueryClient() const createMutation = useMutation(createDashboard) 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({ defaultValue: () => ({ name: dashboard?.name ?? '', }), onSubmit: async (v) => { - if (updateMutation.isLoading || createMutation.isLoading) { + if (isLoading) { return } @@ -54,6 +80,10 @@ export const DashboardModal = ({ dashboard, onClose }: Props) => {
+ + diff --git a/client/src/pages/dashboard/components/DashboardHeader/components/DashboardSwitch.tsx b/client/src/pages/dashboard/components/DashboardHeader/components/DashboardSwitch.tsx index 2de093a..db4b2ae 100644 --- a/client/src/pages/dashboard/components/DashboardHeader/components/DashboardSwitch.tsx +++ b/client/src/pages/dashboard/components/DashboardHeader/components/DashboardSwitch.tsx @@ -3,7 +3,7 @@ import { EditIcon, PlusIcon } from '@/icons' import { useDashboardContext } from '@/pages/dashboard/contexts/DashboardContext' import { useState } from 'preact/hooks' import { useQuery } from 'react-query' -import { DashboardModal } from './DashboardModal' +import { DashboardSettings } from './DashboardSettings' export const DashboardSwitch = () => { const { dashboardId, setDashboardId, dashboard } = useDashboardContext() @@ -26,16 +26,16 @@ export const DashboardSwitch = () => { - {showNew && setShowNew(false)} />} + {showNew && setShowNew(false)} />} {edited && ( - setEdited(undefined)} /> diff --git a/client/src/pages/dashboard/contexts/DashboardContext.tsx b/client/src/pages/dashboard/contexts/DashboardContext.tsx index 9d4ebe3..39c4838 100644 --- a/client/src/pages/dashboard/contexts/DashboardContext.tsx +++ b/client/src/pages/dashboard/contexts/DashboardContext.tsx @@ -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 { useViewportSize } from '@/utils/hooks/useViewportSize' import { intervalToRange } from '@/utils/intervalToRange' @@ -40,6 +45,8 @@ export const DashboardContextProvider = ({ const [dashboardId, setDashboardId] = useState(-1) const isDashboardSelected = !isNaN(dashboardId) && dashboardId >= 0 + const dashboards = useQuery(['/dashboards'], getDashboards) + const dashboard = useQuery( ['/dashboards', dashboardId], () => getDashboard(dashboardId), @@ -77,6 +84,12 @@ export const DashboardContextProvider = ({ setBoxes(dashboardContent?.boxes ?? []) }, [dashboardContent]) + useEffect(() => { + if (dashboards.data && !dashboards.isFetching && !isDashboardSelected) { + setDashboardId(dashboards.data[0]?.id) + } + }, [dashboards.data, isDashboardSelected]) + const [filter, setFilter] = useState(() => { const range = intervalToRange('week', new Date(), new Date()) diff --git a/server/main.go b/server/main.go index 3a596f8..b6f68ed 100644 --- a/server/main.go +++ b/server/main.go @@ -51,6 +51,7 @@ func main() { loginProtected.POST("/api/dashboards", routes.PostDashboard(server)) loginProtected.GET("/api/dashboards/:id", routes.GetDashboardById(server)) loginProtected.PUT("/api/dashboards/:id", routes.PutDashboard(server)) + loginProtected.DELETE("/api/dashboards/:id", routes.DeleteDashboard(server)) loginProtected.POST("/api/logout", routes.Logout(server)) // Routes accessible using auth key diff --git a/server/routes/dashboards.go b/server/routes/dashboards.go index 72d490d..ac7e1c4 100644 --- a/server/routes/dashboards.go +++ b/server/routes/dashboards.go @@ -2,6 +2,7 @@ package routes import ( "basic-sensor-receiver/app" + "database/sql" "net/http" "strconv" @@ -42,6 +43,11 @@ func GetDashboardById(s *app.Server) gin.HandlerFunc { item, err := s.Services.Dashboards.GetById(id) + if err == sql.ErrNoRows { + c.Status(404) + return + } + if err != nil { c.AbortWithError(500, err) 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) { value := c.Param(key) diff --git a/server/services/dashboards_service.go b/server/services/dashboards_service.go index db64dba..dd9fc8c 100644 --- a/server/services/dashboards_service.go +++ b/server/services/dashboards_service.go @@ -72,6 +72,12 @@ func (s *DashboardsService) Update(id int64, name string, contents string) (*Das 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) { item := DashboardItem{}