Skip to content

Commit d5d1d64

Browse files
Pollepsjoepio
authored andcommitted
#682 #675 Proxy resources instead of clone for react
1 parent 6a8f200 commit d5d1d64

File tree

20 files changed

+158
-107
lines changed

20 files changed

+158
-107
lines changed

browser/data-browser/src/components/forms/InputResourceArray.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from 'react';
1+
import React, { useCallback, useState } from 'react';
22
import { ArrayError, useArray, validateDatatype } from '@tomic/react';
33
import { Button } from '../Button';
44
import { InputProps } from './ResourceField';
@@ -20,6 +20,7 @@ export default function InputResourceArray({
2020
validate: false,
2121
commit,
2222
});
23+
2324
/** Add focus to the last added item */
2425
const [lastIsNew, setLastIsNew] = useState(false);
2526

@@ -63,13 +64,16 @@ export default function InputResourceArray({
6364
[property.datatype, setArray],
6465
);
6566

66-
function errMaybe(index: number) {
67-
if (err && err.index === index) {
68-
return err;
69-
}
67+
const errMaybe = useCallback(
68+
(index: number) => {
69+
if (err && err.index === index) {
70+
return err;
71+
}
7072

71-
return undefined;
72-
}
73+
return undefined;
74+
},
75+
[err],
76+
);
7377

7478
return (
7579
<Column>

browser/data-browser/src/components/forms/InputSlug.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export default function InputSlug({
4646

4747
return (
4848
<Wrapper>
49-
<InputWrapper invalid={!!err}>
49+
<InputWrapper $invalid={!!err}>
5050
<InputStyled
5151
value={inputValue ?? ''}
5252
onChange={handleUpdate}

browser/data-browser/src/components/forms/InputString.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export default function InputString({
3636

3737
return (
3838
<Wrapper>
39-
<InputWrapper invalid={!!err}>
39+
<InputWrapper $invalid={!!err}>
4040
<InputStyled
4141
value={value === undefined ? '' : value}
4242
onChange={handleUpdate}

browser/data-browser/src/components/forms/InputStyles.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ export const LabelHelper = styled.label`
2121
`;
2222

2323
export interface InputWrapperProps {
24-
invalid?: boolean;
24+
$invalid?: boolean;
2525
}
2626

2727
/** A wrapper for inputs, for example when you want to add a button to some field */
2828
export const InputWrapper = styled.div<InputWrapperProps>`
2929
display: flex;
3030
flex: 1;
31-
--border-color: ${({ invalid, theme }) =>
32-
invalid ? theme.colors.alert : theme.colors.bg2};
31+
--border-color: ${({ $invalid, theme }) =>
32+
$invalid ? theme.colors.alert : theme.colors.bg2};
3333
border: solid 1px var(--border-color);
3434
border-radius: ${props => props.theme.radius};
3535
overflow: hidden;

browser/data-browser/src/components/forms/NewForm/NewFormDialog.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React, { useState, useCallback } from 'react';
33
import { useEffectOnce } from '../../../hooks/useEffectOnce';
44
import { Button } from '../../Button';
55
import { DialogTitle, DialogContent, DialogActions } from '../../Dialog';
6-
import { ErrorLook } from '../../ErrorLook';
6+
import { ErrorBlock, ErrorLook } from '../../ErrorLook';
77
import { useSaveResource } from '../hooks/useSaveResource';
88
import { InlineErrMessage } from '../InputStyles';
99
import { ResourceForm, ResourceFormVariant } from '../ResourceForm';
@@ -32,7 +32,7 @@ export const NewFormDialog = ({
3232
const [className] = useTitle(klass);
3333
const store = useStore();
3434

35-
const [subject, setSubject] = useState(store.createSubject());
35+
const [subject, setSubject] = useState<string>();
3636

3737
const { subjectErr, subjectValue, setSubjectValue, resource } = useNewForm({
3838
klass,
@@ -70,6 +70,10 @@ export const NewFormDialog = ({
7070
return <ErrorLook>No parent set</ErrorLook>;
7171
}
7272

73+
if (resource.error) {
74+
return <ErrorBlock error={resource.error}></ErrorBlock>;
75+
}
76+
7377
return (
7478
<>
7579
<DialogTitle>

browser/data-browser/src/components/forms/NewForm/NewFormPage.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@ export const NewFormFullPage = ({
1818
const [subject, setSubject] = useQueryString('newSubject');
1919
const [parentSubject] = useQueryString('parent');
2020

21-
const { subjectErr, subjectValue, setSubjectValue, resource } = useNewForm({
22-
klass,
23-
setSubject,
24-
initialSubject: subject,
25-
parent: parentSubject,
26-
});
21+
const { initialized, subjectErr, subjectValue, setSubjectValue, resource } =
22+
useNewForm({
23+
klass,
24+
setSubject,
25+
initialSubject: subject,
26+
parent: parentSubject,
27+
});
28+
29+
if (!initialized) return <>Initializing Resource</>;
2730

2831
return (
2932
<>

browser/data-browser/src/components/forms/NewForm/useNewForm.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
useResource,
77
useArray,
88
Core,
9+
core,
910
} from '@tomic/react';
1011
import { useState, useEffect } from 'react';
1112

@@ -23,6 +24,8 @@ export const useNewForm = (args: UseNewForm) => {
2324
const { klass, setSubject, initialSubject, parent } = args;
2425

2526
const store = useStore();
27+
const [initialized, setInitialized] = useState(false);
28+
2629
const [subjectValue, setSubjectValueInternal] = useState<string>(() => {
2730
if (initialSubject === undefined) {
2831
return store.createSubject(klass.props.shortname);
@@ -33,19 +36,23 @@ export const useNewForm = (args: UseNewForm) => {
3336

3437
const [subjectErr, setSubjectErr] = useState<Error | undefined>(undefined);
3538
const resource = useResource(subjectValue, resourseOpts);
36-
const [parentVal, setParent] = useString(resource, properties.parent);
37-
const [isAVal, setIsA] = useArray(resource, properties.isA);
39+
const [parentVal] = useString(resource, properties.parent);
40+
const [isAVal] = useArray(resource, properties.isA);
3841

3942
// When the resource is created or updated, make sure that the parent and class are present
4043
useEffect(() => {
41-
if (parentVal !== parent) {
42-
setParent(parent);
43-
}
44+
(async () => {
45+
if (parentVal !== parent) {
46+
await resource.set(core.properties.parent, parent, store);
47+
}
4448

45-
if (isAVal.length === 0) {
46-
setIsA([klass.getSubject()]);
47-
}
48-
}, [resource, parent]);
49+
if (isAVal.length === 0) {
50+
await resource.addClasses(store, klass.getSubject());
51+
}
52+
53+
setInitialized(true);
54+
})();
55+
}, [resource]);
4956

5057
async function setSubjectValue(newSubject: string) {
5158
setSubjectValueInternal(newSubject);
@@ -69,5 +76,6 @@ export const useNewForm = (args: UseNewForm) => {
6976
subjectValue,
7077
setSubjectValue,
7178
resource,
79+
initialized,
7280
};
7381
};

browser/data-browser/src/components/forms/RangeInput.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export function RangeInput({
7373

7474
return (
7575
<Row center gap='0.5rem'>
76-
<InputWrapper invalid={invalid}>
76+
<InputWrapper $invalid={invalid}>
7777
<InputStyled
7878
type='number'
7979
max={maxValue}
@@ -84,7 +84,7 @@ export function RangeInput({
8484
/>
8585
</InputWrapper>
8686
{' - '}
87-
<InputWrapper invalid={invalid}>
87+
<InputWrapper $invalid={invalid}>
8888
<InputStyled
8989
type='number'
9090
placeholder='max'

browser/data-browser/src/components/forms/SearchBox/SearchBox.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export function SearchBox({
8080
onChange(newValue);
8181
setInputValue('');
8282
} catch (e) {
83+
console.error(e);
8384
// not a URL
8485
}
8586

@@ -129,7 +130,7 @@ export function SearchBox({
129130
disabled={disabled}
130131
ref={triggerRef}
131132
tabIndex={0}
132-
empty={inputValue.length === 0}
133+
$empty={inputValue.length === 0}
133134
onFocus={handleTriggerFocus}
134135
onClick={() => {
135136
setOpen(true);
@@ -182,7 +183,7 @@ export function SearchBox({
182183
);
183184
}
184185

185-
const TriggerButton = styled.button<{ empty: boolean }>`
186+
const TriggerButton = styled.button<{ $empty: boolean }>`
186187
display: flex;
187188
align-items: center;
188189
padding: 0.5rem;
@@ -194,7 +195,7 @@ const TriggerButton = styled.button<{ empty: boolean }>`
194195
width: 100%;
195196
overflow: hidden;
196197
cursor: text;
197-
color: ${p => (p.empty ? p.theme.colors.textLight : p.theme.colors.text)};
198+
color: ${p => (p.$empty ? p.theme.colors.textLight : p.theme.colors.text)};
198199
199200
&:disabled {
200201
background-color: ${props => props.theme.colors.bg1};

browser/data-browser/src/components/forms/SearchBox/SearchBoxWindow.tsx

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { urls, useServerSearch } from '@tomic/react';
1+
import { core, useServerSearch } from '@tomic/react';
22
import React, { useMemo, useState } from 'react';
33
import styled, { css } from 'styled-components';
44
import { ResourceResultLine, ResultLine } from './ResultLine';
@@ -40,23 +40,22 @@ export function SearchBoxWindow({
4040
const [realIndex, setIndex] = useState<number | undefined>(undefined);
4141
const { below } = useAvailableSpace(true, triggerRef);
4242
const wrapperRef = React.useRef<HTMLDivElement>(null);
43-
const filters = useMemo(
43+
44+
const searchOptions = useMemo(
4445
() => ({
45-
...(isA ? { [urls.properties.isA]: isA } : {}),
46+
filters: {
47+
...(isA ? { [core.properties.isA]: isA } : {}),
48+
},
49+
parents: scopes ?? [drive, 'https://atomicdata.dev'],
4650
}),
47-
[isA],
51+
[isA, scopes],
4852
);
4953

50-
const parents = useMemo(
51-
() => scopes ?? [drive, 'https://atomicdata.dev'],
52-
[scopes],
54+
const { results, error: searchError } = useServerSearch(
55+
searchValue,
56+
searchOptions,
5357
);
5458

55-
const { results } = useServerSearch(searchValue, {
56-
filters,
57-
parents,
58-
});
59-
6059
const isAboveTrigger = below < remToPixels(BOX_HEIGHT_REM);
6160

6261
const offset = onCreateItem ? 1 : 0;
@@ -156,8 +155,16 @@ export function SearchBoxWindow({
156155
}
157156
};
158157

158+
if (searchError) {
159+
return (
160+
<Wrapper onBlur={handleBlur} ref={wrapperRef} $above={isAboveTrigger}>
161+
<CenteredMessage>Error: {searchError.message}</CenteredMessage>
162+
</Wrapper>
163+
);
164+
}
165+
159166
return (
160-
<Wrapper onBlur={handleBlur} ref={wrapperRef} above={isAboveTrigger}>
167+
<Wrapper onBlur={handleBlur} ref={wrapperRef} $above={isAboveTrigger}>
161168
<Input
162169
autoFocus
163170
placeholder={placeholder}
@@ -220,7 +227,7 @@ const ResultBox = styled.div`
220227
overflow: hidden;
221228
`;
222229

223-
const Wrapper = styled.div<{ above: boolean }>`
230+
const Wrapper = styled.div<{ $above: boolean }>`
224231
display: flex;
225232
226233
background-color: ${p => p.theme.colors.bg};
@@ -230,8 +237,8 @@ const Wrapper = styled.div<{ above: boolean }>`
230237
height: ${BOX_HEIGHT_REM}rem;
231238
position: absolute;
232239
width: var(--radix-popover-trigger-width);
233-
${({ above, theme }) =>
234-
above
240+
${({ $above, theme }) =>
241+
$above
235242
? css`
236243
bottom: 0;
237244
flex-direction: column-reverse;

0 commit comments

Comments
 (0)