Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#98 parse nested resources & resource status #99

Merged
merged 12 commits into from
Oct 24, 2021
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
# Changelog

This changelog covers all three packges, as they are (for now) updated as a whole
This changelog covers all three packages, as they are (for now) updated as a whole

## v0.27.0

- Parse nested, named JSON-AD resources #98
- Refactor resource status - remove `Resource.status`, prefer `.loading` and `.error`
- Add loading and error status to Property class, include in `useProperty`
- Improve loading and error states for various components
- Refactor `store.getResourceLoading`, `store.fetchResource`, `useResource` - add option to `acceptIncomplete`.

## v0.26.2

Expand Down
2 changes: 1 addition & 1 deletion data-browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"lerna": "^4.0.0",
"lint-staged": "^10.5.4",
"pretty-quick": "^3.1.0",
"snowpack": "^3.3.5",
"snowpack": "^3.8.8",
"typescript": "^4.2.4"
},
"homepage": "https://joepio.github.io/atomic-data-browser/",
Expand Down
4 changes: 0 additions & 4 deletions data-browser/src/components/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ function AtomicLink({
}: Props): JSX.Element {
const [currentUrl] = useCurrentSubject();
const history = useHistory();
const store = useStore();
if (subject) {
store.fetchResource(subject);
}

if (!subject && !href) {
return <ErrorLook>No subject or href passed to this AtomicLink.</ErrorLook>;
Expand Down
24 changes: 20 additions & 4 deletions data-browser/src/components/PropVal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { truncateUrl, Resource } from '@tomic/lib';
import { truncateUrl, Resource, Datatype } from '@tomic/lib';
import { useProperty } from '@tomic/react';
import React from 'react';
import styled from 'styled-components';
Expand Down Expand Up @@ -47,12 +47,28 @@ function PropVal({
columns,
}: Props): JSX.Element {
const property = useProperty(propertyURL);
const truncated = truncateUrl(propertyURL, 10, true);

if (property == null) {
return null;
if (property.loading) {
return (
<PropValRow columns={columns}>
<PropertyLabel title={propertyURL + ' is loading'}>
loading...
</PropertyLabel>
</PropValRow>
);
}

const truncated = truncateUrl(propertyURL, 10, true);
if (property.error) {
return (
<PropValRow columns={columns}>
<PropertyLabel title={propertyURL + ' could not be loaded'}>
<ErrorLook>{truncated}</ErrorLook>
</PropertyLabel>
<code>{JSON.stringify(resource.get(propertyURL))}</code>
</PropValRow>
);
}

return (
<PropValRow columns={columns}>
Expand Down
21 changes: 13 additions & 8 deletions data-browser/src/components/ResourceSideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { useString, useResource, useTitle } from '@tomic/react';
import { ResourceStatus, urls } from '@tomic/lib';
import { urls } from '@tomic/lib';
import { ErrorLook } from '../views/ResourceInline';
import { useHistory } from 'react-router-dom';
import { useCurrentSubject } from '../helpers/useCurrentSubject';
Expand All @@ -14,7 +14,7 @@ type Props = {

/** Renders a Resource in a bar for the sidebar. */
export function ResourceSideBar({ subject, handleClose }: Props): JSX.Element {
const [resource] = useResource(subject);
const [resource] = useResource(subject, { allowIncomplete: true });
const [currentUrl] = useCurrentSubject();
const title = useTitle(resource);
const [description] = useString(resource, urls.properties.description);
Expand All @@ -36,15 +36,20 @@ export function ResourceSideBar({ subject, handleClose }: Props): JSX.Element {
}
};

const status = resource.getStatus();
if (status == ResourceStatus.loading) {
if (resource.loading) {
return (
<span about={subject} title={`${subject} is loading..`}>
...
</span>
<SideBarItem
clean
onClick={handleClick}
disabled={active}
resource={subject}
title={`${subject} is loading...`}
>
loading...
</SideBarItem>
);
}
if (status == ResourceStatus.error) {
if (resource.error) {
return (
<SideBarItem
clean
Expand Down
6 changes: 3 additions & 3 deletions data-browser/src/components/SideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import styled from 'styled-components';
import * as React from 'react';
import { useArray, useResource, useStore, useTitle } from '@tomic/react';
import { properties, ResourceStatus } from '@tomic/lib';
import { useArray, useResource, useTitle } from '@tomic/react';
import { properties } from '@tomic/lib';
import { useHover } from '../helpers/useHover';
import { useSettings } from '../helpers/AppSettings';
import { useWindowSize } from '../helpers/useWindowSize';
Expand Down Expand Up @@ -206,7 +206,7 @@ function SideBarDrive({ handleClickItem }: SideBarDriveProps): JSX.Element {
/>
);
})
) : drive.getStatus() == ResourceStatus.loading ? null : (
) : drive.loading ? null : (
<SideBarErr>
{drive.getError()?.message || 'Could not load this baseURL'}
</SideBarErr>
Expand Down
4 changes: 2 additions & 2 deletions data-browser/src/components/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function Table({ resource, members, columns }: TableProps): JSX.Element {
// Don't show the shortname, it's already shown in the first row.
const propsArray = columns.filter(item => item !== urls.properties.shortname);

if (resource == null) {
if (resource === null) {
return null;
}

Expand Down Expand Up @@ -124,7 +124,7 @@ type RowProps = {

function Row({ subject, propsArray }: RowProps): JSX.Element {
const [resource] = useResource(subject);
if (resource == null) {
if (resource === null) {
return null;
}
return (
Expand Down
4 changes: 2 additions & 2 deletions data-browser/src/components/forms/InputNumber.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ export default function InputNumber({
<InputStyled
placeholder='Enter a number...'
type='number'
value={value == null ? '' : Number.isNaN(value) ? '' : value}
value={value === null ? '' : Number.isNaN(value) ? '' : value}
onChange={handleUpdate}
{...props}
/>
</InputWrapper>
{value !== null && err && <ErrMessage>{err.message}</ErrMessage>}
{value == null && <ErrMessage>Required</ErrMessage>}
{value === null && <ErrMessage>Required</ErrMessage>}
</>
);
}
2 changes: 1 addition & 1 deletion data-browser/src/components/forms/ResourceField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function ResourceField({
const property = useProperty(propertyURL);
const [collapsedDynamic, setCollapsedDynamic] = useState(true);

if (property == null) {
if (property === null) {
return (
<Field label='loading...'>
<InputWrapper>
Expand Down
18 changes: 5 additions & 13 deletions data-browser/src/components/forms/ResourceForm.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import React, { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import {
Resource,
ResourceStatus,
classes,
properties,
urls,
} from '@tomic/lib';
import { Resource, classes, properties, urls } from '@tomic/lib';
import {
useArray,
useCanWrite,
Expand Down Expand Up @@ -51,8 +45,6 @@ export function ResourceForm({
}
const [klass] = useResource(classSubject);
const store = useStore();
const resourceStatus = resource.getStatus();
const classStatus = klass.getStatus();
const [requires] = useArray(klass, properties.requires);
const [recommends] = useArray(klass, properties.recommends);
const [klassIsa] = useString(klass, properties.isA);
Expand Down Expand Up @@ -117,13 +109,13 @@ export function ResourceForm({
// array changes, but that leads to a weird loop, so that's what the length is for
}, [resource, tempOtherProps, requires.length, recommends.length]);

if (resourceStatus == ResourceStatus.loading) {
if (!resource.new && resource.loading) {
return <>Loading resource...</>;
}
if (resourceStatus == ResourceStatus.error) {
if (resource.error) {
return <ErrMessage>{resource.getError().message}</ErrMessage>;
}
if (classStatus == ResourceStatus.loading) {
if (klass.loading) {
return <>Loading class...</>;
}
if (klassIsa && klassIsa !== classes.class) {
Expand Down Expand Up @@ -182,7 +174,7 @@ export function ResourceForm({

return (
<form about={resource.getSubject()}>
{classStatus == ResourceStatus.error && (
{klass.error && (
<ErrMessage>
Error in class. {klass.getError().message}. You can still edit the
resource, though.
Expand Down
2 changes: 1 addition & 1 deletion data-browser/src/components/forms/ValueForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function ValueForm({
const [err, setErr] = useState<Error>(null);
const haveAgent = agent !== null;

if (!value) {
if (value === null) {
return null;
}

Expand Down
2 changes: 1 addition & 1 deletion data-browser/src/helpers/AppSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const AppSettingsContextProvider = (
try {
setAgent(agent);
agent?.subject && toast.success('Signed in!');
agent == null && toast.success('Signed out.');
agent === null && toast.success('Signed out.');
} catch (e) {
toast.error('Agent setting failed: ' + e.message);
console.log(e);
Expand Down
8 changes: 3 additions & 5 deletions data-browser/src/routes/DataRoute.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { useState } from 'react';
import { useResource, useStore } from '@tomic/react';
import { ResourceStatus } from '@tomic/lib';
import AllProps from '../components/AllProps';
import { ContainerNarrow } from '../components/Containers';
import AtomicLink from '../components/Link';
Expand All @@ -14,16 +13,15 @@ import { ErrMessage } from '../components/forms/InputStyles';
function Data(): JSX.Element {
const [subject] = useCurrentSubject();
const [resource] = useResource(subject);
const status = resource.getStatus();
const [textResponse, setTextResponse] = useState(null);
const [isCopied, setIsCopied] = useState(false);
const [err, setErr] = useState(null);
const store = useStore();

if (status == ResourceStatus.loading) {
return <ContainerNarrow>Loading...</ContainerNarrow>;
if (resource.loading) {
return <ContainerNarrow>Loading {subject}...</ContainerNarrow>;
}
if (status == ResourceStatus.error) {
if (resource.error) {
return <ContainerNarrow>{resource.getError().message}</ContainerNarrow>;
}

Expand Down
2 changes: 2 additions & 0 deletions data-browser/src/routes/EditRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ContainerNarrow } from '../components/Containers';
import { InputStyled } from '../components/forms/InputStyles';
import { ResourceForm } from '../components/forms/ResourceForm';
import { useCurrentSubject } from '../helpers/useCurrentSubject';
import ClassDetail from '../components/ClassDetail';

/** Form for instantiating a new Resource from some Class */
export function Edit(): JSX.Element {
Expand All @@ -25,6 +26,7 @@ export function Edit(): JSX.Element {
{subject ? (
<>
<h1>edit {title}</h1>
<ClassDetail resource={resource} />
{/* Key is required for re-rendering when subject changes */}
<ResourceForm resource={resource} key={subject} />
</>
Expand Down
2 changes: 1 addition & 1 deletion data-browser/src/routes/NewRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function NewForm({ classSubject }: NewFormProps): JSX.Element {
const [showDetails, setShowDetails] = useState(false);
const [subjectErr, setSubjectErr] = useState<Error>(null);
const store = useStore();
const [resource] = useResource(newSubject, true);
const [resource] = useResource(newSubject, { newResource: true });

useEffect(() => {
if (newSubject == undefined) {
Expand Down
7 changes: 3 additions & 4 deletions data-browser/src/views/ResourceCard.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { useInView } from 'react-intersection-observer';
import { useString, useResource, useTitle } from '@tomic/react';
import { Resource, ResourceStatus, properties, urls } from '@tomic/lib';
import { Resource, properties, urls } from '@tomic/lib';
import AllProps from '../components/AllProps';
import AtomicLink from '../components/Link';
import { Card } from '../components/Card';
Expand Down Expand Up @@ -73,11 +73,10 @@ function ResourceCardInner(props: Props): JSX.Element {
const title = useTitle(resource);
const [klass] = useString(resource, properties.isA);

const status = resource.getStatus();
if (status == ResourceStatus.loading) {
if (resource.loading) {
return <p>Loading...</p>;
}
if (status == ResourceStatus.error) {
if (resource.error) {
return (
<ErrorLook>
<AtomicLink subject={subject}>
Expand Down
9 changes: 4 additions & 5 deletions data-browser/src/views/ResourceInline.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import styled from 'styled-components';
import { useString, useResource, useTitle } from '@tomic/react';
import { ResourceStatus, urls } from '@tomic/lib';
import { urls } from '@tomic/lib';
import AtomicLink from '../components/Link';

type Props = {
Expand All @@ -11,19 +11,18 @@ type Props = {

/** Renders a Resource in a small, inline link. */
function ResourceInline({ subject, untabbable }: Props): JSX.Element {
const [resource] = useResource(subject);
const [resource] = useResource(subject, { allowIncomplete: true });
const title = useTitle(resource);
const [description] = useString(resource, urls.properties.description);

const status = resource.getStatus();
if (status == ResourceStatus.loading) {
if (resource.loading) {
return (
<span about={subject} title={`${subject} is loading..`}>
...
</span>
);
}
if (status == ResourceStatus.error) {
if (resource.error) {
return (
<AtomicLink subject={subject} untabbable={untabbable}>
<ErrorLook about={subject} title={resource.getError().message}>
Expand Down
7 changes: 3 additions & 4 deletions data-browser/src/views/ResourceLine.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { useString, useResource, useTitle } from '@tomic/react';
import { ResourceStatus, urls } from '@tomic/lib';
import { urls } from '@tomic/lib';
import ResourceInline, { ErrorLook } from './ResourceInline';

type Props = {
Expand All @@ -14,11 +14,10 @@ function ResourceLine({ subject, clickable }: Props): JSX.Element {
const title = useTitle(resource);
let [description] = useString(resource, urls.properties.description);

const status = resource.getStatus();
if (status == ResourceStatus.loading) {
if (resource.loading) {
return <span about={subject}>Loading...</span>;
}
if (status == ResourceStatus.error) {
if (resource.error) {
return (
<ErrorLook about={subject}>
Error: {resource.getError().message}
Expand Down
5 changes: 2 additions & 3 deletions data-browser/src/views/ResourcePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,10 @@ function ResourcePage({ subject }: Props): JSX.Element {
const [klass] = useString(resource, properties.isA);
const store = useStore();

const status = resource.getStatus();
if (status == ResourceStatus.loading) {
if (resource.loading) {
return <ContainerNarrow>Loading...</ContainerNarrow>;
}
if (status == ResourceStatus.error) {
if (resource.error) {
return (
<ContainerNarrow>
<h1>⚠️ {title}</h1>
Expand Down