From dbc22f90f854c8882e5a46d42368e63045d55a5c Mon Sep 17 00:00:00 2001 From: "Nicholaus (Nico) Halecky" Date: Fri, 31 Jan 2025 16:44:00 -0300 Subject: [PATCH] Revert "feat: DIA-1794: [FE] Implement home page in LSO and LSE (#6885)" This reverts commit e95280e1d4731af31047009a25eebf237964f435. --- Dockerfile.development | 2 +- Makefile | 3 - label_studio/core/templates/home/home.html | 3 - label_studio/core/views.py | 9 +- label_studio/users/views.py | 10 +- web/.stylelintrc.json | 1 - web/apps/labelstudio/src/app/App.jsx | 11 - .../src/components/Menubar/Menubar.jsx | 4 +- .../src/pages/CreateProject/CreateProject.jsx | 6 +- .../labelstudio/src/pages/Home/HomePage.tsx | 213 ------------------ .../Organization/PeoplePage/InviteLink.tsx | 110 --------- .../Organization/PeoplePage/PeoplePage.jsx | 76 ++++++- web/apps/labelstudio/src/pages/index.js | 4 +- .../src/providers/ApiProvider.d.ts | 4 - .../labelstudio/src/providers/ApiProvider.jsx | 2 +- .../src/providers/RoutesProvider.jsx | 20 +- .../labelstudio/src/services/breadrumbs.js | 99 +++++--- web/apps/labelstudio/src/types/Project.d.ts | 5 +- .../labelstudio/src/utils/feature-flags.ts | 2 - web/apps/labelstudio/src/utils/jotai-store.ts | 5 - web/jest.config.ts | 14 -- web/jest.preset.js | 12 +- web/libs/editor/jest.config.js | 3 - web/libs/ui/package.json | 3 +- web/libs/ui/src/assets/icons/external.svg | 3 - web/libs/ui/src/assets/icons/folder-add.svg | 3 - web/libs/ui/src/assets/icons/folder.svg | 3 - web/libs/ui/src/assets/icons/home.svg | 4 - web/libs/ui/src/assets/icons/humansignal.svg | 4 - web/libs/ui/src/assets/icons/index.ts | 8 - web/libs/ui/src/assets/icons/ls-labeling.svg | 10 - web/libs/ui/src/assets/icons/ls-review.svg | 9 - web/libs/ui/src/assets/icons/user-add.svg | 3 - web/libs/ui/src/index.ts | 6 +- .../Toast.module.scss} | 0 .../lib/{toast/toast.tsx => Toast/Toast.tsx} | 2 +- web/libs/ui/src/lib/simple-card/index.tsx | 27 --- web/libs/ui/src/lib/space/Space.module.scss | 46 ---- web/libs/ui/src/lib/space/index.tsx | 42 ---- web/libs/ui/src/lib/space/space.module.scss | 46 ---- .../ui/src/lib/spinner/Spinner.module.scss | 89 -------- web/libs/ui/src/lib/spinner/Spinner.tsx | 28 --- .../ui/src/lib/spinner/spinner.module.scss | 89 -------- web/libs/ui/src/lib/spinner/spinner.tsx | 28 --- web/libs/ui/src/shad/components/ui/badge.tsx | 29 --- web/libs/ui/src/shad/components/ui/button.tsx | 10 +- web/libs/ui/src/shad/components/ui/card.tsx | 43 ---- web/libs/ui/src/shad/components/ui/select.tsx | 2 +- web/libs/ui/src/shad/utils/index.ts | 6 - web/libs/ui/src/tailwind.config.js | 29 +-- web/libs/ui/src/tailwind.css | 14 +- web/libs/ui/src/typography/heading.tsx | 21 -- web/libs/ui/src/typography/index.ts | 2 - web/libs/ui/src/typography/sub.tsx | 11 - web/package.json | 3 - web/tailwind.config.js | 3 - web/tsconfig.base.json | 1 - web/yarn.lock | 30 +-- 58 files changed, 173 insertions(+), 1102 deletions(-) delete mode 100644 label_studio/core/templates/home/home.html delete mode 100644 web/apps/labelstudio/src/pages/Home/HomePage.tsx delete mode 100644 web/apps/labelstudio/src/pages/Organization/PeoplePage/InviteLink.tsx delete mode 100644 web/apps/labelstudio/src/utils/jotai-store.ts delete mode 100644 web/libs/ui/src/assets/icons/external.svg delete mode 100644 web/libs/ui/src/assets/icons/folder-add.svg delete mode 100644 web/libs/ui/src/assets/icons/folder.svg delete mode 100644 web/libs/ui/src/assets/icons/home.svg delete mode 100644 web/libs/ui/src/assets/icons/humansignal.svg delete mode 100644 web/libs/ui/src/assets/icons/ls-labeling.svg delete mode 100644 web/libs/ui/src/assets/icons/ls-review.svg delete mode 100644 web/libs/ui/src/assets/icons/user-add.svg rename web/libs/ui/src/lib/{toast/toast.module.scss => Toast/Toast.module.scss} (100%) rename web/libs/ui/src/lib/{toast/toast.tsx => Toast/Toast.tsx} (99%) delete mode 100644 web/libs/ui/src/lib/simple-card/index.tsx delete mode 100644 web/libs/ui/src/lib/space/Space.module.scss delete mode 100644 web/libs/ui/src/lib/space/index.tsx delete mode 100644 web/libs/ui/src/lib/space/space.module.scss delete mode 100644 web/libs/ui/src/lib/spinner/Spinner.module.scss delete mode 100644 web/libs/ui/src/lib/spinner/Spinner.tsx delete mode 100644 web/libs/ui/src/lib/spinner/spinner.module.scss delete mode 100644 web/libs/ui/src/lib/spinner/spinner.tsx delete mode 100644 web/libs/ui/src/shad/components/ui/badge.tsx delete mode 100644 web/libs/ui/src/shad/components/ui/card.tsx delete mode 100644 web/libs/ui/src/shad/utils/index.ts delete mode 100644 web/libs/ui/src/typography/heading.tsx delete mode 100644 web/libs/ui/src/typography/index.ts delete mode 100644 web/libs/ui/src/typography/sub.tsx delete mode 100644 web/tailwind.config.js diff --git a/Dockerfile.development b/Dockerfile.development index e1b89c13497d..9e312f5f75df 100644 --- a/Dockerfile.development +++ b/Dockerfile.development @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 ARG NODE_VERSION=18 ARG PYTHON_VERSION=3.12 -ARG POETRY_VERSION=2.0.1 +ARG POETRY_VERSION=1.8.4 ARG VERSION_OVERRIDE ARG BRANCH_OVERRIDE diff --git a/Makefile b/Makefile index d1a8f067d5a7..5ea66738f281 100644 --- a/Makefile +++ b/Makefile @@ -33,9 +33,6 @@ docker-run-dev: docker-migrate-dev: docker compose run app python3 /label-studio/label_studio/manage.py migrate -docker-collectstatic-dev: - docker compose run app python3 /label-studio/label_studio/manage.py collectstatic - # Install modules frontend-install: cd web && yarn install --frozen-lockfile; diff --git a/label_studio/core/templates/home/home.html b/label_studio/core/templates/home/home.html deleted file mode 100644 index 3d19a4ecfce8..000000000000 --- a/label_studio/core/templates/home/home.html +++ /dev/null @@ -1,3 +0,0 @@ -{% extends 'base.html' %} -{% load i18n %} -{% load static %} diff --git a/label_studio/core/views.py b/label_studio/core/views.py index dd737f02892d..7c048a19e8ea 100644 --- a/label_studio/core/views.py +++ b/label_studio/core/views.py @@ -13,7 +13,7 @@ import pandas as pd import requests from core import utils -from core.feature_flags import all_flags, flag_set, get_feature_file_path +from core.feature_flags import all_flags, get_feature_file_path from core.label_config import generate_time_series_json from core.utils.common import collect_versions from core.utils.io import find_file @@ -27,7 +27,7 @@ HttpResponseServerError, JsonResponse, ) -from django.shortcuts import redirect, render, reverse +from django.shortcuts import redirect, reverse from django.template import loader from django.utils._os import safe_join from django.views.decorators.csrf import csrf_exempt @@ -55,10 +55,7 @@ def main(request): return redirect(reverse('user-login')) # business mode access - if flag_set('fflag_all_feat_dia_1777_ls_homepage_short'): - return render(request, 'home/home.html') - else: - return redirect(reverse('projects:project-index')) + return redirect(reverse('projects:project-index')) # not authenticated return redirect(reverse('user-login')) diff --git a/label_studio/users/views.py b/label_studio/users/views.py index 52b1f5f76062..77ea4edcb4c0 100644 --- a/label_studio/users/views.py +++ b/label_studio/users/views.py @@ -41,10 +41,7 @@ def user_signup(request): # checks if the URL is a safe redirection. if not next_page or not url_has_allowed_host_and_scheme(url=next_page, allowed_hosts=request.get_host()): - if flag_set('fflag_all_feat_dia_1777_ls_homepage_short'): - next_page = reverse('main') - else: - next_page = reverse('projects:project-index') + next_page = reverse('projects:project-index') user_form = forms.UserSignupForm() organization_form = OrganizationSignupForm() @@ -104,10 +101,7 @@ def user_login(request): # checks if the URL is a safe redirection. if not next_page or not url_has_allowed_host_and_scheme(url=next_page, allowed_hosts=request.get_host()): - if flag_set('fflag_all_feat_dia_1777_ls_homepage_short'): - next_page = reverse('main') - else: - next_page = reverse('projects:project-index') + next_page = reverse('projects:project-index') login_form = load_func(settings.USER_LOGIN_FORM) form = login_form() diff --git a/web/.stylelintrc.json b/web/.stylelintrc.json index f85d1a259049..d50130f5c4ac 100644 --- a/web/.stylelintrc.json +++ b/web/.stylelintrc.json @@ -4,7 +4,6 @@ "selector-class-pattern": null, "custom-property-pattern": null, "no-descending-specificity": null, - "function-no-unknown": null, "scss/no-global-function-names": null, "scss/function-no-unknown": null, "selector-pseudo-class-no-unknown": [ diff --git a/web/apps/labelstudio/src/app/App.jsx b/web/apps/labelstudio/src/app/App.jsx index efbde5452813..573542a085ce 100644 --- a/web/apps/labelstudio/src/app/App.jsx +++ b/web/apps/labelstudio/src/app/App.jsx @@ -20,18 +20,9 @@ import { FF_OPTIC_2, FF_UNSAVED_CHANGES, FF_PRODUCT_TOUR, isFF } from "../utils/ import { TourProvider } from "@humansignal/core"; import { ToastProvider, ToastViewport } from "@humansignal/ui"; import "@humansignal/ui/src/tailwind.css"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { JotaiProvider, JotaiStore } from "../utils/jotai-store"; const baseURL = new URL(APP_SETTINGS.hostname || location.origin); export const UNBLOCK_HISTORY_MESSAGE = "UNBLOCK_HISTORY"; -const queryClient = new QueryClient({ - defaultOptions: { - queries: { - refetchOnWindowFocus: false, - }, - }, -}); const browserHistory = createBrowserHistory({ basename: baseURL.pathname || "/", @@ -66,8 +57,6 @@ const App = ({ content }) => { , - , , , , diff --git a/web/apps/labelstudio/src/components/Menubar/Menubar.jsx b/web/apps/labelstudio/src/components/Menubar/Menubar.jsx index 4ace04b8bad7..c3044a09db2d 100644 --- a/web/apps/labelstudio/src/components/Menubar/Menubar.jsx +++ b/web/apps/labelstudio/src/components/Menubar/Menubar.jsx @@ -26,8 +26,7 @@ import "./Menubar.scss"; import "./MenuContent.scss"; import "./MenuSidebar.scss"; import { ModelsPage } from "../../pages/Organization/Models/ModelsPage"; -import { FF_DIA_835, FF_HOMEPAGE, isFF } from "../../utils/feature-flags"; -import { IconHome } from "@humansignal/ui"; +import { FF_DIA_835, isFF } from "../../utils/feature-flags"; export const MenubarContext = createContext(); @@ -184,7 +183,6 @@ export const Menubar = ({ enabled, defaultOpened, defaultPinned, children, onSid style={{ width: 240 }} > - {isFF(FF_HOMEPAGE) && } data-external exact />} } data-external exact /> } data-external exact /> {isFF(FF_DIA_835) && } exact />} diff --git a/web/apps/labelstudio/src/pages/CreateProject/CreateProject.jsx b/web/apps/labelstudio/src/pages/CreateProject/CreateProject.jsx index b5bf6f075073..42d23ee4d3d4 100644 --- a/web/apps/labelstudio/src/pages/CreateProject/CreateProject.jsx +++ b/web/apps/labelstudio/src/pages/CreateProject/CreateProject.jsx @@ -78,7 +78,7 @@ const ProjectName = ({ name, setName, onSaveName, onSubmit, error, description, ); -export const CreateProject = ({ onClose, redirect = true }) => { +export const CreateProject = ({ onClose }) => { const [step, _setStep] = React.useState("name"); // name | import | config const [waiting, setWaitingStatus] = React.useState(false); @@ -173,9 +173,9 @@ export const CreateProject = ({ onClose, redirect = true }) => { }, }); setWaitingStatus(false); - redirect && history.replace("/projects"); + history.replace("/projects"); onClose?.(); - }, [project, redirect]); + }, [project]); return ( diff --git a/web/apps/labelstudio/src/pages/Home/HomePage.tsx b/web/apps/labelstudio/src/pages/Home/HomePage.tsx deleted file mode 100644 index 5cc44acc9cbb..000000000000 --- a/web/apps/labelstudio/src/pages/Home/HomePage.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import type { Page } from "../types/Page"; -import { Button } from "@humansignal/shad/components/ui/button"; -import { IconFolder, SimpleCard, Spinner } from "@humansignal/ui"; -import { IconExternal, IconFolderAdd, IconHumanSignal, IconUserAdd } from "@humansignal/icons"; -import { HeidiTips } from "../../components/HeidiTips/HeidiTips"; -import { useQuery } from "@tanstack/react-query"; -import { useAPI } from "../../providers/ApiProvider"; -import { useState } from "react"; -import { CreateProject } from "../CreateProject/CreateProject"; -import { InviteLink } from "../Organization/PeoplePage/InviteLink"; -import { Heading, Sub } from "@humansignal/typography"; - -const PROJECTS_TO_SHOW = 10; - -const resources = [ - { - title: "Documentation", - url: "https://labelstud.io/guide/", - }, - { - title: "API Documentation", - url: "https://api.labelstud.io/api-reference/introduction/getting-started", - }, - { - title: "Release Notes", - url: "https://labelstud.io/learn/categories/release-notes/", - }, - { - title: "LabelStud.io Blog", - url: "https://labelstud.io/blog/", - }, - { - title: "Slack Community", - url: "https://slack.labelstud.io", - }, -]; - -const actions = [ - { - title: "Create Project", - icon: IconFolderAdd, - type: "createProject", - }, - { - title: "Invite People", - icon: IconUserAdd, - type: "invitePeople", - }, -] as const; - -type Action = (typeof actions)[number]["type"]; - -export const HomePage: Page = () => { - const api = useAPI(); - const [creationDialogOpen, setCreationDialogOpen] = useState(false); - const [invitationOpen, setInvitationOpen] = useState(false); - const { data, isFetching, isSuccess, isError } = useQuery({ - queryKey: ["projects", { page_size: 10 }], - async queryFn() { - return api.callApi<{ results: APIProject[]; count: number }>("projects", { - params: { page_size: PROJECTS_TO_SHOW }, - }); - }, - }); - - const handleActions = (action: Action) => { - return () => { - switch (action) { - case "createProject": - setCreationDialogOpen(true); - break; - case "invitePeople": - setInvitationOpen(true); - break; - } - }; - }; - - return ( -
-
-
-
- Welcome 👋 - Let's get you started. -
-
- {actions.map((action) => { - return ( - - ); - })} -
- - 0 ? ( - <> - Recent Projects{" "} - - View All - - - ) : null - } - > - {isFetching ? ( -
- -
- ) : isError ? ( -
can't load projects
- ) : isSuccess && data.results.length === 0 ? ( -
-
- -
- Create your first project - Import your data and set up the labeling interface to start annotating - -
- ) : isSuccess && data.results.length > 0 ? ( -
- {data.results.map((project) => { - return ; - })} -
- ) : null} -
-
-
- - - - -
- - Label Studio Version: Community -
-
-
- {creationDialogOpen && setCreationDialogOpen(false)} />} - setInvitationOpen(false)} /> -
- ); -}; - -HomePage.title = "Home"; -HomePage.path = "/"; -HomePage.exact = true; - -function ProjectSimpleCard({ - project, -}: { - project: APIProject; -}) { - const finished = project.finished_task_number ?? 0; - const total = project.task_number ?? 0; - const progress = (total > 0 ? finished / total : 0) * 100; - const white = "#FFFFFF"; - const color = project.color && project.color !== white ? project.color : "#E1DED5"; - - return ( -
-
-
- - {project.title} - -
- {finished} of {total} Tasks ({total > 0 ? Math.round((finished / total) * 100) : 0}%) -
-
-
-
-
-
-
- ); -} diff --git a/web/apps/labelstudio/src/pages/Organization/PeoplePage/InviteLink.tsx b/web/apps/labelstudio/src/pages/Organization/PeoplePage/InviteLink.tsx deleted file mode 100644 index f215a803dcf9..000000000000 --- a/web/apps/labelstudio/src/pages/Organization/PeoplePage/InviteLink.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import { Description } from "apps/labelstudio/src/components/Description/Description"; -import { Block } from "apps/labelstudio/src/components/Menu/MenuContext"; -import { Input } from "../../../components/Form"; -import { useCallback, useEffect, useRef, useState } from "react"; -import { Space } from "@humansignal/ui"; -import { Button } from "@humansignal/shad/components/ui/button"; -import { API } from "apps/labelstudio/src/providers/ApiProvider"; -import { atomWithQuery } from "jotai-tanstack-query"; -import { useAtomValue } from "jotai"; -import { Modal } from "apps/labelstudio/src/components/Modal/ModalPopup"; - -const linkAtom = atomWithQuery(() => ({ - queryKey: ["invite-link"], - async queryFn() { - // called only once when the component is rendered on page reload - // will also be reset when called `refetch()` on the Reset button - const result = await API.resetInviteLink(); - return location.origin + result.invite_url; - }, -})); - -export function InviteLink({ - opened, - onOpened, - onClosed, -}: { - opened: boolean; - onOpened?: () => void; - onClosed?: () => void; -}) { - const modalRef = useRef(); - useEffect(() => { - if (opened) { - modalRef.current?.show?.(); - } else { - modalRef.current?.hide?.(); - } - }, [opened]); - - return ( - } - footer={} - style={{ width: 640, height: 472 }} - onHide={onClosed} - onShow={onOpened} - /> - ); -} - -const InvitationModal = () => { - const { data: link } = useAtomValue(linkAtom); - return ( - - - - - Invite people to join your Label Studio instance. People that you invite have full access to all of your - projects.{" "} - - __lsa("docs.organization.add_people.learn_more", { href: "https://labelstud.io/guide/signup.html" }) - } - > - Learn more - - . - - - ); -}; - -const InvitationFooter = () => { - const { copyText, copied } = useTextCopy(); - const { refetch, data: link } = useAtomValue(linkAtom); - - return ( - - - - - - - - - ); -}; - -function useTextCopy() { - const [copied, setCopied] = useState(false); - - const copyText = useCallback((value: string) => { - setCopied(true); - navigator.clipboard.writeText(value ?? ""); - setTimeout(() => setCopied(false), 1500); - }, []); - - return { copied, copyText }; -} diff --git a/web/apps/labelstudio/src/pages/Organization/PeoplePage/PeoplePage.jsx b/web/apps/labelstudio/src/pages/Organization/PeoplePage/PeoplePage.jsx index 7d0b13246da0..529753d4f6b6 100644 --- a/web/apps/labelstudio/src/pages/Organization/PeoplePage/PeoplePage.jsx +++ b/web/apps/labelstudio/src/pages/Organization/PeoplePage/PeoplePage.jsx @@ -1,19 +1,20 @@ -import { useCallback, useMemo, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { LsPlus } from "../../../assets/icons"; import { Button } from "../../../components"; import { Description } from "../../../components/Description/Description"; import { Input } from "../../../components/Form"; import { HeidiTips } from "../../../components/HeidiTips/HeidiTips"; +import { modal } from "../../../components/Modal/Modal"; import { Space } from "../../../components/Space/Space"; import { useAPI } from "../../../providers/ApiProvider"; import { useConfig } from "../../../providers/ConfigProvider"; import { Block, Elem } from "../../../utils/bem"; import { FF_LSDV_E_297, isFF } from "../../../utils/feature-flags"; +import { copyText } from "../../../utils/helpers"; import "./PeopleInvitation.scss"; import { PeopleList } from "./PeopleList"; import "./PeoplePage.scss"; import { SelectedUser } from "./SelectedUser"; -import { InviteLink } from "./InviteLink"; const InvitationModal = ({ link }) => { return ( @@ -44,7 +45,8 @@ export const PeoplePage = () => { const inviteModal = useRef(); const config = useConfig(); const [selectedUser, setSelectedUser] = useState(null); - const [invitationOpen, setInvitationOpen] = useState(false); + + const [link, setLink] = useState(); const selectUser = useCallback( (user) => { @@ -55,10 +57,75 @@ export const PeoplePage = () => { [setSelectedUser], ); + const setInviteLink = useCallback( + (link) => { + const hostname = config.hostname || location.origin; + + setLink(`${hostname}${link}`); + }, + [config, setLink], + ); + + const updateLink = useCallback(() => { + api.callApi("resetInviteLink").then(({ invite_url }) => { + setInviteLink(invite_url); + }); + }, [setInviteLink]); + + const inviteModalProps = useCallback( + (link) => ({ + title: "Invite people", + style: { width: 640, height: 472 }, + body: () => , + footer: () => { + const [copied, setCopied] = useState(false); + + const copyLink = useCallback(() => { + setCopied(true); + copyText(link); + setTimeout(() => setCopied(false), 1500); + __lsa("organization.add_people.copy_link"); + }, []); + + return ( + + + + + + + + + ); + }, + bareFooter: true, + }), + [], + ); + + const showInvitationModal = useCallback(() => { + inviteModal.current = modal(inviteModalProps(link)); + __lsa("organization.add_people"); + }, [inviteModalProps, link]); + const defaultSelected = useMemo(() => { return localStorage.getItem("selectedUser"); }, []); + useEffect(() => { + api.callApi("inviteLink").then(({ invite_url }) => { + setInviteLink(invite_url); + }); + }, []); + + useEffect(() => { + inviteModal.current?.update(inviteModalProps(link)); + }, [link]); + return ( @@ -66,7 +133,7 @@ export const PeoplePage = () => { - @@ -85,7 +152,6 @@ export const PeoplePage = () => { isFF(FF_LSDV_E_297) && )} - setInvitationOpen(false)} /> ); }; diff --git a/web/apps/labelstudio/src/pages/index.js b/web/apps/labelstudio/src/pages/index.js index 96fe2680b5a1..0c35f0e157f7 100644 --- a/web/apps/labelstudio/src/pages/index.js +++ b/web/apps/labelstudio/src/pages/index.js @@ -1,7 +1,5 @@ import { ProjectsPage } from "./Projects/Projects"; -import { HomePage } from "./Home/HomePage"; import { OrganizationPage } from "./Organization"; import { ModelsPage } from "./Organization/Models/ModelsPage"; -import { FF_HOMEPAGE, isFF } from "../utils/feature-flags"; -export const Pages = [isFF(FF_HOMEPAGE) && HomePage, ProjectsPage, OrganizationPage, ModelsPage].filter(Boolean); +export const Pages = [ProjectsPage, OrganizationPage, ModelsPage]; diff --git a/web/apps/labelstudio/src/providers/ApiProvider.d.ts b/web/apps/labelstudio/src/providers/ApiProvider.d.ts index e7bd4ccf9f2c..f48139390aaa 100644 --- a/web/apps/labelstudio/src/providers/ApiProvider.d.ts +++ b/web/apps/labelstudio/src/providers/ApiProvider.d.ts @@ -1,5 +1,3 @@ -import type { APIProxy } from "libs/datamanager/src/utils/api-proxy"; - export interface Meta { headers: Map; status: number; @@ -23,5 +21,3 @@ export function useAPI(): { }, ) => Promise>; }; - -export const API: APIProxy; diff --git a/web/apps/labelstudio/src/providers/ApiProvider.jsx b/web/apps/labelstudio/src/providers/ApiProvider.jsx index 079ba31f44d0..186556f32fa7 100644 --- a/web/apps/labelstudio/src/providers/ApiProvider.jsx +++ b/web/apps/labelstudio/src/providers/ApiProvider.jsx @@ -5,7 +5,7 @@ import { API_CONFIG } from "../config/ApiConfig"; import { APIProxy } from "../utils/api-proxy"; import { absoluteURL } from "../utils/helpers"; -export const API = new APIProxy(API_CONFIG); +const API = new APIProxy(API_CONFIG); export const ApiContext = createContext(); ApiContext.displayName = "ApiContext"; diff --git a/web/apps/labelstudio/src/providers/RoutesProvider.jsx b/web/apps/labelstudio/src/providers/RoutesProvider.jsx index ee33c9351b80..5e2525b6cab0 100644 --- a/web/apps/labelstudio/src/providers/RoutesProvider.jsx +++ b/web/apps/labelstudio/src/providers/RoutesProvider.jsx @@ -11,22 +11,15 @@ export const RoutesContext = createContext(); const findMacthingComponents = (path, routesMap, parentPath = "") => { const result = []; - const match = - path === "/" - ? routesMap.at(0) - : routesMap.find((route) => { - // if (route.path === "/") return false; + const match = routesMap.find((route) => { + const matchingPath = `${parentPath}${route.path}`; + const match = matchPath(path, { path: matchingPath }); - const isRoot = route.path === "/"; - const matchingPath = `${parentPath}${route.path}`; - const match = matchPath(path, { path: matchingPath, exact: isRoot }); - - return match; - }); + return match; + }); if (match) { const routePath = `${parentPath}${match.path}`; - result.push({ ...match, path: routePath }); if (match.routes) { @@ -100,7 +93,6 @@ export const RoutesProvider = ({ children }) => { } }, [location, routesMap, currentContextProps, routesChain, lastRoute]); - console.log(breadcrumbs); return {children}; }; @@ -113,7 +105,7 @@ export const useFindRouteComponent = () => { }; export const useBreadcrumbs = () => { - return useBreadcrumbControls(); + return useContext(RoutesContext)?.breadcrumbs ?? []; }; export const useCurrentPath = () => { diff --git a/web/apps/labelstudio/src/services/breadrumbs.js b/web/apps/labelstudio/src/services/breadrumbs.js index c1308914401f..b97b6ce13f6d 100644 --- a/web/apps/labelstudio/src/services/breadrumbs.js +++ b/web/apps/labelstudio/src/services/breadrumbs.js @@ -1,6 +1,6 @@ +import { useCallback, useState } from "react"; +import { singletonHook } from "react-singleton-hook"; import { isDefined } from "../utils/helpers"; -import { atom, useAtomValue } from "jotai"; -import { JotaiStore } from "../utils/jotai-store"; const initialBreadcrumbs = []; @@ -10,43 +10,78 @@ const noop = () => { } }; -const crumbsAtom = atom([]); +export let setBreadcrumbs = noop; -export const setBreadcrumbs = (newCrumbs) => { - JotaiStore.set(crumbsAtom, newCrumbs ?? []); -}; +export let addCrumb = noop; -export const addCrumb = (crumb) => { - if (!isDefined(crumb?.key)) throw Error("Crumb must have a key"); +export let deleteCrumb = noop; - JotaiStore.set(crumbsAtom, (crumbs) => [...crumbs, crumb]); -}; +export let addAction = noop; -export const deleteCrumb = (key) => { - JotaiStore.set(crumbsAtom, (crumbs) => crumbs.filter((c) => c.key !== key)); -}; +export let deleteAction = noop; + +let localCrumbs = []; + +export const useBreadcrumbControls = singletonHook(initialBreadcrumbs, () => { + const [breadcrumbs, setBreadcrumbsState] = useState(initialBreadcrumbs); -export const addAction = (key, onClick) => { - JotaiStore.set(crumbsAtom, (crumbs) => - crumbs.map((crumb) => { - if (crumb.key === key) { - return { ...crumb, onClick }; - } - return crumb; - }), + localCrumbs = breadcrumbs; + setBreadcrumbs = (newCrumbs) => { + const crumbs = [...(newCrumbs ?? [])]; + + setBreadcrumbsState(crumbs); + localCrumbs = crumbs; + }; + + addCrumb = useCallback( + (crumb) => { + if (!isDefined(crumb?.key)) throw Error("Crumb must have a key"); + const crumbs = [...localCrumbs, crumb]; + + setBreadcrumbs(crumbs); + localCrumbs = crumbs; + }, + [breadcrumbs], ); -}; -export const deleteAction = (key) => { - JotaiStore.set(crumbsAtom, (crumbs) => - crumbs.map((crumb) => { - if (crumb.key === key) delete crumb.onClick; + deleteCrumb = useCallback( + (key) => { + const crumbs = localCrumbs.filter((c) => c.key !== key); - return crumb; - }), + setBreadcrumbs(crumbs); + localCrumbs = crumbs; + }, + [breadcrumbs], ); -}; -export const useBreadcrumbControls = () => { - return useAtomValue(crumbsAtom); -}; + addAction = useCallback( + (key, onClick) => { + const crumbs = localCrumbs.map((crumb) => { + if (crumb.key === key) { + return { ...crumb, onClick }; + } + return crumb; + }); + + setBreadcrumbs(crumbs); + localCrumbs = crumbs; + }, + [breadcrumbs], + ); + + deleteAction = useCallback( + (key) => { + const crumbs = localCrumbs.map((crumb) => { + if (crumb.key === key) delete crumb.onClick; + + return crumb; + }); + + setBreadcrumbs(crumbs); + localCrumbs = crumbs; + }, + [breadcrumbs], + ); + + return breadcrumbs; +}); diff --git a/web/apps/labelstudio/src/types/Project.d.ts b/web/apps/labelstudio/src/types/Project.d.ts index 962391ae9719..b2ed5689e232 100644 --- a/web/apps/labelstudio/src/types/Project.d.ts +++ b/web/apps/labelstudio/src/types/Project.d.ts @@ -52,7 +52,7 @@ declare type APIProject = { num_tasks_with_annotations?: string; /** Total task number in project */ - task_number?: number; + task_number?: string; /** Useful annotation number in project not including skipped_annotations_number and ground_truth_number. Total annotations = annotation_number + skipped_annotations_number + ground_truth_number */ useful_annotation_number?: string; @@ -66,9 +66,6 @@ declare type APIProject = { /** Total annotations number in project including skipped_annotations_number and ground_truth_number. */ total_annotations_number?: string; - /** Total number of tasks with at least one annotation */ - finished_task_number: number; - /** Total predictions number in project including skipped_annotations_number and ground_truth_number. */ total_predictions_number?: string; sampling?: "Sequential sampling" | "Uniform sampling" | "Uncertainty sampling" | null; diff --git a/web/apps/labelstudio/src/utils/feature-flags.ts b/web/apps/labelstudio/src/utils/feature-flags.ts index 697cb479f1f4..abb10310a1b1 100644 --- a/web/apps/labelstudio/src/utils/feature-flags.ts +++ b/web/apps/labelstudio/src/utils/feature-flags.ts @@ -32,8 +32,6 @@ export const FF_PRODUCT_TOUR = "fflag_feat_dia_1697_product_tour_short"; */ export const FF_UNSAVED_CHANGES = "fflag_feat_front_leap_1198_unsaved_changes_180724"; -export const FF_HOMEPAGE = "fflag_all_feat_dia_1777_ls_homepage_short"; - export function isFF(id: string) { // TODO: remove the override + if statement once LSE and LSO start building react the same way and fflag_fix_front_lsdv_4620_memory_leaks_100723_short is removed const override: Record = { diff --git a/web/apps/labelstudio/src/utils/jotai-store.ts b/web/apps/labelstudio/src/utils/jotai-store.ts deleted file mode 100644 index a8e811787f5d..000000000000 --- a/web/apps/labelstudio/src/utils/jotai-store.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Provider, createStore } from "jotai"; - -export const JotaiStore = createStore(); - -export { Provider as JotaiProvider }; diff --git a/web/jest.config.ts b/web/jest.config.ts index 11c2c9516a86..3e2c3e47c0b3 100644 --- a/web/jest.config.ts +++ b/web/jest.config.ts @@ -1,19 +1,5 @@ import { getJestProjects } from "@nx/jest"; -import { pathsToModuleNameMapper } from "ts-jest"; export default { projects: getJestProjects(), - moduleNameMapper: pathsToModuleNameMapper( - { - "@humansignal/core": ["libs/core/src/index.ts"], - "@humansignal/datamanager": ["libs/datamanager/src/index.js"], - "@humansignal/editor": ["libs/editor/src/index.js"], - "@humansignal/frontend-test/*": ["libs/frontend-test/src/*"], - "@humansignal/ui": ["libs/ui/src/index.ts"], - "@humansignal/icons": ["libs/ui/src/assets/icons"], - "@humansignal/typography": ["libs/ui/src/typography"], - "@humansignal/shad/*": ["./libs/ui/src/shad/*"], - }, - { prefix: "/../../" }, - ), }; diff --git a/web/jest.preset.js b/web/jest.preset.js index 88105ab3e404..0640263d2c6d 100644 --- a/web/jest.preset.js +++ b/web/jest.preset.js @@ -1,13 +1,3 @@ const nxPreset = require("@nx/jest/preset").default; -const tsconfig = require("./tsconfig.base.json"); -const { pathsToModuleNameMapper } = require("ts-jest"); -console.log(__dirname); - -module.exports = { - ...nxPreset, - moduleNameMapper: { - ...nxPreset.moduleNameMapper, - ...pathsToModuleNameMapper(tsconfig.compilerOptions.paths, { prefix: "/../../" }), - }, -}; +module.exports = { ...nxPreset }; diff --git a/web/libs/editor/jest.config.js b/web/libs/editor/jest.config.js index af7b7b00a4be..7bd549bbb24b 100644 --- a/web/libs/editor/jest.config.js +++ b/web/libs/editor/jest.config.js @@ -1,5 +1,3 @@ -const { pathsToModuleNameMapper } = require("ts-jest"); -const tsconfig = require("../../tsconfig.base.json"); /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { bail: true, @@ -59,7 +57,6 @@ module.exports = { "^react-konva-utils": "identity-obj-proxy", "\\.(s[ac]ss|css|svg|png|jpe?g)$": "identity-obj-proxy", "^@humansignal/ui": "/../ui/src/index.ts", - ...pathsToModuleNameMapper(tsconfig.compilerOptions.paths, { prefix: "/../../" }), }, testPathIgnorePatterns: ["/node_modules/", "/e2e/"], testRegex: "__tests__/.*.test.[tj]sx?", diff --git a/web/libs/ui/package.json b/web/libs/ui/package.json index 84568aa1eae4..fd8158609da2 100644 --- a/web/libs/ui/package.json +++ b/web/libs/ui/package.json @@ -4,6 +4,5 @@ "license": "MIT", "private": true, "dependencies": {}, - "main": "src/index.ts", - "files": ["src/tailwind.css", "src/shad/components", "src/ui/assets", "src/ui/typography"] + "main": "src/index.ts" } diff --git a/web/libs/ui/src/assets/icons/external.svg b/web/libs/ui/src/assets/icons/external.svg deleted file mode 100644 index 52a9499af671..000000000000 --- a/web/libs/ui/src/assets/icons/external.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/web/libs/ui/src/assets/icons/folder-add.svg b/web/libs/ui/src/assets/icons/folder-add.svg deleted file mode 100644 index 667816587f73..000000000000 --- a/web/libs/ui/src/assets/icons/folder-add.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/web/libs/ui/src/assets/icons/folder.svg b/web/libs/ui/src/assets/icons/folder.svg deleted file mode 100644 index 9dee105e9034..000000000000 --- a/web/libs/ui/src/assets/icons/folder.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/web/libs/ui/src/assets/icons/home.svg b/web/libs/ui/src/assets/icons/home.svg deleted file mode 100644 index 349a05969bc6..000000000000 --- a/web/libs/ui/src/assets/icons/home.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/web/libs/ui/src/assets/icons/humansignal.svg b/web/libs/ui/src/assets/icons/humansignal.svg deleted file mode 100644 index 9588299bbadf..000000000000 --- a/web/libs/ui/src/assets/icons/humansignal.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/web/libs/ui/src/assets/icons/index.ts b/web/libs/ui/src/assets/icons/index.ts index b654e52a1319..7ad660b91020 100644 --- a/web/libs/ui/src/assets/icons/index.ts +++ b/web/libs/ui/src/assets/icons/index.ts @@ -1,9 +1 @@ export { ReactComponent as IconCross } from "./cross.svg"; -export { ReactComponent as IconExternal } from "./external.svg"; -export { ReactComponent as IconFolderAdd } from "./folder-add.svg"; -export { ReactComponent as IconFolder } from "./folder.svg"; -export { ReactComponent as IconHome } from "./home.svg"; -export { ReactComponent as IconLsLabeling } from "./ls-labeling.svg"; -export { ReactComponent as IconLsReview } from "./ls-review.svg"; -export { ReactComponent as IconUserAdd } from "./user-add.svg"; -export { ReactComponent as IconHumanSignal } from "./humansignal.svg"; diff --git a/web/libs/ui/src/assets/icons/ls-labeling.svg b/web/libs/ui/src/assets/icons/ls-labeling.svg deleted file mode 100644 index d5e096b57064..000000000000 --- a/web/libs/ui/src/assets/icons/ls-labeling.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/web/libs/ui/src/assets/icons/ls-review.svg b/web/libs/ui/src/assets/icons/ls-review.svg deleted file mode 100644 index 1f3332f0eb30..000000000000 --- a/web/libs/ui/src/assets/icons/ls-review.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/web/libs/ui/src/assets/icons/user-add.svg b/web/libs/ui/src/assets/icons/user-add.svg deleted file mode 100644 index 02ffc149449c..000000000000 --- a/web/libs/ui/src/assets/icons/user-add.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/web/libs/ui/src/index.ts b/web/libs/ui/src/index.ts index 96897caa0bf1..72ab72d32482 100644 --- a/web/libs/ui/src/index.ts +++ b/web/libs/ui/src/index.ts @@ -1,8 +1,6 @@ export * from "./lib/checkbox/checkbox"; -export * from "./lib/toast/toast"; +export * from "./lib/Toast/Toast"; export * from "./lib/label/label"; export * from "./lib/toggle/toggle"; -export * from "./lib/spinner/spinner"; -export * from "./lib/space"; -export * from "./lib/simple-card"; + export * from "./assets/icons"; diff --git a/web/libs/ui/src/lib/toast/toast.module.scss b/web/libs/ui/src/lib/Toast/Toast.module.scss similarity index 100% rename from web/libs/ui/src/lib/toast/toast.module.scss rename to web/libs/ui/src/lib/Toast/Toast.module.scss diff --git a/web/libs/ui/src/lib/toast/toast.tsx b/web/libs/ui/src/lib/Toast/Toast.tsx similarity index 99% rename from web/libs/ui/src/lib/toast/toast.tsx rename to web/libs/ui/src/lib/Toast/Toast.tsx index 3633869bde81..f38c8937f9a6 100644 --- a/web/libs/ui/src/lib/toast/toast.tsx +++ b/web/libs/ui/src/lib/Toast/Toast.tsx @@ -1,6 +1,6 @@ import { createContext, type FC, type ReactNode, useCallback, useContext, useState } from "react"; import * as ToastPrimitive from "@radix-ui/react-toast"; -import styles from "./toast.module.scss"; +import styles from "./Toast.module.scss"; import clsx from "clsx"; import { IconCross } from "../../assets/icons"; diff --git a/web/libs/ui/src/lib/simple-card/index.tsx b/web/libs/ui/src/lib/simple-card/index.tsx deleted file mode 100644 index 190a01879872..000000000000 --- a/web/libs/ui/src/lib/simple-card/index.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@humansignal/shad/components/ui/card"; -import { cn } from "@humansignal/shad/utils"; -import type { HtmlHTMLAttributes, PropsWithChildren, ReactNode } from "react"; - -export function SimpleCard({ - children, - title, - description, - className: cls, - ...rest -}: PropsWithChildren< - { - title: ReactNode; - description?: ReactNode; - } & Omit, "title"> ->) { - const className = cn("bg-transparent", cls); - return ( - - - {title} - {description && {description}} - - {children} - - ); -} diff --git a/web/libs/ui/src/lib/space/Space.module.scss b/web/libs/ui/src/lib/space/Space.module.scss deleted file mode 100644 index 10496138ba17..000000000000 --- a/web/libs/ui/src/lib/space/Space.module.scss +++ /dev/null @@ -1,46 +0,0 @@ -.space { - display: grid; - grid-gap: 16px; - grid-auto-flow: column; - align-items: center; - grid-auto-columns: max-content; - -} - -.directionHorizontal { - grid-auto-flow: column; - align-items: center; - grid-auto-columns: max-content; -} - -.directionVertical { - grid-auto-flow: row; - justify-content: center; - grid-auto-rows: max-content; -} - -.alignStart { - justify-content: flex-start; -} - -.alignEnd { - justify-content: flex-end; -} - -.spread { - width: 100%; - justify-content: space-between; -} - -.stretch .directionHorizontal { - grid-auto-columns: 1fr; - grid-auto-rows: 1fr; -} - -.sizeLarge { - grid-gap: 32px; -} - -.sizeSmall { - grid-gap: 12px; -} diff --git a/web/libs/ui/src/lib/space/index.tsx b/web/libs/ui/src/lib/space/index.tsx deleted file mode 100644 index d25ee8c5251a..000000000000 --- a/web/libs/ui/src/lib/space/index.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { cn } from "@humansignal/shad/utils"; -import styles from "./space.module.scss"; -import type { CSSProperties, PropsWithChildren } from "react"; - -export type SpaceProps = PropsWithChildren<{ - direction?: "horizontal" | "vertical"; - size?: "small" | "large"; - className?: string; - style?: CSSProperties; - spread?: boolean; - stretch?: boolean; - align?: "start" | "end"; -}>; - -export const Space = ({ - direction = "horizontal", - size, - className, - style, - children, - spread, - stretch, - align, -}: SpaceProps) => { - const clsToggle = { - [styles.spread]: spread, - [styles.stretch]: stretch, - [styles.sizeSmall]: size === "small", - [styles.sizeLarge]: size === "large", - }; - - const clsList: string[] = [ - direction === "vertical" ? styles.directionVertical : styles.directionHorizontal, - align === "end" ? styles.alignEnv : styles.alignStart, - ]; - - return ( -
- {children} -
- ); -}; diff --git a/web/libs/ui/src/lib/space/space.module.scss b/web/libs/ui/src/lib/space/space.module.scss deleted file mode 100644 index 10496138ba17..000000000000 --- a/web/libs/ui/src/lib/space/space.module.scss +++ /dev/null @@ -1,46 +0,0 @@ -.space { - display: grid; - grid-gap: 16px; - grid-auto-flow: column; - align-items: center; - grid-auto-columns: max-content; - -} - -.directionHorizontal { - grid-auto-flow: column; - align-items: center; - grid-auto-columns: max-content; -} - -.directionVertical { - grid-auto-flow: row; - justify-content: center; - grid-auto-rows: max-content; -} - -.alignStart { - justify-content: flex-start; -} - -.alignEnd { - justify-content: flex-end; -} - -.spread { - width: 100%; - justify-content: space-between; -} - -.stretch .directionHorizontal { - grid-auto-columns: 1fr; - grid-auto-rows: 1fr; -} - -.sizeLarge { - grid-gap: 32px; -} - -.sizeSmall { - grid-gap: 12px; -} diff --git a/web/libs/ui/src/lib/spinner/Spinner.module.scss b/web/libs/ui/src/lib/spinner/Spinner.module.scss deleted file mode 100644 index 14132df4c306..000000000000 --- a/web/libs/ui/src/lib/spinner/Spinner.module.scss +++ /dev/null @@ -1,89 +0,0 @@ -.spinner { - --spinner-size: 50px; - --corner-size: calc(var(--spinner-size) * 0.375); - --spinner-duration: 2.5s; - --spinner-color: var(--persimmon_400); - - position: relative; - width: var(--spinner-size); - height: var(--spinner-size); -} - -.body { - top: 50%; - left: 50%; - width: var(--spinner-size); - height: var(--spinner-size); - position: absolute; - transform: translate(-50%, -50%); - background-color: var(--persimmon_0); - box-shadow: 0 0 0 calc(var(--spinner-size) * 0.0625) var(--persimmon_400) inset, 0 0 0 calc(var(--spinner-size) * 0.0625) var(--persimmon_400); - will-change: transform, width, height; - - - & > span { - position: absolute; - background-color: var(--spinner-color); - width: var(--corner-size); - height: var(--corner-size); - border-radius: calc(var(--corner-size) * 0.16); - } - - &>span:nth-child(1) { - top: 0; - left: 0; - transform: translate(-50%, -50%); - } - - &>span:nth-child(2) { - top: 0; - right: 0; - transform: translate(50%, -50%); - } - - &>span:nth-child(3) { - bottom: 0; - left: 0; - transform: translate(-50%, 50%); - } - - &>span:nth-child(4) { - bottom: 0; - right: 0; - transform: translate(50%, 50%); - } -} - -.body:not(.stopped) { - animation: logo-spin var(--spinner-duration) ease infinite; -} - -@keyframes logo-spin { -0% { - transform: translate(-50%, -50%) rotate(0deg); -} - -20% { - width: 0; - height: 0; - transform: translate(-50%, -50%) rotate(0deg); -} - -45% { - width: 0; - height: 0; - transform: translate(-50%, -50%) rotate(90deg); -} - -70% { - width: var(--spinner-size); - height: var(--spinner-size); - transform: translate(-50%, -50%) rotate(90deg); -} - -100% { - width: var(--spinner-size); - height: var(--spinner-size); - transform: translate(-50%, -50%) rotate(90deg); -} -} diff --git a/web/libs/ui/src/lib/spinner/Spinner.tsx b/web/libs/ui/src/lib/spinner/Spinner.tsx deleted file mode 100644 index ba86d0867285..000000000000 --- a/web/libs/ui/src/lib/spinner/Spinner.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import type { CSSProperties } from "react"; -import styles from "./spinner.module.scss"; -import { cn } from "@humansignal/shad/utils"; - -export type SpinnerProps = { - className?: string; - style?: CSSProperties; - size?: number; - stopped?: boolean; -}; - -export const Spinner = ({ className, style, size = 32, stopped = false }: SpinnerProps) => { - const fullClassName = cn(styles.spinner, className); - const bodyClassName = cn(styles.body, stopped ? styles.stopped : ""); - - const sizeWithUnit = typeof size === "number" ? `${size}px` : size; - - return ( -
-
- - - - -
-
- ); -}; diff --git a/web/libs/ui/src/lib/spinner/spinner.module.scss b/web/libs/ui/src/lib/spinner/spinner.module.scss deleted file mode 100644 index 14132df4c306..000000000000 --- a/web/libs/ui/src/lib/spinner/spinner.module.scss +++ /dev/null @@ -1,89 +0,0 @@ -.spinner { - --spinner-size: 50px; - --corner-size: calc(var(--spinner-size) * 0.375); - --spinner-duration: 2.5s; - --spinner-color: var(--persimmon_400); - - position: relative; - width: var(--spinner-size); - height: var(--spinner-size); -} - -.body { - top: 50%; - left: 50%; - width: var(--spinner-size); - height: var(--spinner-size); - position: absolute; - transform: translate(-50%, -50%); - background-color: var(--persimmon_0); - box-shadow: 0 0 0 calc(var(--spinner-size) * 0.0625) var(--persimmon_400) inset, 0 0 0 calc(var(--spinner-size) * 0.0625) var(--persimmon_400); - will-change: transform, width, height; - - - & > span { - position: absolute; - background-color: var(--spinner-color); - width: var(--corner-size); - height: var(--corner-size); - border-radius: calc(var(--corner-size) * 0.16); - } - - &>span:nth-child(1) { - top: 0; - left: 0; - transform: translate(-50%, -50%); - } - - &>span:nth-child(2) { - top: 0; - right: 0; - transform: translate(50%, -50%); - } - - &>span:nth-child(3) { - bottom: 0; - left: 0; - transform: translate(-50%, 50%); - } - - &>span:nth-child(4) { - bottom: 0; - right: 0; - transform: translate(50%, 50%); - } -} - -.body:not(.stopped) { - animation: logo-spin var(--spinner-duration) ease infinite; -} - -@keyframes logo-spin { -0% { - transform: translate(-50%, -50%) rotate(0deg); -} - -20% { - width: 0; - height: 0; - transform: translate(-50%, -50%) rotate(0deg); -} - -45% { - width: 0; - height: 0; - transform: translate(-50%, -50%) rotate(90deg); -} - -70% { - width: var(--spinner-size); - height: var(--spinner-size); - transform: translate(-50%, -50%) rotate(90deg); -} - -100% { - width: var(--spinner-size); - height: var(--spinner-size); - transform: translate(-50%, -50%) rotate(90deg); -} -} diff --git a/web/libs/ui/src/lib/spinner/spinner.tsx b/web/libs/ui/src/lib/spinner/spinner.tsx deleted file mode 100644 index ba86d0867285..000000000000 --- a/web/libs/ui/src/lib/spinner/spinner.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import type { CSSProperties } from "react"; -import styles from "./spinner.module.scss"; -import { cn } from "@humansignal/shad/utils"; - -export type SpinnerProps = { - className?: string; - style?: CSSProperties; - size?: number; - stopped?: boolean; -}; - -export const Spinner = ({ className, style, size = 32, stopped = false }: SpinnerProps) => { - const fullClassName = cn(styles.spinner, className); - const bodyClassName = cn(styles.body, stopped ? styles.stopped : ""); - - const sizeWithUnit = typeof size === "number" ? `${size}px` : size; - - return ( -
-
- - - - -
-
- ); -}; diff --git a/web/libs/ui/src/shad/components/ui/badge.tsx b/web/libs/ui/src/shad/components/ui/badge.tsx deleted file mode 100644 index 52eb34f5a28e..000000000000 --- a/web/libs/ui/src/shad/components/ui/badge.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import type * as React from "react"; -import { cva, type VariantProps } from "class-variance-authority"; - -import { cn } from "@humansignal/shad/utils"; - -const badgeVariants = cva( - "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", - { - variants: { - variant: { - default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", - secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", - destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", - outline: "text-foreground", - }, - }, - defaultVariants: { - variant: "default", - }, - }, -); - -export interface BadgeProps extends React.HTMLAttributes, VariantProps {} - -function Badge({ className, variant, ...props }: BadgeProps) { - return
; -} - -export { Badge, badgeVariants }; diff --git a/web/libs/ui/src/shad/components/ui/button.tsx b/web/libs/ui/src/shad/components/ui/button.tsx index b6cf6c5836cf..4417bac89b37 100644 --- a/web/libs/ui/src/shad/components/ui/button.tsx +++ b/web/libs/ui/src/shad/components/ui/button.tsx @@ -1,10 +1,10 @@ +import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; import { cva, type VariantProps } from "class-variance-authority"; -import { cn } from "@humansignal/shad/utils"; -import { forwardRef } from "react"; +import { cn } from "@humansignal/shad/utils/utils"; const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border", + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", { variants: { variant: { @@ -14,8 +14,6 @@ const buttonVariants = cva( secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", link: "text-primary underline-offset-4 hover:underline", - lsOutline: - "border-lsPimaryIcon text-lsButtonBg bg-background hover:bg-accent hover:text-accent-foreground disabled:bg-lsNeutralSurface disabled:border-lsNeutralBorder disabled:text-lsNeutralContentSubtlest", }, size: { default: "h-10 px-4 py-2", @@ -37,7 +35,7 @@ export interface ButtonProps asChild?: boolean; } -const Button = forwardRef( +const Button = React.forwardRef( ({ className, variant, size, asChild = false, ...props }, ref) => { const Comp = asChild ? Slot : "button"; return ; diff --git a/web/libs/ui/src/shad/components/ui/card.tsx b/web/libs/ui/src/shad/components/ui/card.tsx deleted file mode 100644 index 4231b618cbb8..000000000000 --- a/web/libs/ui/src/shad/components/ui/card.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import * as React from "react"; - -import { cn } from "@humansignal/shad/utils"; - -const Card = React.forwardRef>(({ className, ...props }, ref) => ( -
-)); -Card.displayName = "Card"; - -const CardHeader = React.forwardRef>( - ({ className, ...props }, ref) => ( -
- ), -); -CardHeader.displayName = "CardHeader"; - -const CardTitle = React.forwardRef>( - ({ className, ...props }, ref) => ( -
- ), -); -CardTitle.displayName = "CardTitle"; - -const CardDescription = React.forwardRef>( - ({ className, ...props }, ref) => ( -
- ), -); -CardDescription.displayName = "CardDescription"; - -const CardContent = React.forwardRef>( - ({ className, ...props }, ref) =>
, -); -CardContent.displayName = "CardContent"; - -const CardFooter = React.forwardRef>( - ({ className, ...props }, ref) => ( -
- ), -); -CardFooter.displayName = "CardFooter"; - -export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }; diff --git a/web/libs/ui/src/shad/components/ui/select.tsx b/web/libs/ui/src/shad/components/ui/select.tsx index 47283bbdf9f2..cae120d148b0 100644 --- a/web/libs/ui/src/shad/components/ui/select.tsx +++ b/web/libs/ui/src/shad/components/ui/select.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import * as SelectPrimitive from "@radix-ui/react-select"; import { Check, ChevronDown, ChevronUp } from "lucide-react"; -import { cn } from "@humansignal/shad/utils"; +import { cn } from "@humansignal/shad/utils/utils"; const Select = SelectPrimitive.Root; diff --git a/web/libs/ui/src/shad/utils/index.ts b/web/libs/ui/src/shad/utils/index.ts deleted file mode 100644 index 365058cebd7d..000000000000 --- a/web/libs/ui/src/shad/utils/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { type ClassValue, clsx } from "clsx"; -import { twMerge } from "tailwind-merge"; - -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} diff --git a/web/libs/ui/src/tailwind.config.js b/web/libs/ui/src/tailwind.config.js index ed9d7df9da50..6021b917ca60 100644 --- a/web/libs/ui/src/tailwind.config.js +++ b/web/libs/ui/src/tailwind.config.js @@ -21,7 +21,7 @@ module.exports = { black: "#181C31", blackho: "#2C3149", blacksection: "#1C2136", - primaryho: "#37447A", + primaryho: "#0063EC", meta: "#20C5A8", waterloo: "#757693", manatee: "#999AA1", @@ -62,27 +62,6 @@ module.exports = { DEFAULT: "hsl(var(--card))", foreground: "hsl(var(--card-foreground))", }, - - // LS color space - lsPrimaryIcon: "#617ADA", - lsPrimaryContent: "#4C5FA9", - lsPrimaryEmphasisSubtle: "#F0F3FE", - lsSubtitle: "#6B6860", - lsNeutralSurface: "#F9F8F6", - lsNeutralBorder: "#E1DED5", - lsNeutralBorderSubtle: "#E1DED5", - lsNeutralContent: "#262522", - lsNeutralContentSubtle: "#45433E", - lsNeutralContentSubtler: "#6B6860", - lsNeutralContentSubtlest: "#A49F95", - lsBorderSubtle: "#617ADA", - lsButtonBg: "#4C5FA9", - lsPositiveSurfaceHover: "#34988D", - - // Accents - lsAccentMangoSubtle: "#FFEED0", - lsAccentMangoBold: "#EB9C14", - lsAccentGrapeSubtle: "#D4DBFB", }, fontSize: { metatitle: ["12px", "20px"], @@ -97,11 +76,6 @@ module.exports = { sectiontitle3: ["44px", "55px"], sectiontitle2: ["40px", "52px"], sectiontitle4: ["34px", "48px"], - // LS styles - lsLabelMedium: ["16px", "24px"], - lsLabelSmall: ["14px", "8px"], - lsLabelSmaller: ["12px", "16px"], - lsLabelSmallest: ["11px", "16px"], }, spacing: { 4.5: "1.125rem", @@ -180,7 +154,6 @@ module.exports = { "solid-11": "0px 6px 20px rgba(45, 74, 170, 0.05)", "solid-12": "0px 2px 10px rgba(0, 0, 0, 0.05)", "solid-13": "0px 2px 19px rgba(0, 0, 0, 0.05)", - "border-1": "inset 0 0 0 1px rgba(0,0,0,1)", }, borderRadius: { lg: "var(--radius)", diff --git a/web/libs/ui/src/tailwind.css b/web/libs/ui/src/tailwind.css index a5aed1933978..828e900f3c67 100644 --- a/web/libs/ui/src/tailwind.css +++ b/web/libs/ui/src/tailwind.css @@ -1,11 +1,8 @@ +@config "./tailwind.config.js"; @tailwind base; @tailwind components; @tailwind utilities; -body { - @apply text-lsNeutralContent; -} - h1, h2, h3, h4, h5, h6 { font-weight: 500; margin: 0; @@ -27,7 +24,7 @@ h6 { font-size: 0.67em; } --card-foreground: 222.2 84% 4.9%; --popover: 0 0% 100%; --popover-foreground: 222.2 84% 4.9%; - --primary: 228 38% 48%; + --primary: 221.2 83.2% 53.3%; --primary-foreground: 210 40% 98%; --secondary: 210 40% 96.1%; --secondary-foreground: 222.2 47.4% 11.2%; @@ -37,7 +34,7 @@ h6 { font-size: 0.67em; } --accent-foreground: 222.2 47.4% 11.2%; --destructive: 0 84.2% 60.2%; --destructive-foreground: 210 40% 98%; - --border: 228 38% 35%; + --border: 214.3 31.8% 91.4%; --input: 214.3 31.8% 91.4%; --ring: 221.2 83.2% 53.3%; --radius: 0.5rem; @@ -74,8 +71,5 @@ h6 { font-size: 0.67em; } --chart-4: 280 65% 60%; --chart-5: 340 75% 55%; } - - a { - @apply text-lsPrimaryContent; - } } + diff --git a/web/libs/ui/src/typography/heading.tsx b/web/libs/ui/src/typography/heading.tsx deleted file mode 100644 index 0edeebbcfd8f..000000000000 --- a/web/libs/ui/src/typography/heading.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { cn } from "@humansignal/shad/utils"; -import { createElement, type HtmlHTMLAttributes, type PropsWithChildren } from "react"; - -export type HeadingProps = PropsWithChildren< - { - size: 1 | 2 | 3 | 4 | 5 | 6; - } & HtmlHTMLAttributes ->; -const Styles: Record = { - 1: "text-2xl", - 2: "text-2xl", - 3: "text-xl", - 4: "text-lg", - 5: "text-normal", - 6: "text-sm", -}; - -export function Heading({ size, children, className: cls, ...tagProps }: HeadingProps) { - const className = cn(Styles[size], cls); - return createElement(`h${size}`, { ...tagProps, className }, children); -} diff --git a/web/libs/ui/src/typography/index.ts b/web/libs/ui/src/typography/index.ts deleted file mode 100644 index ce918394d607..000000000000 --- a/web/libs/ui/src/typography/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { Heading } from "./heading"; -export { Sub } from "./sub"; diff --git a/web/libs/ui/src/typography/sub.tsx b/web/libs/ui/src/typography/sub.tsx deleted file mode 100644 index e54374f93654..000000000000 --- a/web/libs/ui/src/typography/sub.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import type { HtmlHTMLAttributes, PropsWithChildren } from "react"; -import { cn } from "../shad/utils"; - -export function Sub({ children, className: cls, ...rest }: PropsWithChildren>) { - const className = cn("text-sm text-lsSubtitle align-baseline", cls); - return ( - - {children} - - ); -} diff --git a/web/package.json b/web/package.json index d3194fa740a0..e32dc0c1842a 100644 --- a/web/package.json +++ b/web/package.json @@ -45,7 +45,6 @@ "@radix-ui/react-select": "^2.1.4", "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-toast": "^1.1.5", - "@tanstack/react-query": "4", "@thi.ng/rle-pack": "^3.1.30", "antd": "^4.3.3", "chroma-js": "^2.1.1", @@ -60,8 +59,6 @@ "history": "^4.10.1", "html-react-parser": "^1.2.4", "insert-after": "^0.1.4", - "jotai": "^2.11.0", - "jotai-tanstack-query": "^0.9.0", "js-base64": "^3.7.7", "keymaster": "^1.6.2", "konva": "^8.1.3", diff --git a/web/tailwind.config.js b/web/tailwind.config.js deleted file mode 100644 index 756bee9754d7..000000000000 --- a/web/tailwind.config.js +++ /dev/null @@ -1,3 +0,0 @@ -const twConfig = require("./libs/ui/src/tailwind.config"); - -module.exports = twConfig; diff --git a/web/tsconfig.base.json b/web/tsconfig.base.json index 6a54f94add56..3f876324d418 100644 --- a/web/tsconfig.base.json +++ b/web/tsconfig.base.json @@ -6,7 +6,6 @@ "declaration": false, "moduleResolution": "node", "emitDecoratorMetadata": true, - "allowSyntheticDefaultImports": true, "experimentalDecorators": true, "resolveJsonModule": true, "importHelpers": true, diff --git a/web/yarn.lock b/web/yarn.lock index edffd6a55e0d..62e9764253f0 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -6035,19 +6035,6 @@ dependencies: defer-to-connect "^2.0.0" -"@tanstack/query-core@4.36.1": - version "4.36.1" - resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.36.1.tgz#79f8c1a539d47c83104210be2388813a7af2e524" - integrity sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA== - -"@tanstack/react-query@4": - version "4.36.1" - resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.36.1.tgz#acb589fab4085060e2e78013164868c9c785e5d2" - integrity sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw== - dependencies: - "@tanstack/query-core" "4.36.1" - use-sync-external-store "^1.2.0" - "@testing-library/dom@10.4.0": version "10.4.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.4.0.tgz#82a9d9462f11d240ecadbf406607c6ceeeff43a8" @@ -14972,16 +14959,6 @@ joi@^17.3.0: "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" -jotai-tanstack-query@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/jotai-tanstack-query/-/jotai-tanstack-query-0.9.0.tgz#f3c4f96c2ec88f6fdd0b39a1d2eca6a10a8878d6" - integrity sha512-8n7/xV14+ZE63dyqngtmqs6aV1bNnQJF9bJN5Bj70USc2cMFRmsVhGGzL1cSvp5E/xXasU37czFFaZ0vavmyfA== - -jotai@^2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/jotai/-/jotai-2.11.0.tgz#923f8351e0b2d721036af892c0ae25625049d120" - integrity sha512-zKfoBBD1uDw3rljwHkt0fWuja1B76R7CjznuBO+mSX6jpsO1EBeWNRKpeaQho9yPI/pvCv4recGfgOXGxwPZvQ== - jpeg-js@0.4.4, jpeg-js@^0.3.4: version "0.4.4" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa" @@ -21671,11 +21648,6 @@ use-sidecar@^1.1.2: detect-node-es "^1.1.0" tslib "^2.0.0" -use-sync-external-store@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" - integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== - utf8-byte-length@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz#f45f150c4c66eee968186505ab93fcbb8ad6bf61" @@ -22280,7 +22252,7 @@ write-file-atomic@^5.0.1: imurmurhash "^0.1.4" signal-exit "^4.0.1" -ws@6.2.0, ws@8.17.1, ws@^8.11.0, ws@^8.13.0, ws@^8.2.3, ws@~7.4.2: +ws@6.2.0, ws@>=7.5.10, ws@^8.11.0, ws@^8.13.0, ws@^8.2.3, ws@~7.4.2: version "8.17.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==