Skip to content

Commit

Permalink
feat(misc): snapshots improvements (#351)
Browse files Browse the repository at this point in the history
  • Loading branch information
bouassaba authored Oct 12, 2024
1 parent f474ca5 commit 73c3da9
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 108 deletions.
14 changes: 5 additions & 9 deletions api/docs/index.html

Large diffs are not rendered by default.

26 changes: 0 additions & 26 deletions api/docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -641,20 +641,6 @@ definitions:
version:
type: integer
type: object
service.SnapshotActivateOptions:
properties:
fileId:
type: string
required:
- fileId
type: object
service.SnapshotDetachOptions:
properties:
fileId:
type: string
required:
- fileId
type: object
service.SnapshotList:
properties:
data:
Expand Down Expand Up @@ -3080,12 +3066,6 @@ paths:
name: id
required: true
type: string
- description: Body
in: body
name: body
required: true
schema:
$ref: '#/definitions/service.SnapshotActivateOptions'
produces:
- application/json
responses:
Expand All @@ -3110,12 +3090,6 @@ paths:
name: id
required: true
type: string
- description: Body
in: body
name: body
required: true
schema:
$ref: '#/definitions/service.SnapshotDetachOptions'
produces:
- application/json
responses:
Expand Down
14 changes: 14 additions & 0 deletions api/repo/snapshot_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type SnapshotRepo interface {
DeleteMappingsForTree(fileID string) error
DeleteAllDangling() error
GetLatestVersionForFile(fileID string) (int64, error)
GetFileID(id string) (string, error)
CountAssociations(id string) (int64, error)
Attach(sourceFileID string, targetFileID string) error
Detach(id string, fileID string) error
Expand Down Expand Up @@ -655,6 +656,19 @@ func (repo *snapshotRepo) GetLatestVersionForFile(fileID string) (int64, error)
return res.Result, nil
}

func (repo *snapshotRepo) GetFileID(id string) (string, error) {
type Result struct {
Result string
}
var res Result
if db := repo.db.
Raw("SELECT file_id result FROM snapshot_file WHERE snapshot_id = ?", id).
Scan(&res); db.Error != nil {
return "", db.Error
}
return res.Result, nil
}

func (repo *snapshotRepo) CountAssociations(id string) (int64, error) {
var count int64
if db := repo.db.Model(&SnapshotFileEntity{}).
Expand Down
28 changes: 6 additions & 22 deletions api/router/snapshot_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,20 +114,12 @@ func (r *SnapshotRouter) List(c *fiber.Ctx) error {
// @Tags Snapshots
// @Id snapshots_activate
// @Produce json
// @Param id path string true "ID"
// @Param body body service.SnapshotActivateOptions true "Body"
// @Failure 404 {object} errorpkg.ErrorResponse
// @Failure 500 {object} errorpkg.ErrorResponse
// @Param id path string true "ID"
// @Failure 404 {object} errorpkg.ErrorResponse
// @Failure 500 {object} errorpkg.ErrorResponse
// @Router /snapshots/{id}/activate [post]
func (r *SnapshotRouter) Activate(c *fiber.Ctx) error {
opts := new(service.SnapshotActivateOptions)
if err := c.BodyParser(opts); err != nil {
return err
}
if err := validator.New().Struct(opts); err != nil {
return errorpkg.NewRequestBodyValidationError(err)
}
res, err := r.snapshotSvc.Activate(c.Params("id"), *opts, GetUserID(c))
res, err := r.snapshotSvc.Activate(c.Params("id"), GetUserID(c))
if err != nil {
return err
}
Expand All @@ -141,21 +133,13 @@ func (r *SnapshotRouter) Activate(c *fiber.Ctx) error {
// @Tags Snapshots
// @Id snapshots_detach
// @Produce json
// @Param id path string true "ID"
// @Param body body service.SnapshotDetachOptions true "Body"
// @Param id path string true "ID"
// @Success 204
// @Failure 404 {object} errorpkg.ErrorResponse
// @Failure 500 {object} errorpkg.ErrorResponse
// @Router /snapshots/{id}/detach [post]
func (r *SnapshotRouter) Detach(c *fiber.Ctx) error {
opts := new(service.SnapshotDetachOptions)
if err := c.BodyParser(opts); err != nil {
return err
}
if err := validator.New().Struct(opts); err != nil {
return errorpkg.NewRequestBodyValidationError(err)
}
if err := r.snapshotSvc.Detach(c.Params("id"), *opts, GetUserID(c)); err != nil {
if err := r.snapshotSvc.Detach(c.Params("id"), GetUserID(c)); err != nil {
return err
}
return c.SendStatus(http.StatusNoContent)
Expand Down
24 changes: 12 additions & 12 deletions api/service/snapshot_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,12 @@ func (svc *SnapshotService) doPagination(data []model.Snapshot, page, size uint)
return data[startIndex:endIndex], totalElements, totalPages
}

type SnapshotActivateOptions struct {
FileID string `json:"fileId" validate:"required"`
}

func (svc *SnapshotService) Activate(id string, opts SnapshotActivateOptions, userID string) (*File, error) {
file, err := svc.fileCache.Get(opts.FileID)
func (svc *SnapshotService) Activate(id string, userID string) (*File, error) {
fileID, err := svc.snapshotRepo.GetFileID(id)
if err != nil {
return nil, err
}
file, err := svc.fileCache.Get(fileID)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -239,12 +239,12 @@ func (svc *SnapshotService) Activate(id string, opts SnapshotActivateOptions, us
return res, nil
}

type SnapshotDetachOptions struct {
FileID string `json:"fileId" validate:"required"`
}

func (svc *SnapshotService) Detach(id string, opts SnapshotDetachOptions, userID string) error {
file, err := svc.fileCache.Get(opts.FileID)
func (svc *SnapshotService) Detach(id string, userID string) error {
fileID, err := svc.snapshotRepo.GetFileID(id)
if err != nil {
return err
}
file, err := svc.fileCache.Get(fileID)
if err != nil {
return err
}
Expand Down
14 changes: 2 additions & 12 deletions ui/src/client/api/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,6 @@ export type ListQueryParams = {
query?: string
}

export type ActivateOptions = {
fileId: string
}

export type DetachOptions = {
fileId: string
}

export default class SnapshotAPI {
static async list(options: ListOptions) {
return apiFetcher({
Expand Down Expand Up @@ -167,19 +159,17 @@ export default class SnapshotAPI {
return new URLSearchParams(params)
}

static async activate(id: string, options: ActivateOptions) {
static async activate(id: string) {
return apiFetcher({
url: `/snapshots/${id}/activate`,
method: 'POST',
body: JSON.stringify(options),
}) as Promise<File>
}

static async detach(id: string, options: DetachOptions) {
static async detach(id: string) {
return apiFetcher({
url: `/snapshots/${id}/detach`,
method: 'POST',
body: JSON.stringify(options),
})
}
}
15 changes: 5 additions & 10 deletions ui/src/components/snapshot/snapshot-detach.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,17 @@ const SnapshotDetach = () => {
? state.ui.snapshots.selection[0]
: undefined,
)
const fileId = useAppSelector((state) =>
state.ui.files.selection.length > 0
? state.ui.files.selection[0]
: undefined,
)
const mutate = useAppSelector((state) => state.ui.snapshots.snapshotMutate)
const isModalOpen = useAppSelector(
(state) => state.ui.snapshots.isDetachModalOpen,
)
const [isLoading, setIsLoading] = useState(false)

const handleDetach = useCallback(async () => {
async function unlink(id: string, fileId: string) {
async function detach(id: string) {
setIsLoading(true)
try {
await SnapshotAPI.detach(id, { fileId })
await SnapshotAPI.detach(id)
await mutate?.()
dispatch(selectionUpdated([]))
dispatch(detachModalDidClose())
Expand All @@ -56,10 +51,10 @@ const SnapshotDetach = () => {
setIsLoading(false)
}
}
if (id && fileId) {
unlink(id, fileId)
if (id) {
detach(id)
}
}, [id, fileId, dispatch, mutate])
}, [id, dispatch, mutate])

return (
<Modal
Expand Down
46 changes: 29 additions & 17 deletions ui/src/components/snapshot/snapshot-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const SnapshotList = () => {
if (selected) {
try {
setIsActivating(true)
await SnapshotAPI.activate(selected.id, { fileId })
await SnapshotAPI.activate(selected.id)
await snapshotMutate()
mutateFiles?.()
} finally {
Expand All @@ -95,6 +95,13 @@ const SnapshotList = () => {
dispatch(selectionUpdated([snapshot.id]))
}, [])

const isSelected = useCallback(
(snapshot: Snapshot) => {
return selected?.id === snapshot.id || (snapshot.isActive && !selected)
},
[selected],
)

return (
<Modal
size="xl"
Expand Down Expand Up @@ -150,14 +157,14 @@ const SnapshotList = () => {
className={cx(
'cursor-pointer',
'h-[52px]',
{ 'bg-gray-100': selected?.id === s.id },
{ 'dark:bg-gray-600': selected?.id === s.id },
{ 'bg-transparent': selected?.id !== s.id },
{ 'bg-gray-100': isSelected(s) },
{ 'dark:bg-gray-600': isSelected(s) },
{ 'bg-transparent': !isSelected(s) },
)}
onClick={() => handleSelect(s)}
>
<Td className={cx('px-0.5', 'text-center')}>
<Radio size="md" isChecked={selected?.id === s.id} />
<Radio size="md" isChecked={isSelected(s)} />
</Td>
<Td className={cx('px-0.5')}>
<div
Expand All @@ -168,18 +175,23 @@ const SnapshotList = () => {
'gap-1.5',
)}
>
<span className={cx('text-base')}>
{prettyDate(s.createTime)}
</span>
{s.entities ? (
<Badge variant="outline">Insights</Badge>
) : null}
{s.mosaic ? (
<Badge variant="outline">Mosaic</Badge>
) : null}
{s.isActive ? (
<Badge colorScheme="green">Active</Badge>
) : null}
<div className={cx('flex', 'flex-col', 'gap-1')}>
<span className={cx('text-base')}>
{prettyDate(s.createTime)}
</span>
<div className={cx('flex', 'flex-row', 'gap-1')}>
<Badge variant="outline">{`v${s.version}`}</Badge>
{s.entities ? (
<Badge variant="outline">Insights</Badge>
) : null}
{s.mosaic ? (
<Badge variant="outline">Mosaic</Badge>
) : null}
{s.isActive ? (
<Badge colorScheme="green">Active</Badge>
) : null}
</div>
</div>
</div>
</Td>
</Tr>
Expand Down

0 comments on commit 73c3da9

Please sign in to comment.