settled on typings. Now working on ui interaction flow.
This commit is contained in:
27
src/components/LibraryItem.tsx
Normal file
27
src/components/LibraryItem.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import { Composable } from "./IComposable";
|
||||
import { LibraryItem as LibItem } from "../lib/prompt";
|
||||
import AddCircleOutlineOutlinedIcon from '@mui/icons-material/AddCircleOutlineOutlined';
|
||||
import { Button } from "@material-ui/core";
|
||||
|
||||
export interface StyleProps {
|
||||
item: LibItem
|
||||
onAddItem: (item: LibItem) => void;
|
||||
}
|
||||
|
||||
export function LibraryItem(props: StyleProps) {
|
||||
const { item, onAddItem } = props
|
||||
return (
|
||||
<div>
|
||||
<Button onClick={() => onAddItem(item)}>
|
||||
<AddCircleOutlineOutlinedIcon/>
|
||||
</Button>
|
||||
<span>
|
||||
{
|
||||
item.name ? (
|
||||
<div className={`catetory-${item.category}`}>{item.name} - {item.prompt}</div>
|
||||
) : (<div>{item.prompt}</div>)
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
) as Composable;
|
||||
};
|
@ -2,6 +2,7 @@ import { Button, ButtonGroup, Chip, Divider } from '@material-ui/core';
|
||||
import React, { Component, useState } from 'react';
|
||||
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
|
||||
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowUp';
|
||||
import {Composable} from "./IComposable"
|
||||
|
||||
import "./Nugget.css";
|
||||
|
||||
@ -23,5 +24,5 @@ export default function Nugget({ text, initialScore }: { text: string, initialSc
|
||||
</ButtonGroup>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
) as Composable;
|
||||
}
|
@ -3,69 +3,70 @@ import React, { Children, ReactNode } from 'react';
|
||||
import "./Operation.css";
|
||||
import { Op } from "../lib/operator";
|
||||
import { randomUUID } from "crypto";
|
||||
import { Composable } from "./IComposable";
|
||||
|
||||
|
||||
function Operation({ children, initialOp }: { children: ReactNode[], initialOp: Op}) {
|
||||
const [op, setOp] = React.useState(initialOp);
|
||||
const [contextMenu, setContextMenu] = React.useState<{
|
||||
mouseX: number;
|
||||
mouseY: number;
|
||||
} | null>(null);
|
||||
function Operation({ children, initialOp }: { children: ReactNode[], initialOp: Op }) {
|
||||
const [op, setOp] = React.useState(initialOp);
|
||||
const [contextMenu, setContextMenu] = React.useState<{
|
||||
mouseX: number;
|
||||
mouseY: number;
|
||||
} | null>(null);
|
||||
|
||||
const [id, ] = React.useState(randomUUID);
|
||||
const [id,] = React.useState(randomUUID);
|
||||
|
||||
const handleContextMenu = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
setContextMenu(
|
||||
contextMenu === null
|
||||
? {
|
||||
mouseX: event.clientX + 2,
|
||||
mouseY: event.clientY - 6,
|
||||
}
|
||||
: // repeated contextmenu when it is already open closes it with Chrome 84 on Ubuntu
|
||||
// Other native context menus might behave different.
|
||||
// With this behavior we prevent contextmenu from the backdrop to re-locale existing context menus.
|
||||
null,
|
||||
);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setContextMenu(null);
|
||||
};
|
||||
const handleContextMenu = (event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
setContextMenu(
|
||||
contextMenu === null
|
||||
? {
|
||||
mouseX: event.clientX + 2,
|
||||
mouseY: event.clientY - 6,
|
||||
}
|
||||
: // repeated contextmenu when it is already open closes it with Chrome 84 on Ubuntu
|
||||
// Other native context menus might behave different.
|
||||
// With this behavior we prevent contextmenu from the backdrop to re-locale existing context menus.
|
||||
null,
|
||||
);
|
||||
};
|
||||
|
||||
const changeOperator = (opV : string) => {
|
||||
setOp(opV as unknown as Op);
|
||||
handleClose();
|
||||
}
|
||||
const handleClose = () => {
|
||||
setContextMenu(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="operation" onContextMenu={handleContextMenu}>
|
||||
<div className="title">{op}</div>
|
||||
<div className="nuggets">
|
||||
{Children.map(children, child => {
|
||||
return (<div>
|
||||
{child}
|
||||
</div>)
|
||||
})}
|
||||
</div>
|
||||
<Menu
|
||||
open={contextMenu !== null}
|
||||
onClose={handleClose}
|
||||
anchorReference="anchorPosition"
|
||||
anchorPosition={
|
||||
contextMenu !== null
|
||||
? { top: contextMenu.mouseY, left: contextMenu.mouseX }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{Object.values(Op).map((v) => {
|
||||
return (
|
||||
<MenuItem onClick={() => changeOperator(v)}>{v}</MenuItem>
|
||||
)
|
||||
})}
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
const changeOperator = (opV: string) => {
|
||||
setOp(opV as unknown as Op);
|
||||
handleClose();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="operation" onContextMenu={handleContextMenu}>
|
||||
<div className="title">{op}</div>
|
||||
<div className="nuggets">
|
||||
{Children.map(children, child => {
|
||||
return (<div>
|
||||
{child}
|
||||
</div>)
|
||||
})}
|
||||
</div>
|
||||
<Menu
|
||||
open={contextMenu !== null}
|
||||
onClose={handleClose}
|
||||
anchorReference="anchorPosition"
|
||||
anchorPosition={
|
||||
contextMenu !== null
|
||||
? { top: contextMenu.mouseY, left: contextMenu.mouseX }
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{Object.values(Op).map((v) => {
|
||||
return (
|
||||
<MenuItem onClick={() => changeOperator(v)}>{v}</MenuItem>
|
||||
)
|
||||
})}
|
||||
</Menu>
|
||||
</div>
|
||||
) as Composable;
|
||||
}
|
||||
|
||||
export { Operation, Op };
|
@ -18,9 +18,13 @@ export default function PromptArea({ children }: { children?: any }) {
|
||||
|
||||
const handleClose = (value: string) => {
|
||||
setOpen(false);
|
||||
setSelectedValue(value);
|
||||
// setSelectedValue(value);
|
||||
};
|
||||
|
||||
const handleComposableClicked = (composable : Composable) => {
|
||||
setSelectedComposable(composable);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button className="add-button">
|
||||
|
@ -1,42 +1,36 @@
|
||||
import { Dialog, DialogTitle, List, ListItem, ListItemAvatar, Avatar, ListItemText } from "@material-ui/core";
|
||||
import { blue } from "@material-ui/core/colors";
|
||||
import ListItemButton from "@mui/material/ListItemButton";
|
||||
|
||||
export type Category = {
|
||||
id: string,
|
||||
label: string,
|
||||
color?: string,
|
||||
}
|
||||
|
||||
const categories = [
|
||||
{ id: "style", label: "Styles", color: "blue" },
|
||||
{ id: "subject", label: "Subjects", color: "black" },
|
||||
{ id: "vibes", label: "Vibes", color: "gold" },
|
||||
{ id: "mediums", label: "Mediums", color: "black" },
|
||||
] as Category[];
|
||||
import { Dialog, DialogTitle } from "@material-ui/core";
|
||||
import { Composable } from "./IComposable";
|
||||
import { Library as PromptLibraryType, LibraryItem as LibItemType } from "../lib/prompt";
|
||||
import { LibraryItem } from "./LibraryItem";
|
||||
|
||||
export interface SimpleDialogProps {
|
||||
open: boolean;
|
||||
selectedValue: string;
|
||||
onClose: (value: string) => void;
|
||||
onClose: (composable: Composable) => void,
|
||||
library: PromptLibraryType,
|
||||
onAddItem : (item : LibItemType) => void,
|
||||
}
|
||||
|
||||
export function PromptLibrary(props: SimpleDialogProps) {
|
||||
const { onClose, selectedValue, open } = props;
|
||||
const { onClose, library, open, onAddItem } = props;
|
||||
|
||||
const handleClose = () => {
|
||||
onClose(selectedValue);
|
||||
// onClose(selectedValue);
|
||||
};
|
||||
|
||||
const handleNuggetClick = (value: string) => {
|
||||
onClose(value);
|
||||
const handleNuggetClick = (composable : Composable) => {
|
||||
onClose(composable);
|
||||
};
|
||||
|
||||
const handleOnAddItem = (item : LibItemType) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog onClose={handleClose} open={open}>
|
||||
<DialogTitle>Prompt Library</DialogTitle>
|
||||
<div>
|
||||
Prompt Library
|
||||
{
|
||||
library.map(item => <LibraryItem item={item} onAddItem={handleOnAddItem} />)
|
||||
}
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
|
113
src/lib/prompt.ts
Normal file
113
src/lib/prompt.ts
Normal file
@ -0,0 +1,113 @@
|
||||
import { nSQL } from "@nano-sql/core";
|
||||
import { Op } from "./operator";
|
||||
import { RocksDB } from "@nano-sql/adapter-rocksdb";
|
||||
import tables from "./schema.json";
|
||||
import { uuid } from "@nano-sql/core/lib/utilities";
|
||||
|
||||
type Id = string;
|
||||
|
||||
type IdAble = {
|
||||
id: Id,
|
||||
}
|
||||
|
||||
export enum Category {
|
||||
subject = "subject",
|
||||
style = "style",
|
||||
vibes = "vibes",
|
||||
medium = "medium",
|
||||
}
|
||||
|
||||
export type LibraryItem = {
|
||||
id: Id,
|
||||
name?: string,
|
||||
prompt: string,
|
||||
category: Category,
|
||||
}
|
||||
|
||||
export type Library = Array<LibraryItem>;
|
||||
|
||||
export type Nugget = IdAble & {
|
||||
item: LibraryItem,
|
||||
score: number,
|
||||
}
|
||||
|
||||
export type Operation = IdAble & {
|
||||
op: Op,
|
||||
items: Array<Nugget>
|
||||
}
|
||||
|
||||
export type PromptItem = Operation | Nugget
|
||||
|
||||
export type PromptArea = Array<PromptItem>;
|
||||
|
||||
export async function getDb() {
|
||||
return new Promise((resolve, reject) => {
|
||||
// typical setup
|
||||
nSQL().createDatabase({
|
||||
id: "my_db", // can be anything that's a string
|
||||
mode: new RocksDB(),
|
||||
tables: [
|
||||
{
|
||||
"name": "library_item",
|
||||
"model": {
|
||||
"id:uuid": { "pk": true },
|
||||
"name:string": {},
|
||||
"prompt:string": { notNull: true },
|
||||
"category:string": { notNull: true, }
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nugget",
|
||||
"model": {
|
||||
"id:uuid": { "pk": true },
|
||||
"library_item:uuid": {},
|
||||
"score:number": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "operation",
|
||||
"model": {
|
||||
"id:uuid": { pk: true },
|
||||
"op:string": {},
|
||||
"items:array": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "library",
|
||||
"model": {
|
||||
"item:uuid": {},
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "prompt_area",
|
||||
"model": {
|
||||
"type:string": {notNull: true},
|
||||
"item:obj": {notNull: true},
|
||||
}
|
||||
}
|
||||
],
|
||||
version: 1, // current schema/database version
|
||||
onVersionUpdate: (prevVersion) => { // migrate versions
|
||||
return new Promise((res, rej) => {
|
||||
switch (prevVersion) {
|
||||
case 1:
|
||||
// migrate v1 to v2
|
||||
res(2);
|
||||
break;
|
||||
case 2:
|
||||
// migrate v2 to v3
|
||||
res(3);
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}).then((db) => {
|
||||
resolve(db)
|
||||
}).catch((err) => {
|
||||
reject(err);
|
||||
})
|
||||
});
|
||||
|
||||
}
|
27
src/lib/schema.json
Normal file
27
src/lib/schema.json
Normal file
@ -0,0 +1,27 @@
|
||||
[
|
||||
{
|
||||
"name": "library_item",
|
||||
"model": {
|
||||
"id:uuid": {"pk": true},
|
||||
"name:string": {},
|
||||
"prompt:string": {},
|
||||
"type:string": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nugget",
|
||||
"model": {
|
||||
"id:uuid": {"pk": true},
|
||||
"library_item:uuid": {},
|
||||
"score:number": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "operation",
|
||||
"model": {
|
||||
"id:uuid": {"pk": true},
|
||||
"op:string": {},
|
||||
"items:array": {}
|
||||
}
|
||||
}
|
||||
]
|
Reference in New Issue
Block a user