String IDs.

pull/24/head
Sander Vocke 5 years ago
parent cdccfc4551
commit 52865497cd
  1. 1246
      client/package-lock.json
  2. 5
      client/package.json
  3. 18
      client/src/components/windows/manage_tags/ManageTagMenu.tsx
  4. 42
      client/src/components/windows/manage_tags/ManageTagsWindow.tsx
  5. 44
      client/src/components/windows/manage_tags/TagChange.tsx

File diff suppressed because it is too large Load Diff

@ -24,8 +24,9 @@
"react-dnd-html5-backend": "^11.1.3",
"react-dom": "^16.13.1",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.1",
"typescript": "~3.7.2"
"react-scripts": "^3.4.3",
"typescript": "~3.7.2",
"uuid": "^8.3.0"
},
"scripts": {
"dev": "BROWSER=none react-scripts start",

@ -29,7 +29,7 @@ export function PickTag(props: {
tags: any[]
open: boolean
root: boolean
onPick: (v: number | null) => void
onPick: (v: string | null) => void
}) {
return <>
@ -39,28 +39,27 @@ export function PickTag(props: {
return <NestedMenuItem
parentMenuOpen={props.open}
label={tag.name}
onClick={() => props.onPick(tag.tagId)}
onClick={() => props.onPick(tag.tagId.toString())}
>
<PickTag tags={tag.children} open={props.open} root={false} onPick={props.onPick} />
</NestedMenuItem>
}
return <MenuItem onClick={() => props.onPick(tag.tagId)}>{tag.name}</MenuItem>
return <MenuItem onClick={() => props.onPick(tag.tagId.toString())}>{tag.name}</MenuItem>
})
}</>
}
export interface IProps {
export default function ManageTagMenu(props: {
position: null | number[],
open: boolean,
onClose: () => void,
onRename: (s: string) => void,
onDelete: () => void,
onMove: (to: number | null) => void,
onMove: (to: string | null) => void,
onCreateChild: (name: string) => void,
tag: any,
changedTags: any[], // Tags organized hierarchically with "children" fields
}
export default function ManageTagMenu(props: IProps) {
}) {
const pos = props.open && props.position ?
{ left: props.position[0], top: props.position[1] }
: { left: 0, top: 0 }
@ -94,8 +93,7 @@ export default function ManageTagMenu(props: IProps) {
parentMenuOpen={props.open}
label="Move to"
>
<PickTag tags={props.changedTags} open={props.open} root={true} onPick={(v: number | null) => {
console.log("onPick:", v)
<PickTag tags={props.changedTags} open={props.open} root={true} onPick={(v: string | null) => {
props.onClose();
props.onMove(v);
}} />

@ -11,7 +11,10 @@ import { queryTags } from '../../../lib/query/Backend';
var _ = require('lodash');
export interface ManageTagsWindowState extends WindowState {
fetchedTags: Record<number, any> | null,
// Tags are indexed by a string ID. This can be a stringified MuDBase ID integer,
// or a UID for tags which only exist in the front-end and haven't been committed
// to the database.
fetchedTags: Record<string, any> | null,
pendingChanges: TagChange[],
}
@ -37,7 +40,7 @@ export function ManageTagsWindowReducer(state: ManageTagsWindowState, action: an
}
}
export function organiseTags(allTags: Record<number, any>, fromId: number | null): any[] {
export function organiseTags(allTags: Record<string, any>, fromId: string | null): any[] {
const base = Object.values(allTags).filter((tag: any) => {
var par: any = ("proposedParent" in tag) ? tag.proposedParent : tag.parentId;
@ -55,14 +58,21 @@ export function organiseTags(allTags: Record<number, any>, fromId: number | null
export async function getAllTags() {
return (async () => {
var retval: Record<number, any> = {};
var retval: Record<string, any> = {};
const tags = await queryTags({
query: undefined,
offset: 0,
limit: -1,
});
// Convert numeric IDs to string IDs because that is
// what we work with within this component.
tags.forEach((tag: any) => {
retval[tag.tagId] = tag;
retval[tag.tagId.toString()] = {
...tag,
tagId: tag.tagId && tag.tagId.toString(),
parentId: tag.parentId && tag.parentId.toString(),
childIds: tag.childIds && tag.childIds.map((c: number) => c.toString()),
}
});
return retval;
})();
@ -156,7 +166,7 @@ export function SingleTag(props: {
]
})
}}
onMove={(to: number | null) => {
onMove={(to: string | null) => {
props.dispatch({
type: ManageTagsWindowActions.SetPendingChanges,
value: [
@ -168,6 +178,9 @@ export function SingleTag(props: {
}
]
})
}}
onCreateChild={(name: string) => {
}}
tag={tag}
changedTags={props.changedTags}
@ -175,10 +188,10 @@ export function SingleTag(props: {
</>
}
function annotateTagsWithChanges(tags: Record<number, any>, changes: TagChange[]) {
var retval = _.cloneDeep(tags);
function annotateTagsWithChanges(tags: Record<string, any>, changes: TagChange[]) {
var retval: Record<string, any> = tags;
const applyDelete = (id: number) => {
const applyDelete = (id: string) => {
retval[id].proposeDelete = true;
Object.values(tags).filter((t: any) => t.parentId === id)
.forEach((child: any) => applyDelete(child.tagId));
@ -202,10 +215,10 @@ function annotateTagsWithChanges(tags: Record<number, any>, changes: TagChange[]
return retval;
}
function applyTagsChanges(tags: Record<number, any>, changes: TagChange[]) {
function applyTagsChanges(tags: Record<string, any>, changes: TagChange[]) {
var retval = _.cloneDeep(tags);
const applyDelete = (id: number) => {
const applyDelete = (id: string) => {
Object.values(tags).filter((t: any) => t.parentId === id)
.forEach((child: any) => applyDelete(child.tagId));
delete retval[id].proposeDelete;
@ -230,13 +243,11 @@ function applyTagsChanges(tags: Record<number, any>, changes: TagChange[]) {
return retval;
}
export interface IProps {
export default function ManageTagsWindow(props: {
state: ManageTagsWindowState,
dispatch: (action: any) => void,
mainDispatch: (action: any) => void,
}
export default function ManageTagsWindow(props: IProps) {
}) {
useEffect(() => {
if (props.state.fetchedTags !== null) {
return;
@ -284,7 +295,8 @@ export default function ManageTagsWindow(props: IProps) {
type: ManageTagsWindowActions.SetPendingChanges,
value: [],
})}
onSave={() => {}}
onSave={() => { }}
getTagDetails={(id: string) => tagsWithChanges[id]}
/>
</Box>}
<Box

@ -15,48 +15,19 @@ export enum TagChangeType {
export interface TagChange {
type: TagChangeType,
id: number, // MuDBase ID. If not in database yet, negative IDs will be used until submitted.
parent?: number | null, // MuDBase ID. If not in database yet, negative IDs will be used until submitted.
id: string, // Stringified integer == MuDBase ID. Other string == not yet committed to DB.
parent?: string | null, // Stringified integer == MuDBase ID. Other string == not yet committed to DB.
// null refers to the tags root.
name?: string,
}
export async function getTag(id: number) {
return (await queryTags({
query: {
a: QueryLeafBy.TagId,
b: id,
leafOp: QueryLeafOp.Equals,
},
offset: 0,
limit: 1,
}))[0];
}
export function TagChangeDisplay(props: {
change: TagChange,
getTagDetails: (id: string) => any,
}) {
const [tag, setTag] = useState<any>(undefined);
const [oldParent, setOldParent] = useState<any>(undefined);
const [newParent, setNewParent] = useState<any>(undefined);
useEffect(() => {
getTag(props.change.id).then((tag: any) => {
if (tag.parentId) {
getTag(tag.parentId).then((parent: any) => setOldParent(parent));
} else {
setOldParent(null);
}
setTag(tag);
})
if (props.change.type === TagChangeType.MoveTo) {
if (props.change.parent) {
getTag(props.change.parent).then((tag: any) => setNewParent(tag));
} else {
setNewParent(null);
}
}
}, [props.change.id]);
const tag = props.getTagDetails(props.change.id);
const oldParent = tag.parentId ? props.getTagDetails(tag.parentId.toString()) : null;
const newParent = props.change.parent ? props.getTagDetails(props.change.parent) : null;
const MakeTag = (props: { name: string }) => <Chip label={props.name} />
const MainTag = tag ?
@ -88,6 +59,7 @@ export default function ControlTagChanges(props: {
changes: TagChange[],
onSave: () => void,
onDiscard: () => void,
getTagDetails: (id: string) => any,
}) {
return <Box display="flex"><Paper style={{ padding: 10, minWidth: 0 }}>
<Typography variant="h5">Pending changes</Typography>
@ -95,7 +67,7 @@ export default function ControlTagChanges(props: {
{props.changes.map((change: any) =>
<Box display="flex">
<Typography>-&nbsp;</Typography>
<TagChangeDisplay change={change} />
<TagChangeDisplay change={change} getTagDetails={props.getTagDetails} />
</Box>
)}
</Box>

Loading…
Cancel
Save