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

#919 Sort classes in Ontology viewer #932

Merged
merged 3 commits into from
Aug 14, 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
4 changes: 3 additions & 1 deletion Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ VERSION --try 0.8
PROJECT ontola/atomic-server
IMPORT ./browser AS browser
IMPORT github.com/earthly/lib/rust AS rust
FROM rust:buster
FROM rust:bookworm
WORKDIR /code

pipeline:
Expand Down Expand Up @@ -33,6 +33,8 @@ docker-all:

install:
RUN apt-get update -qq
# NASM is required for the image library
RUN apt install nasm
RUN rustup component add clippy
RUN rustup component add rustfmt
RUN cargo install cross
Expand Down
1 change: 1 addition & 0 deletions browser/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ This changelog covers all five packages, as they are (for now) updated as a whol
- [#861](https://github.com/atomicdata-dev/atomic-server/issues/861) Fix long usernames overflowing on the share page.
- [#906](https://github.com/atomicdata-dev/atomic-server/issues/906) Reset changes after clicking the cancel button in a form or navigating away.
- [#914](https://github.com/atomicdata-dev/atomic-server/issues/914) Fix an issue where changing the subject in a new resource form could update the parent of existing resources if their subject matched the new subject.
- [#919](https://github.com/atomicdata-dev/atomic-server/issues/919) Automatically sort classes and properties in the ontology editor.

### @tomic/lib

Expand Down
7 changes: 7 additions & 0 deletions browser/data-browser/src/components/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,11 @@ const StyledMain = memo(styled.main<ViewTransitionProps>`
${p => transitionName(RESOURCE_PAGE_TRANSITION_TAG, p.subject)};
height: calc(100vh - ${p => p.theme.heights.breadCrumbBar});
overflow-y: auto;
scroll-padding: calc(
${p => p.theme.heights.breadCrumbBar} + ${p => p.theme.size(2)}
);

@media (prefers-reduced-motion: no-preference) {
scroll-behavior: smooth;
}
`);
20 changes: 17 additions & 3 deletions browser/data-browser/src/hooks/useAddToOntology.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import {
Server,
unknownSubject,
core,
Core,
} from '@tomic/react';
import { useSettings } from '../helpers/AppSettings';
import { useCallback } from 'react';
import { sortSubjectList } from '../views/OntologyPage/sortSubjectList';

export function useAddToOntology(ontologySubject?: string) {
const store = useStore();
const { drive: driveSubject } = useSettings();
const drive = useResource<Server.Drive>(driveSubject);

const ontology = useResource(
const ontology = useResource<Core.Ontology>(
ontologySubject ?? drive.props.defaultOntology ?? unknownSubject,
);

Expand All @@ -31,9 +33,21 @@ export function useAddToOntology(ontologySubject?: string) {
await resource.save();

if (resource.hasClasses(core.classes.class)) {
ontology.push(core.properties.classes, [resource.subject], true);
await ontology.set(
core.properties.classes,
await sortSubjectList(store, [
...(ontology.props.classes ?? []),
resource.subject,
]),
);
} else if (resource.hasClasses(core.classes.property)) {
ontology.push(core.properties.properties, [resource.subject], true);
await ontology.set(
core.properties.properties,
await sortSubjectList(store, [
...(ontology.props.properties ?? []),
resource.subject,
]),
);
} else {
ontology.push(core.properties.instances, [resource.subject], true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { InputStyled, InputWrapper } from '../../components/forms/InputStyles';
import { stringToSlug } from '../../helpers/stringToSlug';
import { Column } from '../../components/Row';
import { newClass, subjectForClass } from './newClass';
import { toAnchorId } from './toAnchorId';

interface NewClassButtonProps {
resource: Resource;
Expand All @@ -29,8 +30,10 @@ export function NewClassButton({ resource }: NewClassButtonProps): JSX.Element {
const subject = subjectForClass(resource, inputValue);

const [dialogProps, show, hide, isOpen] = useDialog({
onSuccess: () => {
newClass(inputValue, resource, store);
onSuccess: async () => {
const createdClass = await newClass(inputValue, resource, store);
const id = toAnchorId(createdClass);
document.getElementById(id)?.scrollIntoView({ behavior: 'smooth' });
},
});

Expand Down
17 changes: 14 additions & 3 deletions browser/data-browser/src/views/OntologyPage/OntologyContext.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { Resource, unknownSubject, urls, useArray } from '@tomic/react';
import {
core,
Resource,
unknownSubject,
urls,
useArray,
useStore,
} from '@tomic/react';
import { createContext, useCallback, useContext, useMemo } from 'react';
import { sortSubjectList } from './sortSubjectList';

interface OntologyContext {
addClass: (subject: string) => Promise<void>;
Expand Down Expand Up @@ -29,7 +37,8 @@ export function OntologyContextProvider({
ontology,
children,
}: React.PropsWithChildren<OntologyContextProviderProps>) {
const [classes, setClasses] = useArray(ontology, urls.properties.classes, {
const store = useStore();
const [classes, setClasses] = useArray(ontology, core.properties.classes, {
commit: true,
});

Expand All @@ -55,7 +64,9 @@ export function OntologyContextProvider({

const addProperty = useCallback(
async (subject: string) => {
await setProperties([...properties, subject]);
await setProperties(
await sortSubjectList(store, [...properties, subject]),
);
},
[properties, setProperties],
);
Expand Down
11 changes: 5 additions & 6 deletions browser/data-browser/src/views/OntologyPage/OntologyPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ export function OntologyPage({ resource }: ResourcePageProps) {
<OntologyDescription edit={editMode} resource={resource} />
<h2>Classes</h2>
<StyledUl>
{editMode && (
<li>
<NewClassButton resource={resource} />
</li>
)}
{classes.map(c => (
<li key={c}>
{editMode ? (
Expand All @@ -67,11 +72,6 @@ export function OntologyPage({ resource }: ResourcePageProps) {
)}
</li>
))}
{editMode && (
<li>
<NewClassButton resource={resource} />
</li>
)}
</StyledUl>
<h2>Properties</h2>
<StyledUl>
Expand Down Expand Up @@ -118,7 +118,6 @@ const ListSlot = styled.div`
const FullPageWrapper = styled.div<{ edit: boolean }>`
--ontology-graph-position: sticky;
--ontology-graph-ratio: 9 / 16;

display: grid;
grid-template-areas: ${p =>
p.edit
Expand Down
12 changes: 9 additions & 3 deletions browser/data-browser/src/views/OntologyPage/newClass.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Resource, Store, core } from '@tomic/react';
import { Resource, Store, core, type Core } from '@tomic/react';
import { sortSubjectList } from './sortSubjectList';

const DEFAULT_DESCRIPTION = 'Change me';

Expand All @@ -7,7 +8,7 @@ export const subjectForClass = (parent: Resource, shortName: string): string =>

export async function newClass(
shortName: string,
parent: Resource,
parent: Resource<Core.Ontology>,
store: Store,
): Promise<string> {
const subject = subjectForClass(parent, shortName);
Expand All @@ -24,7 +25,12 @@ export async function newClass(

await resource.save();

parent.push(core.properties.classes, [subject]);
const classes = parent.props.classes ?? [];

await parent.set(
core.properties.classes,
await sortSubjectList(store, [...classes, subject]),
);

await parent.save();

Expand Down
16 changes: 16 additions & 0 deletions browser/data-browser/src/views/OntologyPage/sortSubjectList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { type Resource, type Store } from '@tomic/react';

export async function sortSubjectList(
store: Store,
subjectList: string[],
): Promise<string[]> {
const resources: Resource[] = [];

for (const subject of subjectList) {
resources.push(await store.getResource(subject));
}

resources.sort((a, b) => a.title.localeCompare(b.title));

return resources.map(r => r.subject);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { FormValidationContextProvider } from '../../../components/forms/formVal
import { randomString } from '../../../helpers/randomString';
import { PropertyForm } from './PropertyForm';
import { PropertyFormCategory } from './categories';
import { sortSubjectList } from '../../OntologyPage/sortSubjectList';

interface NewPropertyDialogProps {
showDialog: boolean;
Expand Down Expand Up @@ -117,10 +118,12 @@ export function NewPropertyDialog({
if (tableClassParent.hasClasses(core.classes.ontology)) {
await resource.set(core.properties.parent, tableClassParent.subject);

tableClassParent.push(
const ontologyProps =
tableClassParent.get(core.properties.properties) ?? [];

await tableClassParent.set(
core.properties.properties,
[resource.subject],
true,
await sortSubjectList(store, [...ontologyProps, resource.subject]),
);

await tableClassParent.save();
Expand Down
2 changes: 1 addition & 1 deletion browser/data-browser/src/views/TablePage/TablePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function TablePage({ resource }: ResourcePageProps): JSX.Element {

const tablePageContext: TablePageContextType = useMemo(
() => ({
tableClassSubject: tableClass.getSubject(),
tableClassSubject: tableClass.subject,
sorting,
setSortBy,
addItemsToHistoryStack,
Expand Down
4 changes: 2 additions & 2 deletions browser/e2e/tests/ontology.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ test.describe('Ontology', async () => {

await page
.getByRole('button', { name: 'add an item to the allows-only list' })
.nth(1)
.nth(0)
.click();
await page.getByRole('button', { name: 'Search for a arrow-kind' }).click();
await page
Expand All @@ -248,7 +248,7 @@ test.describe('Ontology', async () => {

await page
.getByRole('button', { name: 'add an item to the allows-only list' })
.nth(1)
.nth(0)
.click();
await page.getByRole('button', { name: 'Search for a arrow-kind' }).click();
await page
Expand Down
Loading