Skip to content

Commit

Permalink
Merge pull request #435 from Decatur-Robotics/local-storage-db-interface
Browse files Browse the repository at this point in the history
LocalStorageDbInterface
  • Loading branch information
renatodellosso authored Feb 6, 2025
2 parents 2db79c7 + 850cb4f commit 31e988f
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 6 deletions.
57 changes: 57 additions & 0 deletions lib/client/dbinterfaces/LocalStorageDbInterface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { ObjectId } from "bson";
import CollectionId, { CollectionIdToType } from "@/lib/client/CollectionId";
import DbInterface, {
WithStringOrObjectIdId,
} from "@/lib/client/dbinterfaces/DbInterface";
import { default as BaseLocalStorageDbInterface } from "mongo-anywhere/LocalStorageDbInterface";

export default class LocalStorageDbInterface
extends BaseLocalStorageDbInterface<
CollectionId,
CollectionIdToType<CollectionId>
>
implements DbInterface
{
init(): Promise<void> {
return super.init(Object.values(CollectionId));
}
addObject<TId extends CollectionId, TObj extends CollectionIdToType<TId>>(
collection: TId,
object: WithStringOrObjectIdId<TObj>,
): Promise<TObj> {
return super.addObject(collection, object);
}
deleteObjectById(collection: CollectionId, id: ObjectId): Promise<void> {
return super.deleteObjectById(collection, id);
}
updateObjectById<
TId extends CollectionId,
TObj extends CollectionIdToType<TId>,
>(collection: TId, id: ObjectId, newValues: Partial<TObj>): Promise<void> {
return super.updateObjectById(collection, id, newValues);
}
findObjectById<
TId extends CollectionId,
TObj extends CollectionIdToType<TId>,
>(collection: TId, id: ObjectId): Promise<TObj | undefined> {
return super.findObjectById(collection, id);
}
findObject<TId extends CollectionId, TObj extends CollectionIdToType<TId>>(
collection: TId,
query: object,
): Promise<TObj | undefined> {
return super.findObject(collection, query);
}
findObjects<TId extends CollectionId, TObj extends CollectionIdToType<TId>>(
collection: TId,
query: object,
): Promise<TObj[]> {
return super.findObjects(collection, query);
}
countObjects(
collection: CollectionId,
query: object,
): Promise<number | undefined> {
return super.countObjects(collection, query);
}
}
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sj3",
"version": "1.1.18",
"version": "1.1.19",
"private": true,
"repository": "https://github.com/Decatur-Robotics/Gearbox",
"license": "CC BY-NC-SA 4.0",
Expand Down
192 changes: 192 additions & 0 deletions pages/dev/localstoragedb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import Container from "@/components/Container";
import CollectionId from "@/lib/client/CollectionId";
import LocalStorageDbInterface from "@/lib/client/dbinterfaces/LocalStorageDbInterface";
import { ObjectId } from "bson";
import { useEffect, useState } from "react";
import toast from "react-hot-toast";

export default function LocalStorageDb() {
const [db, setDb] = useState<LocalStorageDbInterface>();
const [collection, setCollection] = useState<CollectionId>();
const [json, setJson] = useState<string>();

const [dbData, setDbData] = useState<{ [collection: string]: object[] }>({});
const [flagCount, setFlagCount] = useState(0);

useEffect(() => {
const db = new LocalStorageDbInterface();
db.init().then(() => {
setDb(db);
updateDbData(db);
});
}, []);

async function updateDbData(db: LocalStorageDbInterface) {
if (!db) return;

const newDbData: { [collection: string]: object[] } = {};
await Promise.all(
Object.values(CollectionId).map(async (collection) => {
const objects = await db.findObjects(collection, {});
newDbData[collection] = objects;
}),
);
setDbData(newDbData);

const flaggedDocs: object[] = (
await Promise.all(
Object.values(CollectionId).map(
async (collection) =>
await db.findObjects(collection, { flagged: true }),
),
)
).flat();
setFlagCount(flaggedDocs.length);
}

async function addObject() {
if (!db || !collection || !json) return;

const obj = JSON.parse(json);

console.log("Adding object", obj, "to", collection);

try {
await db.addObject(collection, obj);
} catch (e: any) {
toast.error(e.message);
}
updateDbData(db);
}

async function deleteObject(collection: CollectionId, _id: ObjectId) {
if (!db) return;

console.log("Deleting object", _id.toString(), "from", collection);

await db.deleteObjectById(collection, _id);
updateDbData(db);
}

async function increment(collection: CollectionId, _id: ObjectId) {
if (!db) return;

console.log("Incrementing object", _id.toString(), "in", collection);

const object = await db.findObjectById(collection, _id);

if (!object) {
toast.error("Object not found:" + _id.toString());
return;
}

await db.updateObjectById(collection, _id, {
count: (object.count ?? 0) + 1,
});

updateDbData(db);
}

async function toggleFlag(collection: CollectionId, _id: ObjectId) {
if (!db) return;

console.log("Toggling flag on object", _id.toString(), "in", collection);

const object = await db.findObjectById(collection, _id);

if (!object) {
toast.error("Object not found:" + _id.toString());
return;
}

await db.updateObjectById(collection, _id, {
flagged: !object.flagged,
});

updateDbData(db);
}

return (
<Container
requireAuthentication={false}
title={"LocalStorage DB"}
>
<h1 className="text-xl">LocalStorage DB</h1>
<div className="flex flex-col">
<select
onChange={(e) => setCollection(e.target.value as CollectionId)}
defaultValue={"Select Collection"}
>
<option disabled>Select Collection</option>
{Object.keys(CollectionId).map((collection) => (
<option key={collection}>{collection}</option>
))}
</select>
<textarea
onChange={(e) => setJson(e.target.value)}
placeholder="Enter JSON..."
/>
<button
onClick={addObject}
className="btn btn-primary"
>
Add Object
</button>
</div>
<div className="divider" />
<div>
DB:{" "}
{db ? (
<span className="text-success">Ready</span>
) : (
<span className="text-error">Not ready</span>
)}
</div>
<div>Flagged docs: {flagCount}</div>
<div className="divider" />
<ul>
{db &&
Object.values(CollectionId).map((collection) => (
<li key={collection}>
<h2>{collection}</h2>
<ol className="ml-4">
{dbData[collection] &&
dbData[collection].map((object) => (
<li
key={JSON.stringify(object)}
className="flex items-center"
>
<div>{JSON.stringify(object)}</div>
<button
className="btn btn-warning btn-sm"
onClick={() =>
deleteObject(collection, (object as any)._id)
}
>
Delete
</button>
<button
className="btn btn-secondary btn-sm"
onClick={() =>
increment(collection, (object as any)._id)
}
>
Increment
</button>
<button
className="btn btn-secondary btn-sm"
onClick={() =>
toggleFlag(collection, (object as any)._id)
}
>
{(object as any).flagged ? "Unflag" : "Flag"}
</button>
</li>
))}
</ol>
</li>
))}
</ul>
</Container>
);
}

0 comments on commit 31e988f

Please sign in to comment.