Skip to content

Commit

Permalink
Add tagging feature + tag search #459
Browse files Browse the repository at this point in the history
  • Loading branch information
Polleps committed Feb 26, 2025
1 parent 17428a6 commit c744c50
Show file tree
Hide file tree
Showing 50 changed files with 4,338 additions and 971 deletions.
2 changes: 2 additions & 0 deletions browser/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ This changelog covers all five packages, as they are (for now) updated as a whol
- [#1008](https://github.com/atomicdata-dev/atomic-server/issues/1008) Add 'open' option to classes and properties in the ontology edit view.
- [#1008](https://github.com/atomicdata-dev/atomic-server/issues/1008) Updated the look of the resource selector and made it more responsive.
- [#1008](https://github.com/atomicdata-dev/atomic-server/issues/1008) Add info dropdowns to different sections of the ontology editor for more information about the section.
- [#459](https://github.com/atomicdata-dev/atomic-server/issues/459) New feature: Add tags to your resources to better organize your data. Search for resources with specific tags in the search bar with `tag:[name]`.

### @tomic/lib

Expand All @@ -25,6 +26,7 @@ This changelog covers all five packages, as they are (for now) updated as a whol
- Fix generated ontologies not working in a Next.js server context.
- SEMI BREAKING CHANGE: When using generated types by cli, @tomic/lib now requires them to be generated by @tomic/cli v0.41.0 or above.
- Fix types masquerading as esm module in cjs build.
- `store.search()` now handles multiple values for the same property correctly.

### @tomic/react

Expand Down
2 changes: 1 addition & 1 deletion browser/data-browser/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"@types/react-pdf": "^7.0.0",
"@types/react-window": "^1.8.8",
"@vitejs/plugin-react": "^4.3.4",
"babel-plugin-react-compiler": "19.0.0-beta-37ed2a7-20241206",
"babel-plugin-react-compiler": "19.0.0-beta-21e868a-20250216",
"babel-plugin-styled-components": "^2.1.4",
"csstype": "^3.1.3",
"gh-pages": "^5.0.0",
Expand Down
6 changes: 6 additions & 0 deletions browser/data-browser/src/components/EditableTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from '../helpers/transitionName';
import { ViewTransitionProps } from '../helpers/ViewTransitionProps';
import { UnsavedIndicator } from './UnsavedIndicator';
import { Flex } from './Row';

export interface EditableTitleProps {
resource: Resource;
Expand Down Expand Up @@ -142,6 +143,11 @@ const TitleInput = styled.input`
&:focus {
outline: none;
}
${Flex} & {
// When rendered inside a flex container the margin is already provided by the gap.
margin-bottom: 0;
}
`;

const Icon = styled(FaPencil)`
Expand Down
5 changes: 4 additions & 1 deletion browser/data-browser/src/components/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ViewTransitionProps } from '../helpers/ViewTransitionProps';
import { MAIN_CONTAINER } from '../helpers/containers';
import Parent from './Parent';
import { useResource } from '@tomic/react';
import { CalculatedPageHeight } from '../globalCssVars';

/** Main landmark. Every page should have one of these.
* If the pages shows a resource a subject can be passed that enables view transitions to work. */
Expand Down Expand Up @@ -36,7 +37,9 @@ export function Main({
const StyledMain = memo(styled.main<ViewTransitionProps>`
container: ${MAIN_CONTAINER} / inline-size;
${p => transitionName(RESOURCE_PAGE_TRANSITION_TAG, p.subject)};
height: calc(100vh - ${p => p.theme.heights.breadCrumbBar});
height: calc(
${CalculatedPageHeight.var()} - ${p => p.theme.heights.breadCrumbBar}
);
overflow-y: auto;
scroll-padding: calc(
${p => p.theme.heights.breadCrumbBar} + ${p => p.theme.size(2)}
Expand Down
113 changes: 65 additions & 48 deletions browser/data-browser/src/components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,53 @@ import { FaArrowLeft, FaArrowRight, FaBars } from 'react-icons/fa';
import { styled } from 'styled-components';

import { ButtonBar } from './Button';
import { useCurrentSubject } from '../helpers/useCurrentSubject';
import { useSettings } from '../helpers/AppSettings';
import { SideBar } from './SideBar';
import { isRunningInTauri } from '../helpers/tauri';
import { shortcuts } from './HotKeyWrapper';
import { NavBarSpacer } from './NavBarSpacer';
import { Searchbar } from './Searchbar';
import { Searchbar } from './Searchbar/Searchbar';
import { useMediaQuery } from '../hooks/useMediaQuery';
import { useBackForward } from '../hooks/useNavigateWithTransition';
import { NAVBAR_TRANSITION_TAG } from '../helpers/transitionName';
import { SearchbarFakeInput } from './Searchbar/SearchbarInput';
import { CalculatedPageHeight } from '../globalCssVars';

interface NavWrapperProps {
children: React.ReactNode;
}
enum NavBarPosition {
Top,
Floating,
Bottom,
}

const getPosition = (
navbarTop: boolean,
navbarFloating: boolean,
): NavBarPosition => {
if (navbarTop) return NavBarPosition.Top;
if (navbarFloating) return NavBarPosition.Floating;

return NavBarPosition.Bottom;
};

/** Wraps the entire app and adds a navbar at the bottom or the top */
export function NavWrapper({ children }: NavWrapperProps): JSX.Element {
const { navbarTop, navbarFloating } = useSettings();
const contentRef = React.useRef<HTMLDivElement>(null);

const navbarPosition = getPosition(navbarTop, navbarFloating);

return (
<>
{navbarTop && <NavBar />}
<SideBarWrapper>
<SideBarWrapper navbarPosition={navbarPosition}>
<SideBar />
<Content
ref={contentRef}
navbarTop={navbarTop}
navbarFloating={navbarFloating}
>
<NavBarSpacer position='top' />
{children}
</Content>
</SideBarWrapper>
Expand All @@ -58,10 +74,8 @@ const Content = styled.div<ContentProps>`
function NavBar(): JSX.Element {
const { back, forward } = useBackForward();

const [subject] = useCurrentSubject();
const { navbarTop, navbarFloating, sideBarLocked, setSideBarLocked } =
useSettings();
const [showButtons, setShowButtons] = React.useState<boolean>(true);

const machesStandalone = useMediaQuery(
'(display-mode: standalone) or (display-mode: fullscreen)',
Expand All @@ -77,13 +91,6 @@ function NavBar(): JSX.Element {
[machesStandalone],
);

/** Hide buttons if the input element is quite small */
function maybeHideButtons(event: React.FocusEvent<HTMLInputElement>) {
if (event.target.getBoundingClientRect().width < 280) {
setShowButtons(false);
}
}

const ConditionalNavbar = navbarFloating ? NavBarFloating : NavBarFixed;

return (
Expand All @@ -92,35 +99,29 @@ function NavBar(): JSX.Element {
aria-label='search'
floating={navbarFloating}
>
{showButtons && (
<>
<ButtonBar
leftPadding
type='button'
onClick={() => setSideBarLocked(!sideBarLocked)}
title={`Show / hide sidebar (${shortcuts.sidebarToggle})`}
data-test='sidebar-toggle'
>
<FaBars />
</ButtonBar>
{isInStandaloneMode && (
<>
<ButtonBar type='button' title='Go back' onClick={back}>
<FaArrowLeft />
</ButtonBar>{' '}
<ButtonBar type='button' title='Go forward' onClick={forward}>
<FaArrowRight />
</ButtonBar>
</>
)}
</>
)}
<>
<ButtonBar
leftPadding
type='button'
onClick={() => setSideBarLocked(!sideBarLocked)}
title={`Show / hide sidebar (${shortcuts.sidebarToggle})`}
data-test='sidebar-toggle'
>
<FaBars />
</ButtonBar>
{isInStandaloneMode && (
<>
<ButtonBar type='button' title='Go back' onClick={back}>
<FaArrowLeft />
</ButtonBar>{' '}
<ButtonBar type='button' title='Go forward' onClick={forward}>
<FaArrowRight />
</ButtonBar>
</>
)}
</>
<VerticalDivider />
<Searchbar
subject={subject}
onFocus={maybeHideButtons}
onBlur={() => setShowButtons(true)}
/>
<Searchbar />
</ConditionalNavbar>
);
}
Expand All @@ -140,11 +141,20 @@ const NavBarBase = styled.div<NavBarStyledProps>`
border: solid 1px ${props => props.theme.colors.bg2};
background-color: ${props => props.theme.colors.bg};
view-transition-name: ${NAVBAR_TRANSITION_TAG};
container-name: search-bar;
container-type: inline-size;
/* Hide buttons when the searchbar is small and has focus. */
&:has(${SearchbarFakeInput}:focus) ${ButtonBar} {
@container search-bar (max-inline-size: 280px) {
display: none;
}
}
`;

/** Width of the floating navbar in rem */
const NavBarFloating = styled(NavBarBase)`
box-shadow: ${props => props.theme.boxShadow};
box-shadow: ${props => props.theme.boxShadowSoft};
border-radius: 999px;
overflow: hidden;
max-width: calc(100% - 2rem);
Expand All @@ -157,7 +167,7 @@ const NavBarFloating = styled(NavBarBase)`
top: ${props => (props.top ? '2rem' : 'auto')};
bottom: ${props => (props.top ? 'auto' : '1rem')};
&:has(input:focus) {
&:has(${SearchbarFakeInput}:focus) {
box-shadow: 0px 0px 0px 1px ${props => props.theme.colors.main};
border-color: ${props => props.theme.colors.main};
}
Expand Down Expand Up @@ -193,12 +203,19 @@ const VerticalDivider = styled.div`
height: 100%;
margin-left: ${p => p.theme.size(2)};
`;
const SideBarWrapper = styled('div')`

const SideBarWrapper = styled.div<{ navbarPosition: NavBarPosition }>`
${CalculatedPageHeight.define(p =>
p.navbarPosition === NavBarPosition.Floating
? '100dvh'
: `calc(100dvh - 2.5rem)`,
)}
display: flex;
height: 100vh;
height: ${CalculatedPageHeight.var()};
position: fixed;
top: 0;
bottom: 0;
top: ${p => (p.navbarPosition === NavBarPosition.Top ? '2.5rem' : 'auto')};
bottom: ${p =>
p.navbarPosition === NavBarPosition.Bottom ? '2.5rem' : 'auto'};
left: 0;
right: 0;
Expand Down
8 changes: 7 additions & 1 deletion browser/data-browser/src/components/Row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,13 @@ export const Column = forwardRef<

Column.displayName = 'Column';

const Flex = styled.div<FlexProps>`
/**
* Underlying layout of the Row and Column components.
* Do not use this component directly and don't extend it.
*
* This component is only exported so it can be used in css selectors.
*/
export const Flex = styled.div<FlexProps>`
align-items: ${p => (p.center ? 'center' : 'initial')};
display: flex;
gap: ${p => p.gap ?? `${p.theme.margin}rem`};
Expand Down
1 change: 1 addition & 0 deletions browser/data-browser/src/components/ScrollArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const Thumb = styled(RadixScrollArea.Thumb)`
export const ScrollViewPort = styled(RadixScrollArea.Viewport)`
width: 100%;
height: 100%;
& > div[style] {
/* Radix gives this div a display of table to fix an obscure bug (that we don't have).
This messes with the accessibility tree and stops the TableEditor from working correctly for screen readers. */
Expand Down
Loading

0 comments on commit c744c50

Please sign in to comment.