From b257b4ef4628b3c256c12f564af517dcc1b797c3 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Sat, 20 Jan 2024 16:20:32 +0100 Subject: [PATCH 001/135] Replaced dummy logos with a half-way decent placeholder --- src/apps/dashboard-projects/Header/Header.css | 1 + src/apps/dashboard-projects/Header/Header.tsx | 3 +- .../RecogitoLogo/RecogitoCircleLogo.tsx | 32 ++++++++++++++++++ src/components/RecogitoLogo/RecogitoLogo.tsx | 33 +++++++++++++++++++ src/components/RecogitoLogo/index.ts | 2 ++ src/layouts/project/NavItem.tsx | 6 ++-- src/layouts/project/ProjectSidebar.css | 6 +++- src/layouts/project/ProjectSidebar.tsx | 12 +++---- 8 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 src/components/RecogitoLogo/RecogitoCircleLogo.tsx create mode 100644 src/components/RecogitoLogo/RecogitoLogo.tsx create mode 100644 src/components/RecogitoLogo/index.ts diff --git a/src/apps/dashboard-projects/Header/Header.css b/src/apps/dashboard-projects/Header/Header.css index cefe80fa..7baa8e93 100644 --- a/src/apps/dashboard-projects/Header/Header.css +++ b/src/apps/dashboard-projects/Header/Header.css @@ -16,6 +16,7 @@ .dashboard-header h1 { font-size: 1.4em; + display: flex; margin: 0; padding: 0; } diff --git a/src/apps/dashboard-projects/Header/Header.tsx b/src/apps/dashboard-projects/Header/Header.tsx index 81772d70..a310f197 100644 --- a/src/apps/dashboard-projects/Header/Header.tsx +++ b/src/apps/dashboard-projects/Header/Header.tsx @@ -5,6 +5,7 @@ import { initProject } from '@backend/helpers'; import { AccountActions } from '@components/AccountActions'; import { Button } from '@components/Button'; import { Notifications } from '@components/Notifications'; +import { RecogitoLogo } from '@components/RecogitoLogo'; import type { Invitation, MyProfile, ExtendedProjectData, Translations, Policies } from 'src/Types'; import { ProjectFilter } from '../ProjectsHome'; import { HeaderSearchAction } from './Search'; @@ -75,7 +76,7 @@ export const Header = (props: HeaderProps) => {

- + {t['Projects']}

diff --git a/src/components/RecogitoLogo/RecogitoCircleLogo.tsx b/src/components/RecogitoLogo/RecogitoCircleLogo.tsx new file mode 100644 index 00000000..d012d532 --- /dev/null +++ b/src/components/RecogitoLogo/RecogitoCircleLogo.tsx @@ -0,0 +1,32 @@ +export interface RecogitoCircleLogoProps { + + className?: string; + + height?: number; + + width?: number; + +} + +/** + * Icon from https://www.svgrepo.com/svg/347710/comment-discussion + * MIT-Licensed + */ +export const RecogitoCircleLogo = (props: RecogitoCircleLogoProps) => { + + const height = props.height || 40; + + const width = props.width || 40; + + return ( + + + + ) + +} diff --git a/src/components/RecogitoLogo/RecogitoLogo.tsx b/src/components/RecogitoLogo/RecogitoLogo.tsx new file mode 100644 index 00000000..607bea6a --- /dev/null +++ b/src/components/RecogitoLogo/RecogitoLogo.tsx @@ -0,0 +1,33 @@ +export interface RecogitoLogoProps { + + height?: number; + + width?: number; + +} + +/** + * Icon from https://www.svgrepo.com/svg/347710/comment-discussion + * MIT-Licensed + */ +export const RecogitoLogo = (props: RecogitoLogoProps) => { + + const height = props.height || 22; + + const width = props.width || 22; + + return ( + + + + + ) + +} diff --git a/src/components/RecogitoLogo/index.ts b/src/components/RecogitoLogo/index.ts new file mode 100644 index 00000000..a80d7548 --- /dev/null +++ b/src/components/RecogitoLogo/index.ts @@ -0,0 +1,2 @@ +export * from './RecogitoCircleLogo'; +export * from './RecogitoLogo'; \ No newline at end of file diff --git a/src/layouts/project/NavItem.tsx b/src/layouts/project/NavItem.tsx index 4af2df2c..384984cb 100644 --- a/src/layouts/project/NavItem.tsx +++ b/src/layouts/project/NavItem.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import type { ReactNode } from 'react'; import type { Icon } from "@phosphor-icons/react"; export interface NavItemProps { @@ -7,7 +7,7 @@ export interface NavItemProps { className?: string; - icon: Icon; + icon: ReactNode; label: string; @@ -26,7 +26,7 @@ export const NavItem = (props: NavItemProps) => { className={props.className ? `${cls} ${props.className}` : cls}> - {React.createElement(props.icon, { size: 21 })} + {props.icon} diff --git a/src/layouts/project/ProjectSidebar.css b/src/layouts/project/ProjectSidebar.css index 8b3faa36..da57ac8e 100644 --- a/src/layouts/project/ProjectSidebar.css +++ b/src/layouts/project/ProjectSidebar.css @@ -9,6 +9,10 @@ --light-blue: #cbd4e2; } +.project-sidebar .recogito-logo-circle { + margin: 0 0.6em 0 0.3em; +} + .project-sidebar ul { list-style-type: none; margin: 0; @@ -41,7 +45,7 @@ transition: color 100ms ease-in-out; position: relative; top: -1px; - width: 40px; + width: 44px; } .project-sidebar-col.collapsible { diff --git a/src/layouts/project/ProjectSidebar.tsx b/src/layouts/project/ProjectSidebar.tsx index 9ee49284..3a4c383e 100644 --- a/src/layouts/project/ProjectSidebar.tsx +++ b/src/layouts/project/ProjectSidebar.tsx @@ -2,13 +2,13 @@ import { useEffect, useState } from 'react'; import { ArrowLineLeft, Folders, - GooglePodcastsLogo, GraduationCap, Sliders, UsersThree, } from '@phosphor-icons/react'; import { AccountActions } from '@components/AccountActions'; import { Avatar } from '@components/Avatar'; +import { RecogitoCircleLogo } from '@components/RecogitoLogo'; import { NavItem } from './NavItem'; import type { ExtendedProjectData, @@ -73,14 +73,14 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { } label='Recogito' link={`/${lang}/projects`} /> } label={t['Documents']} link={link()} /> @@ -88,7 +88,7 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { {isAdmin && ( } label={t['Collaboration']} link={link('collaboration')} /> @@ -96,7 +96,7 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { } label={t['Assignments']} link={link('assignments')} /> @@ -110,7 +110,7 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { {isAdmin && ( } label={t['Settings']} link={link('settings')} /> From 271a2bee21e9f3ba9006b080d919de6b8660425e Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Sat, 20 Jan 2024 16:22:03 +0100 Subject: [PATCH 002/135] Revert "Replaced dummy logos with a half-way decent placeholder" This reverts commit b257b4ef4628b3c256c12f564af517dcc1b797c3. --- src/apps/dashboard-projects/Header/Header.css | 1 - src/apps/dashboard-projects/Header/Header.tsx | 3 +- .../RecogitoLogo/RecogitoCircleLogo.tsx | 32 ------------------ src/components/RecogitoLogo/RecogitoLogo.tsx | 33 ------------------- src/components/RecogitoLogo/index.ts | 2 -- src/layouts/project/NavItem.tsx | 6 ++-- src/layouts/project/ProjectSidebar.css | 6 +--- src/layouts/project/ProjectSidebar.tsx | 12 +++---- 8 files changed, 11 insertions(+), 84 deletions(-) delete mode 100644 src/components/RecogitoLogo/RecogitoCircleLogo.tsx delete mode 100644 src/components/RecogitoLogo/RecogitoLogo.tsx delete mode 100644 src/components/RecogitoLogo/index.ts diff --git a/src/apps/dashboard-projects/Header/Header.css b/src/apps/dashboard-projects/Header/Header.css index 7baa8e93..cefe80fa 100644 --- a/src/apps/dashboard-projects/Header/Header.css +++ b/src/apps/dashboard-projects/Header/Header.css @@ -16,7 +16,6 @@ .dashboard-header h1 { font-size: 1.4em; - display: flex; margin: 0; padding: 0; } diff --git a/src/apps/dashboard-projects/Header/Header.tsx b/src/apps/dashboard-projects/Header/Header.tsx index a310f197..81772d70 100644 --- a/src/apps/dashboard-projects/Header/Header.tsx +++ b/src/apps/dashboard-projects/Header/Header.tsx @@ -5,7 +5,6 @@ import { initProject } from '@backend/helpers'; import { AccountActions } from '@components/AccountActions'; import { Button } from '@components/Button'; import { Notifications } from '@components/Notifications'; -import { RecogitoLogo } from '@components/RecogitoLogo'; import type { Invitation, MyProfile, ExtendedProjectData, Translations, Policies } from 'src/Types'; import { ProjectFilter } from '../ProjectsHome'; import { HeaderSearchAction } from './Search'; @@ -76,7 +75,7 @@ export const Header = (props: HeaderProps) => {

- + {t['Projects']}

diff --git a/src/components/RecogitoLogo/RecogitoCircleLogo.tsx b/src/components/RecogitoLogo/RecogitoCircleLogo.tsx deleted file mode 100644 index d012d532..00000000 --- a/src/components/RecogitoLogo/RecogitoCircleLogo.tsx +++ /dev/null @@ -1,32 +0,0 @@ -export interface RecogitoCircleLogoProps { - - className?: string; - - height?: number; - - width?: number; - -} - -/** - * Icon from https://www.svgrepo.com/svg/347710/comment-discussion - * MIT-Licensed - */ -export const RecogitoCircleLogo = (props: RecogitoCircleLogoProps) => { - - const height = props.height || 40; - - const width = props.width || 40; - - return ( - - - - ) - -} diff --git a/src/components/RecogitoLogo/RecogitoLogo.tsx b/src/components/RecogitoLogo/RecogitoLogo.tsx deleted file mode 100644 index 607bea6a..00000000 --- a/src/components/RecogitoLogo/RecogitoLogo.tsx +++ /dev/null @@ -1,33 +0,0 @@ -export interface RecogitoLogoProps { - - height?: number; - - width?: number; - -} - -/** - * Icon from https://www.svgrepo.com/svg/347710/comment-discussion - * MIT-Licensed - */ -export const RecogitoLogo = (props: RecogitoLogoProps) => { - - const height = props.height || 22; - - const width = props.width || 22; - - return ( - - - - - ) - -} diff --git a/src/components/RecogitoLogo/index.ts b/src/components/RecogitoLogo/index.ts deleted file mode 100644 index a80d7548..00000000 --- a/src/components/RecogitoLogo/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './RecogitoCircleLogo'; -export * from './RecogitoLogo'; \ No newline at end of file diff --git a/src/layouts/project/NavItem.tsx b/src/layouts/project/NavItem.tsx index 384984cb..4af2df2c 100644 --- a/src/layouts/project/NavItem.tsx +++ b/src/layouts/project/NavItem.tsx @@ -1,4 +1,4 @@ -import type { ReactNode } from 'react'; +import React from 'react'; import type { Icon } from "@phosphor-icons/react"; export interface NavItemProps { @@ -7,7 +7,7 @@ export interface NavItemProps { className?: string; - icon: ReactNode; + icon: Icon; label: string; @@ -26,7 +26,7 @@ export const NavItem = (props: NavItemProps) => { className={props.className ? `${cls} ${props.className}` : cls}>
- {props.icon} + {React.createElement(props.icon, { size: 21 })} diff --git a/src/layouts/project/ProjectSidebar.css b/src/layouts/project/ProjectSidebar.css index da57ac8e..8b3faa36 100644 --- a/src/layouts/project/ProjectSidebar.css +++ b/src/layouts/project/ProjectSidebar.css @@ -9,10 +9,6 @@ --light-blue: #cbd4e2; } -.project-sidebar .recogito-logo-circle { - margin: 0 0.6em 0 0.3em; -} - .project-sidebar ul { list-style-type: none; margin: 0; @@ -45,7 +41,7 @@ transition: color 100ms ease-in-out; position: relative; top: -1px; - width: 44px; + width: 40px; } .project-sidebar-col.collapsible { diff --git a/src/layouts/project/ProjectSidebar.tsx b/src/layouts/project/ProjectSidebar.tsx index 3a4c383e..9ee49284 100644 --- a/src/layouts/project/ProjectSidebar.tsx +++ b/src/layouts/project/ProjectSidebar.tsx @@ -2,13 +2,13 @@ import { useEffect, useState } from 'react'; import { ArrowLineLeft, Folders, + GooglePodcastsLogo, GraduationCap, Sliders, UsersThree, } from '@phosphor-icons/react'; import { AccountActions } from '@components/AccountActions'; import { Avatar } from '@components/Avatar'; -import { RecogitoCircleLogo } from '@components/RecogitoLogo'; import { NavItem } from './NavItem'; import type { ExtendedProjectData, @@ -73,14 +73,14 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { } + icon={GooglePodcastsLogo} label='Recogito' link={`/${lang}/projects`} /> } + icon={Folders} label={t['Documents']} link={link()} /> @@ -88,7 +88,7 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { {isAdmin && ( } + icon={UsersThree} label={t['Collaboration']} link={link('collaboration')} /> @@ -96,7 +96,7 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { } + icon={GraduationCap} label={t['Assignments']} link={link('assignments')} /> @@ -110,7 +110,7 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { {isAdmin && ( } + icon={Sliders} label={t['Settings']} link={link('settings')} /> From 718bb4b420d18cc4110d09710eb232d20b79bf2b Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Sun, 21 Jan 2024 10:07:44 +0100 Subject: [PATCH 003/135] Replaced logo placeholders --- src/apps/dashboard-projects/Header/Header.css | 1 + src/apps/dashboard-projects/Header/Header.tsx | 5 +-- .../RecogitoLogo/RecogitoCircleLogo.tsx | 32 ++++++++++++++++++ src/components/RecogitoLogo/RecogitoLogo.tsx | 33 +++++++++++++++++++ src/components/RecogitoLogo/index.ts | 2 ++ src/layouts/project/NavItem.tsx | 7 ++-- src/layouts/project/ProjectSidebar.css | 6 +++- src/layouts/project/ProjectSidebar.tsx | 12 +++---- 8 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 src/components/RecogitoLogo/RecogitoCircleLogo.tsx create mode 100644 src/components/RecogitoLogo/RecogitoLogo.tsx create mode 100644 src/components/RecogitoLogo/index.ts diff --git a/src/apps/dashboard-projects/Header/Header.css b/src/apps/dashboard-projects/Header/Header.css index cefe80fa..a7aa016d 100644 --- a/src/apps/dashboard-projects/Header/Header.css +++ b/src/apps/dashboard-projects/Header/Header.css @@ -15,6 +15,7 @@ } .dashboard-header h1 { + display: flex; font-size: 1.4em; margin: 0; padding: 0; diff --git a/src/apps/dashboard-projects/Header/Header.tsx b/src/apps/dashboard-projects/Header/Header.tsx index 81772d70..2757046b 100644 --- a/src/apps/dashboard-projects/Header/Header.tsx +++ b/src/apps/dashboard-projects/Header/Header.tsx @@ -1,10 +1,11 @@ import { useState } from 'react'; -import { Kanban, Plus } from '@phosphor-icons/react'; +import { Plus } from '@phosphor-icons/react'; import { supabase } from '@backend/supabaseBrowserClient'; import { initProject } from '@backend/helpers'; import { AccountActions } from '@components/AccountActions'; import { Button } from '@components/Button'; import { Notifications } from '@components/Notifications'; +import { RecogitoLogo } from '@components/RecogitoLogo'; import type { Invitation, MyProfile, ExtendedProjectData, Translations, Policies } from 'src/Types'; import { ProjectFilter } from '../ProjectsHome'; import { HeaderSearchAction } from './Search'; @@ -75,7 +76,7 @@ export const Header = (props: HeaderProps) => {

- + {t['Projects']}

diff --git a/src/components/RecogitoLogo/RecogitoCircleLogo.tsx b/src/components/RecogitoLogo/RecogitoCircleLogo.tsx new file mode 100644 index 00000000..13dc2249 --- /dev/null +++ b/src/components/RecogitoLogo/RecogitoCircleLogo.tsx @@ -0,0 +1,32 @@ +export interface RecogitoCircleLogoProps { + + className?: string; + + height?: number; + + width?: number; + +} + +/** + * Icon from https://www.svgrepo.com/svg/347710/comment-discussion + * MIT-Licensed + */ +export const RecogitoCircleLogo = (props: RecogitoCircleLogoProps) => { + + const height = props.height || 40; + + const width = props.width || 40; + + return ( + + + + ) + +} \ No newline at end of file diff --git a/src/components/RecogitoLogo/RecogitoLogo.tsx b/src/components/RecogitoLogo/RecogitoLogo.tsx new file mode 100644 index 00000000..580c4554 --- /dev/null +++ b/src/components/RecogitoLogo/RecogitoLogo.tsx @@ -0,0 +1,33 @@ +export interface RecogitoLogoProps { + + height?: number; + + width?: number; + +} + +/** + * Icon from https://www.svgrepo.com/svg/347710/comment-discussion + * MIT-Licensed + */ +export const RecogitoLogo = (props: RecogitoLogoProps) => { + + const height = props.height || 22; + + const width = props.width || 22; + + return ( + + + + + ) + +} \ No newline at end of file diff --git a/src/components/RecogitoLogo/index.ts b/src/components/RecogitoLogo/index.ts new file mode 100644 index 00000000..a80d7548 --- /dev/null +++ b/src/components/RecogitoLogo/index.ts @@ -0,0 +1,2 @@ +export * from './RecogitoCircleLogo'; +export * from './RecogitoLogo'; \ No newline at end of file diff --git a/src/layouts/project/NavItem.tsx b/src/layouts/project/NavItem.tsx index 4af2df2c..5606b209 100644 --- a/src/layouts/project/NavItem.tsx +++ b/src/layouts/project/NavItem.tsx @@ -1,5 +1,4 @@ -import React from 'react'; -import type { Icon } from "@phosphor-icons/react"; +import type { ReactNode } from 'react'; export interface NavItemProps { @@ -7,7 +6,7 @@ export interface NavItemProps { className?: string; - icon: Icon; + icon: ReactNode; label: string; @@ -26,7 +25,7 @@ export const NavItem = (props: NavItemProps) => { className={props.className ? `${cls} ${props.className}` : cls}>
- {React.createElement(props.icon, { size: 21 })} + {props.icon} diff --git a/src/layouts/project/ProjectSidebar.css b/src/layouts/project/ProjectSidebar.css index 8b3faa36..da57ac8e 100644 --- a/src/layouts/project/ProjectSidebar.css +++ b/src/layouts/project/ProjectSidebar.css @@ -9,6 +9,10 @@ --light-blue: #cbd4e2; } +.project-sidebar .recogito-logo-circle { + margin: 0 0.6em 0 0.3em; +} + .project-sidebar ul { list-style-type: none; margin: 0; @@ -41,7 +45,7 @@ transition: color 100ms ease-in-out; position: relative; top: -1px; - width: 40px; + width: 44px; } .project-sidebar-col.collapsible { diff --git a/src/layouts/project/ProjectSidebar.tsx b/src/layouts/project/ProjectSidebar.tsx index 9ee49284..3a4c383e 100644 --- a/src/layouts/project/ProjectSidebar.tsx +++ b/src/layouts/project/ProjectSidebar.tsx @@ -2,13 +2,13 @@ import { useEffect, useState } from 'react'; import { ArrowLineLeft, Folders, - GooglePodcastsLogo, GraduationCap, Sliders, UsersThree, } from '@phosphor-icons/react'; import { AccountActions } from '@components/AccountActions'; import { Avatar } from '@components/Avatar'; +import { RecogitoCircleLogo } from '@components/RecogitoLogo'; import { NavItem } from './NavItem'; import type { ExtendedProjectData, @@ -73,14 +73,14 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { } label='Recogito' link={`/${lang}/projects`} /> } label={t['Documents']} link={link()} /> @@ -88,7 +88,7 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { {isAdmin && ( } label={t['Collaboration']} link={link('collaboration')} /> @@ -96,7 +96,7 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { } label={t['Assignments']} link={link('assignments')} /> @@ -110,7 +110,7 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { {isAdmin && ( } label={t['Settings']} link={link('settings')} /> From 68c372dc950aed2c00c10222837e307c96533b15 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 22 Jan 2024 11:33:29 +0100 Subject: [PATCH 004/135] A first pass at redesigning the image annotation view --- .../ImageAnnotationDesktop.css | 74 +------- .../ImageAnnotationDesktop.tsx | 158 ++++++++++-------- src/apps/annotation-image/Menubar/Menubar.css | 133 +++++++++++++++ src/apps/annotation-image/Menubar/Menubar.tsx | 145 ++++++++++++++++ src/apps/annotation-image/Menubar/index.ts | 0 src/apps/annotation-image/Toolbar/index.ts | 1 - .../{Toolbar => Toolpanel}/Icons.css | 0 .../{Toolbar => Toolpanel}/Icons.tsx | 0 .../annotation-image/Toolpanel/Toolpanel.css | 69 ++++++++ .../Toolbar.tsx => Toolpanel/Toolpanel.tsx} | 17 +- src/apps/annotation-image/Toolpanel/index.ts | 1 + .../AnnotationDesktop/ViewMenu/ViewMenu.tsx | 2 +- src/components/Branding/BrandFooter.tsx | 24 +++ src/components/Branding/BrandHeader.tsx | 30 ++++ src/components/Branding/Branding.css | 52 ++++++ src/components/Branding/index.ts | 2 + src/components/Presence/PresenceStack.css | 8 - src/components/Presence/PresenceStack.tsx | 2 +- src/components/ProjectCard/ProjectCard.css | 1 + src/layouts/BaseLayout.astro | 6 + src/layouts/project/ProjectLayout.astro | 1 + .../annotate/[context]/[document]/index.astro | 45 ++--- src/themes/default/index.css | 1 - tsconfig.json | 1 + 24 files changed, 595 insertions(+), 178 deletions(-) create mode 100644 src/apps/annotation-image/Menubar/Menubar.css create mode 100644 src/apps/annotation-image/Menubar/Menubar.tsx create mode 100644 src/apps/annotation-image/Menubar/index.ts delete mode 100644 src/apps/annotation-image/Toolbar/index.ts rename src/apps/annotation-image/{Toolbar => Toolpanel}/Icons.css (100%) rename src/apps/annotation-image/{Toolbar => Toolpanel}/Icons.tsx (100%) create mode 100644 src/apps/annotation-image/Toolpanel/Toolpanel.css rename src/apps/annotation-image/{Toolbar/Toolbar.tsx => Toolpanel/Toolpanel.tsx} (86%) create mode 100644 src/apps/annotation-image/Toolpanel/index.ts create mode 100644 src/components/Branding/BrandFooter.tsx create mode 100644 src/components/Branding/BrandHeader.tsx create mode 100644 src/components/Branding/Branding.css create mode 100644 src/components/Branding/index.ts diff --git a/src/apps/annotation-image/ImageAnnotationDesktop.css b/src/apps/annotation-image/ImageAnnotationDesktop.css index b6de9e75..e513a453 100644 --- a/src/apps/annotation-image/ImageAnnotationDesktop.css +++ b/src/apps/annotation-image/ImageAnnotationDesktop.css @@ -1,10 +1,18 @@ @import '@annotorious/react/annotorious-react.css'; .ia-desktop { + display: flex; + flex-direction: column; height: 100%; + overscroll-behavior: none; width: 100%; } +.ia-desktop main { + flex-grow: 1; + position: relative; +} + .ia-osd-container { height: 100%; position: relative; @@ -13,70 +21,4 @@ .openseadragon-canvas { outline: none; -} - -.ia-toolbar-container { - align-items: center; - display: flex; -} - -.ia-toolbar-context { - border: none; - border-radius: 50%; - margin: 0 6px; - transition: opacity 250ms ease-in-out; -} - -.ia-toolbar-context.hidden { - opacity: 0; -} - -.ia-toolbar-context button { - border-radius: 50%; -} - -.ia-toolbar-context button.delete { - background-color: var(--red-500); -} - -.ia-toolbar-context button.delete svg { - color: #fff; -} - -.ia-toolbar { - align-items: center; - bottom: 30px; - border-radius: 9999px; - display: flex; - flex-direction: row; -} - -.ia-toolbar button { - border-radius: 50%; - vertical-align: bottom; -} - -.ia-toolbar button svg { - color: var(--font-dark); -} - -.ia-toolbar :is(button, a.button) + :is(button, a.button) { - margin-left: 6px; -} - -.ia-toolbar section { - padding: 6px; -} - -.ia-toolbar section.privacy { - padding-left: 0; -} - -.ia-desktop .presence-stack { - margin: 4px 8px; -} - -.ia-desktop .presence-stack .avatar { - height: 36px; - width: 36px; } \ No newline at end of file diff --git a/src/apps/annotation-image/ImageAnnotationDesktop.tsx b/src/apps/annotation-image/ImageAnnotationDesktop.tsx index 5a272cf0..06f513d2 100644 --- a/src/apps/annotation-image/ImageAnnotationDesktop.tsx +++ b/src/apps/annotation-image/ImageAnnotationDesktop.tsx @@ -4,13 +4,14 @@ import { getAllDocumentLayersInProject, isDefaultContext } from '@backend/helper import { useLayerPolicies, useTagVocabulary } from '@backend/hooks'; import { supabase } from '@backend/supabaseBrowserClient'; import { Annotation } from '@components/Annotation'; +import { BrandFooter, BrandHeader } from '@components/Branding'; import { LoadingOverlay } from '@components/LoadingOverlay'; import { createAppearenceProvider, PresenceStack } from '@components/Presence'; import { AnnotationDesktop, ViewMenuPanel } from '@components/AnnotationDesktop'; import type { PrivacyMode } from '@components/PrivacySelector'; import { SupabasePlugin } from '@components/SupabasePlugin'; import type { Layer } from 'src/Types'; -import { Toolbar } from './Toolbar'; +import { Toolpanel } from './Toolpanel'; import type { ImageAnnotationProps } from './ImageAnnotation'; import { Annotation as Anno, @@ -26,9 +27,9 @@ import { } from '@annotorious/react'; import './ImageAnnotationDesktop.css'; +import { Menubar } from './Menubar/Menubar'; const SUPABASE: string = import.meta.env.PUBLIC_SUPABASE; - const SUPABASE_API_KEY: string = import.meta.env.PUBLIC_SUPABASE_API_KEY; export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { @@ -151,81 +152,96 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { )} - {policies && ( - +
+ - - - {layers && - layer.id)} - appearanceProvider={appearance} - onInitialLoad={() => setLoading(false)} - onPresence={setPresent} - onConnectError={onConnectError} - privacyMode={privacy === 'PRIVATE'} /> - } - - - - {usePopup && ( - ( - )} /> - )} - -
- -
- -
- - - setFilter(() => f)} - onChangeAnnotationStyle={s => setStyle(() => s)} - beforeSelectAnnotation={beforeSelectAnnotation} /> -
- -
- +
+ +
+ {policies && ( + + + + + {layers && + layer.id)} + appearanceProvider={appearance} + onInitialLoad={() => setLoading(false)} + onPresence={setPresent} + onConnectError={onConnectError} + privacyMode={privacy === 'PRIVATE'} /> + } + + + + {usePopup && ( + ( + )} /> + )} + + {/*
+ +
+ +
+ + + setFilter(() => f)} + onChangeAnnotationStyle={s => setStyle(() => s)} + beforeSelectAnnotation={beforeSelectAnnotation} /> +
+ */} + + + -
-
- )} + + )} + + +
+ +
) diff --git a/src/apps/annotation-image/Menubar/Menubar.css b/src/apps/annotation-image/Menubar/Menubar.css new file mode 100644 index 00000000..80e2dfd6 --- /dev/null +++ b/src/apps/annotation-image/Menubar/Menubar.css @@ -0,0 +1,133 @@ +.ia-menubar { + align-items: center; + background-color: #fff; + box-shadow: 0px 0px 16px -1px rgba(0, 0, 0, 0.15), + 0px 0px 16px -8px rgba(0, 0, 0, 0.25), + 0px 0px 16px -12px rgba(0, 0, 0, 0.32), 0px 0px 2px 0px rgba(0, 0, 0, 0.28); + display: flex; + height: 48px; + justify-content: space-between; + pointer-events: auto; + position: relative; + z-index: 1; +} + +.ia-menubar .ia-menubar-left { + align-items: center; + border-radius: 0 0 12px 0; + border-width: 0 0 1px 1px; + box-sizing: border-box; + display: flex; + padding: 0 20px 0 10px; + pointer-events: all; +} + +.ia-menubar .ia-menubar-left h1 { + font-size: var(--font-tiny); + font-family: Inter; + font-weight: 500; + margin: 0; +} + +.ia-menubar .ia-menubar-left .assignment-icon { + align-items: center; + background-color: var(--font-dark); + border-radius: 50%; + color: #fff; + display: inline-flex; + height: 28px; + justify-content: center; + width: 28px; +} + +.ia-menubar .ia-menubar-left a { + color: var(--font-dark); +} + +.ia-menubar .ia-menubar-title { + padding-right: 0.6em; +} + +.ia-menubar .ia-menubar-left a svg { + display: block; +} + +.ia-menubar .ia-menubar-left span { + color: var(--font-light); +} + +.ia-menubar .ia-menubar-left button { + border-radius: 50%; + height: 36px; + vertical-align: bottom; + width: 36px; +} + +.ia-menubar .ia-menubar-left button svg { + color: var(--font-dark); +} + +.ia-menubar :is(button, a.button) + :is(button, a.button) { + margin-left: 0; +} + +.ia-menubar .ia-menubar-right { + align-items: center; + display: flex; + padding-right: 10px; +} + +.ia-menubar button { + background: transparent; + border: none; + border-radius: 50%; + box-shadow: none; + height: 36px; + min-width: auto; + outline: none; + padding: 0; + vertical-align: bottom; + width: 36px; +} + +.ia-menubar-section { + align-items: center; + display: flex; +} + +.ia-menubar .ia-menubar-right button:hover { + box-shadow: inset 0 0 0 150px rgba(0, 0, 0, 0.06); +} + +.ia-menubar .ia-menubar-right button svg { + color: var(--font-dark); +} + +.ia-menubar .ia-menubar-right button.active { + background-color: var(--bright-blue); + color: #fff; +} + +.ia-menubar .ia-menubar-right button.active svg { + color: #fff; +} + +.ia-menubar .avatar { + height: 30px; + width: 30px; +} + +.ia-menubar .presence-stack .avatar { + height: 34px; + width: 34px; +} + +.ia-menubar .avatar:hover { + box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.06); +} + +.ia-menubar .ia-menubar-me { + padding-left: 10px; +} + + diff --git a/src/apps/annotation-image/Menubar/Menubar.tsx b/src/apps/annotation-image/Menubar/Menubar.tsx new file mode 100644 index 00000000..dbffd8f7 --- /dev/null +++ b/src/apps/annotation-image/Menubar/Menubar.tsx @@ -0,0 +1,145 @@ +import { isMe } from '@recogito/annotorious-supabase'; +import type { DocumentInTaggedContext, Translations } from 'src/Types'; +import { + ArrowsOutSimple, + CaretLeft, + CaretUp, + Chats, + GraduationCap, + ListBullets, + MagnifyingGlassMinus, + MagnifyingGlassPlus, + NotePencil, + StackSimple +} from '@phosphor-icons/react'; + +import './Menubar.css'; +import { PresenceStack } from '@components/Presence'; +import type { PresentUser } from '@annotorious/react'; +import { Avatar } from '@components/Avatar'; + +interface MenubarProps { + + i18n: Translations; + + document: DocumentInTaggedContext; + + present: PresentUser[]; + +} + +export const Menubar = (props: MenubarProps) => { + + const { t } = props.i18n; + + const contextName = props.document.context.name; + + const { id, project_id } = props.document.context; + + const back = contextName ? + `/${props.i18n.lang}/projects/${project_id}/assignments/${id}` : + `/${props.i18n.lang}/projects/${project_id}`; + + const me = props.present.find(isMe)!; + + return ( +
+
+
+ {contextName ? ( + <> + + + + +

+ {contextName} / {props.document.name} +

+ + ) : ( + <> + + + + +

+ {props.document.name} +

+ + )} +
+ +
+ +
+ +
+
+ +
+
+ + + +
+ + {props.present.length > 1 && ( + <> +
+ +
+ +
+ + )} + +
+ +
+ + + + + +
+ +
+ +
+ +
+ + {me && ( +
+ +
+ )} +
+
+ ) + +} \ No newline at end of file diff --git a/src/apps/annotation-image/Menubar/index.ts b/src/apps/annotation-image/Menubar/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/apps/annotation-image/Toolbar/index.ts b/src/apps/annotation-image/Toolbar/index.ts deleted file mode 100644 index 5de1afd2..00000000 --- a/src/apps/annotation-image/Toolbar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Toolbar'; \ No newline at end of file diff --git a/src/apps/annotation-image/Toolbar/Icons.css b/src/apps/annotation-image/Toolpanel/Icons.css similarity index 100% rename from src/apps/annotation-image/Toolbar/Icons.css rename to src/apps/annotation-image/Toolpanel/Icons.css diff --git a/src/apps/annotation-image/Toolbar/Icons.tsx b/src/apps/annotation-image/Toolpanel/Icons.tsx similarity index 100% rename from src/apps/annotation-image/Toolbar/Icons.tsx rename to src/apps/annotation-image/Toolpanel/Icons.tsx diff --git a/src/apps/annotation-image/Toolpanel/Toolpanel.css b/src/apps/annotation-image/Toolpanel/Toolpanel.css new file mode 100644 index 00000000..8679a1f3 --- /dev/null +++ b/src/apps/annotation-image/Toolpanel/Toolpanel.css @@ -0,0 +1,69 @@ +.ia-toolpanel-container { + align-items: center; + bottom: 20px; + display: flex; + justify-content: center; + position: absolute; + width: 100%; +} + +.ia-toolpanel-context { + border: none; + border-radius: 50%; + margin: 0 6px; + transition: opacity 250ms ease-in-out; + width: 38px; +} + +.ia-toolpanel-context.hidden { + opacity: 0; +} + +.ia-toolpanel-context button { + border-radius: 50%; +} + +.ia-toolpanel-context button.delete { + background-color: var(--red-500); +} + +.ia-toolpanel-context button.delete svg { + color: #fff; +} + +.ia-toolpanel { + align-items: center; + bottom: 30px; + border-radius: 9999px; + display: flex; + flex-direction: row; +} + +.ia-toolpanel button { + border-radius: 50%; + vertical-align: bottom; +} + +.ia-toolpanel button svg { + color: var(--font-dark); +} + +.ia-toolpanel :is(button, a.button) + :is(button, a.button) { + margin-left: 3px; +} + +.ia-toolpanel section { + padding: 6px 0; +} + +.ia-toolpanel section:first-child { + padding-left: 6px; +} + +.ia-toolpanel section:last-child { + padding-right: 6px; +} + +.ia-toolpanel section.privacy { + padding-left: 0; +} diff --git a/src/apps/annotation-image/Toolbar/Toolbar.tsx b/src/apps/annotation-image/Toolpanel/Toolpanel.tsx similarity index 86% rename from src/apps/annotation-image/Toolbar/Toolbar.tsx rename to src/apps/annotation-image/Toolpanel/Toolpanel.tsx index 62527076..f931b216 100644 --- a/src/apps/annotation-image/Toolbar/Toolbar.tsx +++ b/src/apps/annotation-image/Toolpanel/Toolpanel.tsx @@ -11,7 +11,9 @@ import { PrivacyMode, PrivacySelector } from '@components/PrivacySelector'; import type { Translations } from 'src/Types'; import { AdminOverrideAlert } from '@components/Annotation/Comment/PublicComment/PublicCommentActions'; -interface ToolbarProps { +import './Toolpanel.css'; + +interface ToolpanelProps { i18n: Translations; isAdmin: boolean; @@ -23,7 +25,8 @@ interface ToolbarProps { onChangePrivacy(mode: PrivacyMode): void; } -export const Toolbar = (props: ToolbarProps) => { +export const Toolpanel = (props: ToolpanelProps) => { + const { t } = props.i18n; const { selected } = useSelection(); @@ -53,10 +56,10 @@ export const Toolbar = (props: ToolbarProps) => { selected.every(({ annotation }) => annotation.target.creator?.id === me.id); return ( -
-
+
+
-
+
- {policies && ( - setLoading(false)} /> - )} + + +
+ {policies && ( + setLoading(false)} /> + )} +
+ +
From 37d1f4be0554d6e64df96ce6f45f449a881530dd Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 22 Jan 2024 15:02:28 +0100 Subject: [PATCH 007/135] Proof-of-concept: new view layout with left + right drawers --- .../AnnotatedImage/AnnotatedImage.tsx | 4 +- .../DrawerLeft/DrawerLeft.tsx | 13 -- src/apps/annotation-image/DrawerLeft/index.ts | 1 - .../DrawerRight/DrawerRight.tsx | 13 -- .../annotation-image/DrawerRight/index.ts | 1 - .../ImageAnnotationDesktop.css | 3 + .../ImageAnnotationDesktop.tsx | 127 ++++++++----- src/apps/annotation-image/Menubar/Menubar.css | 4 +- src/apps/annotation-image/Menubar/Menubar.tsx | 27 ++- .../AnnotationList/AnnotationList.css | 21 ++- .../AnnotationList/AnnotationList.tsx | 4 +- .../DocumentMenu.css | 0 .../DocumentMenu.tsx | 0 .../PDFScaleSelector.tsx | 0 .../index.ts | 0 .../DocumentNotes/DocumentNotes/useNotes.ts | 2 +- .../ColorSettings/ColorCoding.ts | 0 .../ColorSettings/ColorPalettes.ts | 0 .../ColorSettings/ColorSettings.tsx | 0 .../ColorSettings/ColorState.tsx | 0 .../colorCodings/colorByAssignment.ts | 0 .../colorCodings/colorByCreator.ts | 0 .../colorCodings/colorByFirstTag.ts | 0 .../colorCodings/colorByPrivacy.ts | 0 .../ColorSettings/colorCodings/index.ts | 0 .../ColorSettings/index.ts | 0 .../FilterSettings/FilterConfig.ts | 0 .../FilterSettings/FilterSettings.tsx | 0 .../FilterSettings/FilterState.tsx | 0 .../filters/filterByAssignment.ts | 0 .../FilterSettings/filters/filterByCreator.ts | 0 .../FilterSettings/filters/filterByPrivacy.ts | 0 .../FilterSettings/filters/filterByTag.ts | 0 .../FilterSettings/filters/index.ts | 0 .../FilterSettings/index.ts | 0 .../LayersPanelMenuIcon.tsx | 0 .../LayerConfigurationMenuIcon}/index.ts | 0 .../LayerConfigurationPanel.css} | 0 .../LayerConfigurationPanel.tsx} | 6 +- .../LayerConfiguration/index.ts | 4 + .../utils.ts | 0 .../AnnotationDesktop/LayersPanel/index.ts | 4 - .../RightDrawer.css} | 59 ++---- .../RightDrawer/RightDrawer.tsx | 83 +++++++++ .../RightDrawerPanel.ts} | 2 +- .../AnnotationDesktop/RightDrawer/index.ts | 2 + .../AnnotationDesktop/ViewMenu/ViewMenu.tsx | 170 ------------------ .../AnnotationDesktop/ViewMenu/index.ts | 2 - src/components/AnnotationDesktop/index.ts | 20 +-- src/themes/default/button/index.css | 3 +- 50 files changed, 233 insertions(+), 342 deletions(-) delete mode 100644 src/apps/annotation-image/DrawerLeft/DrawerLeft.tsx delete mode 100644 src/apps/annotation-image/DrawerLeft/index.ts delete mode 100644 src/apps/annotation-image/DrawerRight/DrawerRight.tsx delete mode 100644 src/apps/annotation-image/DrawerRight/index.ts rename src/components/AnnotationDesktop/{DocumentMenu => DeprecatedDocumentMenu}/DocumentMenu.css (100%) rename src/components/AnnotationDesktop/{DocumentMenu => DeprecatedDocumentMenu}/DocumentMenu.tsx (100%) rename src/components/AnnotationDesktop/{DocumentMenu => DeprecatedDocumentMenu}/PDFScaleSelector.tsx (100%) rename src/components/AnnotationDesktop/{DocumentMenu => DeprecatedDocumentMenu}/index.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/ColorSettings/ColorCoding.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/ColorSettings/ColorPalettes.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/ColorSettings/ColorSettings.tsx (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/ColorSettings/ColorState.tsx (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/ColorSettings/colorCodings/colorByAssignment.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/ColorSettings/colorCodings/colorByCreator.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/ColorSettings/colorCodings/colorByFirstTag.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/ColorSettings/colorCodings/colorByPrivacy.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/ColorSettings/colorCodings/index.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/ColorSettings/index.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/FilterSettings/FilterConfig.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/FilterSettings/FilterSettings.tsx (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/FilterSettings/FilterState.tsx (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/FilterSettings/filters/filterByAssignment.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/FilterSettings/filters/filterByCreator.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/FilterSettings/filters/filterByPrivacy.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/FilterSettings/filters/filterByTag.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/FilterSettings/filters/index.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/FilterSettings/index.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel/LayersPanelMenuIcon => LayerConfiguration/LayerConfigurationMenuIcon}/LayersPanelMenuIcon.tsx (100%) rename src/components/AnnotationDesktop/{LayersPanel/LayersPanelMenuIcon => LayerConfiguration/LayerConfigurationMenuIcon}/index.ts (100%) rename src/components/AnnotationDesktop/{LayersPanel/LayersPanel.css => LayerConfiguration/LayerConfigurationPanel.css} (100%) rename src/components/AnnotationDesktop/{LayersPanel/LayersPanel.tsx => LayerConfiguration/LayerConfigurationPanel.tsx} (82%) create mode 100644 src/components/AnnotationDesktop/LayerConfiguration/index.ts rename src/components/AnnotationDesktop/{LayersPanel => LayerConfiguration}/utils.ts (100%) delete mode 100644 src/components/AnnotationDesktop/LayersPanel/index.ts rename src/components/AnnotationDesktop/{ViewMenu/ViewMenu.css => RightDrawer/RightDrawer.css} (55%) create mode 100644 src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx rename src/components/AnnotationDesktop/{ViewMenu/ViewMenuPanel.ts => RightDrawer/RightDrawerPanel.ts} (75%) create mode 100644 src/components/AnnotationDesktop/RightDrawer/index.ts delete mode 100644 src/components/AnnotationDesktop/ViewMenu/ViewMenu.tsx delete mode 100644 src/components/AnnotationDesktop/ViewMenu/index.ts diff --git a/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx b/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx index 4d839618..2ef89e3b 100644 --- a/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx +++ b/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx @@ -1,6 +1,6 @@ import { useMemo, useState } from 'react'; import { Annotation } from '@components/Annotation'; -import { AnnotationDesktop } from '@components/AnnotationDesktop'; +import { UndoStack } from '@components/AnnotationDesktop'; import { createAppearenceProvider } from '@components/Presence'; import type { PrivacyMode } from '@components/PrivacySelector'; import { SupabasePlugin } from '@components/SupabasePlugin'; @@ -105,7 +105,7 @@ export const AnnotatedImage = (props: AnnotatedImageProps) => { filter={props.filter} style={props.style}> - {props.layers && diff --git a/src/apps/annotation-image/DrawerLeft/DrawerLeft.tsx b/src/apps/annotation-image/DrawerLeft/DrawerLeft.tsx deleted file mode 100644 index 924f9a26..00000000 --- a/src/apps/annotation-image/DrawerLeft/DrawerLeft.tsx +++ /dev/null @@ -1,13 +0,0 @@ -interface DrawerLeftProps { - - open?: boolean; - -} - -export const DrawerLeft = (props: DrawerLeftProps) => { - - return ( -
- ) - -} \ No newline at end of file diff --git a/src/apps/annotation-image/DrawerLeft/index.ts b/src/apps/annotation-image/DrawerLeft/index.ts deleted file mode 100644 index ba0968db..00000000 --- a/src/apps/annotation-image/DrawerLeft/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './DrawerLeft'; \ No newline at end of file diff --git a/src/apps/annotation-image/DrawerRight/DrawerRight.tsx b/src/apps/annotation-image/DrawerRight/DrawerRight.tsx deleted file mode 100644 index 47441677..00000000 --- a/src/apps/annotation-image/DrawerRight/DrawerRight.tsx +++ /dev/null @@ -1,13 +0,0 @@ -interface DrawerRightProps { - - open?: boolean; - -} - -export const DrawerRight = (props: DrawerRightProps) => { - - return ( -
- ) - -} \ No newline at end of file diff --git a/src/apps/annotation-image/DrawerRight/index.ts b/src/apps/annotation-image/DrawerRight/index.ts deleted file mode 100644 index 31c813d2..00000000 --- a/src/apps/annotation-image/DrawerRight/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './DrawerRight'; \ No newline at end of file diff --git a/src/apps/annotation-image/ImageAnnotationDesktop.css b/src/apps/annotation-image/ImageAnnotationDesktop.css index 7c0ca981..228eb5bc 100644 --- a/src/apps/annotation-image/ImageAnnotationDesktop.css +++ b/src/apps/annotation-image/ImageAnnotationDesktop.css @@ -4,6 +4,7 @@ display: flex; flex-direction: column; height: 100%; + overflow: hidden; overscroll-behavior: none; width: 100%; } @@ -13,11 +14,13 @@ flex-direction: row; flex-grow: 1; position: relative; + overflow: auto; } .ia-annotated-image-container { flex-grow: 1; height: 100%; + overflow: hidden; position: relative; width: 100%; } diff --git a/src/apps/annotation-image/ImageAnnotationDesktop.tsx b/src/apps/annotation-image/ImageAnnotationDesktop.tsx index 37802207..7b0a3ecd 100644 --- a/src/apps/annotation-image/ImageAnnotationDesktop.tsx +++ b/src/apps/annotation-image/ImageAnnotationDesktop.tsx @@ -4,7 +4,7 @@ import { useLayerPolicies, useTagVocabulary } from '@backend/hooks'; import { supabase } from '@backend/supabaseBrowserClient'; import { BrandFooter, BrandHeader } from '@components/Branding'; import { LoadingOverlay } from '@components/LoadingOverlay'; -import { ViewMenuPanel } from '@components/AnnotationDesktop'; +import { ColorState, DocumentNotes, FilterState, RightDrawer, RightDrawerPanel } from '@components/AnnotationDesktop'; import type { Layer } from 'src/Types'; import { AnnotatedImage } from './AnnotatedImage'; import type { ImageAnnotationProps } from './ImageAnnotation'; @@ -18,8 +18,6 @@ import { } from '@annotorious/react'; import './ImageAnnotationDesktop.css'; -import { DrawerLeft } from './DrawerLeft'; -import { DrawerRight } from './DrawerRight'; export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { @@ -31,6 +29,8 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { const [present, setPresent] = useState([]); + const [rightPanel, setRightPanel] = useState(); + const tagVocabulary = useTagVocabulary(props.document.context.project_id); const [style, setStyle] = useState<((a: ImageAnnotation) => DrawingStyle) | undefined>(undefined); @@ -71,14 +71,16 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { const onConnectError = () => window.location.href = `/${props.i18n.lang}/sign-in`; - const onChangeViewMenuPanel = (panel: ViewMenuPanel | undefined) => { - if (panel === ViewMenuPanel.ANNOTATIONS) { + const onSetRightPanel = (panel?: RightDrawerPanel) => { + if (panel === RightDrawerPanel.ANNOTATIONS) { // Don't use the popup if the annotation list is open setUsePopup(false); } else { if (!usePopup) setUsePopup(true) } + + setRightPanel(panel); } const beforeSelectAnnotation = (a?: ImageAnnotation) => { @@ -94,51 +96,78 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { } } + const onError = (error: Error) => { + console.error(error); + // TODO UI feedback + } + return ( -
- {loading && ( - - )} - -
- - - -
- -
- - -
- {policies && ( - setLoading(false)} /> - )} -
- - -
- -
- -
-
+ + + + +
+ {loading && ( + + )} + +
+ + + +
+ +
+
+ +
+ {policies && ( + setLoading(false)} /> + )} +
+ + +
+ +
+ +
+
+
+
+
) } \ No newline at end of file diff --git a/src/apps/annotation-image/Menubar/Menubar.css b/src/apps/annotation-image/Menubar/Menubar.css index 80e2dfd6..deb020c2 100644 --- a/src/apps/annotation-image/Menubar/Menubar.css +++ b/src/apps/annotation-image/Menubar/Menubar.css @@ -9,7 +9,7 @@ justify-content: space-between; pointer-events: auto; position: relative; - z-index: 1; + z-index: 2; } .ia-menubar .ia-menubar-left { @@ -68,7 +68,7 @@ } .ia-menubar :is(button, a.button) + :is(button, a.button) { - margin-left: 0; + margin-left: 2px; } .ia-menubar .ia-menubar-right { diff --git a/src/apps/annotation-image/Menubar/Menubar.tsx b/src/apps/annotation-image/Menubar/Menubar.tsx index 7de3f476..bb576616 100644 --- a/src/apps/annotation-image/Menubar/Menubar.tsx +++ b/src/apps/annotation-image/Menubar/Menubar.tsx @@ -1,4 +1,5 @@ import { isMe } from '@recogito/annotorious-supabase'; +import { RightDrawerPanel } from '@components/AnnotationDesktop'; import { Avatar } from '@components/Avatar'; import { PresenceStack } from '@components/Presence'; import type { PresentUser } from '@annotorious/react'; @@ -25,6 +26,10 @@ interface MenubarProps { present: PresentUser[]; + rightPanel?: RightDrawerPanel; + + onSetRightDrawer(panel?: RightDrawerPanel): void; + } export const Menubar = (props: MenubarProps) => { @@ -41,6 +46,13 @@ export const Menubar = (props: MenubarProps) => { const me = props.present.find(isMe)!; + const toggleRightDrawer = (panel: RightDrawerPanel) => { + if (panel === props.rightPanel) + props.onSetRightDrawer(); + else + props.onSetRightDrawer(panel); + } + return (
@@ -107,15 +119,24 @@ export const Menubar = (props: MenubarProps) => {
- - -
diff --git a/src/components/AnnotationDesktop/AnnotationList/AnnotationList.css b/src/components/AnnotationDesktop/AnnotationList/AnnotationList.css index 20101e0a..41a0f6a8 100644 --- a/src/components/AnnotationDesktop/AnnotationList/AnnotationList.css +++ b/src/components/AnnotationDesktop/AnnotationList/AnnotationList.css @@ -1,42 +1,41 @@ -.anno-sidepanel.annotation-list { - overflow-y: auto; - padding: 0 8px; - scroll-padding: 20px; +.anno-drawer-panel.annotation-list { + box-sizing: border-box; + padding: 0 10px 40px 10px; } -.anno-sidepanel.annotation-list > ul { +.anno-drawer-panel.annotation-list > ul { height: 100%; list-style-type: none; margin: 0; padding: 0; } -.anno-sidepanel.annotation-list .annotation-card { +.anno-drawer-panel.annotation-list .annotation-card { border: 1px solid var(--gray-300); border-radius: 6px; margin: 8px 0; } -.anno-sidepanel.annotation-list .annotation-card:not(.private) { +.anno-drawer-panel.annotation-list .annotation-card:not(.private) { background-color: #fff; } -.anno-sidepanel.annotation-list .annotation-card.selected { +.anno-drawer-panel.annotation-list .annotation-card.selected { box-shadow: 0 0 0 3px var(--button-focus-outline-color); } -.anno-sidepanel.annotation-list .annotation-list-filter { +.anno-drawer-panel.annotation-list .annotation-list-filter { color: var(--font-light); font-size: var(--font-tiny); padding: 0.5em 8px 0em 0; text-align: right; } -.anno-sidepanel.annotation-list .annotation-list-filter label { +.anno-drawer-panel.annotation-list .annotation-list-filter label { margin-right: 0.5ch; } -.anno-sidepanel.annotation-list .annotation-list-filter button { +.anno-drawer-panel.annotation-list .annotation-list-filter button { all: unset; cursor: pointer; text-decoration: underline; diff --git a/src/components/AnnotationDesktop/AnnotationList/AnnotationList.tsx b/src/components/AnnotationDesktop/AnnotationList/AnnotationList.tsx index 6c2724d3..ef3ea950 100644 --- a/src/components/AnnotationDesktop/AnnotationList/AnnotationList.tsx +++ b/src/components/AnnotationDesktop/AnnotationList/AnnotationList.tsx @@ -3,7 +3,7 @@ import { Annotation } from '@components/Annotation'; import type { Policies, Translations } from 'src/Types'; import { SupabaseAnnotation, Visibility } from '@recogito/annotorious-supabase'; import { ViewportFilter, ViewportFilterToggle } from './ViewportFilterToggle'; -import { useFilterSettings } from '../LayersPanel'; +import { useFilterSettings } from '../LayerConfiguration'; import { Annotation as Anno, AnnotationBody, @@ -137,7 +137,7 @@ export const AnnotationList = (props: AnnotationListProps) => { }, [pointerEvent, selected.map(s => s.annotation.id).join('-')]); return ( -
+
diff --git a/src/components/AnnotationDesktop/DocumentMenu/DocumentMenu.css b/src/components/AnnotationDesktop/DeprecatedDocumentMenu/DocumentMenu.css similarity index 100% rename from src/components/AnnotationDesktop/DocumentMenu/DocumentMenu.css rename to src/components/AnnotationDesktop/DeprecatedDocumentMenu/DocumentMenu.css diff --git a/src/components/AnnotationDesktop/DocumentMenu/DocumentMenu.tsx b/src/components/AnnotationDesktop/DeprecatedDocumentMenu/DocumentMenu.tsx similarity index 100% rename from src/components/AnnotationDesktop/DocumentMenu/DocumentMenu.tsx rename to src/components/AnnotationDesktop/DeprecatedDocumentMenu/DocumentMenu.tsx diff --git a/src/components/AnnotationDesktop/DocumentMenu/PDFScaleSelector.tsx b/src/components/AnnotationDesktop/DeprecatedDocumentMenu/PDFScaleSelector.tsx similarity index 100% rename from src/components/AnnotationDesktop/DocumentMenu/PDFScaleSelector.tsx rename to src/components/AnnotationDesktop/DeprecatedDocumentMenu/PDFScaleSelector.tsx diff --git a/src/components/AnnotationDesktop/DocumentMenu/index.ts b/src/components/AnnotationDesktop/DeprecatedDocumentMenu/index.ts similarity index 100% rename from src/components/AnnotationDesktop/DocumentMenu/index.ts rename to src/components/AnnotationDesktop/DeprecatedDocumentMenu/index.ts diff --git a/src/components/AnnotationDesktop/DocumentNotes/DocumentNotes/useNotes.ts b/src/components/AnnotationDesktop/DocumentNotes/DocumentNotes/useNotes.ts index a79048dd..e4eb4d88 100644 --- a/src/components/AnnotationDesktop/DocumentNotes/DocumentNotes/useNotes.ts +++ b/src/components/AnnotationDesktop/DocumentNotes/DocumentNotes/useNotes.ts @@ -9,7 +9,7 @@ import { insertNote, updateVisibility, upsertBody -} from '../../DocumentNotes/DocumentNotes/postgres/pgCrud'; +} from './postgres/pgCrud'; export const useNotes = () => { diff --git a/src/components/AnnotationDesktop/LayersPanel/ColorSettings/ColorCoding.ts b/src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/ColorCoding.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/ColorSettings/ColorCoding.ts rename to src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/ColorCoding.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/ColorSettings/ColorPalettes.ts b/src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/ColorPalettes.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/ColorSettings/ColorPalettes.ts rename to src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/ColorPalettes.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/ColorSettings/ColorSettings.tsx b/src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/ColorSettings.tsx similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/ColorSettings/ColorSettings.tsx rename to src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/ColorSettings.tsx diff --git a/src/components/AnnotationDesktop/LayersPanel/ColorSettings/ColorState.tsx b/src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/ColorState.tsx similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/ColorSettings/ColorState.tsx rename to src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/ColorState.tsx diff --git a/src/components/AnnotationDesktop/LayersPanel/ColorSettings/colorCodings/colorByAssignment.ts b/src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/colorCodings/colorByAssignment.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/ColorSettings/colorCodings/colorByAssignment.ts rename to src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/colorCodings/colorByAssignment.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/ColorSettings/colorCodings/colorByCreator.ts b/src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/colorCodings/colorByCreator.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/ColorSettings/colorCodings/colorByCreator.ts rename to src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/colorCodings/colorByCreator.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/ColorSettings/colorCodings/colorByFirstTag.ts b/src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/colorCodings/colorByFirstTag.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/ColorSettings/colorCodings/colorByFirstTag.ts rename to src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/colorCodings/colorByFirstTag.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/ColorSettings/colorCodings/colorByPrivacy.ts b/src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/colorCodings/colorByPrivacy.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/ColorSettings/colorCodings/colorByPrivacy.ts rename to src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/colorCodings/colorByPrivacy.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/ColorSettings/colorCodings/index.ts b/src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/colorCodings/index.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/ColorSettings/colorCodings/index.ts rename to src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/colorCodings/index.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/ColorSettings/index.ts b/src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/index.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/ColorSettings/index.ts rename to src/components/AnnotationDesktop/LayerConfiguration/ColorSettings/index.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/FilterSettings/FilterConfig.ts b/src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/FilterConfig.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/FilterSettings/FilterConfig.ts rename to src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/FilterConfig.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/FilterSettings/FilterSettings.tsx b/src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/FilterSettings.tsx similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/FilterSettings/FilterSettings.tsx rename to src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/FilterSettings.tsx diff --git a/src/components/AnnotationDesktop/LayersPanel/FilterSettings/FilterState.tsx b/src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/FilterState.tsx similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/FilterSettings/FilterState.tsx rename to src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/FilterState.tsx diff --git a/src/components/AnnotationDesktop/LayersPanel/FilterSettings/filters/filterByAssignment.ts b/src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/filters/filterByAssignment.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/FilterSettings/filters/filterByAssignment.ts rename to src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/filters/filterByAssignment.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/FilterSettings/filters/filterByCreator.ts b/src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/filters/filterByCreator.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/FilterSettings/filters/filterByCreator.ts rename to src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/filters/filterByCreator.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/FilterSettings/filters/filterByPrivacy.ts b/src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/filters/filterByPrivacy.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/FilterSettings/filters/filterByPrivacy.ts rename to src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/filters/filterByPrivacy.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/FilterSettings/filters/filterByTag.ts b/src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/filters/filterByTag.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/FilterSettings/filters/filterByTag.ts rename to src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/filters/filterByTag.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/FilterSettings/filters/index.ts b/src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/filters/index.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/FilterSettings/filters/index.ts rename to src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/filters/index.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/FilterSettings/index.ts b/src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/index.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/FilterSettings/index.ts rename to src/components/AnnotationDesktop/LayerConfiguration/FilterSettings/index.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/LayersPanelMenuIcon/LayersPanelMenuIcon.tsx b/src/components/AnnotationDesktop/LayerConfiguration/LayerConfigurationMenuIcon/LayersPanelMenuIcon.tsx similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/LayersPanelMenuIcon/LayersPanelMenuIcon.tsx rename to src/components/AnnotationDesktop/LayerConfiguration/LayerConfigurationMenuIcon/LayersPanelMenuIcon.tsx diff --git a/src/components/AnnotationDesktop/LayersPanel/LayersPanelMenuIcon/index.ts b/src/components/AnnotationDesktop/LayerConfiguration/LayerConfigurationMenuIcon/index.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/LayersPanelMenuIcon/index.ts rename to src/components/AnnotationDesktop/LayerConfiguration/LayerConfigurationMenuIcon/index.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/LayersPanel.css b/src/components/AnnotationDesktop/LayerConfiguration/LayerConfigurationPanel.css similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/LayersPanel.css rename to src/components/AnnotationDesktop/LayerConfiguration/LayerConfigurationPanel.css diff --git a/src/components/AnnotationDesktop/LayersPanel/LayersPanel.tsx b/src/components/AnnotationDesktop/LayerConfiguration/LayerConfigurationPanel.tsx similarity index 82% rename from src/components/AnnotationDesktop/LayersPanel/LayersPanel.tsx rename to src/components/AnnotationDesktop/LayerConfiguration/LayerConfigurationPanel.tsx index b94268f5..52816fe5 100644 --- a/src/components/AnnotationDesktop/LayersPanel/LayersPanel.tsx +++ b/src/components/AnnotationDesktop/LayerConfiguration/LayerConfigurationPanel.tsx @@ -3,9 +3,9 @@ import type { Layer, Translations } from 'src/Types'; import { ColorSettings } from './ColorSettings'; import { FilterSettings } from './FilterSettings'; -import './LayersPanel.css'; +import './LayerConfigurationPanel.css'; -interface LayersPanelProps { +interface LayerConfigurationPanelProps { i18n: Translations; @@ -19,7 +19,7 @@ interface LayersPanelProps { } -export const LayersPanel = (props: LayersPanelProps) => { +export const LayerConfigurationPanel = (props: LayerConfigurationPanelProps) => { return (
diff --git a/src/components/AnnotationDesktop/LayerConfiguration/index.ts b/src/components/AnnotationDesktop/LayerConfiguration/index.ts new file mode 100644 index 00000000..a4d929d0 --- /dev/null +++ b/src/components/AnnotationDesktop/LayerConfiguration/index.ts @@ -0,0 +1,4 @@ +export * from './ColorSettings'; +export * from './FilterSettings'; +export * from './LayerConfigurationMenuIcon'; +export * from './LayerConfigurationPanel'; \ No newline at end of file diff --git a/src/components/AnnotationDesktop/LayersPanel/utils.ts b/src/components/AnnotationDesktop/LayerConfiguration/utils.ts similarity index 100% rename from src/components/AnnotationDesktop/LayersPanel/utils.ts rename to src/components/AnnotationDesktop/LayerConfiguration/utils.ts diff --git a/src/components/AnnotationDesktop/LayersPanel/index.ts b/src/components/AnnotationDesktop/LayersPanel/index.ts deleted file mode 100644 index b38253d9..00000000 --- a/src/components/AnnotationDesktop/LayersPanel/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './LayersPanel'; -export * from './ColorSettings'; -export * from './FilterSettings'; -export * from './LayersPanelMenuIcon'; \ No newline at end of file diff --git a/src/components/AnnotationDesktop/ViewMenu/ViewMenu.css b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css similarity index 55% rename from src/components/AnnotationDesktop/ViewMenu/ViewMenu.css rename to src/components/AnnotationDesktop/RightDrawer/RightDrawer.css index d379368a..10dc9323 100644 --- a/src/components/AnnotationDesktop/ViewMenu/ViewMenu.css +++ b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css @@ -1,61 +1,26 @@ -.anno-sidebar-container { - max-width: 324px; -} - -.anno-sidebar-container:not([data-collapsed]) { - box-shadow: - 0px 0px 16px -1px rgba(0, 0, 0, 0.15), - 0px 0px 16px -8px rgba(0, 0, 0, 0.25), - 0px 0px 16px -12px rgba(0, 0, 0, 0.32), - 0px 0px 2px 0px rgba(0, 0, 0, 0.28); -} - -.view-menu { - border-radius: 0 0 0 12px; - border-width: 0 0 1px 1px; - box-sizing: border-box; - display: flex; - padding: 0 5px; - pointer-events: all; -} - -.anno-sidebar-container:not([data-collapsed]) .view-menu { - border-radius: 0; - box-shadow: none; -} - -.anno-sidebar-container { - display: flex; - flex-direction: column; +.anno-right-drawer { + overflow-y: scroll; + pointer-events: auto; + scroll-padding: 20px; + z-index: 1; } .anno-sidebar-container aside { background-color: var(--gray-50); + box-sizing: border-box; border-top: 1px solid var(--gray-200); - flex-grow: 1; - overflow-y: auto; - pointer-events: all; } -.view-menu button { - border-radius: 50%; - height: 36px; - vertical-align: bottom; - width: 36px; +.anno-right-drawer:not([data-collapsed]) { + box-shadow: + 0px 0px 16px -1px rgba(0, 0, 0, 0.15), + 0px 0px 16px -8px rgba(0, 0, 0, 0.25), + 0px 0px 16px -12px rgba(0, 0, 0, 0.32), + 0px 0px 2px 0px rgba(0, 0, 0, 0.28); } -.view-menu button svg { - color: var(--font-dark); -} -.view-menu :is(button, a.button) + :is(button, a.button) { - margin-left: 0; -} -.view-menu .avatar { - height: 36px; - width: 36px; -} .view-menu .close { text-align: right; diff --git a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx new file mode 100644 index 00000000..8001ad90 --- /dev/null +++ b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx @@ -0,0 +1,83 @@ +import { useTransition, animated } from '@react-spring/web' +import { isMe } from '@recogito/annotorious-supabase'; +import type { Annotation, DrawingStyle, PresentUser } from '@annotorious/react'; +import type { Layer, Policies, Translations } from 'src/Types'; +import { RightDrawerPanel } from './RightDrawerPanel'; +import { AnnotationList } from '../AnnotationList'; +import { LayerConfigurationPanel } from '../LayerConfiguration'; +import { DocumentNotesList } from '../DocumentNotes'; + +import './RightDrawer.css'; + +interface RightDrawerProps { + + i18n: Translations; + + present: PresentUser[]; + + currentPanel?: RightDrawerPanel; + + policies?: Policies; + + sorting?: ((a: Annotation, b: Annotation) => number); + + layers?: Layer[]; + + tagVocabulary?: string[]; + + beforeSelectAnnotation(a?: Annotation): void; + + onChangeAnnotationFilter(fn: ((a: Annotation) => boolean)): void; + + onChangeAnnotationStyle(fn: ((a: Annotation) => DrawingStyle)): void; + +} + +export const RightDrawer = (props: RightDrawerProps) => { + + const me = props.present.find(isMe)!; + + const drawerTransition = useTransition([props.currentPanel], { + from: { width: 0 }, + enter: { width: 420 }, + leave: { width: 0 }, + config: { + duration: 100 + } + }); + + return drawerTransition((style, panel) => panel && ( + + + + + ) + ) + +} \ No newline at end of file diff --git a/src/components/AnnotationDesktop/ViewMenu/ViewMenuPanel.ts b/src/components/AnnotationDesktop/RightDrawer/RightDrawerPanel.ts similarity index 75% rename from src/components/AnnotationDesktop/ViewMenu/ViewMenuPanel.ts rename to src/components/AnnotationDesktop/RightDrawer/RightDrawerPanel.ts index 7c3fe659..b8b48908 100644 --- a/src/components/AnnotationDesktop/ViewMenu/ViewMenuPanel.ts +++ b/src/components/AnnotationDesktop/RightDrawer/RightDrawerPanel.ts @@ -1,4 +1,4 @@ -export enum ViewMenuPanel { +export enum RightDrawerPanel { ANNOTATIONS = 'ANNOTATIONS', diff --git a/src/components/AnnotationDesktop/RightDrawer/index.ts b/src/components/AnnotationDesktop/RightDrawer/index.ts new file mode 100644 index 00000000..eb16cf15 --- /dev/null +++ b/src/components/AnnotationDesktop/RightDrawer/index.ts @@ -0,0 +1,2 @@ +export * from './RightDrawer'; +export * from './RightDrawerPanel'; diff --git a/src/components/AnnotationDesktop/ViewMenu/ViewMenu.tsx b/src/components/AnnotationDesktop/ViewMenu/ViewMenu.tsx deleted file mode 100644 index c8ddc9ac..00000000 --- a/src/components/AnnotationDesktop/ViewMenu/ViewMenu.tsx +++ /dev/null @@ -1,170 +0,0 @@ -import { useState } from 'react'; -import type { PostgrestError } from '@supabase/supabase-js'; -import { Chats, X } from '@phosphor-icons/react'; -import { useTransition, animated } from '@react-spring/web' -import { Avatar } from '@components/Avatar'; -import { isMe } from '@recogito/annotorious-supabase'; -import type { Annotation, DrawingStyle, PresentUser } from '@annotorious/react'; -import type { Layer, Policies, Translations } from 'src/Types'; -import { ViewMenuPanel } from './ViewMenuPanel'; -import { AnnotationList } from '../AnnotationList'; -import { LayersPanel, LayersPanelMenuIcon } from '../LayersPanel'; -import { DocumentNotes, DocumentNotesList, DocumentNotesMenuIcon } from '../DocumentNotes'; -import { ColorState, FilterState } from '../LayersPanel'; - -import './ViewMenu.css'; - -interface ViewMenuProps { - - i18n: Translations; - - present: PresentUser[]; - - policies?: Policies; - - layers?: Layer[]; - - channel: string; - - defaultLayer?: string; - - sorting?: ((a: Annotation, b: Annotation) => number); - - tagVocabulary?: string[]; - - onChangePanel(panel: ViewMenuPanel | undefined): void; - - beforeSelectAnnotation(a?: Annotation): void; - - onChangeAnnotationFilter(fn: ((a: Annotation) => boolean)): void; - - onChangeAnnotationStyle(fn: ((a: Annotation) => DrawingStyle)): void; - -} - -export const ViewMenu = (props: ViewMenuProps) => { - - const { t } = props.i18n; - - const me = props.present.find(isMe)!; - - const [panel, _setPanel] = useState(); - - const headerTransition = useTransition([panel], { - from: { opacity: 0, width: 0 }, - enter: { opacity: 1, width: 140 }, - leave: { opacity: 0, width: 0 }, - config: { - duration: 125 - } - }); - - const panelTransition = useTransition([panel], { - from: { opacity: 0 }, - enter: { opacity: 1 }, - leave: { opacity: 0 }, - config: { - duration: 100 - } - }); - - const setPanel = (p: ViewMenuPanel | undefined) => { - _setPanel(p); - props.onChangePanel(p); - } - - const togglePanel = (p: ViewMenuPanel) => - panel === p ? setPanel(undefined) : setPanel(p); - - const onError = (error: Error | PostgrestError) => { - console.error(error); - // TODO UI feedback - } - - return ( -
- - - - - -
-
- - - togglePanel(ViewMenuPanel.LAYERS)} /> - - togglePanel(ViewMenuPanel.DOCUMENT_NOTES)} /> -
- - {me && ( -
- -
- )} - - {headerTransition((style, panel) => panel && ( - - - - ))} -
- - {panelTransition((style, panel) => panel && ( - - {panel === ViewMenuPanel.ANNOTATIONS ? ( - - ) : panel === ViewMenuPanel.LAYERS ? ( - - ) : panel === ViewMenuPanel.DOCUMENT_NOTES ? props.defaultLayer && ( - - ) : undefined} - - ))} -
-
-
-
- ) - -} \ No newline at end of file diff --git a/src/components/AnnotationDesktop/ViewMenu/index.ts b/src/components/AnnotationDesktop/ViewMenu/index.ts deleted file mode 100644 index bb4f3701..00000000 --- a/src/components/AnnotationDesktop/ViewMenu/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './ViewMenu'; -export * from './ViewMenuPanel'; \ No newline at end of file diff --git a/src/components/AnnotationDesktop/index.ts b/src/components/AnnotationDesktop/index.ts index 6ef17d47..5e9316a5 100644 --- a/src/components/AnnotationDesktop/index.ts +++ b/src/components/AnnotationDesktop/index.ts @@ -1,15 +1,5 @@ -import { DocumentMenu } from './DocumentMenu'; -import { UndoStack } from './UndoStack'; -import { ViewMenu } from './ViewMenu'; - -export const AnnotationDesktop = { - - DocumentMenu, - - UndoStack, - - ViewMenu - -} - -export { ViewMenuPanel } from './ViewMenu' +export * from './AnnotationList'; +export * from './DocumentNotes'; +export * from './LayerConfiguration'; +export * from './RightDrawer'; +export * from './UndoStack'; diff --git a/src/themes/default/button/index.css b/src/themes/default/button/index.css index 53f91255..876a0f45 100644 --- a/src/themes/default/button/index.css +++ b/src/themes/default/button/index.css @@ -52,8 +52,7 @@ button:disabled svg { } button:hover:not(:disabled), a.button:hover { - box-shadow: - inset 0 0 0 150px rgba(0, 0, 0, 0.06); + box-shadow: inset 0 0 0 150px rgba(0, 0, 0, 0.06); } button:focus-visible { From 5afc26c55488b62642b2d5d658da36d9a340b008 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Mon, 22 Jan 2024 15:29:54 +0100 Subject: [PATCH 008/135] Fighting animation glitches --- .../RightDrawer/RightDrawer.css | 9 ++- .../RightDrawer/RightDrawer.tsx | 78 ++++++++++--------- 2 files changed, 48 insertions(+), 39 deletions(-) diff --git a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css index 10dc9323..b9bcc2bc 100644 --- a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css +++ b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css @@ -1,7 +1,9 @@ .anno-right-drawer { overflow-y: scroll; pointer-events: auto; + position: relative; scroll-padding: 20px; + width: 420px; z-index: 1; } @@ -9,6 +11,10 @@ background-color: var(--gray-50); box-sizing: border-box; border-top: 1px solid var(--gray-200); + position: absolute; + left: 0; + width: 100%; + height: 100%; } .anno-right-drawer:not([data-collapsed]) { @@ -19,9 +25,6 @@ 0px 0px 2px 0px rgba(0, 0, 0, 0.28); } - - - .view-menu .close { text-align: right; padding-right: 0; diff --git a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx index 8001ad90..cec24bcd 100644 --- a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx +++ b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx @@ -1,3 +1,4 @@ +import { useLayoutEffect, useRef } from 'react'; import { useTransition, animated } from '@react-spring/web' import { isMe } from '@recogito/annotorious-supabase'; import type { Annotation, DrawingStyle, PresentUser } from '@annotorious/react'; @@ -35,49 +36,54 @@ interface RightDrawerProps { export const RightDrawer = (props: RightDrawerProps) => { + const previous = useRef(); + const me = props.present.find(isMe)!; const drawerTransition = useTransition([props.currentPanel], { - from: { width: 0 }, - enter: { width: 420 }, - leave: { width: 0 }, + from: previous.current ? { opacity: 0 } : { transform: 'translateX(420px)', opacity: 0 }, + enter: { transform: 'translateX(0px)', opacity: 1 }, + leave: props.currentPanel ? { opacity:0 } : { transform: 'translateX(420px)', opacity: 0 }, config: { - duration: 100 + duration: previous.current ? 0 : 250 } }); + useLayoutEffect(() => { + previous.current = props.currentPanel; + }, [props.currentPanel]) + return drawerTransition((style, panel) => panel && ( - - - - - ) - ) + + + + + )) } \ No newline at end of file From a81a8207129b5692d37ce2ecd91ba4cd58b7bc50 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 25 Jan 2024 11:46:27 +0100 Subject: [PATCH 009/135] Figured out the right drawer layout + transition animation setup --- .../AnnotatedImage/AnnotatedImage.tsx | 3 ++- .../ImageAnnotationDesktop.css | 12 +++++++--- .../RightDrawer/RightDrawer.css | 23 ++++++++----------- .../RightDrawer/RightDrawer.tsx | 23 ++++++++++++------- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx b/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx index 2ef89e3b..ec0ce386 100644 --- a/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx +++ b/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx @@ -74,7 +74,8 @@ export const AnnotatedImage = (props: AnnotatedImageProps) => { clickToZoom: false }, showNavigationControl: false, - crossOriginPolicy: 'Anonymous' + crossOriginPolicy: 'Anonymous', + minZoomLevel: 0.4 }), [props.document.meta_data?.url]); const selectAction = (annotation: ImageAnnotation) => { diff --git a/src/apps/annotation-image/ImageAnnotationDesktop.css b/src/apps/annotation-image/ImageAnnotationDesktop.css index 228eb5bc..6f3e6378 100644 --- a/src/apps/annotation-image/ImageAnnotationDesktop.css +++ b/src/apps/annotation-image/ImageAnnotationDesktop.css @@ -10,11 +10,9 @@ } .ia-desktop main { - display: flex; - flex-direction: row; flex-grow: 1; position: relative; - overflow: auto; + overflow: hidden; } .ia-annotated-image-container { @@ -32,4 +30,12 @@ .openseadragon-canvas { outline: none; +} + +.ia-drawer { + height: 100%; + overflow-y: auto; + pointer-events: auto; + position: absolute; + z-index: 1; } \ No newline at end of file diff --git a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css index b9bcc2bc..a5f23d26 100644 --- a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css +++ b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css @@ -1,23 +1,18 @@ -.anno-right-drawer { - overflow-y: scroll; - pointer-events: auto; - position: relative; - scroll-padding: 20px; - width: 420px; - z-index: 1; +.ia-right-drawer { + background-color: var(--gray-100); + right: 0; + scroll-padding: 40px; + top: 0; + transform: translateX(360px); + width: 360px; } -.anno-sidebar-container aside { - background-color: var(--gray-50); +.ia-right-drawer aside { box-sizing: border-box; border-top: 1px solid var(--gray-200); - position: absolute; - left: 0; - width: 100%; - height: 100%; } -.anno-right-drawer:not([data-collapsed]) { +.ia-right-drawer:not([data-collapsed]) { box-shadow: 0px 0px 16px -1px rgba(0, 0, 0, 0.15), 0px 0px 16px -8px rgba(0, 0, 0, 0.25), diff --git a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx index cec24bcd..51038e93 100644 --- a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx +++ b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx @@ -1,4 +1,4 @@ -import { useLayoutEffect, useRef } from 'react'; +import { useEffect, useRef } from 'react'; import { useTransition, animated } from '@react-spring/web' import { isMe } from '@recogito/annotorious-supabase'; import type { Annotation, DrawingStyle, PresentUser } from '@annotorious/react'; @@ -36,27 +36,34 @@ interface RightDrawerProps { export const RightDrawer = (props: RightDrawerProps) => { + // We need to keep the current panel until exit transition is done const previous = useRef(); const me = props.present.find(isMe)!; + const shouldAnimate = + // Drawer closed, and should open + !previous.current && props.currentPanel || + // Drawer open, and should close + previous.current && !props.currentPanel; + const drawerTransition = useTransition([props.currentPanel], { - from: previous.current ? { opacity: 0 } : { transform: 'translateX(420px)', opacity: 0 }, + from: { transform: 'translateX(180px)', opacity: 0 }, enter: { transform: 'translateX(0px)', opacity: 1 }, - leave: props.currentPanel ? { opacity:0 } : { transform: 'translateX(420px)', opacity: 0 }, + leave: { transform: 'translateX(180px)', opacity: 0 }, config: { - duration: previous.current ? 0 : 250 + duration: shouldAnimate ? 120 : 0 } }); - useLayoutEffect(() => { + useEffect(() => { previous.current = props.currentPanel; }, [props.currentPanel]) return drawerTransition((style, panel) => panel && ( - +
@@ -157,8 +154,8 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { present={present} tagVocabulary={tagVocabulary} beforeSelectAnnotation={beforeSelectAnnotation} - onChangeAnnotationFilter={setFilter} - onChangeAnnotationStyle={setStyle} /> + onChangeAnnotationFilter={f => setFilter(() => f)} + onChangeAnnotationStyle={s => setStyle(() => s)} />
diff --git a/src/apps/annotation-image/Menubar/Menubar.tsx b/src/apps/annotation-image/Menubar/Menubar.tsx index bb576616..bb7d7a05 100644 --- a/src/apps/annotation-image/Menubar/Menubar.tsx +++ b/src/apps/annotation-image/Menubar/Menubar.tsx @@ -46,6 +46,10 @@ export const Menubar = (props: MenubarProps) => { const me = props.present.find(isMe)!; + const onZoom = (factor: number) => { + // viewer.viewport.zoomBy(factor); + } + const toggleRightDrawer = (panel: RightDrawerPanel) => { if (panel === props.rightPanel) props.onSetRightDrawer(); @@ -90,19 +94,19 @@ export const Menubar = (props: MenubarProps) => {
- -
@@ -123,21 +127,21 @@ export const Menubar = (props: MenubarProps) => { className={props.rightPanel === RightDrawerPanel.ANNOTATIONS ? 'active' : undefined} aria-label={t['Show annotation list']} onClick={() => toggleRightDrawer(RightDrawerPanel.ANNOTATIONS)}> - +
@@ -145,7 +149,7 @@ export const Menubar = (props: MenubarProps) => {
diff --git a/src/components/AnnotationDesktop/AnnotationList/AnnotationList.tsx b/src/components/AnnotationDesktop/AnnotationList/AnnotationList.tsx index ef3ea950..41ea7fa5 100644 --- a/src/components/AnnotationDesktop/AnnotationList/AnnotationList.tsx +++ b/src/components/AnnotationDesktop/AnnotationList/AnnotationList.tsx @@ -127,11 +127,13 @@ export const AnnotationList = (props: AnnotationListProps) => { useEffect(() => { // Scroll the first selected card into view if (selected?.length > 0) { - const card = el.current?.querySelector('.selected'); - if (card) - card.scrollIntoView({ behavior: 'smooth' }); + setTimeout(() => { + const card = el.current?.querySelector('.selected'); + if (card) + card.scrollIntoView({ behavior: 'smooth' }); + }, 250); } - + // Don't focus reply before pointer up, otherwise the selection breaks! setAutofocus(pointerEvent?.type === 'pointerup'); }, [pointerEvent, selected.map(s => s.annotation.id).join('-')]); diff --git a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css index a5f23d26..2251f929 100644 --- a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css +++ b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css @@ -9,7 +9,7 @@ .ia-right-drawer aside { box-sizing: border-box; - border-top: 1px solid var(--gray-200); + padding: 0 5px; } .ia-right-drawer:not([data-collapsed]) { From 4428c2715a79a3a56bb8c2ebb4b11aca9dd04a24 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 25 Jan 2024 12:36:34 +0100 Subject: [PATCH 011/135] Re-enabled notification pips on layers + notes menu icon --- package.json | 2 +- src/apps/annotation-image/Menubar/Menubar.css | 2 +- src/apps/annotation-image/Menubar/Menubar.tsx | 30 +++++++++---------- .../RightDrawer/RightDrawer.css | 16 ++-------- 4 files changed, 19 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index c7b2dfa8..1c5668fa 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.1", "scripts": { "dev": "astro dev", - "start": "astro dev --host", + "start": "astro dev", "build": "astro build", "build-node": "astro build --config astro.config.node.mjs", "preview-node": "node ./dist/server/entry.mjs", diff --git a/src/apps/annotation-image/Menubar/Menubar.css b/src/apps/annotation-image/Menubar/Menubar.css index deb020c2..04f54b98 100644 --- a/src/apps/annotation-image/Menubar/Menubar.css +++ b/src/apps/annotation-image/Menubar/Menubar.css @@ -67,7 +67,7 @@ color: var(--font-dark); } -.ia-menubar :is(button, a.button) + :is(button, a.button) { +.ia-menubar :is(button, a.button, .with-notification) + :is(button, a.button, .with-notification) { margin-left: 2px; } diff --git a/src/apps/annotation-image/Menubar/Menubar.tsx b/src/apps/annotation-image/Menubar/Menubar.tsx index bb7d7a05..d78b754a 100644 --- a/src/apps/annotation-image/Menubar/Menubar.tsx +++ b/src/apps/annotation-image/Menubar/Menubar.tsx @@ -1,9 +1,13 @@ import { isMe } from '@recogito/annotorious-supabase'; -import { RightDrawerPanel } from '@components/AnnotationDesktop'; +import type { PresentUser } from '@annotorious/react'; import { Avatar } from '@components/Avatar'; import { PresenceStack } from '@components/Presence'; -import type { PresentUser } from '@annotorious/react'; import type { DocumentInTaggedContext, Translations } from 'src/Types'; +import { + DocumentNotesMenuIcon, + LayersPanelMenuIcon, + RightDrawerPanel +} from '@components/AnnotationDesktop'; import { ArrowsOutSimple, CaretLeft, @@ -12,8 +16,6 @@ import { ListBullets, MagnifyingGlassMinus, MagnifyingGlassPlus, - NotePencil, - StackSimple } from '@phosphor-icons/react'; import './Menubar.css'; @@ -130,19 +132,15 @@ export const Menubar = (props: MenubarProps) => { - + toggleRightDrawer(RightDrawerPanel.LAYERS)} /> - + toggleRightDrawer(RightDrawerPanel.DOCUMENT_NOTES)} />
diff --git a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css index 2251f929..ed644c80 100644 --- a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css +++ b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css @@ -20,17 +20,12 @@ 0px 0px 2px 0px rgba(0, 0, 0, 0.28); } -.view-menu .close { - text-align: right; - padding-right: 0; -} - -.view-menu .with-notification { +.with-notification { display: inline-block; position: relative; } -.view-menu .notification-bubble { +.notification-bubble { all: unset; align-items: center; background-color: var(--bright-blue); @@ -45,12 +40,7 @@ margin: 0; padding: 0; position: absolute; - right: 0; - top: -1px; - width: 13px; -} - -.view-menu .with-notification.active .notification-bubble { right: -2px; top: -2px; + width: 13px; } \ No newline at end of file From f474429c42a0dadcfb42d1969b60df7f92fb1d5c Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 25 Jan 2024 12:43:25 +0100 Subject: [PATCH 012/135] Branding/header footer now collapsible --- .../AnnotatedImage/AnnotatedImage.tsx | 3 ++- .../annotation-image/ImageAnnotationDesktop.tsx | 15 +++++++++++---- src/apps/annotation-image/Menubar/Menubar.tsx | 4 +++- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx b/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx index d4e3153d..75e41472 100644 --- a/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx +++ b/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx @@ -76,7 +76,8 @@ export const AnnotatedImage = (props: AnnotatedImageProps) => { showNavigationControl: false, crossOriginPolicy: 'Anonymous', minZoomLevel: 0.4, - visibilityRatio: 0.2 + visibilityRatio: 0.2, + preserveImageSizeOnResize: true }), [props.document.meta_data?.url]); const selectAction = (annotation: ImageAnnotation) => { diff --git a/src/apps/annotation-image/ImageAnnotationDesktop.tsx b/src/apps/annotation-image/ImageAnnotationDesktop.tsx index 5f1f6c37..daec4b43 100644 --- a/src/apps/annotation-image/ImageAnnotationDesktop.tsx +++ b/src/apps/annotation-image/ImageAnnotationDesktop.tsx @@ -27,6 +27,8 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { const [loading, setLoading] = useState(true); + const [showBranding, setShowBranding] = useState(true); + const [present, setPresent] = useState([]); const [rightPanel, setRightPanel] = useState(); @@ -113,13 +115,16 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { )}
- + {showBranding && ( + + )} setShowBranding(!showBranding)} onSetRightDrawer={onSetRightPanel} />
@@ -158,9 +163,11 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { onChangeAnnotationStyle={s => setStyle(() => s)} /> -
- -
+ {showBranding && ( +
+ +
+ )}
diff --git a/src/apps/annotation-image/Menubar/Menubar.tsx b/src/apps/annotation-image/Menubar/Menubar.tsx index d78b754a..2109eae0 100644 --- a/src/apps/annotation-image/Menubar/Menubar.tsx +++ b/src/apps/annotation-image/Menubar/Menubar.tsx @@ -30,6 +30,8 @@ interface MenubarProps { rightPanel?: RightDrawerPanel; + onToggleBranding(): void; + onSetRightDrawer(panel?: RightDrawerPanel): void; } @@ -146,7 +148,7 @@ export const Menubar = (props: MenubarProps) => {
-
From 374b56fb51dcf08a3ebc6e18d62e6925e28f23bf Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 25 Jan 2024 12:59:25 +0100 Subject: [PATCH 013/135] Enabled menubar zoom icons --- .../annotation-image/AnnotatedImage/AnnotatedImage.tsx | 8 +++++--- src/apps/annotation-image/ImageAnnotationDesktop.tsx | 10 +++++++++- src/apps/annotation-image/Menubar/Menubar.tsx | 10 ++++------ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx b/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx index 75e41472..920f521c 100644 --- a/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx +++ b/src/apps/annotation-image/AnnotatedImage/AnnotatedImage.tsx @@ -1,4 +1,5 @@ -import { useMemo, useState } from 'react'; +import { forwardRef, useMemo, useState } from 'react'; +import type OpenSeadragon from 'openseadragon'; import { Annotation } from '@components/Annotation'; import { UndoStack } from '@components/AnnotationDesktop'; import { createAppearenceProvider } from '@components/Presence'; @@ -54,7 +55,7 @@ interface AnnotatedImageProps { } -export const AnnotatedImage = (props: AnnotatedImageProps) => { +export const AnnotatedImage = forwardRef((props, ref) => { const { i18n, policies, present, tagVocabulary } = props; @@ -126,6 +127,7 @@ export const AnnotatedImage = (props: AnnotatedImageProps) => { } @@ -149,4 +151,4 @@ export const AnnotatedImage = (props: AnnotatedImageProps) => { ) -} \ No newline at end of file +}); \ No newline at end of file diff --git a/src/apps/annotation-image/ImageAnnotationDesktop.tsx b/src/apps/annotation-image/ImageAnnotationDesktop.tsx index daec4b43..d53e8fd1 100644 --- a/src/apps/annotation-image/ImageAnnotationDesktop.tsx +++ b/src/apps/annotation-image/ImageAnnotationDesktop.tsx @@ -1,4 +1,5 @@ -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; +import type OpenSeadragon from 'openseadragon'; import { getAllDocumentLayersInProject, isDefaultContext } from '@backend/helpers'; import { useLayerPolicies, useTagVocabulary } from '@backend/hooks'; import { supabase } from '@backend/supabaseBrowserClient'; @@ -23,6 +24,8 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { const anno = useAnnotator(); + const viewer = useRef(null); + const policies = useLayerPolicies(props.document.layers[0].id); const [loading, setLoading] = useState(true); @@ -73,6 +76,9 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { const onConnectError = () => window.location.href = `/${props.i18n.lang}/sign-in`; + const onZoom = (factor: number) => + viewer.current?.viewport.zoomBy(factor); + const onSetRightPanel = (panel?: RightDrawerPanel) => { if (panel === RightDrawerPanel.ANNOTATIONS) setUsePopup(false); // Don't use the popup if annotation list is open @@ -124,6 +130,7 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { document={props.document} present={present} rightPanel={rightPanel} + onZoom={onZoom} onToggleBranding={() => setShowBranding(!showBranding)} onSetRightDrawer={onSetRightPanel} />
@@ -134,6 +141,7 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => {
{policies && ( { const me = props.present.find(isMe)!; - const onZoom = (factor: number) => { - // viewer.viewport.zoomBy(factor); - } - const toggleRightDrawer = (panel: RightDrawerPanel) => { if (panel === props.rightPanel) props.onSetRightDrawer(); @@ -105,11 +103,11 @@ export const Menubar = (props: MenubarProps) => {
- -
From e63e821f7ae607c07f3d4cb183b304fa7047394f Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 25 Jan 2024 13:28:30 +0100 Subject: [PATCH 014/135] CSS tweak --- src/layouts/HeaderLayout.astro | 1 - 1 file changed, 1 deletion(-) diff --git a/src/layouts/HeaderLayout.astro b/src/layouts/HeaderLayout.astro index f6817816..bcf00dee 100644 --- a/src/layouts/HeaderLayout.astro +++ b/src/layouts/HeaderLayout.astro @@ -80,7 +80,6 @@ const favicon = `/${config.branding.favicon}` || '/favicon.svg'; .slot-container { bottom: 0; - display: flex; flex-direction: column; margin: 50px 0; position: absolute; From 73af9d3f10895163f6165816dc7ac006a5b65130 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 25 Jan 2024 13:32:21 +0100 Subject: [PATCH 015/135] Fixed regressions in text view, after image view changes --- .../annotation-text/TextAnnotationDesktop.css | 3 +-- .../annotation-text/TextAnnotationDesktop.tsx | 17 ++++++++--------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/apps/annotation-text/TextAnnotationDesktop.css b/src/apps/annotation-text/TextAnnotationDesktop.css index 3f7c4a1f..98a64997 100644 --- a/src/apps/annotation-text/TextAnnotationDesktop.css +++ b/src/apps/annotation-text/TextAnnotationDesktop.css @@ -1,7 +1,6 @@ .r6o-highlight-layer { box-sizing: border-box; - border: 2px solid red; - z-index: 99999 !important; + z-index: 99 !important; } .content-wrapper { diff --git a/src/apps/annotation-text/TextAnnotationDesktop.tsx b/src/apps/annotation-text/TextAnnotationDesktop.tsx index a7fa1707..39c44fea 100644 --- a/src/apps/annotation-text/TextAnnotationDesktop.tsx +++ b/src/apps/annotation-text/TextAnnotationDesktop.tsx @@ -22,10 +22,6 @@ import { import { useLayerPolicies, useTagVocabulary } from '@backend/hooks'; import { PresenceStack, createAppearenceProvider } from '@components/Presence'; import { Annotation } from '@components/Annotation'; -import { - AnnotationDesktop, - ViewMenuPanel, -} from '@components/AnnotationDesktop'; import { LoadingOverlay } from '@components/LoadingOverlay'; import type { PrivacyMode } from '@components/PrivacySelector'; import { SupabasePlugin } from '@components/SupabasePlugin'; @@ -39,6 +35,7 @@ import './TEI.css'; import './TextAnnotationDesktop.css'; import '@recogito/react-text-annotator/react-text-annotator.css'; import { DynamicStyle } from '@components/DynamicStyle'; +import { RightDrawerPanel, UndoStack } from '@components/AnnotationDesktop'; const SUPABASE = import.meta.env.PUBLIC_SUPABASE; @@ -114,8 +111,8 @@ export const TextAnnotationDesktop = (props: TextAnnotationProps) => { // max number of avatars displayed in the top right const limit = 5; - const onChangeViewMenuPanel = (panel: ViewMenuPanel | undefined) => { - if (panel === ViewMenuPanel.ANNOTATIONS) { + const onChangeViewMenuPanel = (panel: RightDrawerPanel | undefined) => { + if (panel === RightDrawerPanel.ANNOTATIONS) { // Don't use the popup if the annotation list is open setUsePopup(false); } else { @@ -194,7 +191,7 @@ export const TextAnnotationDesktop = (props: TextAnnotationProps) => {
- + {layers && ( { )}
- + /> */}
+ {/* { onChangeAnnotationStyle={(s) => setStyle(() => s)} beforeSelectAnnotation={beforeSelectAnnotation} /> + */}
From df7e545609bd721aa2b060aa7f48a67f71fcf31f Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 25 Jan 2024 14:11:55 +0100 Subject: [PATCH 016/135] Started full refactoring of the text annotation view --- .../AnnotatedText/AnnotatedText.tsx | 145 ++++++++++++ .../annotation-text/AnnotatedText/index.ts | 1 + src/apps/annotation-text/Menubar/Menubar.css | 0 src/apps/annotation-text/Menubar/Menubar.tsx | 15 ++ src/apps/annotation-text/Menubar/index.ts | 1 + .../annotation-text/TextAnnotationDesktop.tsx | 217 +++++------------- 6 files changed, 214 insertions(+), 165 deletions(-) create mode 100644 src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx create mode 100644 src/apps/annotation-text/AnnotatedText/index.ts create mode 100644 src/apps/annotation-text/Menubar/Menubar.css create mode 100644 src/apps/annotation-text/Menubar/Menubar.tsx create mode 100644 src/apps/annotation-text/Menubar/index.ts diff --git a/src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx b/src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx new file mode 100644 index 00000000..8226fc76 --- /dev/null +++ b/src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx @@ -0,0 +1,145 @@ +import { useEffect, useState } from 'react'; +import type { DrawingStyle, PresentUser } from '@annotorious/react'; +import { CETEIcean, TEIAnnotator, TextAnnotation, TextAnnotator, TextAnnotatorPopup } from '@recogito/react-text-annotator'; +import { Annotation } from '@components/Annotation'; +import { UndoStack } from '@components/AnnotationDesktop'; +import { DynamicStyle } from '@components/DynamicStyle'; +import type { PrivacyMode } from '@components/PrivacySelector'; +import { SupabasePlugin } from '@components/SupabasePlugin'; +import { PDFViewer } from '../PDFViewer'; +import { useContent } from '../useContent'; +import type { DocumentInTaggedContext, Layer, Policies, Translations } from 'src/Types'; +import { createAppearenceProvider } from '@components/Presence'; + +const SUPABASE = import.meta.env.PUBLIC_SUPABASE; + +const SUPABASE_API_KEY = import.meta.env.PUBLIC_SUPABASE_API_KEY; + +interface AnnotatedTextProps { + + channelId: string; + + defaultLayer?: Layer; + + document: DocumentInTaggedContext; + + filter?: (a: TextAnnotation) => boolean; + + i18n: Translations; + + layers?: Layer[]; + + policies: Policies; + + present: PresentUser[]; + + style?: (a: TextAnnotation) => DrawingStyle; + + styleSheet?: string; + + tagVocabulary: string[]; + + usePopup: boolean; + + onChangePresent(present: PresentUser[]): void; + + onLoad(): void; + +} + +export const AnnotatedText = (props: AnnotatedTextProps) => { + + const { i18n, policies, present, tagVocabulary } = props; + + const contentType = props.document.content_type; + + const text = useContent(props.document); + + const [annotationsLoading, setAnnotationsLoading] = useState(true); + + const [pdfLoading, setPDFLoading] = useState( + contentType === 'application/pdf' + ); + + const loading = annotationsLoading || pdfLoading || !text; + + const [privacy, setPrivacy] = useState('PUBLIC'); + + useEffect(() => { + if (!loading) + props.onLoad(); + }, [loading]); + + return ( +
+ + {contentType === 'text/xml' && text ? ( + <> + + + + + + + ) : contentType === 'application/pdf' && text ? ( + setPDFLoading(false)} /> + ) : text && ( + +

{text}

+
+ )} + + + + {props.layers && ( + layer.id)} + appearanceProvider={createAppearenceProvider()} + onInitialLoad={() => setAnnotationsLoading(false)} + onPresence={props.onChangePresent} + privacyMode={privacy === 'PRIVATE'} + /> + )} + + {props.usePopup && ( + ( + + )} + /> + )} +
+ ) + +} \ No newline at end of file diff --git a/src/apps/annotation-text/AnnotatedText/index.ts b/src/apps/annotation-text/AnnotatedText/index.ts new file mode 100644 index 00000000..ad2febf6 --- /dev/null +++ b/src/apps/annotation-text/AnnotatedText/index.ts @@ -0,0 +1 @@ +export * from './AnnotatedText'; \ No newline at end of file diff --git a/src/apps/annotation-text/Menubar/Menubar.css b/src/apps/annotation-text/Menubar/Menubar.css new file mode 100644 index 00000000..e69de29b diff --git a/src/apps/annotation-text/Menubar/Menubar.tsx b/src/apps/annotation-text/Menubar/Menubar.tsx new file mode 100644 index 00000000..88291e39 --- /dev/null +++ b/src/apps/annotation-text/Menubar/Menubar.tsx @@ -0,0 +1,15 @@ +import './Menubar.css'; + +export const Menubar = () => { + + return ( +
+
+
+ +
+
+
+ ) + +} \ No newline at end of file diff --git a/src/apps/annotation-text/Menubar/index.ts b/src/apps/annotation-text/Menubar/index.ts new file mode 100644 index 00000000..ab03fe15 --- /dev/null +++ b/src/apps/annotation-text/Menubar/index.ts @@ -0,0 +1 @@ +export * from './Menubar'; \ No newline at end of file diff --git a/src/apps/annotation-text/TextAnnotationDesktop.tsx b/src/apps/annotation-text/TextAnnotationDesktop.tsx index 39c44fea..2e140968 100644 --- a/src/apps/annotation-text/TextAnnotationDesktop.tsx +++ b/src/apps/annotation-text/TextAnnotationDesktop.tsx @@ -1,18 +1,7 @@ import { useEffect, useState } from 'react'; import { useAnnotator } from '@annotorious/react'; -import type { - Annotation as Anno, - PresentUser, - DrawingStyle, -} from '@annotorious/react'; -import { - RecogitoTextAnnotator, - TEIAnnotator, - TextAnnotator, - TextAnnotatorPopup, - TextAnnotation, - CETEIcean, -} from '@recogito/react-text-annotator'; +import type { PresentUser, DrawingStyle } from '@annotorious/react'; +import type { RecogitoTextAnnotator, TextAnnotation } from '@recogito/react-text-annotator'; import type { PDFAnnotation } from '@recogito/react-pdf-annotator'; import { supabase } from '@backend/supabaseBrowserClient'; import { @@ -20,59 +9,37 @@ import { isDefaultContext, } from '@backend/helpers'; import { useLayerPolicies, useTagVocabulary } from '@backend/hooks'; -import { PresenceStack, createAppearenceProvider } from '@components/Presence'; -import { Annotation } from '@components/Annotation'; +import { RightDrawerPanel } from '@components/AnnotationDesktop'; +import { BrandHeader } from '@components/Branding'; import { LoadingOverlay } from '@components/LoadingOverlay'; -import type { PrivacyMode } from '@components/PrivacySelector'; -import { SupabasePlugin } from '@components/SupabasePlugin'; -import { useContent } from './useContent'; -import { PDFViewer } from './PDFViewer'; import type { TextAnnotationProps } from './TextAnnotation'; -import { Toolbar } from './Toolbar'; +import { Menubar } from './Menubar'; +import { AnnotatedText } from './AnnotatedText'; import type { Layer } from 'src/Types'; import './TEI.css'; import './TextAnnotationDesktop.css'; import '@recogito/react-text-annotator/react-text-annotator.css'; -import { DynamicStyle } from '@components/DynamicStyle'; -import { RightDrawerPanel, UndoStack } from '@components/AnnotationDesktop'; - -const SUPABASE = import.meta.env.PUBLIC_SUPABASE; - -const SUPABASE_API_KEY = import.meta.env.PUBLIC_SUPABASE_API_KEY; export const TextAnnotationDesktop = (props: TextAnnotationProps) => { - const { i18n } = props; - - const contentType = props.document.content_type; const anno = useAnnotator(); const policies = useLayerPolicies(props.document.layers[0].id); - const text = useContent(props.document); + const [loading, setLoading] = useState(true); - const [annotationsLoading, setAnnotationsLoading] = useState(true); - - const [pdfLoading, setPDFLoading] = useState( - contentType === 'application/pdf' - ); - - const loading = annotationsLoading || pdfLoading || !text; + const [showBranding, setShowBranding] = useState(true); const [present, setPresent] = useState([]); - const [style, setStyle] = useState< - ((a: TextAnnotation) => DrawingStyle) | undefined - >(undefined); + const tagVocabulary = useTagVocabulary(props.document.context.project_id); - const [filter, setFilter] = useState<((a: Anno) => boolean) | undefined>( - undefined - ); + const [style, setStyle] = useState<((a: TextAnnotation) => DrawingStyle) | undefined>(undefined); - const [usePopup, setUsePopup] = useState(true); + const [filter, setFilter] = useState<((a: TextAnnotation) => boolean) | undefined>(undefined); - const [privacy, setPrivacy] = useState('PUBLIC'); + const [usePopup, setUsePopup] = useState(true); const [layers, setLayers] = useState(); @@ -83,7 +50,6 @@ export const TextAnnotationDesktop = (props: TextAnnotationProps) => { ? layers.find((l) => !l.context.name) || layers[0] : undefined; - const vocabulary = useTagVocabulary(props.document.context.project_id); useEffect(() => { if (policies) { @@ -120,18 +86,17 @@ export const TextAnnotationDesktop = (props: TextAnnotationProps) => { } }; - const beforeSelectAnnotation = (a?: Anno) => { + const beforeSelectAnnotation = (a?: TextAnnotation) => { if (a && !usePopup && anno) { - const t = a as TextAnnotation; // Don't fit the view if the annotation is already selected - if (anno.state.selection.isSelected(t)) return; + if (anno.state.selection.isSelected(a)) return; - anno.scrollIntoView(t); + anno.scrollIntoView(a); } }; const sorting = - contentType === 'application/pdf' + props.document.content_type === 'application/pdf' ? (a: PDFAnnotation, b: PDFAnnotation) => { const pages = a.target.selector.pageNumber - b.target.selector.pageNumber; @@ -143,122 +108,44 @@ export const TextAnnotationDesktop = (props: TextAnnotationProps) => { a.target.selector.start - b.target.selector.start; return ( -
- {loading && } - -
- {contentType === 'text/xml' && text ? ( - <> - - - - - - ) : contentType === 'application/pdf' && text ? ( - setPDFLoading(false)} - /> - ) : ( - text && ( - -

{text}

-
- ) - )} -
- -
- - - {layers && ( - layer.id)} - appearanceProvider={createAppearenceProvider()} - onInitialLoad={() => setAnnotationsLoading(false)} - onPresence={setPresent} - privacyMode={privacy === 'PRIVATE'} - /> - )} - - {usePopup && ( - ( - - )} - /> +
+ {loading && ( + + )} + +
+ {showBranding && ( + )} + + +
-
- {/* */} -
- -
- {/* - - - setFilter(() => f)} - onChangeAnnotationStyle={(s) => setStyle(() => s)} - beforeSelectAnnotation={beforeSelectAnnotation} - /> - */} +
+
+ +
+ {policies && ( + setLoading(false)} /> + )}
-
- -
-
+
+
- ); -}; + ) + +} From 440dd688b48c543bddaccd1a29aa3aca521f16d8 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 25 Jan 2024 14:44:47 +0100 Subject: [PATCH 017/135] More work in progress: refactoring + redesigning text annotation view --- src/apps/annotation-image/Menubar/Menubar.css | 133 ----------------- src/apps/annotation-image/Menubar/Menubar.tsx | 20 ++- src/apps/annotation-text/Menubar/Menubar.tsx | 134 +++++++++++++++++- .../annotation-text/TextAnnotationDesktop.tsx | 111 ++++++++++----- src/apps/annotation-text/Toolbar/index.ts | 1 - .../Toolbar.tsx => Toolpanel/Toolpanel.tsx} | 19 +-- src/apps/annotation-text/Toolpanel/index.ts | 1 + src/themes/default/annotation/index.css | 134 +++++++++++++++++- 8 files changed, 354 insertions(+), 199 deletions(-) delete mode 100644 src/apps/annotation-image/Menubar/Menubar.css delete mode 100644 src/apps/annotation-text/Toolbar/index.ts rename src/apps/annotation-text/{Toolbar/Toolbar.tsx => Toolpanel/Toolpanel.tsx} (93%) create mode 100644 src/apps/annotation-text/Toolpanel/index.ts diff --git a/src/apps/annotation-image/Menubar/Menubar.css b/src/apps/annotation-image/Menubar/Menubar.css deleted file mode 100644 index 04f54b98..00000000 --- a/src/apps/annotation-image/Menubar/Menubar.css +++ /dev/null @@ -1,133 +0,0 @@ -.ia-menubar { - align-items: center; - background-color: #fff; - box-shadow: 0px 0px 16px -1px rgba(0, 0, 0, 0.15), - 0px 0px 16px -8px rgba(0, 0, 0, 0.25), - 0px 0px 16px -12px rgba(0, 0, 0, 0.32), 0px 0px 2px 0px rgba(0, 0, 0, 0.28); - display: flex; - height: 48px; - justify-content: space-between; - pointer-events: auto; - position: relative; - z-index: 2; -} - -.ia-menubar .ia-menubar-left { - align-items: center; - border-radius: 0 0 12px 0; - border-width: 0 0 1px 1px; - box-sizing: border-box; - display: flex; - padding: 0 20px 0 10px; - pointer-events: all; -} - -.ia-menubar .ia-menubar-left h1 { - font-size: var(--font-tiny); - font-family: Inter; - font-weight: 500; - margin: 0; -} - -.ia-menubar .ia-menubar-left .assignment-icon { - align-items: center; - background-color: var(--font-dark); - border-radius: 50%; - color: #fff; - display: inline-flex; - height: 28px; - justify-content: center; - width: 28px; -} - -.ia-menubar .ia-menubar-left a { - color: var(--font-dark); -} - -.ia-menubar .ia-menubar-title { - padding-right: 0.6em; -} - -.ia-menubar .ia-menubar-left a svg { - display: block; -} - -.ia-menubar .ia-menubar-left span { - color: var(--font-light); -} - -.ia-menubar .ia-menubar-left button { - border-radius: 50%; - height: 36px; - vertical-align: bottom; - width: 36px; -} - -.ia-menubar .ia-menubar-left button svg { - color: var(--font-dark); -} - -.ia-menubar :is(button, a.button, .with-notification) + :is(button, a.button, .with-notification) { - margin-left: 2px; -} - -.ia-menubar .ia-menubar-right { - align-items: center; - display: flex; - padding-right: 10px; -} - -.ia-menubar button { - background: transparent; - border: none; - border-radius: 50%; - box-shadow: none; - height: 36px; - min-width: auto; - outline: none; - padding: 0; - vertical-align: bottom; - width: 36px; -} - -.ia-menubar-section { - align-items: center; - display: flex; -} - -.ia-menubar .ia-menubar-right button:hover { - box-shadow: inset 0 0 0 150px rgba(0, 0, 0, 0.06); -} - -.ia-menubar .ia-menubar-right button svg { - color: var(--font-dark); -} - -.ia-menubar .ia-menubar-right button.active { - background-color: var(--bright-blue); - color: #fff; -} - -.ia-menubar .ia-menubar-right button.active svg { - color: #fff; -} - -.ia-menubar .avatar { - height: 30px; - width: 30px; -} - -.ia-menubar .presence-stack .avatar { - height: 34px; - width: 34px; -} - -.ia-menubar .avatar:hover { - box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.06); -} - -.ia-menubar .ia-menubar-me { - padding-left: 10px; -} - - diff --git a/src/apps/annotation-image/Menubar/Menubar.tsx b/src/apps/annotation-image/Menubar/Menubar.tsx index c8e7a362..fc536fd5 100644 --- a/src/apps/annotation-image/Menubar/Menubar.tsx +++ b/src/apps/annotation-image/Menubar/Menubar.tsx @@ -18,8 +18,6 @@ import { MagnifyingGlassPlus, } from '@phosphor-icons/react'; -import './Menubar.css'; - interface MenubarProps { i18n: Translations; @@ -60,9 +58,9 @@ export const Menubar = (props: MenubarProps) => { } return ( -
-
-
+
+
+
{contextName ? ( <> {
-
-
+
+
@@ -116,7 +114,7 @@ export const Menubar = (props: MenubarProps) => { <>
-
+
@@ -124,7 +122,7 @@ export const Menubar = (props: MenubarProps) => {
-
+
{me && ( -
+
{ +interface MenubarProps { + + i18n: Translations; + + document: DocumentInTaggedContext; + + present: PresentUser[]; + + rightPanel?: RightDrawerPanel; + + onToggleBranding(): void; + + onSetRightDrawer(panel?: RightDrawerPanel): void; + +} + +export const Menubar = (props: MenubarProps) => { + + const { t } = props.i18n; + + const contextName = props.document.context.name; + + const { id, project_id } = props.document.context; + + const back = contextName ? + `/${props.i18n.lang}/projects/${project_id}/assignments/${id}` : + `/${props.i18n.lang}/projects/${project_id}`; + + const me = props.present.find(isMe)!; + + const toggleRightDrawer = (panel: RightDrawerPanel) => { + if (panel === props.rightPanel) + props.onSetRightDrawer(); + else + props.onSetRightDrawer(panel); + } return ( -
-
+
+
+ {contextName ? ( + <> + + + + +

+ {contextName} / {props.document.name} +

+ + ) : ( + <> + + + + +

+ {props.document.name} +

+ + )} + +
+ +
+ +
-
+
+ {props.present.length > 1 && ( + <> +
+ +
+ +
+ + )} + +
+ +
+ + + toggleRightDrawer(RightDrawerPanel.LAYERS)} /> + + toggleRightDrawer(RightDrawerPanel.DOCUMENT_NOTES)} /> +
+ +
+ +
+ +
+ + {me && ( +
+ +
+ )}
) diff --git a/src/apps/annotation-text/TextAnnotationDesktop.tsx b/src/apps/annotation-text/TextAnnotationDesktop.tsx index 2e140968..f060b342 100644 --- a/src/apps/annotation-text/TextAnnotationDesktop.tsx +++ b/src/apps/annotation-text/TextAnnotationDesktop.tsx @@ -9,7 +9,7 @@ import { isDefaultContext, } from '@backend/helpers'; import { useLayerPolicies, useTagVocabulary } from '@backend/hooks'; -import { RightDrawerPanel } from '@components/AnnotationDesktop'; +import { ColorState, DocumentNotes, FilterState, RightDrawerPanel } from '@components/AnnotationDesktop'; import { BrandHeader } from '@components/Branding'; import { LoadingOverlay } from '@components/LoadingOverlay'; import type { TextAnnotationProps } from './TextAnnotation'; @@ -33,6 +33,8 @@ export const TextAnnotationDesktop = (props: TextAnnotationProps) => { const [present, setPresent] = useState([]); + const [rightPanel, setRightPanel] = useState(); + const tagVocabulary = useTagVocabulary(props.document.context.project_id); const [style, setStyle] = useState<((a: TextAnnotation) => DrawingStyle) | undefined>(undefined); @@ -86,6 +88,15 @@ export const TextAnnotationDesktop = (props: TextAnnotationProps) => { } }; + const onSetRightPanel = (panel?: RightDrawerPanel) => { + if (panel === RightDrawerPanel.ANNOTATIONS) + setUsePopup(false); // Don't use the popup if annotation list is open + else if (!usePopup) + setUsePopup(true) + + setRightPanel(panel); + } + const beforeSelectAnnotation = (a?: TextAnnotation) => { if (a && !usePopup && anno) { // Don't fit the view if the annotation is already selected @@ -107,45 +118,67 @@ export const TextAnnotationDesktop = (props: TextAnnotationProps) => { : (a: TextAnnotation, b: TextAnnotation) => a.target.selector.start - b.target.selector.start; + const onError = (error: Error) => { + // TODO UI feedback + console.error(error); + } + return ( -
- {loading && ( - - )} - -
- {showBranding && ( - - )} - - -
- -
-
- -
- {policies && ( - setLoading(false)} /> - )} -
- -
-
-
+ + + + +
+ {loading && ( + + )} + +
+ {showBranding && ( + + )} + + setShowBranding(!showBranding)} + onSetRightDrawer={onSetRightPanel} /> +
+ +
+
+ +
+ {policies && ( + setLoading(false)} /> + )} +
+ +
+
+
+
+
+
) } diff --git a/src/apps/annotation-text/Toolbar/index.ts b/src/apps/annotation-text/Toolbar/index.ts deleted file mode 100644 index 5de1afd2..00000000 --- a/src/apps/annotation-text/Toolbar/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './Toolbar'; \ No newline at end of file diff --git a/src/apps/annotation-text/Toolbar/Toolbar.tsx b/src/apps/annotation-text/Toolpanel/Toolpanel.tsx similarity index 93% rename from src/apps/annotation-text/Toolbar/Toolbar.tsx rename to src/apps/annotation-text/Toolpanel/Toolpanel.tsx index 1b263d1c..e1b04956 100644 --- a/src/apps/annotation-text/Toolbar/Toolbar.tsx +++ b/src/apps/annotation-text/Toolpanel/Toolpanel.tsx @@ -1,9 +1,4 @@ -import { - Annotation, - useAnnotationStore, - useAnnotator, - useSelection, -} from '@annotorious/react'; +import { Annotation, useAnnotationStore, useAnnotator, useSelection } from '@annotorious/react'; import { Trash } from '@phosphor-icons/react'; import { PrivacyMode, PrivacySelector } from '@components/PrivacySelector'; import type { Translations } from 'src/Types'; @@ -11,6 +6,7 @@ import { AdminOverrideAlert } from '@components/Annotation/Comment/PublicComment import { useState } from 'react'; interface ToolbarProps { + i18n: Translations; isAdmin?: boolean; @@ -18,9 +14,11 @@ interface ToolbarProps { privacy: PrivacyMode; onChangePrivacy(mode: PrivacyMode): void; + } -export const Toolbar = (props: ToolbarProps) => { +export const Toolpanel = (props: ToolbarProps) => { + const { selected } = useSelection(); const store = useAnnotationStore(); @@ -28,6 +26,7 @@ export const Toolbar = (props: ToolbarProps) => { const anno = useAnnotator(); const me = anno?.getUser(); + const [confirmOpen, setConfirmOpen] = useState(false); const isMine = (selected: { annotation: Annotation }[]) => @@ -80,5 +79,7 @@ export const Toolbar = (props: ToolbarProps) => {
)}
- ); -}; + + ) + +} diff --git a/src/apps/annotation-text/Toolpanel/index.ts b/src/apps/annotation-text/Toolpanel/index.ts new file mode 100644 index 00000000..b90957dd --- /dev/null +++ b/src/apps/annotation-text/Toolpanel/index.ts @@ -0,0 +1 @@ +export * from './Toolpanel'; \ No newline at end of file diff --git a/src/themes/default/annotation/index.css b/src/themes/default/annotation/index.css index 3e8fcf1c..eb907591 100644 --- a/src/themes/default/annotation/index.css +++ b/src/themes/default/annotation/index.css @@ -73,6 +73,136 @@ right: 0; } -.anno-menubar section { - padding: 6px; +.anno-menubar { + align-items: center; + background-color: #fff; + box-shadow: 0px 0px 16px -1px rgba(0, 0, 0, 0.15), + 0px 0px 16px -8px rgba(0, 0, 0, 0.25), + 0px 0px 16px -12px rgba(0, 0, 0, 0.32), 0px 0px 2px 0px rgba(0, 0, 0, 0.28); + display: flex; + height: 48px; + justify-content: space-between; + pointer-events: auto; + position: relative; + z-index: 2; +} + +.anno-menubar .anno-menubar-left { + align-items: center; + border-radius: 0 0 12px 0; + border-width: 0 0 1px 1px; + box-sizing: border-box; + display: flex; + padding: 0 20px 0 10px; + pointer-events: all; +} + +.anno-menubar .anno-menubar-left h1 { + font-size: var(--font-tiny); + font-family: Inter; + font-weight: 500; + margin: 0; +} + +.anno-menubar .anno-menubar-left .assignment-icon { + align-items: center; + background-color: var(--font-dark); + border-radius: 50%; + color: #fff; + display: inline-flex; + height: 28px; + justify-content: center; + width: 28px; +} + +.anno-menubar .anno-menubar-left a { + color: var(--font-dark); +} + +.anno-menubar .anno-menubar-title { + padding-right: 0.6em; +} + +.anno-menubar .anno-menubar-left a svg { + display: block; +} + +.anno-menubar .anno-menubar-left span { + color: var(--font-light); +} + +.anno-menubar .anno-menubar-left button { + border-radius: 50%; + height: 36px; + vertical-align: bottom; + width: 36px; +} + +.anno-menubar .anno-menubar-left button svg { + color: var(--font-dark); +} + +.anno-menubar :is(button, a.button, .with-notification) + :is(button, a.button, .with-notification) { + margin-left: 2px; +} + +.anno-menubar .anno-menubar-right { + align-items: center; + display: flex; + padding-right: 10px; } + +.anno-menubar button { + background: transparent; + border: none; + border-radius: 50%; + box-shadow: none; + height: 36px; + min-width: auto; + outline: none; + padding: 0; + vertical-align: bottom; + width: 36px; +} + +.anno-menubar-section { + align-items: center; + display: flex; +} + +.anno-menubar .anno-menubar-right button:hover { + box-shadow: inset 0 0 0 150px rgba(0, 0, 0, 0.06); +} + +.anno-menubar .anno-menubar-right button svg { + color: var(--font-dark); +} + +.anno-menubar .anno-menubar-right button.active { + background-color: var(--bright-blue); + color: #fff; +} + +.anno-menubar .anno-menubar-right button.active svg { + color: #fff; +} + +.anno-menubar .avatar { + height: 30px; + width: 30px; +} + +.anno-menubar .presence-stack .avatar { + height: 34px; + width: 34px; +} + +.anno-menubar .avatar:hover { + box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.06); +} + +.anno-menubar .anno-menubar-me { + padding-left: 10px; +} + + From f629adbf6b36aab16653326e88db4cd4c75806bf Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 25 Jan 2024 18:15:34 +0100 Subject: [PATCH 018/135] Redesigned CSS styles for text annotation view --- .../ImageAnnotationDesktop.css | 9 -- .../AnnotatedText/AnnotatedText.tsx | 127 +++++++++--------- .../annotation-text/TextAnnotationDesktop.css | 34 +++-- .../annotation-text/TextAnnotationDesktop.tsx | 8 +- src/themes/default/annotation/index.css | 6 + 5 files changed, 93 insertions(+), 91 deletions(-) diff --git a/src/apps/annotation-image/ImageAnnotationDesktop.css b/src/apps/annotation-image/ImageAnnotationDesktop.css index 28cbe54b..712fa5a4 100644 --- a/src/apps/annotation-image/ImageAnnotationDesktop.css +++ b/src/apps/annotation-image/ImageAnnotationDesktop.css @@ -1,14 +1,5 @@ @import '@annotorious/react/annotorious-react.css'; -.ia-desktop { - display: flex; - flex-direction: column; - height: 100%; - overflow: hidden; - overscroll-behavior: none; - width: 100%; -} - .ia-desktop main { flex-grow: 1; position: relative; diff --git a/src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx b/src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx index 8226fc76..8235456a 100644 --- a/src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx +++ b/src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx @@ -71,74 +71,75 @@ export const AnnotatedText = (props: AnnotatedTextProps) => { }, [loading]); return ( -
- - {contentType === 'text/xml' && text ? ( - <> - - - +
+ {contentType === 'text/xml' && text ? ( + <> + + + + + + + ) : contentType === 'application/pdf' && text ? ( + setPDFLoading(false)} /> + ) : text && ( + - - - - ) : contentType === 'application/pdf' && text ? ( - setPDFLoading(false)} /> - ) : text && ( - -

{text}

-
- )} - - - - {props.layers && ( - layer.id)} - appearanceProvider={createAppearenceProvider()} - onInitialLoad={() => setAnnotationsLoading(false)} - onPresence={props.onChangePresent} - privacyMode={privacy === 'PRIVATE'} - /> - )} - - {props.usePopup && ( - ( - - )} - /> - )} +

{text}

+
+ )} + + + + {props.layers && ( + layer.id)} + appearanceProvider={createAppearenceProvider()} + onInitialLoad={() => setAnnotationsLoading(false)} + onPresence={props.onChangePresent} + privacyMode={privacy === 'PRIVATE'} + /> + )} + + {props.usePopup && ( + ( + + )} + /> + )} +
) diff --git a/src/apps/annotation-text/TextAnnotationDesktop.css b/src/apps/annotation-text/TextAnnotationDesktop.css index 98a64997..e0425d47 100644 --- a/src/apps/annotation-text/TextAnnotationDesktop.css +++ b/src/apps/annotation-text/TextAnnotationDesktop.css @@ -1,16 +1,14 @@ -.r6o-highlight-layer { - box-sizing: border-box; - z-index: 99 !important; +.ta-desktop main { + overflow: hidden; } -.content-wrapper { +.ta-desktop main .ta-annotated-text-container { display: flex; justify-content: center; - height: 100%; - width: 100%; + overflow-y: scroll; } -.content-wrapper main { +.ta-desktop main .ta-annotated-text-container .content-wrapper { background-color: #fff; border-color: var(--gray-300); border-style: solid; @@ -26,6 +24,14 @@ word-wrap: break-word; } +.r6o-highlight-layer { + box-sizing: border-box; + z-index: 99 !important; +} + + + + .content-wrapper.text main { height: fit-content; white-space: pre-line; @@ -69,17 +75,9 @@ max-width: 100%; } -.ta-desktop { - bottom: 0; - position: fixed; - top: 0; - width: 100%; - margin: 50px 0; - z-index: 9999; -} - -.ta-desktop .presence-stack { - margin: 4px 8px; +.ta-desktop main { + flex-grow: 1; + position: relative; } .ta-toolbar-container { diff --git a/src/apps/annotation-text/TextAnnotationDesktop.tsx b/src/apps/annotation-text/TextAnnotationDesktop.tsx index f060b342..0359885d 100644 --- a/src/apps/annotation-text/TextAnnotationDesktop.tsx +++ b/src/apps/annotation-text/TextAnnotationDesktop.tsx @@ -10,7 +10,7 @@ import { } from '@backend/helpers'; import { useLayerPolicies, useTagVocabulary } from '@backend/hooks'; import { ColorState, DocumentNotes, FilterState, RightDrawerPanel } from '@components/AnnotationDesktop'; -import { BrandHeader } from '@components/Branding'; +import { BrandFooter, BrandHeader } from '@components/Branding'; import { LoadingOverlay } from '@components/LoadingOverlay'; import type { TextAnnotationProps } from './TextAnnotation'; import { Menubar } from './Menubar'; @@ -175,6 +175,12 @@ export const TextAnnotationDesktop = (props: TextAnnotationProps) => {
+ + {showBranding && ( +
+ +
+ )}
diff --git a/src/themes/default/annotation/index.css b/src/themes/default/annotation/index.css index eb907591..bee0f2fb 100644 --- a/src/themes/default/annotation/index.css +++ b/src/themes/default/annotation/index.css @@ -1,5 +1,11 @@ .anno-desktop { + display: flex; + flex-direction: column; + height: 100%; + overflow: hidden; + overscroll-behavior: none; pointer-events: none; + width: 100%; } .anno-desktop-left { From 5eadf1ed357d69c48f2b6b6e2567a18946c60f3c Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Thu, 25 Jan 2024 18:19:32 +0100 Subject: [PATCH 019/135] Minor tweak --- src/apps/annotation-text/TextAnnotationDesktop.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/apps/annotation-text/TextAnnotationDesktop.tsx b/src/apps/annotation-text/TextAnnotationDesktop.tsx index 0359885d..aa115b32 100644 --- a/src/apps/annotation-text/TextAnnotationDesktop.tsx +++ b/src/apps/annotation-text/TextAnnotationDesktop.tsx @@ -9,7 +9,7 @@ import { isDefaultContext, } from '@backend/helpers'; import { useLayerPolicies, useTagVocabulary } from '@backend/hooks'; -import { ColorState, DocumentNotes, FilterState, RightDrawerPanel } from '@components/AnnotationDesktop'; +import { ColorState, DocumentNotes, FilterState, RightDrawer, RightDrawerPanel } from '@components/AnnotationDesktop'; import { BrandFooter, BrandHeader } from '@components/Branding'; import { LoadingOverlay } from '@components/LoadingOverlay'; import type { TextAnnotationProps } from './TextAnnotation'; @@ -173,7 +173,16 @@ export const TextAnnotationDesktop = (props: TextAnnotationProps) => { )}
-
+ setFilter(() => f)} + onChangeAnnotationStyle={s => setStyle(() => s)} /> {showBranding && ( From ae9fcc6d3ebacc2664959cfd9ecfbcd1835da348 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Fri, 26 Jan 2024 09:11:14 +0100 Subject: [PATCH 020/135] More workspace refactoring, image vs. text specific drawers --- .../ImageAnnotationDesktop.tsx | 13 +-- src/apps/annotation-image/Menubar/Menubar.tsx | 24 +++-- .../RightDrawer/RightDrawer.css | 13 +++ .../RightDrawer/RightDrawer.tsx | 88 +++++++++++++++++++ .../annotation-image/RightDrawer/index.ts | 1 + src/apps/annotation-text/Menubar/Menubar.tsx | 20 ++--- .../RightDrawer/RightDrawer.css | 20 +++++ .../RightDrawer/RightDrawer.tsx | 41 ++++----- src/apps/annotation-text/RightDrawer/index.ts | 1 + .../annotation-text/TextAnnotationDesktop.css | 26 +++--- .../annotation-text/TextAnnotationDesktop.tsx | 25 +++--- .../RightDrawerPanel.ts => DrawerPanel.ts} | 2 +- .../RightDrawer/RightDrawer.css | 46 ---------- .../AnnotationDesktop/RightDrawer/index.ts | 2 - src/components/AnnotationDesktop/index.ts | 2 +- src/themes/default/annotation/index.css | 25 ++++++ 16 files changed, 221 insertions(+), 128 deletions(-) create mode 100644 src/apps/annotation-image/RightDrawer/RightDrawer.css create mode 100644 src/apps/annotation-image/RightDrawer/RightDrawer.tsx create mode 100644 src/apps/annotation-image/RightDrawer/index.ts create mode 100644 src/apps/annotation-text/RightDrawer/RightDrawer.css rename src/{components/AnnotationDesktop => apps/annotation-text}/RightDrawer/RightDrawer.tsx (65%) create mode 100644 src/apps/annotation-text/RightDrawer/index.ts rename src/components/AnnotationDesktop/{RightDrawer/RightDrawerPanel.ts => DrawerPanel.ts} (75%) delete mode 100644 src/components/AnnotationDesktop/RightDrawer/RightDrawer.css delete mode 100644 src/components/AnnotationDesktop/RightDrawer/index.ts diff --git a/src/apps/annotation-image/ImageAnnotationDesktop.tsx b/src/apps/annotation-image/ImageAnnotationDesktop.tsx index d53e8fd1..d0dd2747 100644 --- a/src/apps/annotation-image/ImageAnnotationDesktop.tsx +++ b/src/apps/annotation-image/ImageAnnotationDesktop.tsx @@ -5,11 +5,12 @@ import { useLayerPolicies, useTagVocabulary } from '@backend/hooks'; import { supabase } from '@backend/supabaseBrowserClient'; import { BrandFooter, BrandHeader } from '@components/Branding'; import { LoadingOverlay } from '@components/LoadingOverlay'; -import { ColorState, DocumentNotes, FilterState, RightDrawer, RightDrawerPanel } from '@components/AnnotationDesktop'; +import { ColorState, DocumentNotes, FilterState, DrawerPanel } from '@components/AnnotationDesktop'; import type { Layer } from 'src/Types'; import { AnnotatedImage } from './AnnotatedImage'; import type { ImageAnnotationProps } from './ImageAnnotation'; import { Menubar } from './Menubar'; +import { RightDrawer } from './RightDrawer'; import { AnnotoriousOpenSeadragonAnnotator, DrawingStyle, @@ -34,7 +35,7 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { const [present, setPresent] = useState([]); - const [rightPanel, setRightPanel] = useState(); + const [rightPanel, setRightPanel] = useState(); const tagVocabulary = useTagVocabulary(props.document.context.project_id); @@ -79,11 +80,11 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { const onZoom = (factor: number) => viewer.current?.viewport.zoomBy(factor); - const onSetRightPanel = (panel?: RightDrawerPanel) => { - if (panel === RightDrawerPanel.ANNOTATIONS) + const onSetRightPanel = (panel?: DrawerPanel) => { + if (panel === DrawerPanel.ANNOTATIONS) setUsePopup(false); // Don't use the popup if annotation list is open else if (!usePopup) - setUsePopup(true) + setUsePopup(true); setRightPanel(panel); } @@ -159,7 +160,7 @@ export const ImageAnnotationDesktop = (props: ImageAnnotationProps) => { )}
- { const me = props.present.find(isMe)!; - const toggleRightDrawer = (panel: RightDrawerPanel) => { + const toggleRightDrawer = (panel: DrawerPanel) => { if (panel === props.rightPanel) props.onSetRightDrawer(); else @@ -124,21 +120,21 @@ export const Menubar = (props: MenubarProps) => {
toggleRightDrawer(RightDrawerPanel.LAYERS)} /> + active={props.rightPanel === DrawerPanel.LAYERS} + onSelect={() => toggleRightDrawer(DrawerPanel.LAYERS)} /> toggleRightDrawer(RightDrawerPanel.DOCUMENT_NOTES)} /> + active={props.rightPanel === DrawerPanel.DOCUMENT_NOTES} + onSelect={() => toggleRightDrawer(DrawerPanel.DOCUMENT_NOTES)} />
diff --git a/src/apps/annotation-image/RightDrawer/RightDrawer.css b/src/apps/annotation-image/RightDrawer/RightDrawer.css new file mode 100644 index 00000000..e609fb43 --- /dev/null +++ b/src/apps/annotation-image/RightDrawer/RightDrawer.css @@ -0,0 +1,13 @@ +.ia-right-drawer { + background-color: var(--gray-100); + box-shadow: + 0px 0px 16px -1px rgba(0, 0, 0, 0.15), + 0px 0px 16px -8px rgba(0, 0, 0, 0.25), + 0px 0px 16px -12px rgba(0, 0, 0, 0.32), + 0px 0px 2px 0px rgba(0, 0, 0, 0.28); + right: 0; + scroll-padding: 40px; + top: 0; + transform: translateX(360px); + width: 360px; +} \ No newline at end of file diff --git a/src/apps/annotation-image/RightDrawer/RightDrawer.tsx b/src/apps/annotation-image/RightDrawer/RightDrawer.tsx new file mode 100644 index 00000000..591f23a6 --- /dev/null +++ b/src/apps/annotation-image/RightDrawer/RightDrawer.tsx @@ -0,0 +1,88 @@ +import { ReactNode, useEffect, useRef } from 'react'; +import { useTransition, animated } from '@react-spring/web'; +import type { Annotation, DrawingStyle, ImageAnnotation, PresentUser } from '@annotorious/react'; +import { isMe } from '@recogito/annotorious-supabase'; +import { AnnotationList, DocumentNotesList, LayerConfigurationPanel, DrawerPanel } from '@components/AnnotationDesktop'; +import type { Layer, Policies, Translations } from 'src/Types'; + +import './RightDrawer.css'; + +interface RightDrawerProps { + + i18n: Translations; + + present: PresentUser[]; + + currentPanel?: DrawerPanel; + + policies?: Policies; + + layers?: Layer[]; + + tagVocabulary?: string[]; + + beforeSelectAnnotation(a?: ImageAnnotation): void; + + onChangeAnnotationFilter(fn: ((a: Annotation) => boolean)): void; + + onChangeAnnotationStyle(fn: ((a: Annotation) => DrawingStyle)): void; + +} + +export const RightDrawer = (props: RightDrawerProps) => { + + const previous = useRef(); + + const me = props.present.find(isMe)!; + + const shouldAnimate = + // Drawer currently closed, and should open + !previous.current && props.currentPanel || + // Drawer currently open, and should close + previous.current && !props.currentPanel; + + const drawerTransition = useTransition([props.currentPanel], { + from: { transform: 'translateX(180px)', opacity: 0 }, + enter: { transform: 'translateX(0px)', opacity: 1 }, + leave: { transform: 'translateX(180px)', opacity: 0 }, + config: { + duration: shouldAnimate ? 120 : 0 + } + }); + + useEffect(() => { + previous.current = props.currentPanel; + }, [props.currentPanel]); + + return drawerTransition((style, panel) => panel && ( + + + + )) + +} \ No newline at end of file diff --git a/src/apps/annotation-image/RightDrawer/index.ts b/src/apps/annotation-image/RightDrawer/index.ts new file mode 100644 index 00000000..bacb41b2 --- /dev/null +++ b/src/apps/annotation-image/RightDrawer/index.ts @@ -0,0 +1 @@ +export * from './RightDrawer'; \ No newline at end of file diff --git a/src/apps/annotation-text/Menubar/Menubar.tsx b/src/apps/annotation-text/Menubar/Menubar.tsx index 388c9662..707adab5 100644 --- a/src/apps/annotation-text/Menubar/Menubar.tsx +++ b/src/apps/annotation-text/Menubar/Menubar.tsx @@ -1,7 +1,7 @@ import { ArrowsOutSimple, CaretLeft, Chats, GraduationCap, ListBullets } from '@phosphor-icons/react'; import type { PresentUser } from '@annotorious/react'; import { isMe } from '@recogito/annotorious-supabase'; -import { DocumentNotesMenuIcon, LayersPanelMenuIcon, RightDrawerPanel } from '@components/AnnotationDesktop'; +import { DocumentNotesMenuIcon, LayersPanelMenuIcon, DrawerPanel } from '@components/AnnotationDesktop'; import { Avatar } from '@components/Avatar'; import { PresenceStack } from '@components/Presence'; import type { DocumentInTaggedContext, Translations } from 'src/Types'; @@ -16,11 +16,11 @@ interface MenubarProps { present: PresentUser[]; - rightPanel?: RightDrawerPanel; + rightPanel?: DrawerPanel; onToggleBranding(): void; - onSetRightDrawer(panel?: RightDrawerPanel): void; + onSetRightDrawer(panel?: DrawerPanel): void; } @@ -38,7 +38,7 @@ export const Menubar = (props: MenubarProps) => { const me = props.present.find(isMe)!; - const toggleRightDrawer = (panel: RightDrawerPanel) => { + const toggleRightDrawer = (panel: DrawerPanel) => { if (panel === props.rightPanel) props.onSetRightDrawer(); else @@ -100,21 +100,21 @@ export const Menubar = (props: MenubarProps) => {
toggleRightDrawer(RightDrawerPanel.LAYERS)} /> + active={props.rightPanel === DrawerPanel.LAYERS} + onSelect={() => toggleRightDrawer(DrawerPanel.LAYERS)} /> toggleRightDrawer(RightDrawerPanel.DOCUMENT_NOTES)} /> + active={props.rightPanel === DrawerPanel.DOCUMENT_NOTES} + onSelect={() => toggleRightDrawer(DrawerPanel.DOCUMENT_NOTES)} />
diff --git a/src/apps/annotation-text/RightDrawer/RightDrawer.css b/src/apps/annotation-text/RightDrawer/RightDrawer.css new file mode 100644 index 00000000..922ee223 --- /dev/null +++ b/src/apps/annotation-text/RightDrawer/RightDrawer.css @@ -0,0 +1,20 @@ +.ta-right-drawer { + background-color: var(--gray-100); + box-shadow: + 0px 0px 16px -1px rgba(0, 0, 0, 0.15), + 0px 0px 16px -8px rgba(0, 0, 0, 0.25), + 0px 0px 16px -12px rgba(0, 0, 0, 0.32), + 0px 0px 2px 0px rgba(0, 0, 0, 0.28); + flex-grow: 0; + flex-shrink: 0; + flex-basis: 0; + position: relative; + scroll-padding: 40px; +} + +.ta-right-drawer aside { + position: absolute; + top: 0; + left: 0; + width: 360px; +} \ No newline at end of file diff --git a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx b/src/apps/annotation-text/RightDrawer/RightDrawer.tsx similarity index 65% rename from src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx rename to src/apps/annotation-text/RightDrawer/RightDrawer.tsx index 51038e93..4ad29583 100644 --- a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.tsx +++ b/src/apps/annotation-text/RightDrawer/RightDrawer.tsx @@ -1,12 +1,9 @@ import { useEffect, useRef } from 'react'; -import { useTransition, animated } from '@react-spring/web' -import { isMe } from '@recogito/annotorious-supabase'; +import { useTransition, animated } from '@react-spring/web'; import type { Annotation, DrawingStyle, PresentUser } from '@annotorious/react'; +import { isMe } from '@recogito/annotorious-supabase'; +import { AnnotationList, DocumentNotesList, LayerConfigurationPanel, DrawerPanel } from '@components/AnnotationDesktop'; import type { Layer, Policies, Translations } from 'src/Types'; -import { RightDrawerPanel } from './RightDrawerPanel'; -import { AnnotationList } from '../AnnotationList'; -import { LayerConfigurationPanel } from '../LayerConfiguration'; -import { DocumentNotesList } from '../DocumentNotes'; import './RightDrawer.css'; @@ -16,7 +13,7 @@ interface RightDrawerProps { present: PresentUser[]; - currentPanel?: RightDrawerPanel; + currentPanel?: DrawerPanel; policies?: Policies; @@ -36,37 +33,35 @@ interface RightDrawerProps { export const RightDrawer = (props: RightDrawerProps) => { - // We need to keep the current panel until exit transition is done - const previous = useRef(); + const previous = useRef(); const me = props.present.find(isMe)!; const shouldAnimate = - // Drawer closed, and should open + // Drawer currently closed, and should open !previous.current && props.currentPanel || - // Drawer open, and should close + // Drawer currently open, and should close previous.current && !props.currentPanel; const drawerTransition = useTransition([props.currentPanel], { - from: { transform: 'translateX(180px)', opacity: 0 }, - enter: { transform: 'translateX(0px)', opacity: 1 }, - leave: { transform: 'translateX(180px)', opacity: 0 }, + from: { flexBasis: 0 }, + enter: { flexBasis: 360 }, + leave: { flexBasis: 0 }, config: { - duration: shouldAnimate ? 120 : 0 + duration: shouldAnimate ? 180 : 0 } }); useEffect(() => { previous.current = props.currentPanel; - }, [props.currentPanel]) + }, [props.currentPanel]); return drawerTransition((style, panel) => panel && ( - - +
- setFilter(() => f)} - onChangeAnnotationStyle={s => setStyle(() => s)} /> + onChangeAnnotationStyle={s => setStyle(() => s)} /> {showBranding && ( diff --git a/src/components/AnnotationDesktop/RightDrawer/RightDrawerPanel.ts b/src/components/AnnotationDesktop/DrawerPanel.ts similarity index 75% rename from src/components/AnnotationDesktop/RightDrawer/RightDrawerPanel.ts rename to src/components/AnnotationDesktop/DrawerPanel.ts index b8b48908..81b06ad8 100644 --- a/src/components/AnnotationDesktop/RightDrawer/RightDrawerPanel.ts +++ b/src/components/AnnotationDesktop/DrawerPanel.ts @@ -1,4 +1,4 @@ -export enum RightDrawerPanel { +export enum DrawerPanel { ANNOTATIONS = 'ANNOTATIONS', diff --git a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css b/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css deleted file mode 100644 index ed644c80..00000000 --- a/src/components/AnnotationDesktop/RightDrawer/RightDrawer.css +++ /dev/null @@ -1,46 +0,0 @@ -.ia-right-drawer { - background-color: var(--gray-100); - right: 0; - scroll-padding: 40px; - top: 0; - transform: translateX(360px); - width: 360px; -} - -.ia-right-drawer aside { - box-sizing: border-box; - padding: 0 5px; -} - -.ia-right-drawer:not([data-collapsed]) { - box-shadow: - 0px 0px 16px -1px rgba(0, 0, 0, 0.15), - 0px 0px 16px -8px rgba(0, 0, 0, 0.25), - 0px 0px 16px -12px rgba(0, 0, 0, 0.32), - 0px 0px 2px 0px rgba(0, 0, 0, 0.28); -} - -.with-notification { - display: inline-block; - position: relative; -} - -.notification-bubble { - all: unset; - align-items: center; - background-color: var(--bright-blue); - border-radius: 999px; - border: 1px solid #fff; - color: #fff !important; - display: flex; - gap: 1px; - font-size: 9px; - height: 13px; - justify-content: center; - margin: 0; - padding: 0; - position: absolute; - right: -2px; - top: -2px; - width: 13px; -} \ No newline at end of file diff --git a/src/components/AnnotationDesktop/RightDrawer/index.ts b/src/components/AnnotationDesktop/RightDrawer/index.ts deleted file mode 100644 index eb16cf15..00000000 --- a/src/components/AnnotationDesktop/RightDrawer/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './RightDrawer'; -export * from './RightDrawerPanel'; diff --git a/src/components/AnnotationDesktop/index.ts b/src/components/AnnotationDesktop/index.ts index 5e9316a5..98c5b1e5 100644 --- a/src/components/AnnotationDesktop/index.ts +++ b/src/components/AnnotationDesktop/index.ts @@ -1,5 +1,5 @@ export * from './AnnotationList'; export * from './DocumentNotes'; export * from './LayerConfiguration'; -export * from './RightDrawer'; export * from './UndoStack'; +export * from './DrawerPanel'; diff --git a/src/themes/default/annotation/index.css b/src/themes/default/annotation/index.css index bee0f2fb..3fe3ecaf 100644 --- a/src/themes/default/annotation/index.css +++ b/src/themes/default/annotation/index.css @@ -211,4 +211,29 @@ padding-left: 10px; } +.anno-menubar .with-notification { + display: inline-block; + position: relative; +} + +.anno-menubar .notification-bubble { + all: unset; + align-items: center; + background-color: var(--bright-blue); + border-radius: 999px; + border: 1px solid #fff; + color: #fff !important; + display: flex; + gap: 1px; + font-size: 9px; + height: 13px; + justify-content: center; + margin: 0; + padding: 0; + position: absolute; + right: -2px; + top: -2px; + width: 13px; +} + From 62b51f936d3a8c3e1dd7dd4afe23e3a44d10656f Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Fri, 26 Jan 2024 10:02:48 +0100 Subject: [PATCH 021/135] Re-added text annotation tool panel --- .../AnnotatedText/AnnotatedText.tsx | 137 ++++++++++-------- src/apps/annotation-text/Menubar/Menubar.css | 3 + .../RightDrawer/RightDrawer.css | 3 +- .../annotation-text/TextAnnotationDesktop.tsx | 34 ++--- .../annotation-text/Toolpanel/Toolpanel.css | 70 +++++++++ .../annotation-text/Toolpanel/Toolpanel.tsx | 11 +- 6 files changed, 170 insertions(+), 88 deletions(-) create mode 100644 src/apps/annotation-text/Toolpanel/Toolpanel.css diff --git a/src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx b/src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx index 8235456a..f340ba78 100644 --- a/src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx +++ b/src/apps/annotation-text/AnnotatedText/AnnotatedText.tsx @@ -4,12 +4,13 @@ import { CETEIcean, TEIAnnotator, TextAnnotation, TextAnnotator, TextAnnotatorPo import { Annotation } from '@components/Annotation'; import { UndoStack } from '@components/AnnotationDesktop'; import { DynamicStyle } from '@components/DynamicStyle'; +import { createAppearenceProvider } from '@components/Presence'; import type { PrivacyMode } from '@components/PrivacySelector'; import { SupabasePlugin } from '@components/SupabasePlugin'; import { PDFViewer } from '../PDFViewer'; import { useContent } from '../useContent'; +import { Toolpanel } from '../Toolpanel'; import type { DocumentInTaggedContext, Layer, Policies, Translations } from 'src/Types'; -import { createAppearenceProvider } from '@components/Presence'; const SUPABASE = import.meta.env.PUBLIC_SUPABASE; @@ -71,75 +72,83 @@ export const AnnotatedText = (props: AnnotatedTextProps) => { }, [loading]); return ( -
-
- {contentType === 'text/xml' && text ? ( - <> - - - +
+
+ {contentType === 'text/xml' && text ? ( + <> + + + + + + + ) : contentType === 'application/pdf' && text ? ( + setPDFLoading(false)} /> + ) : text && ( + - - - - ) : contentType === 'application/pdf' && text ? ( - setPDFLoading(false)} /> - ) : text && ( - -

{text}

-
- )} - - - - {props.layers && ( - layer.id)} - appearanceProvider={createAppearenceProvider()} - onInitialLoad={() => setAnnotationsLoading(false)} - onPresence={props.onChangePresent} - privacyMode={privacy === 'PRIVATE'} - /> - )} - - {props.usePopup && ( - ( - - )} - /> - )} +

{text}

+
+ )} + + + + {props.layers && ( + layer.id)} + appearanceProvider={createAppearenceProvider()} + onInitialLoad={() => setAnnotationsLoading(false)} + onPresence={props.onChangePresent} + privacyMode={privacy === 'PRIVATE'} + /> + )} + + {props.usePopup && ( + ( + + )} + /> + )} +
+ +
) diff --git a/src/apps/annotation-text/Menubar/Menubar.css b/src/apps/annotation-text/Menubar/Menubar.css index e69de29b..11f3a6db 100644 --- a/src/apps/annotation-text/Menubar/Menubar.css +++ b/src/apps/annotation-text/Menubar/Menubar.css @@ -0,0 +1,3 @@ +.ta-menubar { + z-index: 10; +} \ No newline at end of file diff --git a/src/apps/annotation-text/RightDrawer/RightDrawer.css b/src/apps/annotation-text/RightDrawer/RightDrawer.css index 922ee223..0194e8a7 100644 --- a/src/apps/annotation-text/RightDrawer/RightDrawer.css +++ b/src/apps/annotation-text/RightDrawer/RightDrawer.css @@ -1,4 +1,4 @@ -.ta-right-drawer { +.ta-drawer.ta-right-drawer { background-color: var(--gray-100); box-shadow: 0px 0px 16px -1px rgba(0, 0, 0, 0.15), @@ -10,6 +10,7 @@ flex-basis: 0; position: relative; scroll-padding: 40px; + z-index: 9; } .ta-right-drawer aside { diff --git a/src/apps/annotation-text/TextAnnotationDesktop.tsx b/src/apps/annotation-text/TextAnnotationDesktop.tsx index 62643dcc..d4b300d8 100644 --- a/src/apps/annotation-text/TextAnnotationDesktop.tsx +++ b/src/apps/annotation-text/TextAnnotationDesktop.tsx @@ -152,24 +152,22 @@ export const TextAnnotationDesktop = (props: TextAnnotationProps) => {
-
- {policies && ( - setLoading(false)} /> - )} -
+ {policies && ( + setLoading(false)} /> + )} { store.bulkDeleteAnnotation(selected.map((s) => s.annotation)); return ( -
-
+
+
@@ -65,8 +67,8 @@ export const Toolpanel = (props: ToolbarProps) => {
0 - ? 'ta-toolbar-context ta-toolbar-context-right anno-desktop-overlay' - : 'ta-toolbar-context ta-toolbar-context-right anno-desktop-overlay hidden' + ? 'ta-toolpanel-context ta-toolpanel-context-right anno-desktop-overlay' + : 'ta-toolpanel-context ta-toolpanel-context-right anno-desktop-overlay hidden' } >
)}
- ) } From 97d816af4aac949487a1f0d1abb7e848960a7d55 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Fri, 26 Jan 2024 10:51:27 +0100 Subject: [PATCH 022/135] Upgraded to latest Annotorious + Text Annotator deps --- package-lock.json | 294 +++++++++++++++++++++++----------------------- package.json | 4 +- 2 files changed, 149 insertions(+), 149 deletions(-) diff --git a/package-lock.json b/package-lock.json index 16399c56..9a6fb288 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "recogito-client", "version": "0.0.1", "dependencies": { - "@annotorious/react": "^3.0.0-rc.18", + "@annotorious/react": "^3.0.0-rc.19", "@astrojs/netlify": "^2.2.3", "@astrojs/node": "^5.3.3", "@astrojs/react": "^2.2.0", @@ -29,7 +29,7 @@ "@react-spring/web": "^9.7.3", "@recogito/annotorious-supabase": "^3.0.0-rc.7", "@recogito/react-pdf-annotator": "1.0.0-rc.7", - "@recogito/react-text-annotator": "^3.0.0-rc.10", + "@recogito/react-text-annotator": "^3.0.0-rc.11", "@supabase/auth-helpers-shared": "^0.3.4", "@supabase/supabase-js": "^2.32.0", "@table-library/react-table-library": "^4.1.7", @@ -96,9 +96,9 @@ } }, "node_modules/@annotorious/annotorious": { - "version": "3.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@annotorious/annotorious/-/annotorious-3.0.0-rc.18.tgz", - "integrity": "sha512-9UOf8nhCc+DfVPuij82yR3S8K0l6EzNZxyAT3Nkv4aV+j0bxGji7IqPoYdJXk6eFXkFD8uqM5VxfpXk5R+fKdA==", + "version": "3.0.0-rc.19", + "resolved": "https://registry.npmjs.org/@annotorious/annotorious/-/annotorious-3.0.0-rc.19.tgz", + "integrity": "sha512-DPVW9rFihxqAjMeCSlSce8ae/FzqHg+wtWnqoYf4Z4wVJ+taY/ZYtLYMr+m+uVt7S0er0GtPhU8FEQo6JzZcHQ==", "peer": true, "dependencies": { "rbush": "^3.0.1", @@ -109,9 +109,9 @@ } }, "node_modules/@annotorious/core": { - "version": "3.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@annotorious/core/-/core-3.0.0-rc.18.tgz", - "integrity": "sha512-CvS5l99OUQYMWY2ULdIqP66kpZ7d9v0l2bmFqaVLi+Pc5DIO3JuvVae8SjymkWaRwTMlfq/8sjuvi6UdV7ks2w==", + "version": "3.0.0-rc.19", + "resolved": "https://registry.npmjs.org/@annotorious/core/-/core-3.0.0-rc.19.tgz", + "integrity": "sha512-FE74AYY8ZK+849gMCNRMZeSPftA4SQBjO9TOGcaGv64Fb2x8tCtQZhLMzpaomOfRsGCdrHXN0nyIcakTaZb5NA==", "peer": true, "dependencies": { "dequal": "^2.0.3", @@ -121,9 +121,9 @@ } }, "node_modules/@annotorious/react": { - "version": "3.0.0-rc.18", - "resolved": "https://registry.npmjs.org/@annotorious/react/-/react-3.0.0-rc.18.tgz", - "integrity": "sha512-HpLOHdVAz6dDnKY3XieCwN049ewRbc3NnVkkPEu0Z/7O3CUDv3ErcysHRgeXyRzZk1qbmmYeQjqITpvLeGxMew==", + "version": "3.0.0-rc.19", + "resolved": "https://registry.npmjs.org/@annotorious/react/-/react-3.0.0-rc.19.tgz", + "integrity": "sha512-EckUfqATkUbSkMqbBZHqI0l1tuo6R9A2omSAt7ODwmyurNFN0XBxcAeqpgiPdri92LzXzx21FnkWjxXnbAa3Bw==", "dependencies": { "@neodrag/react": "^2.0.3" }, @@ -143,9 +143,9 @@ } }, "node_modules/@astrojs/compiler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.4.2.tgz", - "integrity": "sha512-aPdo8rtdN1eBmyERfP5TnYZOnImLYZ8VPHl0eKhFaWIcEIRYhT5NHSohCwtiKcv1M+BprZWRQymojJ3uuk+x7Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.5.1.tgz", + "integrity": "sha512-o2hKiFJXZOm1Gov+RGXSWnKlnb/UF7KRTx/Y2uazYe3+MrLY+sqLN+yB4EH2bElc0l1K9cDb4mZSejuq563rGQ==", "dev": true }, "node_modules/@astrojs/internal-helpers": { @@ -332,20 +332,20 @@ } }, "node_modules/@babel/core": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", - "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.9.tgz", + "integrity": "sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw==", "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.23.5", "@babel/generator": "^7.23.6", "@babel/helper-compilation-targets": "^7.23.6", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.7", - "@babel/parser": "^7.23.6", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.7", - "@babel/types": "^7.23.6", + "@babel/helpers": "^7.23.9", + "@babel/parser": "^7.23.9", + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -531,13 +531,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz", - "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.9.tgz", + "integrity": "sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ==", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.7", - "@babel/types": "^7.23.6" + "@babel/template": "^7.23.9", + "@babel/traverse": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" @@ -557,9 +557,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", - "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.9.tgz", + "integrity": "sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==", "bin": { "parser": "bin/babel-parser.js" }, @@ -600,9 +600,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", - "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", + "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -611,22 +611,22 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.23.9.tgz", + "integrity": "sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", - "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.9.tgz", + "integrity": "sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg==", "dependencies": { "@babel/code-frame": "^7.23.5", "@babel/generator": "^7.23.6", @@ -634,8 +634,8 @@ "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.6", - "@babel/types": "^7.23.6", + "@babel/parser": "^7.23.9", + "@babel/types": "^7.23.9", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -644,9 +644,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", - "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.9.tgz", + "integrity": "sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q==", "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -1229,28 +1229,28 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.5.3.tgz", - "integrity": "sha512-O0WKDOo0yhJuugCx6trZQj5jVJ9yR0ystG2JaNAemYUWce+pmM6WUEFIibnWyEJKdrDxhm75NoSRME35FNaM/Q==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", + "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==", "dependencies": { - "@floating-ui/utils": "^0.2.0" + "@floating-ui/utils": "^0.2.1" } }, "node_modules/@floating-ui/dom": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.5.4.tgz", - "integrity": "sha512-jByEsHIY+eEdCjnTVu+E3ephzTOzkQ8hgUfGwos+bg7NlH33Zc5uO+QHz1mrQUOgIKKDD1RtS201P9NvAfq3XQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.0.tgz", + "integrity": "sha512-SZ0BEXzsaaS6THZfZJUcAobbZTD+MvfGM42bxgeg0Tnkp4/an/avqwAXiVLsFtIBZtfsx3Ymvwx0+KnnhdA/9g==", "dependencies": { - "@floating-ui/core": "^1.5.3", - "@floating-ui/utils": "^0.2.0" + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.1" } }, "node_modules/@floating-ui/react-dom": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.6.tgz", - "integrity": "sha512-IB8aCRFxr8nFkdYZgH+Otd9EVQPJoynxeFRGTB8voPoZMRWo8XjYuCRgpI1btvuKY69XMiLnW+ym7zoBHM90Rw==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.0.7.tgz", + "integrity": "sha512-B5GJxKUyPcGsvE1vua+Abvw0t6zVMyTbtG+Jk7BoI4hfc5Ahv50dstRIAn0nS0274kR9gnKwxIXyGA8EzBZJrA==", "dependencies": { - "@floating-ui/dom": "^1.5.4" + "@floating-ui/dom": "^1.6.0" }, "peerDependencies": { "react": ">=16.8.0", @@ -1352,9 +1352,9 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.21", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz", - "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -2568,9 +2568,9 @@ } }, "node_modules/@recogito/react-text-annotator": { - "version": "3.0.0-rc.10", - "resolved": "https://registry.npmjs.org/@recogito/react-text-annotator/-/react-text-annotator-3.0.0-rc.10.tgz", - "integrity": "sha512-xbBw1Iw7DZeyvlNjlnagDR6qEc03nHnz7tPA+5eDB9I9/FCqocJ+HdRqcCsdeVEVsZOzsQxz/wihq4OgQCaWOQ==", + "version": "3.0.0-rc.11", + "resolved": "https://registry.npmjs.org/@recogito/react-text-annotator/-/react-text-annotator-3.0.0-rc.11.tgz", + "integrity": "sha512-XysYrrmjIOBSabXYGrvG1Lg0O0bk/I4/FgnTzmn6XO80bHQ+P58UWgnab9TlNdOkZfLdBnngiI0qE/Z52c/5eQ==", "dependencies": { "@neodrag/react": "^2.0.3", "CETEIcean": "^1.9.2" @@ -2601,9 +2601,9 @@ } }, "node_modules/@supabase/gotrue-js": { - "version": "2.62.0", - "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.62.0.tgz", - "integrity": "sha512-4eBuZNXGOk7ewqJuHPYMnk8clCtEx6Hfnu6yHLjZlx7w18TqcojcTRUBZagErtpgwwdfzUwKbquexhbrpH/ysw==", + "version": "2.62.2", + "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-2.62.2.tgz", + "integrity": "sha512-AP6e6W9rQXFTEJ7sTTNYQrNf0LCcnt1hUW+RIgUK+Uh3jbWvcIST7wAlYyNZiMlS9+PYyymWQ+Ykz/rOYSO0+A==", "dependencies": { "@supabase/node-fetch": "^2.6.14" } @@ -2723,9 +2723,9 @@ } }, "node_modules/@types/crypto-js": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.1.tgz", - "integrity": "sha512-FSPGd9+OcSok3RsM0UZ/9fcvMOXJ1ENE/ZbLfOPlBWj7BgXtEAM8VYfTtT760GiLbQIMoVozwVuisjvsVwqYWw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz", + "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==", "dev": true }, "node_modules/@types/debug": { @@ -2791,9 +2791,9 @@ } }, "node_modules/@types/node": { - "version": "20.11.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", - "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", + "version": "20.11.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.7.tgz", + "integrity": "sha512-GPmeN1C3XAyV5uybAf4cMLWT9fDWcmQhZVtMFu7OR32WjrqGG+Wnk2V1d0bmtUyE/Zy1QJ9BxyiTih9z8Oks8A==", "dependencies": { "undici-types": "~5.26.4" } @@ -2886,9 +2886,9 @@ "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" }, "node_modules/@types/uuid": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", - "integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==", + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", "dev": true }, "node_modules/@types/ws": { @@ -2905,16 +2905,16 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.0.tgz", - "integrity": "sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.1.tgz", + "integrity": "sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.19.0", - "@typescript-eslint/type-utils": "6.19.0", - "@typescript-eslint/utils": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/type-utils": "6.19.1", + "@typescript-eslint/utils": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -2940,15 +2940,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.0.tgz", - "integrity": "sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.19.1.tgz", + "integrity": "sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.19.0", - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/typescript-estree": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4" }, "engines": { @@ -2968,13 +2968,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz", - "integrity": "sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.19.1.tgz", + "integrity": "sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0" + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2985,13 +2985,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.0.tgz", - "integrity": "sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.19.1.tgz", + "integrity": "sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.19.0", - "@typescript-eslint/utils": "6.19.0", + "@typescript-eslint/typescript-estree": "6.19.1", + "@typescript-eslint/utils": "6.19.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -3012,9 +3012,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.0.tgz", - "integrity": "sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.19.1.tgz", + "integrity": "sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -3025,13 +3025,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz", - "integrity": "sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.1.tgz", + "integrity": "sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/visitor-keys": "6.19.0", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/visitor-keys": "6.19.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3053,17 +3053,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.0.tgz", - "integrity": "sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.19.1.tgz", + "integrity": "sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.19.0", - "@typescript-eslint/types": "6.19.0", - "@typescript-eslint/typescript-estree": "6.19.0", + "@typescript-eslint/scope-manager": "6.19.1", + "@typescript-eslint/types": "6.19.1", + "@typescript-eslint/typescript-estree": "6.19.1", "semver": "^7.5.4" }, "engines": { @@ -3078,12 +3078,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz", - "integrity": "sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==", + "version": "6.19.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.1.tgz", + "integrity": "sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.19.0", + "@typescript-eslint/types": "6.19.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3232,9 +3232,9 @@ "integrity": "sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==" }, "node_modules/@vscode/l10n": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/@vscode/l10n/-/l10n-0.0.16.tgz", - "integrity": "sha512-JT5CvrIYYCrmB+dCana8sUqJEcGB1ZDXNLMQ2+42bW995WmNoenijWMUdZfwmuQUTQcEVVIa2OecZzTYWUW9Cg==" + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/@vscode/l10n/-/l10n-0.0.18.tgz", + "integrity": "sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==" }, "node_modules/accept-language-parser": { "version": "1.5.0", @@ -3940,9 +3940,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001579", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz", - "integrity": "sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==", + "version": "1.0.30001580", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001580.tgz", + "integrity": "sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==", "funding": [ { "type": "opencollective", @@ -4494,9 +4494,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.637", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.637.tgz", - "integrity": "sha512-G7j3UCOukFtxVO1vWrPQUoDk3kL70mtvjc/DC/k2o7lE0wAdq+Vwp1ipagOow+BH0uVztFysLWbkM/RTIrbK3w==" + "version": "1.4.647", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.647.tgz", + "integrity": "sha512-Z/fTNGwc45WrYQhPaEcz5tAJuZZ8G7S/DBnhS6Kgp4BxnS40Z/HqlJ0hHg3Z79IGVzuVartIlTcjw/cQbPLgOw==" }, "node_modules/emmet": { "version": "2.4.6", @@ -8671,9 +8671,9 @@ } }, "node_modules/property-information": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.4.0.tgz", - "integrity": "sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.4.1.tgz", + "integrity": "sha512-OHYtXfu5aI2sS2LWFSN5rgJjrQ4pCy8i1jubJLe2QvMF8JJ++HXTUIVWFLfXJoaOfvYYjk2SN8J2wFUWIGXT4w==", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -9614,9 +9614,9 @@ } }, "node_modules/shiki/node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==" }, "node_modules/side-channel": { "version": "1.0.4", @@ -10510,9 +10510,9 @@ } }, "node_modules/vite": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz", - "integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", + "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", "dependencies": { "esbuild": "^0.18.10", "postcss": "^8.4.27", @@ -10943,22 +10943,22 @@ } }, "node_modules/vscode-css-languageservice": { - "version": "6.2.11", - "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.2.11.tgz", - "integrity": "sha512-qn49Wa6K94LnizpVxmlYrcPf1Cb36gq1nNueW0COhi4shylXBzET5wuDbH8ZWQlJD0HM5Mmnn7WE9vQVVs+ULA==", + "version": "6.2.12", + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.2.12.tgz", + "integrity": "sha512-PS9r7HgNjqzRl3v91sXpCyZPc8UDotNo6gntFNtGCKPhGA9Frk7g/VjX1Mbv3F00pn56D+rxrFzR9ep4cawOgA==", "dependencies": { - "@vscode/l10n": "^0.0.16", + "@vscode/l10n": "^0.0.18", "vscode-languageserver-textdocument": "^1.0.11", "vscode-languageserver-types": "3.17.5", "vscode-uri": "^3.0.8" } }, "node_modules/vscode-html-languageservice": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.1.1.tgz", - "integrity": "sha512-JenrspIIG/Q+93R6G3L6HdK96itSisMynE0glURqHpQbL3dKAKzdm8L40lAHNkwJeBg+BBPpAshZKv/38onrTQ==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.1.2.tgz", + "integrity": "sha512-wkWfEx/IIR3s2P5yD4aTGHiOb8IAzFxgkSt1uSC3itJ4oDAm23yG7o0L29JljUdnXDDgLafPAvhv8A2I/8riHw==", "dependencies": { - "@vscode/l10n": "^0.0.16", + "@vscode/l10n": "^0.0.18", "vscode-languageserver-textdocument": "^1.0.11", "vscode-languageserver-types": "^3.17.5", "vscode-uri": "^3.0.8" diff --git a/package.json b/package.json index 1c5668fa..e5c6f212 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "astro": "astro" }, "dependencies": { - "@annotorious/react": "^3.0.0-rc.18", + "@annotorious/react": "^3.0.0-rc.19", "@astrojs/netlify": "^2.2.3", "@astrojs/node": "^5.3.3", "@astrojs/react": "^2.2.0", @@ -32,7 +32,7 @@ "@react-spring/web": "^9.7.3", "@recogito/annotorious-supabase": "^3.0.0-rc.7", "@recogito/react-pdf-annotator": "1.0.0-rc.7", - "@recogito/react-text-annotator": "^3.0.0-rc.10", + "@recogito/react-text-annotator": "^3.0.0-rc.11", "@supabase/auth-helpers-shared": "^0.3.4", "@supabase/supabase-js": "^2.32.0", "@table-library/react-table-library": "^4.1.7", From cb91184b1c732270f6dba22f9d4a769e91d2fd31 Mon Sep 17 00:00:00 2001 From: Rainer Simon Date: Fri, 26 Jan 2024 14:33:38 +0100 Subject: [PATCH 023/135] Changed 'Back' icon + label in project sidebar --- package.json | 2 +- src/i18n/de/project-sidebar.json | 1 + src/i18n/en/project-sidebar.json | 1 + src/layouts/project/ProjectSidebar.tsx | 7 +++++-- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index c7b2dfa8..1c5668fa 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.1", "scripts": { "dev": "astro dev", - "start": "astro dev --host", + "start": "astro dev", "build": "astro build", "build-node": "astro build --config astro.config.node.mjs", "preview-node": "node ./dist/server/entry.mjs", diff --git a/src/i18n/de/project-sidebar.json b/src/i18n/de/project-sidebar.json index 80c71098..abb9b154 100644 --- a/src/i18n/de/project-sidebar.json +++ b/src/i18n/de/project-sidebar.json @@ -1,4 +1,5 @@ { + "Back to Projects": "Zurück zu Projekte", "Projects": "Projekte", "Documents": "Dokumente", "Collaboration": "Projektteam", diff --git a/src/i18n/en/project-sidebar.json b/src/i18n/en/project-sidebar.json index 3eca6dd7..8d2a66bb 100644 --- a/src/i18n/en/project-sidebar.json +++ b/src/i18n/en/project-sidebar.json @@ -1,4 +1,5 @@ { + "Back to Projects": "Back to Projects", "Projects": "Projects", "Documents": "Documents", "Collaboration": "Collaboration", diff --git a/src/layouts/project/ProjectSidebar.tsx b/src/layouts/project/ProjectSidebar.tsx index 3a4c383e..ced0fa77 100644 --- a/src/layouts/project/ProjectSidebar.tsx +++ b/src/layouts/project/ProjectSidebar.tsx @@ -1,8 +1,11 @@ import { useEffect, useState } from 'react'; import { ArrowLineLeft, + CaretCircleLeft, + CaretLeft, Folders, GraduationCap, + House, Sliders, UsersThree, } from '@phosphor-icons/react'; @@ -73,8 +76,8 @@ export const ProjectSidebar = (props: ProjectSidebarProps) => { } - label='Recogito' + icon={} + label={t['Back to Projects']} link={`/${lang}/projects`} /> From 16c88b5f178edad32fdd2d6176e6e6fe9c53c75d Mon Sep 17 00:00:00 2001 From: lorinjameson Date: Wed, 24 Jan 2024 13:43:26 -0500 Subject: [PATCH 024/135] WIP --- package-lock.json | 54 ++++++ package.json | 2 + src/apps/dashboard-projects/Header/Header.tsx | 156 ++++++++++++------ .../CreateProjectDialog.css | 76 +++++++++ .../CreateProjectDialog.tsx | 123 ++++++++++++++ src/components/CreateProjectDialog/index.ts | 1 + src/components/InfoTooltip/InfoTooltip.css | 95 +++++++++++ src/components/InfoTooltip/InfoTooltip.tsx | 25 +++ src/components/InfoTooltip/index.ts | 1 + src/i18n/en/dashboard-projects.json | 12 +- src/themes/default/index.css | 1 + 11 files changed, 490 insertions(+), 56 deletions(-) create mode 100644 src/components/CreateProjectDialog/CreateProjectDialog.css create mode 100644 src/components/CreateProjectDialog/CreateProjectDialog.tsx create mode 100644 src/components/CreateProjectDialog/index.ts create mode 100644 src/components/InfoTooltip/InfoTooltip.css create mode 100644 src/components/InfoTooltip/InfoTooltip.tsx create mode 100644 src/components/InfoTooltip/index.ts diff --git a/package-lock.json b/package-lock.json index 9a6fb288..f41b2eb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,10 +19,12 @@ "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dropdown-menu": "^2.0.4", + "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-progress": "^1.0.3", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^1.2.2", + "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-toast": "^1.1.3", "@radix-ui/react-tooltip": "^1.0.7", @@ -1783,6 +1785,29 @@ } } }, + "node_modules/@radix-ui/react-label": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz", + "integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-menu": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.6.tgz", @@ -2216,6 +2241,35 @@ } } }, + "node_modules/@radix-ui/react-switch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.3.tgz", + "integrity": "sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-use-size": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-tabs": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.0.4.tgz", diff --git a/package.json b/package.json index e5c6f212..c44f419d 100644 --- a/package.json +++ b/package.json @@ -22,10 +22,12 @@ "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dropdown-menu": "^2.0.4", + "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.6", "@radix-ui/react-progress": "^1.0.3", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^1.2.2", + "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tabs": "^1.0.4", "@radix-ui/react-toast": "^1.1.3", "@radix-ui/react-tooltip": "^1.0.7", diff --git a/src/apps/dashboard-projects/Header/Header.tsx b/src/apps/dashboard-projects/Header/Header.tsx index 2757046b..af1abd2c 100644 --- a/src/apps/dashboard-projects/Header/Header.tsx +++ b/src/apps/dashboard-projects/Header/Header.tsx @@ -1,20 +1,32 @@ import { useState } from 'react'; import { Plus } from '@phosphor-icons/react'; import { supabase } from '@backend/supabaseBrowserClient'; -import { initProject } from '@backend/helpers'; import { AccountActions } from '@components/AccountActions'; import { Button } from '@components/Button'; import { Notifications } from '@components/Notifications'; import { RecogitoLogo } from '@components/RecogitoLogo'; -import type { Invitation, MyProfile, ExtendedProjectData, Translations, Policies } from 'src/Types'; +import type { + Invitation, + MyProfile, + ExtendedProjectData, + Translations, + Policies, +} from 'src/Types'; +import type { + Invitation, + MyProfile, + ExtendedProjectData, + Translations, + Policies, +} from 'src/Types'; import { ProjectFilter } from '../ProjectsHome'; import { HeaderSearchAction } from './Search'; import { HeaderSortAction, SortFunction } from './Sort'; +import { CreateProjectDialog } from '@components/CreateProjectDialog'; import './Header.css'; interface HeaderProps { - i18n: Translations; me: MyProfile; @@ -35,127 +47,161 @@ interface HeaderProps { onProjectCreated(project: ExtendedProjectData): void; - onInvitationAccepted(invitation: Invitation, project: ExtendedProjectData): void; + onInvitationAccepted( + invitation: Invitation, + project: ExtendedProjectData + ): void; onInvitationDeclined(invitation: Invitation): void; onError(error: string): void; - } export const Header = (props: HeaderProps) => { - const { t } = props.i18n; - + const { filter, onChangeFilter } = props; const [all, mine, shared] = props.projects; // 'Create new project' button state const [creating, setCreating] = useState(false); + const [createProjectOpen, setCreateProjectOpen] = useState(false); const onCreateProject = () => { - if (creating) - return; + if (creating) return; - setCreating(true); + setCreateProjectOpen(true); - initProject(supabase, t['Untitled Project']) - .then(project => { - props.onProjectCreated(project); - setCreating(false); + setCreating(true); + // + // initProject(supabase, t['Untitled Project']) + // .then(project => { + // props.onProjectCreated(project); + // setCreating(false); + // }) + // .catch(error => { + // console.error(error); + // setCreating(false); + // props.onError('Something went wrong'); + // }); + }; + + const handleSaveProject = ( + name: string, + description: string, + openJoin: boolean, + openEdit: boolean + ) => { + supabase + .rpc('create_project_rpc', { + _description: description, + _is_open_edit: openEdit, + _is_open_join: openJoin, + _name: name, }) - .catch(error => { - console.error(error); - setCreating(false); - props.onError('Something went wrong'); + .then(({ data, error }) => { + if (error) { + setCreating(false); + props.onError('Something went wrong'); + } else { + props.onProjectCreated(data); + window.location.href = `/${props.i18n.lang}/projects/${data[0].id}`; + } }); - } + }; return ( -
-
+
+

{t['Projects']}

-
- +
{props.policies?.get('projects').has('INSERT') && ( - )} - - + onInvitationDeclined={props.onInvitationDeclined} + onError={props.onError} + /> +
-
-
    +
    +
    • onChangeFilter(ProjectFilter.ALL)}> + onClick={() => onChangeFilter(ProjectFilter.ALL)} + > - - + + {all.length}
    • onChangeFilter(ProjectFilter.MINE)}> + onClick={() => onChangeFilter(ProjectFilter.MINE)} + > - + {mine.length}
    • onChangeFilter(ProjectFilter.SHARED)}> + onClick={() => onChangeFilter(ProjectFilter.SHARED)} + > - + {shared.length}
    -
      +
      • - +
      • - + onChangeSort={props.onChangeSort} + />
      + setCreateProjectOpen(false)} + onSaveProject={handleSaveProject} + i18n={props.i18n} + />
- ) - -} \ No newline at end of file + ); +}; diff --git a/src/components/CreateProjectDialog/CreateProjectDialog.css b/src/components/CreateProjectDialog/CreateProjectDialog.css new file mode 100644 index 00000000..0c42fd28 --- /dev/null +++ b/src/components/CreateProjectDialog/CreateProjectDialog.css @@ -0,0 +1,76 @@ +.create-project-input { + margin-bottom: 10px; +} + +.create-project-root { + margin-top: 24px; + display: flex; + flex-direction: column; +} +.create-project-dialog-button-container { + display: flex; + justify-content: flex-end; +} +.create-project-switch-root { + width: 42px; + height: 25px; + padding: 0; + background-color: var(--gray-200); + border-radius: 9999px; + position: relative; + box-shadow: 0 2px 10px var(--gray-200); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + box-sizing: content-box; + display: block; + min-width: 42px; +} + +.create-project-switch-root[data-state='checked'] { + background-color: var(--light-blue); +} + +.create-project-switch-thumb { + display: block; + width: 21px; + height: 21px; + background-color: var(--gray-500); + border-radius: 9999px; + box-shadow: 0 2px 2px var(--bright-blue); + transition: transform 100ms; + transform: translateX(2px); + will-change: transform; +} +.create-project-switch-thumb[data-state='checked'] { + transform: translateX(19px); + background-color: var(--bright-blue); +} + +.create-project-switch-label { + color: --var(--gray-900); + font-size: 15px; + line-height: 1; + margin-left: 3px; +} + +.create-project-label-root { + font-size: 15px; + font-weight: 500; + line-height: 35px; + color: --var(--gray-900); +} + +.create-project-buttons { + display: flex; + flex-direction: row; + width: 100%; + justify-content: space-between; + margin-top: 24px; +} + +.create-project-switches { + display: flex; + flex-direction: row; + margin-top: 24px; + align-items: center; + justify-content: center; +} diff --git a/src/components/CreateProjectDialog/CreateProjectDialog.tsx b/src/components/CreateProjectDialog/CreateProjectDialog.tsx new file mode 100644 index 00000000..52fef82d --- /dev/null +++ b/src/components/CreateProjectDialog/CreateProjectDialog.tsx @@ -0,0 +1,123 @@ +import * as Dialog from '@radix-ui/react-dialog'; +import type { Translations } from 'src/Types'; +import * as Switch from '@radix-ui/react-switch'; +import * as Label from '@radix-ui/react-label'; +import './CreateProjectDialog.css'; +import { Button } from '@components/Button'; +import { useState } from 'react'; +import { InfoTooltip } from '@components/InfoTooltip'; + +interface CreateProjectDialogProps { + open: boolean; + + i18n: Translations; + + onSaveProject( + name: string, + description: string, + isOpenJoin: boolean, + isOpenEdit: boolean + ): void; + + onClose(): void; +} + +export const CreateProjectDialog = (props: CreateProjectDialogProps) => { + const { t } = props.i18n; + + const [name, setName] = useState(''); + const [description, setDescription] = useState(''); + const [openJoin, setOpenJoin] = useState(false); + const [openEdit, setOpenEdit] = useState(false); + + const handleCreateProject = () => { + props.onSaveProject(name, description, !!openJoin, !!openEdit); + }; + + return ( + + + + + + + {t['Create Project']} + +
+ + {t['Project Name']} + + setName(evt.target.value)} + /> + + {t['Project Description']} + + setDescription(evt.target.value)} + /> +
+ + + setOpenJoin(!openJoin)} + > + + +
+ + + setOpenEdit(!openEdit)} + > + + +
+
+ + + +
+
+ + + + ); +}; diff --git a/src/components/CreateProjectDialog/index.ts b/src/components/CreateProjectDialog/index.ts new file mode 100644 index 00000000..cd84f070 --- /dev/null +++ b/src/components/CreateProjectDialog/index.ts @@ -0,0 +1 @@ +export * from './CreateProjectDialog'; diff --git a/src/components/InfoTooltip/InfoTooltip.css b/src/components/InfoTooltip/InfoTooltip.css new file mode 100644 index 00000000..32c28d55 --- /dev/null +++ b/src/components/InfoTooltip/InfoTooltip.css @@ -0,0 +1,95 @@ +.info-tooltip-content { + border-radius: 4px; + padding: 10px 15px; + font-size: 15px; + line-height: 1; + color: var(--violet-11); + background-color: white; + box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, + hsl(206 22% 7% / 20%) 0px 10px 20px -15px; + user-select: none; + animation-duration: 400ms; + animation-timing-function: cubic-bezier(0.16, 0.5, 0.3, 0.5); + will-change: transform, opacity; +} +.info-tooltip-content[data-state='delayed-open'][data-side='top'] { + animation-name: slideDownAndFade; +} +.info-tooltip-content[data-state='delayed-open'][data-side='right'] { + animation-name: slideLeftAndFade; +} +.info-tooltip-content[data-state='delayed-open'][data-side='bottom'] { + animation-name: slideUpAndFade; +} +.info-tooltip-content[data-state='delayed-open'][data-side='left'] { + animation-name: slideRightAndFade; +} + +.info-tooltip-arrow { + fill: white; +} + +.info-tooltip-icon { + font-family: inherit; + color: var(--bright-blue); +} + +.info-tooltip-icon-button { + width: 14px; + min-width: 16px; + height: 14px; + padding: 0; + background-color: transparent; + border: none; +} + +.info-tooltip-icon-button:hover { + background-color: var(--violet-3); +} +.info-tooltip-icon-button:focus { + box-shadow: 0 0 0 2px black; +} + +@keyframes slideUpAndFade { + from { + opacity: 0; + transform: translateY(2px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideRightAndFade { + from { + opacity: 0; + transform: translateX(-2px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes slideDownAndFade { + from { + opacity: 0; + transform: translateY(-2px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideLeftAndFade { + from { + opacity: 0; + transform: translateX(2px); + } + to { + opacity: 1; + transform: translateX(0); + } +} diff --git a/src/components/InfoTooltip/InfoTooltip.tsx b/src/components/InfoTooltip/InfoTooltip.tsx new file mode 100644 index 00000000..46d57014 --- /dev/null +++ b/src/components/InfoTooltip/InfoTooltip.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import * as Tooltip from '@radix-ui/react-tooltip'; +import { Info } from '@phosphor-icons/react'; +import './InfoTooltip.css'; + +interface InfoTooltipProps { + content: string; +} +export const InfoTooltip = (props: InfoTooltipProps) => { + return ( + + + + + + + + {props.content} + + + + + + ); +}; diff --git a/src/components/InfoTooltip/index.ts b/src/components/InfoTooltip/index.ts new file mode 100644 index 00000000..d42977a0 --- /dev/null +++ b/src/components/InfoTooltip/index.ts @@ -0,0 +1 @@ +export * from './InfoTooltip'; diff --git a/src/i18n/en/dashboard-projects.json b/src/i18n/en/dashboard-projects.json index 291815d2..5ca7885b 100644 --- a/src/i18n/en/dashboard-projects.json +++ b/src/i18n/en/dashboard-projects.json @@ -41,5 +41,15 @@ "This feature will become available soon.": "This feature will become available soon.", "User Profile Message": "Please complete your User Profile.", "Complete Profile": "Complete Profile", - "User Profile": "User Profile" + "User Profile": "User Profile", + "Create Project": "Create Project", + "Create": "Create", + "Project Name": "Project Name", + "Name your project": "Name your project", + "Project Description": "Project Description", + "Describe your project": "Describe your project", + "Open Join": "Open Join", + "Open Edit": "Open Edit", + "open-join-info": "With 'Open Join' switched on, any registered user can join your project without an invitation.", + "open-edit-info": "With 'Open Edit' switched on, any member of your project can edit the default assignment" } \ No newline at end of file diff --git a/src/themes/default/index.css b/src/themes/default/index.css index 91fdcbf7..97bde948 100644 --- a/src/themes/default/index.css +++ b/src/themes/default/index.css @@ -113,6 +113,7 @@ --dark-blue: #07498a; --bright-blue: #07529a; --brighter-blue: #0969c3; + --light-blue: #88bcf7; --sand: #987116; --mud-gray: #808073; --orange: #e9b44a; From 2f31083a84ad6033c4d1d3bedb70a97357325cf5 Mon Sep 17 00:00:00 2001 From: lorinjameson Date: Thu, 25 Jan 2024 11:57:10 -0500 Subject: [PATCH 025/135] WIP --- src/Types.ts | 2 + src/apps/dashboard-projects/ProjectsHome.tsx | 13 +- src/apps/project-home/ProjectHome.tsx | 8 +- src/apps/project-home/useDocumentList.ts | 30 ++-- src/backend/helpers/projectHelpers.ts | 18 +++ .../CreateProjectDialog.tsx | 8 +- .../ProjectCard/JoinProjectDialog.css | 18 +++ .../ProjectCard/JoinProjectDialog.tsx | 62 +++++++++ src/components/ProjectCard/OpenJoin.css | 13 ++ src/components/ProjectCard/OpenJoin.tsx | 23 ++++ src/components/ProjectCard/ProjectCard.tsx | 128 ++++++++++++------ src/i18n/en/dashboard-projects.json | 5 +- 12 files changed, 262 insertions(+), 66 deletions(-) create mode 100644 src/components/ProjectCard/JoinProjectDialog.css create mode 100644 src/components/ProjectCard/JoinProjectDialog.tsx create mode 100644 src/components/ProjectCard/OpenJoin.css create mode 100644 src/components/ProjectCard/OpenJoin.tsx diff --git a/src/Types.ts b/src/Types.ts index d5db907f..6484e7de 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -53,6 +53,8 @@ export interface ExtendedProjectData { description?: string; + is_open_join?: boolean; + contexts: Context[]; layers: [ diff --git a/src/apps/dashboard-projects/ProjectsHome.tsx b/src/apps/dashboard-projects/ProjectsHome.tsx index c4620577..69313371 100644 --- a/src/apps/dashboard-projects/ProjectsHome.tsx +++ b/src/apps/dashboard-projects/ProjectsHome.tsx @@ -57,9 +57,10 @@ export const ProjectsHome = (props: ProjectsHomeProps) => { const [showProfileNag, setShowProfileNag] = useState( !me.first_name || - !me.first_name.length || - !me.last_name || - !me.last_name.length); + !me.first_name.length || + !me.last_name || + !me.last_name.length + ); useEffect(() => { getMyProfile(supabase).then(({ error }) => { @@ -77,10 +78,14 @@ export const ProjectsHome = (props: ProjectsHomeProps) => { ) ); + const openJoinProjects = projects.filter( + (p) => p.is_open_join && p.contexts.length === 0 + ); + // All projects are different for admins vs. mere mortals const allProjects = me.isOrgAdmin ? projects - : [...myProjects, ...sharedProjects]; + : [...myProjects, ...sharedProjects, ...openJoinProjects]; const filteredProjects = // All projects diff --git a/src/apps/project-home/ProjectHome.tsx b/src/apps/project-home/ProjectHome.tsx index 233145b2..8dce3b30 100644 --- a/src/apps/project-home/ProjectHome.tsx +++ b/src/apps/project-home/ProjectHome.tsx @@ -55,8 +55,6 @@ export const ProjectHome = (props: ProjectHomeProps) => { const isAdmin = projectPolicies?.get('projects').has('UPDATE'); - const canUpload = projectPolicies?.get('documents').has('INSERT'); - const [toast, setToast] = useState(null); const [showUploads, setShowUploads] = useState(false); @@ -71,7 +69,7 @@ export const ProjectHome = (props: ProjectHomeProps) => { const { addDocumentIds } = useDocumentList( project.id, - defaultContext!.id, + defaultContext?.id, (document) => setDocuments((d) => [...d, document]) ); @@ -212,7 +210,7 @@ export const ProjectHome = (props: ProjectHomeProps) => { onError={() => onError('Error updating project description.')} /> - {canUpload && ( + {isAdmin && (
+ +
+ + + + + + + + ); +}; diff --git a/src/components/ProjectCard/OpenJoin.css b/src/components/ProjectCard/OpenJoin.css new file mode 100644 index 00000000..f6816af6 --- /dev/null +++ b/src/components/ProjectCard/OpenJoin.css @@ -0,0 +1,13 @@ +.open-join-bar { + width: 100%; + display: flex; + flex-direction: row; + justify-content: flex-end; +} + +.open-join-button { + min-height: 34px; + height: 34px; + background-color: var(--dark-blue); + color: var(--gray-100); +} diff --git a/src/components/ProjectCard/OpenJoin.tsx b/src/components/ProjectCard/OpenJoin.tsx new file mode 100644 index 00000000..ad293e00 --- /dev/null +++ b/src/components/ProjectCard/OpenJoin.tsx @@ -0,0 +1,23 @@ +import type { Translations } from 'src/Types'; +import './OpenJoin.css'; +import { SignIn } from '@phosphor-icons/react'; + +interface OpenJoinProps { + projectId: string; + + i18n: Translations; + + onJoin(): void; +} +export const OpenJoin = (props: OpenJoinProps) => { + const { t } = props.i18n; + + return ( +
+ +
+ ); +}; diff --git a/src/components/ProjectCard/ProjectCard.tsx b/src/components/ProjectCard/ProjectCard.tsx index 2576cd07..e42bd05f 100644 --- a/src/components/ProjectCard/ProjectCard.tsx +++ b/src/components/ProjectCard/ProjectCard.tsx @@ -1,13 +1,23 @@ import { Article, GraduationCap, Image } from '@phosphor-icons/react'; import { useProjectPolicies } from '@backend/hooks'; +import { joinProject } from '@backend/helpers'; import { Avatar } from '@components/Avatar'; -import type { ContentType, ExtendedProjectData, MyProfile, Translations, UserProfile } from 'src/Types'; +import type { + ContentType, + ExtendedProjectData, + MyProfile, + Translations, + UserProfile, +} from 'src/Types'; import { ProjectCardActions } from './ProjectCardActions'; +import { OpenJoin } from './OpenJoin'; import './ProjectCard.css'; +import { JoinProjectDialog } from './JoinProjectDialog'; +import { useState } from 'react'; +import { supabase } from '@backend/supabaseBrowserClient'; interface ProjectCardProps { - i18n: Translations; me: MyProfile; @@ -19,83 +29,114 @@ interface ProjectCardProps { onDetailsChanged(updated: ExtendedProjectData): void; onError(error: string): void; - } export const ProjectCard = (props: ProjectCardProps) => { - - const { contexts, description, layers, id, groups, name } = props.project; + const { contexts, description, layers, id, groups, name, is_open_join } = + props.project; const policies = useProjectPolicies(props.project.id); - const members = groups.reduce((members, group) => ( - [...members, ...group.members] - ), [] as Array<{ user: UserProfile, since: string }>).reverse(); + const [joinProjectOpen, setJoinProjectOpen] = useState(false); + + const members = groups + .reduce( + (members, group) => [...members, ...group.members], + [] as Array<{ user: UserProfile; since: string }> + ) + .reverse(); - // TODO needs more robustness for new content types + // TODO needs more robustness for new content types // in the future const documents = layers.reduce((documents, layer) => { - if (documents.some(d => d.id === layer.document?.id)) + if (documents.some((d) => d.id === layer.document?.id)) return [...documents]; - else if (layer.document) - return [...documents, layer.document]; - else - return documents; - }, [] as {id: string, content_type?: ContentType }[]); + else if (layer.document) return [...documents, layer.document]; + else return documents; + }, [] as { id: string; content_type?: ContentType }[]); const images = documents.filter(({ content_type }) => !content_type); const texts = documents.filter(({ content_type }) => content_type); - const onClick = () => - window.location.href = `./projects/${id}`; + const onClick = () => { + if (!is_open_join || members.length > 0) { + window.location.href = `./projects/${id}`; + } + }; + + const handleJoinProject = () => { + setJoinProjectOpen(true); + }; + + const handleConfirmJoin = () => { + setJoinProjectOpen(false); + joinProject(supabase, id).then((resp) => { + if (resp) { + window.location.href = `./projects/${id}`; + } else { + props.onError(props.i18n.t['Something happened']); + } + }); + }; return ( -
-
-

{name}

+
+
+

+ {name} +

{description ? (

{description}

) : ( -

- {props.i18n.t['No description.']} -

+

{props.i18n.t['No description.']}

)} -
    +
      {contexts.length > 1 && (
    • - {contexts.length - 1} + {contexts.length - 1}
    • )} {images.length > 0 && (
    • - {images.length} + {images.length}
    • )} {texts.length > 0 && (
    • - {texts.length} + {texts.length}
    • )}
- -
-
+ setJoinProjectOpen(false)} + i18n={props.i18n} + project={props.project} + onJoin={handleConfirmJoin} + /> +
+
{members.slice(0, 5).map(({ user }) => ( str).join(' ').trim()} - avatar={user.avatar_url} /> + name={ + user.nickname + ? user.nickname + : [user.first_name, user.last_name] + .filter((str) => str) + .join(' ') + .trim() + } + avatar={user.avatar_url} + /> ))}
@@ -104,12 +145,19 @@ export const ProjectCard = (props: ProjectCardProps) => { i18n={props.i18n} me={props.me} project={props.project} - onDeleted={props.onDeleted} + onDeleted={props.onDeleted} onDetailsChanged={props.onDetailsChanged} - onError={props.onError} /> + onError={props.onError} + /> + )} + {is_open_join && members.length === 0 && ( + )}
- ) - -} \ No newline at end of file + ); +}; diff --git a/src/i18n/en/dashboard-projects.json b/src/i18n/en/dashboard-projects.json index 5ca7885b..1bf1c597 100644 --- a/src/i18n/en/dashboard-projects.json +++ b/src/i18n/en/dashboard-projects.json @@ -51,5 +51,8 @@ "Open Join": "Open Join", "Open Edit": "Open Edit", "open-join-info": "With 'Open Join' switched on, any registered user can join your project without an invitation.", - "open-edit-info": "With 'Open Edit' switched on, any member of your project can edit the default assignment" + "open-edit-info": "With 'Open Edit' switched on, any member of your project can edit the default assignment", + "Join": "Join", + "Join Project": "Join Project", + "Join Project Message": "This project allows all users to become members. Would you like to join?" } \ No newline at end of file From c1ca00d54d64a79a516ce8e3e5f9a0b808419444 Mon Sep 17 00:00:00 2001 From: lorinjameson Date: Mon, 29 Jan 2024 13:49:05 -0500 Subject: [PATCH 026/135] Project settings updates --- src/Types.ts | 2 + src/apps/project-settings/ProjectSettings.css | 88 ++++++- src/apps/project-settings/ProjectSettings.tsx | 230 ++++++++++++++---- src/backend/helpers/documentHelpers.ts | 17 +- src/backend/helpers/projectHelpers.ts | 25 +- src/i18n/de/dashboard-projects.json | 15 +- src/i18n/de/project-settings.json | 11 +- src/i18n/en/project-settings.json | 11 +- 8 files changed, 335 insertions(+), 64 deletions(-) diff --git a/src/Types.ts b/src/Types.ts index 6484e7de..6f643917 100644 --- a/src/Types.ts +++ b/src/Types.ts @@ -55,6 +55,8 @@ export interface ExtendedProjectData { is_open_join?: boolean; + is_open_edit?: boolean; + contexts: Context[]; layers: [ diff --git a/src/apps/project-settings/ProjectSettings.css b/src/apps/project-settings/ProjectSettings.css index bddcffd5..5b44ea04 100644 --- a/src/apps/project-settings/ProjectSettings.css +++ b/src/apps/project-settings/ProjectSettings.css @@ -3,6 +3,26 @@ width: 100%; } +.project-settings-inputs { + display: flex; + flex-direction: column; + margin-bottom: 20px; +} + +.project-settings .project-settings-switch { + display: flex; + flex-direction: row; + align-items: center; + margin-bottom: 20px; + width: 100%; +} + +.project-settings-switch-description { + font-size: smaller; + margin-left: 20px; + width: 600px; +} + .project-settings .tagging-vocabulary { background-color: var(--gray-50); border: 1px solid var(--gray-200); @@ -34,4 +54,70 @@ display: flex; gap: 0.2em; align-items: center; -} \ No newline at end of file +} + +.project-settings-switch-root { + width: 42px; + height: 25px; + padding: 0; + background-color: var(--gray-200); + border-radius: 9999px; + position: relative; + box-shadow: 0 2px 10px var(--gray-200); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + box-sizing: content-box; + display: block; + min-width: 42px; +} + +.project-settings-switch-root[data-state='checked'] { + background-color: var(--light-blue); +} + +.project-settings-switch-thumb { + display: block; + width: 21px; + height: 21px; + background-color: var(--gray-500); + border-radius: 9999px; + box-shadow: 0 2px 2px var(--bright-blue); + transition: transform 100ms; + transform: translateX(2px); + will-change: transform; +} +.project-settings-switch-thumb[data-state='checked'] { + transform: translateX(19px); + background-color: var(--bright-blue); +} + +.project-settings-switch-label { + color: --var(--gray-900); + font-size: 15px; + line-height: 1; + margin-left: 3px; + width: 90px; + max-width: 90px; +} + +.project-settings-label-root { + font-size: 15px; + font-weight: 500; + line-height: 35px; + color: --var(--gray-900); +} + +.project-settings-buttons { + display: flex; + flex-direction: row; + width: 100%; + justify-content: space-between; + margin-top: 24px; +} + +.project-settings-switches { + display: flex; + flex-direction: row; + margin-top: 24px; + align-items: center; + justify-content: center; +} diff --git a/src/apps/project-settings/ProjectSettings.tsx b/src/apps/project-settings/ProjectSettings.tsx index db494552..14af2285 100644 --- a/src/apps/project-settings/ProjectSettings.tsx +++ b/src/apps/project-settings/ProjectSettings.tsx @@ -1,23 +1,27 @@ import { useEffect, useState } from 'react'; -import { clearProjectTagVocabulary, getProjectTagVocabulary, setProjectTagVocabulary } from '@backend/helpers'; +import { + clearProjectTagVocabulary, + getProjectTagVocabulary, + setProjectTagVocabulary, + updateProject, +} from '@backend/helpers'; import { supabase } from '@backend/supabaseBrowserClient'; import { Button } from '@components/Button'; import { SaveState, TinySaveIndicator } from '@components/TinySaveIndicator'; import { Toast, ToastContent, ToastProvider } from '@components/Toast'; import type { ExtendedProjectData, Translations } from 'src/Types'; +import * as Switch from '@radix-ui/react-switch'; +import * as Label from '@radix-ui/react-label'; import './ProjectSettings.css'; interface ProjectSettingsProps { - i18n: Translations; project: ExtendedProjectData; - -}; +} export const ProjectSettings = (props: ProjectSettingsProps) => { - const { t } = props.i18n; const [toast, setToast] = useState(null); @@ -25,46 +29,88 @@ export const ProjectSettings = (props: ProjectSettingsProps) => { const [vocabulary, setVocabulary] = useState([]); const [state, setState] = useState('idle'); + const [openEdit, setOpenEdit] = useState(false); + const [openJoin, setOpenJoin] = useState(false); + const [name, setName] = useState(''); + const [description, setDescription] = useState(''); + const [project, setProject] = useState(); useEffect(() => { - getProjectTagVocabulary(supabase, props.project.id) - .then(({ error, data }) => { + getProjectTagVocabulary(supabase, props.project.id).then( + ({ error, data }) => { if (error) { - setToast({ - title: t['Something went wrong'], - description: t['Error loading tag vocabulary.'], - type: 'error' + setToast({ + title: t['Something went wrong'], + description: t['Error loading tag vocabulary.'], + type: 'error', }); } else { - setVocabulary(data.map(t => t.name)); + setVocabulary(data.map((t) => t.name)); } - }); + } + ); }, []); + useEffect(() => { + if (props.project) { + setOpenEdit(props.project.is_open_edit || false); + setOpenJoin(props.project.is_open_join || false); + setName(props.project.name); + setDescription(props.project.description || ''); + setProject(props.project); + } + }, [props.project]); + const onChange = (evt: React.ChangeEvent) => { const { value } = evt.target; setVocabulary(value.split('\n')); - } + }; const saveVocabulary = () => { setState('saving'); setProjectTagVocabulary(supabase, props.project.id, vocabulary) - .then(() => { + .then(() => { setState('success'); }) - .catch(error => { + .catch((error) => { console.error(error); - setToast({ - title: t['Something went wrong'], - description: t['Error saving tag vocabulary.'], - type: 'error' + setToast({ + title: t['Something went wrong'], + description: t['Error saving tag vocabulary.'], + type: 'error', }); setState('failed'); }); - } + }; + + const saveProjectSettings = () => { + setState('saving'); + + updateProject( + supabase, + props.project.id, + name, + description, + openJoin, + openEdit + ).then((result) => { + if (result) { + setProject({ + ...props.project, + name: name, + description: description, + is_open_join: openJoin, + is_open_edit: openEdit, + }); + setState('success'); + } else { + setState('failed'); + } + }); + }; const clearVocabulary = () => { setState('saving'); @@ -78,10 +124,10 @@ export const ProjectSettings = (props: ProjectSettingsProps) => { setState('success'); }) .catch(() => { - setToast({ - title: t['Something went wrong'], - description: t['Error saving tag vocabulary.'], - type: 'error' + setToast({ + title: t['Something went wrong'], + description: t['Error saving tag vocabulary.'], + type: 'error', }); setState('failed'); @@ -89,52 +135,136 @@ export const ProjectSettings = (props: ProjectSettingsProps) => { // Roll back setVocabulary(prev); }); - } + }; + + const saveDisabled = + project && + project.name === name && + project.description === description && + project.is_open_join === openJoin && + project.is_open_edit === openEdit; return ( -
+

{t['Project Settings']}

-
+
+

{t['Name and Access Settings']}

+
+ + {t['Project Name']} + + setName(evt.target.value)} + /> + + {t['Project Description']} + + setDescription(evt.target.value)} + /> +
+
+ + { + setOpenJoin(!openJoin); + }} + > + + +
+ {t['open-join-info']} +
+
+
+
+ + setOpenEdit(!openEdit)} + > + + +
+ {t['open-edit-info']} +
+
+
+ + + +
+
+ +

{t['Tagging Vocabulary']}

-

- {t['You can pre-define a tagging vocabulary']} -

+

{t['You can pre-define a tagging vocabulary']}

-

- {t['The terms will appear as autocomplete options']} -

+

{t['The terms will appear as autocomplete options']}

-