diff --git a/store/db/mysql/resource.go b/store/db/mysql/resource.go index f077f0ba..070584ae 100644 --- a/store/db/mysql/resource.go +++ b/store/db/mysql/resource.go @@ -75,7 +75,7 @@ func (d *DB) ListResources(ctx context.Context, find *store.FindResource) ([]*st fields = append(fields, "`blob`") } - query := fmt.Sprintf("SELECT %s FROM `resource` WHERE %s ORDER BY `created_ts` DESC", strings.Join(fields, ", "), strings.Join(where, " AND ")) + query := fmt.Sprintf("SELECT %s FROM `resource` WHERE %s ORDER BY `updated_ts` DESC", strings.Join(fields, ", "), strings.Join(where, " AND ")) if find.Limit != nil { query = fmt.Sprintf("%s LIMIT %d", query, *find.Limit) if find.Offset != nil { diff --git a/store/db/postgres/resource.go b/store/db/postgres/resource.go index 30232bbd..ae38eddf 100644 --- a/store/db/postgres/resource.go +++ b/store/db/postgres/resource.go @@ -71,7 +71,7 @@ func (d *DB) ListResources(ctx context.Context, find *store.FindResource) ([]*st %s FROM resource WHERE %s - ORDER BY created_ts DESC + ORDER BY updated_ts DESC `, strings.Join(fields, ", "), strings.Join(where, " AND ")) if find.Limit != nil { query = fmt.Sprintf("%s LIMIT %d", query, *find.Limit) diff --git a/store/db/sqlite/resource.go b/store/db/sqlite/resource.go index d6952034..20507a80 100644 --- a/store/db/sqlite/resource.go +++ b/store/db/sqlite/resource.go @@ -68,7 +68,7 @@ func (d *DB) ListResources(ctx context.Context, find *store.FindResource) ([]*st fields = append(fields, "`blob`") } - query := fmt.Sprintf("SELECT %s FROM `resource` WHERE %s ORDER BY `created_ts` DESC", strings.Join(fields, ", "), strings.Join(where, " AND ")) + query := fmt.Sprintf("SELECT %s FROM `resource` WHERE %s ORDER BY `updated_ts` DESC", strings.Join(fields, ", "), strings.Join(where, " AND ")) if find.Limit != nil { query = fmt.Sprintf("%s LIMIT %d", query, *find.Limit) if find.Offset != nil { diff --git a/web/package.json b/web/package.json index 36c03580..85906884 100644 --- a/web/package.json +++ b/web/package.json @@ -8,6 +8,9 @@ "postinstall": "cd ../proto && buf generate" }, "dependencies": { + "@dnd-kit/core": "^6.1.0", + "@dnd-kit/sortable": "^8.0.0", + "@dnd-kit/utilities": "^3.2.2", "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", "@github/relative-time-element": "^4.4.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 9ba5a42a..d3a0ac17 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -8,6 +8,15 @@ importers: .: dependencies: + '@dnd-kit/core': + specifier: ^6.1.0 + version: 6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@dnd-kit/sortable': + specifier: ^8.0.0 + version: 8.0.0(@dnd-kit/core@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + '@dnd-kit/utilities': + specifier: ^3.2.2 + version: 3.2.2(react@18.3.1) '@emotion/react': specifier: ^11.11.4 version: 11.11.4(@types/react@18.3.1)(react@18.3.1) @@ -348,6 +357,28 @@ packages: engines: {node: '>=12'} hasBin: true + '@dnd-kit/accessibility@3.1.0': + resolution: {integrity: sha512-ea7IkhKvlJUv9iSHJOnxinBcoOI3ppGnnL+VDJ75O45Nss6HtZd8IdN8touXPDtASfeI2T2LImb8VOZcL47wjQ==} + peerDependencies: + react: '>=16.8.0' + + '@dnd-kit/core@6.1.0': + resolution: {integrity: sha512-J3cQBClB4TVxwGo3KEjssGEXNJqGVWx17aRTZ1ob0FliR5IjYgTxl5YJbKTzA6IzrtelotH19v6y7uoIRUZPSg==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@dnd-kit/sortable@8.0.0': + resolution: {integrity: sha512-U3jk5ebVXe1Lr7c2wU7SBZjcWdQP+j7peHJfCspnA81enlu88Mgd7CC8Q+pub9ubP7eKVETzJW+IBAhsqbSu/g==} + peerDependencies: + '@dnd-kit/core': ^6.1.0 + react: '>=16.8.0' + + '@dnd-kit/utilities@3.2.2': + resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==} + peerDependencies: + react: '>=16.8.0' + '@emotion/babel-plugin@11.11.0': resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} @@ -3234,6 +3265,31 @@ snapshots: '@bufbuild/buf-win32-arm64': 1.31.0 '@bufbuild/buf-win32-x64': 1.31.0 + '@dnd-kit/accessibility@3.1.0(react@18.3.1)': + dependencies: + react: 18.3.1 + tslib: 2.6.2 + + '@dnd-kit/core@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@dnd-kit/accessibility': 3.1.0(react@18.3.1) + '@dnd-kit/utilities': 3.2.2(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + tslib: 2.6.2 + + '@dnd-kit/sortable@8.0.0(@dnd-kit/core@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': + dependencies: + '@dnd-kit/core': 6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@dnd-kit/utilities': 3.2.2(react@18.3.1) + react: 18.3.1 + tslib: 2.6.2 + + '@dnd-kit/utilities@3.2.2(react@18.3.1)': + dependencies: + react: 18.3.1 + tslib: 2.6.2 + '@emotion/babel-plugin@11.11.0': dependencies: '@babel/helper-module-imports': 7.24.3 diff --git a/web/src/components/MemoEditor/ResourceListView.tsx b/web/src/components/MemoEditor/ResourceListView.tsx index dd18a628..9275c413 100644 --- a/web/src/components/MemoEditor/ResourceListView.tsx +++ b/web/src/components/MemoEditor/ResourceListView.tsx @@ -1,6 +1,9 @@ +import { DndContext, closestCenter, MouseSensor, TouchSensor, useSensor, useSensors, DragEndEvent } from "@dnd-kit/core"; +import { arrayMove, SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable"; import { Resource } from "@/types/proto/api/v1/resource_service"; import Icon from "../Icon"; import ResourceIcon from "../ResourceIcon"; +import SortableItem from "./SortableItem"; interface Props { resourceList: Resource[]; @@ -9,33 +12,48 @@ interface Props { const ResourceListView = (props: Props) => { const { resourceList, setResourceList } = props; + const sensors = useSensors(useSensor(MouseSensor), useSensor(TouchSensor)); const handleDeleteResource = async (name: string) => { setResourceList(resourceList.filter((resource) => resource.name !== name)); }; + const handleDragEnd = (event: DragEndEvent) => { + const { active, over } = event; + + if (over && active.id !== over.id) { + const oldIndex = resourceList.findIndex((resource) => resource.name === active.id); + const newIndex = resourceList.findIndex((resource) => resource.name === over.id); + + setResourceList(arrayMove(resourceList, oldIndex, newIndex)); + } + }; + return ( - <> - {resourceList.length > 0 && ( -