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

#845 tables and ontologies #871

Merged
merged 19 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ docker-musl:
SAVE IMAGE --push ${tags}

setup-playwright:
FROM mcr.microsoft.com/playwright:v1.38.0-jammy
FROM mcr.microsoft.com/playwright:v1.43.1-jammy
RUN curl -f https://get.pnpm.io/v6.14.js | node - add --global pnpm
RUN apt update && apt install -y zip
RUN pnpx playwright install --with-deps
Expand Down
3 changes: 2 additions & 1 deletion browser/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ module.exports = {
'lib/tsconfig.json',
'cli/tsconfig.json',
'react/tsconfig.json',
'data-browser/tsconfig.json'
'data-browser/tsconfig.json',
'e2e/tsconfig.json',
],
},
plugins: ['react', '@typescript-eslint', 'prettier', 'react-hooks', 'jsx-a11y'],
Expand Down
5 changes: 4 additions & 1 deletion browser/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Changelog

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

## Unreleased

### Atomic Browser

- [#845](https://github.com/atomicdata-dev/atomic-server/issues/845) Add option to create instances and tables from the ontology view.
- [#845](https://github.com/atomicdata-dev/atomic-server/issues/845) Add default Ontology option to drives.
- [#841](https://github.com/atomicdata-dev/atomic-server/issues/841) Add better inputs for `Timestamp` and `Date` datatypes.
- [#842](https://github.com/atomicdata-dev/atomic-server/issues/842) Add media picker for properties with classtype file.
- [#850](https://github.com/atomicdata-dev/atomic-server/issues/850) Add drag & drop sorting to ResourceArray inputs.
Expand All @@ -24,6 +26,7 @@ This changelog covers all three packages, as they are (for now) updated as a who
- Added `collection.totalPages`.
- BREAKING CHANGE: Renamed `resource.getCommitsCollection` to `resource.getCommitsCollectionSubject`.
- BREAKING CHANGE: `resource.getChildrenCollection()` now returns a `Promise<Collection>` instead of a subject.
- BREAKING CHANGE: `resource.createSubject()` no longer accepts a class name as an argument and defaults to a fully random subject.
- BREAKING CHANGE: Resource now keeps a reference to store internally, therefore all methods that required you to pass a store have been changed to not require a store.
These methods are:
- `resource.canWrite()`
Expand Down
2 changes: 1 addition & 1 deletion browser/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"watch": "tsc --build --watch",
"start": "pnpm watch",
"tsc": "tsc --build",
"typecheck": "tsc --noEmit"
"typecheck": "pnpm exec tsc --noEmit"
},
"bin": {
"ad-generate": "./bin/src/index.js"
Expand Down
4 changes: 2 additions & 2 deletions browser/data-browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"@types/react-window": "^1.8.7",
"@vitejs/plugin-react-swc": "^3.5.0",
"csstype": "^3.1.0",
"gh-pages": "^3.1.0",
"gh-pages": "^5.0.0",
"lint-staged": "^10.5.4",
"types-wm": "^1.1.0",
"vite-plugin-pwa": "^0.17.0",
Expand Down Expand Up @@ -78,6 +78,6 @@
"preview": "vite preview",
"start": "vite",
"test": "jest",
"typecheck": "tsc --noEmit"
"typecheck": "pnpm exec tsc --noEmit"
}
}
1 change: 1 addition & 0 deletions browser/data-browser/src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const ButtonClean = styled.button<ButtonPropsStyled>`
appearance: none;
background-color: initial;
-webkit-tap-highlight-color: transparent; /* Remove the tap / click effect on touch devices */
user-select: none;
`;

/** Base button style. You're likely to want to use ButtonMargin in most places */
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PropsWithChildren, useCallback, useEffect, useState } from 'react';
import { styled } from 'styled-components';
import { FaCaretRight } from 'react-icons/fa';
import { Collapse } from '../Collapse';
import { Collapse } from './Collapse';

export interface DetailsProps {
open?: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Waits for when the document becomes active again after it has been inert.
* (Useful for waiting for a dialog to close before navigating to a new page)
*/
export function waitForActiveDocument(callback: () => void) {
const observer = new MutationObserver(() => {
if (!document.body.hasAttribute('inert')) {
callback();
observer.disconnect();
}
});

observer.observe(document.body, {
attributes: true,
attributeFilter: ['inert'],
});
}
25 changes: 16 additions & 9 deletions browser/data-browser/src/components/Dropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ export type MenuItemMinimial = {
shortcut?: string;
};

export type Item = typeof DIVIDER | MenuItemMinimial;
export type DropdownItem = typeof DIVIDER | MenuItemMinimial;

interface DropdownMenuProps {
/** The list of menu items */
items: Item[];
items: DropdownItem[];
trigger: DropdownTriggerRenderFunction;
/** Enables the keyboard shortcut */
isMainMenu?: boolean;
Expand All @@ -51,7 +51,7 @@ export const isItem = (
): item is MenuItemMinimial =>
typeof item !== 'string' && typeof item?.label === 'string';

const shouldSkip = (item?: Item) => !isItem(item) || item.disabled;
const shouldSkip = (item?: DropdownItem) => !isItem(item) || item.disabled;

const getAdditionalOffest = (increment: number) =>
increment === 0 ? 1 : Math.sign(increment);
Expand All @@ -62,7 +62,7 @@ const getAdditionalOffest = (increment: number) =>
* Returns 0 when no suitable index is found.
*/
const createIndexOffset =
(items: Item[]) => (startingPoint: number, offset: number) => {
(items: DropdownItem[]) => (startingPoint: number, offset: number) => {
const findNextAvailable = (
scopedStartingPoint: number,
scopedOffset: number,
Expand All @@ -84,8 +84,8 @@ const createIndexOffset =
return findNextAvailable(startingPoint, offset);
};

function normalizeItems(items: Item[]) {
return items.reduce((acc: Item[], current, i) => {
function normalizeItems(items: DropdownItem[]) {
return items.reduce((acc: DropdownItem[], current, i) => {
// If the item is a divider at the start or end of the list, remove it.
if ((i === 0 || i === items.length - 1) && !isItem(current)) {
return acc;
Expand Down Expand Up @@ -136,7 +136,6 @@ export function DropdownMenu({

useClickAwayListener([triggerRef, dropdownRef], handleClose, isActive, [
'click',
'mouseout',
]);

const normalizedItems = useMemo(() => normalizeItems(items), [items]);
Expand Down Expand Up @@ -412,19 +411,27 @@ const MenuItemStyled = styled(Button)<MenuItemStyledProps>`
p.selected ? p.theme.colors.bg1 : p.theme.colors.bg};
text-decoration: ${p => (p.selected ? 'underline' : 'none')};

& svg {
color: ${p => p.theme.colors.textLight};
}
&:hover {
background-color: ${p => p.theme.colors.bg1};
}
&:active {
background-color: ${p => p.theme.colors.bg2};
}
&:disabled {
color: ${p => p.theme.colors.textLight};
color: ${p => p.theme.colors.textLight2};
cursor: default;
background-color: ${p => p.theme.colors.bg};

&:hover {
cursor: 'default';
}
background-color: ${p => p.theme.colors.bg};

& svg {
color: ${p => p.theme.colors.textLight2};
}
}

svg {
Expand Down
10 changes: 5 additions & 5 deletions browser/data-browser/src/components/InviteForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface InviteFormProps {
*/
export function InviteForm({ target }: InviteFormProps) {
const store = useStore();
const [subject] = useState(() => store.createSubject('invite'));
const [subject] = useState(() => store.createSubject());
const invite = useResource(subject, {
newResource: true,
});
Expand Down Expand Up @@ -59,7 +59,7 @@ export function InviteForm({ target }: InviteFormProps) {
return (
<Card>
<ResourceField
label={'Give edit rights'}
label={'Allow edits'}
propertyURL={server.properties.write}
resource={invite}
/>
Expand All @@ -69,11 +69,11 @@ export function InviteForm({ target }: InviteFormProps) {
resource={invite}
/>
<ResourceField
label={'How many times this link can be used. No value = no limit.'}
label={'Limit Usages (optional)'}
propertyURL={server.properties.usagesLeft}
resource={invite}
/>
<Button onClick={createInvite}>Create Invite</Button>
<Button onClick={createInvite}>Create</Button>
{err && (
<p>
<ErrorLook>{err.message}</ErrorLook>
Expand All @@ -84,7 +84,7 @@ export function InviteForm({ target }: InviteFormProps) {
} else
return (
<Card>
<p>Invite created and copied to clipboard! Send it to your buddy:</p>
<p>Invite created and copied to clipboard! 🚀</p>
<CodeBlock content={invite.subject} data-test='invite-code' />
</Card>
);
Expand Down
51 changes: 51 additions & 0 deletions browser/data-browser/src/components/ParentPicker/ParentPicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { styled } from 'styled-components';
import { Column } from '../Row';
import { ParentPickerItem } from './ParentPickerItem';
import { InputStyled, InputWrapper } from '../forms/InputStyles';
import { useSettings } from '../../helpers/AppSettings';
import { FaFolderOpen } from 'react-icons/fa6';

export interface ParentPickerProps {
root?: string;
value: string | undefined;
onChange: (subject: string) => void;
}

export function ParentPicker({
root,
value,
onChange,
}: ParentPickerProps): React.JSX.Element {
const { drive } = useSettings();

return (
<Column>
<InputWrapper hasPrefix>
<FaFolderOpen size='1rem' />
<InputStyled
placeholder='Enter a subject'
value={value ?? ''}
onChange={e => onChange(e.target.value)}
/>
</InputWrapper>
<PickerWrapper aria-label='parent selector'>
<ParentPickerItem
inialOpen={true}
subject={root ?? drive}
onClick={onChange}
selectedValue={value}
/>
</PickerWrapper>
</Column>
);
}

const PickerWrapper = styled.section`
background-color: ${p => p.theme.colors.bg};
border-radius: ${p => p.theme.radius};
border: 1px solid ${p => p.theme.colors.bg2};
padding: ${p => p.theme.margin}rem;

height: 20.5rem;
overflow-y: auto;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { useEffect, useState } from 'react';
import {
Dialog,
DialogActions,
DialogContent,
DialogTitle,
useDialog,
} from '../Dialog';
import { ParentPicker } from './ParentPicker';
import { Button } from '../Button';
import { waitForActiveDocument } from '../Dialog/waitForActiveDocument';

interface ParentPickerDialogProps {
root?: string;
open: boolean;
onSelect: (subject: string) => void;
onCancel?: () => void;
onOpenChange?: (open: boolean) => void;
title?: string;
}

export function ParentPickerDialog({
open,
root,
title,
onSelect,
onCancel,
onOpenChange,
}: ParentPickerDialogProps): React.JSX.Element {
const [selected, setSelected] = useState<string>();

const [dialogProps, show, close, isOpen] = useDialog({
onCancel,
bindShow: onOpenChange,
});

const select = () => {
if (!selected) return;

waitForActiveDocument(() => {
onSelect(selected);
});
close(true);
};

useEffect(() => {
if (open) {
show();
} else {
close();
setSelected(undefined);
}
}, [open]);

return (
<Dialog {...dialogProps}>
{isOpen && (
<>
<DialogTitle>
<h1>{title ?? 'Select a location'}</h1>
</DialogTitle>
<DialogContent>
<ParentPicker root={root} value={selected} onChange={setSelected} />
</DialogContent>
<DialogActions>
<Button subtle onClick={() => close(false)}>
Cancel
</Button>
<Button onClick={select} disabled={!selected}>
Select
</Button>
</DialogActions>
</>
)}
</Dialog>
);
}
Loading
Loading