diff --git a/.github/workflows/i18n-sync-check.yml b/.github/workflows/i18n-sync-check.yml index 448d301b..4fd6a133 100644 --- a/.github/workflows/i18n-sync-check.yml +++ b/.github/workflows/i18n-sync-check.yml @@ -52,3 +52,10 @@ jobs: - name: Run sync check run: pnpm dlx tsx packages/i18n/scripts/sync-check.ts --ci + + # Report only, and deliberately not a gate: it infers whether a key is used from the string literals in apps/ and packages/, which is a heuristic that goes wrong the moment a key is assembled somewhere the template-prefix scan does not model. Gating on it would fail an unrelated PR for a key it never touched. `--summary` keeps it to counts and per-namespace totals; run `pnpm --filter @pace/i18n unused:check` locally for the full key list, and `--max=` if this is ever ratcheted. + # + # The job's path filters are not widened for this step even though it reads every app: the number only needs to be visible when someone is already working on the catalogue, and triggering this workflow on all of apps/ would run it on nearly every PR to print a figure nothing gates on. + - name: Report unused keys + continue-on-error: true + run: pnpm dlx tsx packages/i18n/scripts/unused-check.ts --summary diff --git a/.rebase-pr.sh b/.rebase-pr.sh new file mode 100755 index 00000000..0d05e55e --- /dev/null +++ b/.rebase-pr.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# Rebase a PR branch onto origin/main, auto-resolving the workspace version bump +# that every branch carries and that therefore conflicts on every merge. Any +# conflict outside those package.json files stops the script for a human read. +set -uo pipefail +cd /Users/e-hu/Workspace/pace +BRANCH="$1"; VERSION="$2" +git checkout "$BRANCH" >/dev/null 2>&1 || exit 1 +git rebase origin/main >/dev/null 2>&1 +while [ -d .git/rebase-merge ] || [ -d .git/rebase-apply ]; do + UNMERGED=$(git diff --diff-filter=U --name-only) + if [ -z "$UNMERGED" ]; then + git -c core.editor=true rebase --continue >/dev/null 2>&1 || { echo "STUCK: rebase --continue failed"; exit 1; } + continue + fi + OTHER=$(echo "$UNMERGED" | grep -v -E '(^|/)package\.json$' || true) + if [ -n "$OTHER" ]; then + echo "MANUAL CONFLICT:"; echo "$OTHER"; exit 2 + fi + echo "$UNMERGED" | xargs git checkout --ours -- + ./.setver.sh "$VERSION" >/dev/null + echo "$UNMERGED" | xargs git add + git -c core.editor=true rebase --continue >/dev/null 2>&1 || { echo "STUCK after resolve"; exit 1; } +done +# The bump commit may have been rebased before the version reached its final value. +CURRENT=$(node -p "require('/Users/e-hu/Workspace/pace/package.json').version") +if [ "$CURRENT" != "$VERSION" ]; then + ./.setver.sh "$VERSION" >/dev/null + git commit -aqm "chore: bump the workspace version, which check-version requires of every PR" +fi +echo "REBASED $BRANCH onto $(git rev-parse --short origin/main) at version $VERSION" +git log --oneline origin/main..HEAD diff --git a/.setver.sh b/.setver.sh new file mode 100755 index 00000000..bb2aa0db --- /dev/null +++ b/.setver.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Set every workspace package.json that is version-locked to the workspace release train. +set -euo pipefail +cd /Users/e-hu/Workspace/pace +V="$1" +for f in package.json apps/admin/package.json apps/space/package.json apps/web/package.json \ + packages/codemods/package.json packages/constants/package.json packages/editor/package.json \ + packages/hooks/package.json packages/i18n/package.json packages/propel/package.json \ + packages/services/package.json packages/shared-state/package.json \ + packages/tailwind-config/package.json packages/types/package.json \ + packages/typescript-config/package.json packages/ui/package.json packages/utils/package.json; do + [ -f "$f" ] || continue + node -e ' + const fs=require("fs"); const [f,v]=process.argv.slice(1); + let s=fs.readFileSync(f,"utf8"); + const out=s.replace(/^(\s*"version":\s*")[^"]+(",?)$/m, `$1${v}$2`); + if(!/^\s*"version":\s*"/m.test(s)) { console.error("no version field in "+f); process.exit(1); } + fs.writeFileSync(f,out); + ' "$f" "$V" +done +echo "all package.json set to $V" diff --git a/apps/admin/core/assets/images/plane-takeoff.png b/apps/admin/core/assets/images/plane-takeoff.png deleted file mode 100644 index 417ff829..00000000 Binary files a/apps/admin/core/assets/images/plane-takeoff.png and /dev/null differ diff --git a/apps/admin/core/store/instance.store.ts b/apps/admin/core/store/instance.store.ts index 039d713a..a315c1aa 100644 --- a/apps/admin/core/store/instance.store.ts +++ b/apps/admin/core/store/instance.store.ts @@ -108,7 +108,6 @@ export class InstanceStore implements IInstanceStore { if (this.instance === undefined && !instanceInfo?.instance?.workspaces_exist) this.store.theme.toggleNewUserPopup(); runInAction(() => { - // console.log("instanceInfo: ", instanceInfo); this.isLoading = false; this.instance = instanceInfo.instance; this.config = instanceInfo.config; diff --git a/apps/admin/package.json b/apps/admin/package.json index 9ffdc3c5..82bdc417 100644 --- a/apps/admin/package.json +++ b/apps/admin/package.json @@ -1,6 +1,6 @@ { "name": "admin", - "version": "1.4.42", + "version": "1.4.43", "private": true, "description": "Admin UI for Pace", "license": "AGPL-3.0", diff --git a/apps/api/internal/project/issue_create_handler.go b/apps/api/internal/project/issue_create_handler.go index c3daf5ab..9bfc58e6 100644 --- a/apps/api/internal/project/issue_create_handler.go +++ b/apps/api/internal/project/issue_create_handler.go @@ -242,10 +242,3 @@ func issueCreateJSON(row issueListRow, location *time.Location) gin.H { data["updated_at"] = row.UpdatedAt.In(location) return data } - -func stringOrEmpty(value any) string { - if text, ok := value.(string); ok { - return text - } - return "" -} diff --git a/apps/api/internal/workspace/sidebar_preferences_handler.go b/apps/api/internal/workspace/sidebar_preferences_handler.go index b2f2bb1d..68d03b62 100644 --- a/apps/api/internal/workspace/sidebar_preferences_handler.go +++ b/apps/api/internal/workspace/sidebar_preferences_handler.go @@ -177,7 +177,3 @@ func preferenceFloat(raw json.RawMessage) (float64, error) { } return result, nil } - -func sidebarPreferenceJSON(preference WorkspaceUserPreference) gin.H { - return gin.H{"key": preference.Key, "is_pinned": preference.IsPinned, "sort_order": preference.SortOrder, "updated_at": preference.UpdatedAt} -} diff --git a/apps/space/core/assets/instance/intake-sent-dark.png b/apps/space/core/assets/instance/intake-sent-dark.png deleted file mode 100644 index 70a62730..00000000 Binary files a/apps/space/core/assets/instance/intake-sent-dark.png and /dev/null differ diff --git a/apps/space/core/assets/instance/intake-sent-light.png b/apps/space/core/assets/instance/intake-sent-light.png deleted file mode 100644 index 9425c072..00000000 Binary files a/apps/space/core/assets/instance/intake-sent-light.png and /dev/null differ diff --git a/apps/space/core/assets/instance/plane-instance-not-ready.webp b/apps/space/core/assets/instance/plane-instance-not-ready.webp deleted file mode 100644 index a0efca52..00000000 Binary files a/apps/space/core/assets/instance/plane-instance-not-ready.webp and /dev/null differ diff --git a/apps/space/core/assets/instance/plane-takeoff.png b/apps/space/core/assets/instance/plane-takeoff.png deleted file mode 100644 index 417ff829..00000000 Binary files a/apps/space/core/assets/instance/plane-takeoff.png and /dev/null differ diff --git a/apps/space/core/assets/logos/github-square.svg b/apps/space/core/assets/logos/github-square.svg deleted file mode 100644 index a7836db8..00000000 --- a/apps/space/core/assets/logos/github-square.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - diff --git a/apps/space/core/assets/logos/github-white.svg b/apps/space/core/assets/logos/github-white.svg deleted file mode 100644 index 90fe34d8..00000000 --- a/apps/space/core/assets/logos/github-white.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - diff --git a/apps/space/core/assets/project-not-published.svg b/apps/space/core/assets/project-not-published.svg deleted file mode 100644 index db4b404d..00000000 --- a/apps/space/core/assets/project-not-published.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/space/core/components/issues/issue-layouts/properties/member.tsx b/apps/space/core/components/issues/issue-layouts/properties/member.tsx index 552409ea..c12fa7b4 100644 --- a/apps/space/core/components/issues/issue-layouts/properties/member.tsx +++ b/apps/space/core/components/issues/issue-layouts/properties/member.tsx @@ -11,10 +11,10 @@ import { MembersOutline } from "@pace/propel/icons"; import { Avatar, AvatarGroup } from "@pace/propel/avatar"; // pace utils import { cn } from "@pace/utils"; +// pace types +import type { TPublicMember } from "@pace/types"; // hooks import { useMember } from "@/hooks/store/use-member"; -// -import type { TPublicMember } from "@/types/member"; type Props = { memberIds: string[]; diff --git a/apps/space/core/hooks/store/use-instance.ts b/apps/space/core/hooks/store/use-instance.ts index 3f783a90..a4c9bae4 100644 --- a/apps/space/core/hooks/store/use-instance.ts +++ b/apps/space/core/hooks/store/use-instance.ts @@ -12,6 +12,6 @@ import type { IInstanceStore } from "@/store/instance.store"; export const useInstance = (): IInstanceStore => { const context = useContext(StoreContext); - if (context === undefined) throw new Error("useUserProfile must be used within StoreProvider"); + if (context === undefined) throw new Error("useInstance must be used within StoreProvider"); return context.instance; }; diff --git a/apps/space/core/hooks/store/use-issue-details.tsx b/apps/space/core/hooks/store/use-issue-details.tsx index a30403e1..30106249 100644 --- a/apps/space/core/hooks/store/use-issue-details.tsx +++ b/apps/space/core/hooks/store/use-issue-details.tsx @@ -12,6 +12,6 @@ import type { IIssueDetailStore } from "@/store/issue-detail.store"; export const useIssueDetails = (): IIssueDetailStore => { const context = useContext(StoreContext); - if (context === undefined) throw new Error("useUserProfile must be used within StoreProvider"); + if (context === undefined) throw new Error("useIssueDetails must be used within StoreProvider"); return context.issueDetail; }; diff --git a/apps/space/core/hooks/store/use-issue-filter.ts b/apps/space/core/hooks/store/use-issue-filter.ts index 1f60bae9..e4a9e57c 100644 --- a/apps/space/core/hooks/store/use-issue-filter.ts +++ b/apps/space/core/hooks/store/use-issue-filter.ts @@ -12,6 +12,6 @@ import type { IIssueFilterStore } from "@/store/issue-filters.store"; export const useIssueFilter = (): IIssueFilterStore => { const context = useContext(StoreContext); - if (context === undefined) throw new Error("useUserProfile must be used within StoreProvider"); + if (context === undefined) throw new Error("useIssueFilter must be used within StoreProvider"); return context.issueFilter; }; diff --git a/apps/space/core/hooks/store/use-state.ts b/apps/space/core/hooks/store/use-state.ts index 8f239777..58e52d4f 100644 --- a/apps/space/core/hooks/store/use-state.ts +++ b/apps/space/core/hooks/store/use-state.ts @@ -12,6 +12,6 @@ import type { IStateStore } from "@/store/state.store"; export const useStates = (): IStateStore => { const context = useContext(StoreContext); - if (context === undefined) throw new Error("useState must be used within StoreProvider"); + if (context === undefined) throw new Error("useStates must be used within StoreProvider"); return context.state; }; diff --git a/apps/space/core/hooks/store/use-user-profile.ts b/apps/space/core/hooks/store/use-user-profile.ts deleted file mode 100644 index ec53da95..00000000 --- a/apps/space/core/hooks/store/use-user-profile.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useContext } from "react"; -// lib -import { StoreContext } from "@/lib/store-provider"; -// store -import type { IProfileStore } from "@/store/profile.store"; - -export const useUserProfile = (): IProfileStore => { - const context = useContext(StoreContext); - if (context === undefined) throw new Error("useUserProfile must be used within StoreProvider"); - return context.user.profile; -}; diff --git a/apps/space/core/hooks/use-mention.tsx b/apps/space/core/hooks/use-mention.tsx deleted file mode 100644 index c0785e78..00000000 --- a/apps/space/core/hooks/use-mention.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useRef, useEffect } from "react"; -import useSWR from "swr"; -// pace imports -import { UserService } from "@pace/services"; -import type { IUser } from "@pace/types"; - -export const useMention = () => { - const userService = new UserService(); - const { data: user, isLoading: userDataLoading } = useSWR("currentUser", async () => userService.me()); - - const userRef = useRef(undefined); - - useEffect(() => { - if (userRef) { - userRef.current = user; - } - }, [user]); - - const waitForUserDate = async () => - new Promise((resolve) => { - const checkData = () => { - if (userRef.current) { - resolve(userRef.current); - } else { - setTimeout(checkData, 100); - } - }; - checkData(); - }); - - const mentionHighlights = async () => { - if (!userDataLoading && userRef.current) { - return [userRef.current.id]; - } else { - const user = await waitForUserDate(); - return [user.id]; - } - }; - - return { - mentionHighlights, - }; -}; diff --git a/apps/space/core/store/cycle.store.ts b/apps/space/core/store/cycle.store.ts index 090ee217..e439c798 100644 --- a/apps/space/core/store/cycle.store.ts +++ b/apps/space/core/store/cycle.store.ts @@ -7,7 +7,7 @@ import { action, makeObservable, observable, runInAction } from "mobx"; // pace imports import { SitesCycleService } from "@pace/services"; -import type { TPublicCycle } from "@/types/cycle"; +import type { TPublicCycle } from "@pace/types"; // store import type { RootStore } from "./root.store"; diff --git a/apps/space/core/store/issue-detail.store.ts b/apps/space/core/store/issue-detail.store.ts index 0af4f2ab..58639228 100644 --- a/apps/space/core/store/issue-detail.store.ts +++ b/apps/space/core/store/issue-detail.store.ts @@ -179,7 +179,7 @@ export class IssueDetailStore implements IIssueDetailStore { } return issueCommentResponse; } catch (error) { - console.log("Failed to add issue comment"); + console.error("Failed to add issue comment"); throw error; } }; @@ -229,7 +229,7 @@ export class IssueDetailStore implements IIssueDetailStore { }; }); } catch (_error) { - console.log("Failed to add issue vote"); + console.error("Failed to delete issue comment"); } }; @@ -245,7 +245,7 @@ export class IssueDetailStore implements IIssueDetailStore { ); return res; } catch (error) { - console.log("Error in uploading comment asset:", error); + console.error("Error in uploading comment asset:", error); throw new Error("Asset upload failed. Please try again later."); } }; @@ -262,7 +262,7 @@ export class IssueDetailStore implements IIssueDetailStore { ); return res; } catch (error) { - console.log("Error in uploading comment asset:", error); + console.error("Error in uploading issue asset:", error); throw new Error("Asset upload failed. Please try again later."); } }; @@ -363,7 +363,7 @@ export class IssueDetailStore implements IIssueDetailStore { reaction: reactionHex, }); } catch (_error) { - console.log("Failed to add issue vote"); + console.error("Failed to add issue reaction"); const issueReactions = await this.issueService.listReactions(anchor, issueID); runInAction(() => { set(this.details, [issueID, "reaction_items"], issueReactions); @@ -383,7 +383,7 @@ export class IssueDetailStore implements IIssueDetailStore { await this.issueService.removeReaction(anchor, issueID, reactionHex); } catch (_error) { - console.log("Failed to remove issue reaction"); + console.error("Failed to remove issue reaction"); const reactions = await this.issueService.listReactions(anchor, issueID); runInAction(() => { set(this.details, [issueID, "reaction_items"], reactions); @@ -415,7 +415,7 @@ export class IssueDetailStore implements IIssueDetailStore { await this.issueService.addVote(anchor, issueID, data); } catch (_error) { - console.log("Failed to add issue vote"); + console.error("Failed to add issue vote"); const issueVotes = await this.issueService.listVotes(anchor, issueID); runInAction(() => { @@ -436,7 +436,7 @@ export class IssueDetailStore implements IIssueDetailStore { await this.issueService.removeVote(anchor, issueID); } catch (_error) { - console.log("Failed to remove issue vote"); + console.error("Failed to remove issue vote"); const issueVotes = await this.issueService.listVotes(anchor, issueID); runInAction(() => { diff --git a/apps/space/core/store/members.store.ts b/apps/space/core/store/members.store.ts index 5a92cd6d..5d2a82c9 100644 --- a/apps/space/core/store/members.store.ts +++ b/apps/space/core/store/members.store.ts @@ -8,7 +8,7 @@ import { set } from "lodash-es"; import { action, computed, makeObservable, observable, runInAction } from "mobx"; // pace imports import { SitesMemberService } from "@pace/services"; -import type { TPublicMember } from "@/types/member"; +import type { TPublicMember } from "@pace/types"; import type { RootStore } from "./root.store"; export interface IIssueMemberStore { diff --git a/apps/space/core/store/module.store.ts b/apps/space/core/store/module.store.ts index 3268e47c..dfb9fe0b 100644 --- a/apps/space/core/store/module.store.ts +++ b/apps/space/core/store/module.store.ts @@ -8,8 +8,7 @@ import { set } from "lodash-es"; import { action, computed, makeObservable, observable, runInAction } from "mobx"; // pace imports import { SitesModuleService } from "@pace/services"; -// types -import type { TPublicModule } from "@/types/modules"; +import type { TPublicModule } from "@pace/types"; // root store import type { RootStore } from "./root.store"; diff --git a/apps/space/core/types/cycle.d.ts b/apps/space/core/types/cycle.d.ts deleted file mode 100644 index edf8f31a..00000000 --- a/apps/space/core/types/cycle.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type TPublicCycle = { - id: string; - name: string; - status: string; -}; diff --git a/apps/space/core/types/intake.d.ts b/apps/space/core/types/intake.d.ts deleted file mode 100644 index 9cf2934f..00000000 --- a/apps/space/core/types/intake.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type TIntakeIssueForm = { - name: string; - email: string; - username: string; - description_html: string; -}; diff --git a/apps/space/core/types/member.d.ts b/apps/space/core/types/member.d.ts deleted file mode 100644 index 34c95daf..00000000 --- a/apps/space/core/types/member.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -export type TPublicMember = { - id: string; - member: string; - member__display_name: string; - member__avatar: string; -}; diff --git a/apps/space/core/types/modules.d.ts b/apps/space/core/types/modules.d.ts deleted file mode 100644 index 8bc35ce6..00000000 --- a/apps/space/core/types/modules.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type TPublicModule = { - id: string; - name: string; -}; diff --git a/apps/space/helpers/common.helper.ts b/apps/space/helpers/common.helper.ts deleted file mode 100644 index f11f634e..00000000 --- a/apps/space/helpers/common.helper.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -export const resolveGeneralTheme = (resolvedTheme: string | undefined) => - resolvedTheme?.includes("light") ? "light" : resolvedTheme?.includes("dark") ? "dark" : "system"; diff --git a/apps/space/helpers/file.helper.ts b/apps/space/helpers/file.helper.ts deleted file mode 100644 index cf122f20..00000000 --- a/apps/space/helpers/file.helper.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -// pace imports -import { API_BASE_URL } from "@pace/constants"; - -/** - * @description combine the file path with the base URL - * @param {string} path - * @returns {string} final URL with the base URL - */ -export const getFileURL = (path: string): string | undefined => { - if (!path) return undefined; - const isValidURL = path.startsWith("http"); - if (isValidURL) return path; - return `${API_BASE_URL}${path}`; -}; - -/** - * @description this function returns the assetId from the asset source - * @param {string} src - * @returns {string} assetId - */ -export const getAssetIdFromUrl = (src: string): string => { - const sourcePaths = src.split("/"); - const assetUrl = sourcePaths[sourcePaths.length - 1]; - return assetUrl ?? ""; -}; diff --git a/apps/space/package.json b/apps/space/package.json index 2fcfbf8e..f08b1b6a 100644 --- a/apps/space/package.json +++ b/apps/space/package.json @@ -1,6 +1,6 @@ { "name": "space", - "version": "1.4.42", + "version": "1.4.43", "private": true, "license": "AGPL-3.0", "type": "module", diff --git a/apps/web/app/routes/redirects/core/index.ts b/apps/web/app/routes/redirects/core/index.ts deleted file mode 100644 index e1eaeca4..00000000 --- a/apps/web/app/routes/redirects/core/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { route } from "@react-router/dev/routes"; -import type { RouteConfigEntry } from "@react-router/dev/routes"; - -export const coreRedirectRoutes: RouteConfigEntry[] = [ - // ======================================================================== - // WORKSPACE & PROJECT REDIRECTS - // ======================================================================== - - // Project settings redirect: /:workspaceSlug/projects/:projectId/settings/:path* - // → /:workspaceSlug/settings/projects/:projectId/:path* - route(":workspaceSlug/projects/:projectId/settings/*", "routes/redirects/core/project-settings.tsx"), - - // Analytics redirect: /:workspaceSlug/analytics → /:workspaceSlug/analytics/overview - route(":workspaceSlug/analytics", "routes/redirects/core/analytics.tsx"), - - // API tokens redirect: /:workspaceSlug/settings/api-tokens - // → /settings/profile/api-tokens - route(":workspaceSlug/settings/api-tokens", "routes/redirects/core/api-tokens.tsx"), - - // Inbox redirect: /:workspaceSlug/projects/:projectId/inbox - // → /:workspaceSlug/projects/:projectId/intake - route(":workspaceSlug/projects/:projectId/inbox", "routes/redirects/core/inbox.tsx"), - - // ======================================================================== - // AUTHENTICATION REDIRECTS - // ======================================================================== - - // Sign-up redirects - route("accounts/sign-up", "routes/redirects/core/accounts-signup.tsx"), - - // Sign-in redirects (all redirect to home page) - route("sign-in", "routes/redirects/core/sign-in.tsx"), - route("signin", "routes/redirects/core/signin.tsx"), - route("login", "routes/redirects/core/login.tsx"), - - // Register redirect - route("register", "routes/redirects/core/register.tsx"), -]; diff --git a/apps/web/app/routes/redirects/extended/index.ts b/apps/web/app/routes/redirects/extended/index.ts deleted file mode 100644 index 7b4da929..00000000 --- a/apps/web/app/routes/redirects/extended/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import type { RouteConfigEntry } from "@react-router/dev/routes"; - -export const extendedRedirectRoutes: RouteConfigEntry[] = []; diff --git a/apps/web/app/routes/redirects/index.ts b/apps/web/app/routes/redirects/index.ts deleted file mode 100644 index b736b22f..00000000 --- a/apps/web/app/routes/redirects/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import type { RouteConfigEntry } from "@react-router/dev/routes"; -import { coreRedirectRoutes } from "./core"; -import { extendedRedirectRoutes } from "./extended"; - -/** - * REDIRECT ROUTES - * Centralized configuration for all route redirects - * Migrated from Next.js next.config.js redirects - */ -export const redirectRoutes: RouteConfigEntry[] = [...coreRedirectRoutes, ...extendedRedirectRoutes]; diff --git a/apps/web/core/assets/auth/access-denied.svg b/apps/web/core/assets/auth/access-denied.svg deleted file mode 100644 index c7979fee..00000000 --- a/apps/web/core/assets/auth/access-denied.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/emoji/project-emoji.svg b/apps/web/core/assets/emoji/project-emoji.svg deleted file mode 100644 index a2b9a620..00000000 --- a/apps/web/core/assets/emoji/project-emoji.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/apps/web/core/assets/empty-state/active-cycle/cycle-dark.webp b/apps/web/core/assets/empty-state/active-cycle/cycle-dark.webp deleted file mode 100644 index d0923080..00000000 Binary files a/apps/web/core/assets/empty-state/active-cycle/cycle-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/active-cycle/cycle-light.webp b/apps/web/core/assets/empty-state/active-cycle/cycle-light.webp deleted file mode 100644 index a218d4d2..00000000 Binary files a/apps/web/core/assets/empty-state/active-cycle/cycle-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/all-issues-dark.webp b/apps/web/core/assets/empty-state/all-issues/all-issues-dark.webp deleted file mode 100644 index f570ad50..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/all-issues-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/all-issues-light.webp b/apps/web/core/assets/empty-state/all-issues/all-issues-light.webp deleted file mode 100644 index eba388d0..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/all-issues-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/assigned-dark.webp b/apps/web/core/assets/empty-state/all-issues/assigned-dark.webp deleted file mode 100644 index 23bc60ac..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/assigned-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/assigned-light.webp b/apps/web/core/assets/empty-state/all-issues/assigned-light.webp deleted file mode 100644 index f48b9cf7..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/assigned-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/created-dark.webp b/apps/web/core/assets/empty-state/all-issues/created-dark.webp deleted file mode 100644 index 69d35fc1..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/created-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/created-light.webp b/apps/web/core/assets/empty-state/all-issues/created-light.webp deleted file mode 100644 index be4f67d6..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/created-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/custom-view-dark.webp b/apps/web/core/assets/empty-state/all-issues/custom-view-dark.webp deleted file mode 100644 index 48dec16a..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/custom-view-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/custom-view-light.webp b/apps/web/core/assets/empty-state/all-issues/custom-view-light.webp deleted file mode 100644 index 53b551c7..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/custom-view-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/no-project-dark.webp b/apps/web/core/assets/empty-state/all-issues/no-project-dark.webp deleted file mode 100644 index 641ec828..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/no-project-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/no-project-light.webp b/apps/web/core/assets/empty-state/all-issues/no-project-light.webp deleted file mode 100644 index 1c7a810f..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/no-project-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/subscribed-dark.webp b/apps/web/core/assets/empty-state/all-issues/subscribed-dark.webp deleted file mode 100644 index 68b3b30b..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/subscribed-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/all-issues/subscribed-light.webp b/apps/web/core/assets/empty-state/all-issues/subscribed-light.webp deleted file mode 100644 index 4dbbedca..00000000 Binary files a/apps/web/core/assets/empty-state/all-issues/subscribed-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/analytics/empty-chart-area-dark.webp b/apps/web/core/assets/empty-state/analytics/empty-chart-area-dark.webp deleted file mode 100644 index 509f66cc..00000000 Binary files a/apps/web/core/assets/empty-state/analytics/empty-chart-area-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/analytics/empty-chart-area-light.webp b/apps/web/core/assets/empty-state/analytics/empty-chart-area-light.webp deleted file mode 100644 index cfa27c8c..00000000 Binary files a/apps/web/core/assets/empty-state/analytics/empty-chart-area-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/analytics/empty-chart-bar-dark.webp b/apps/web/core/assets/empty-state/analytics/empty-chart-bar-dark.webp deleted file mode 100644 index e519574c..00000000 Binary files a/apps/web/core/assets/empty-state/analytics/empty-chart-bar-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/analytics/empty-chart-bar-light.webp b/apps/web/core/assets/empty-state/analytics/empty-chart-bar-light.webp deleted file mode 100644 index e6eeb09d..00000000 Binary files a/apps/web/core/assets/empty-state/analytics/empty-chart-bar-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/analytics/empty-chart-radar-dark.webp b/apps/web/core/assets/empty-state/analytics/empty-chart-radar-dark.webp deleted file mode 100644 index 94e2f514..00000000 Binary files a/apps/web/core/assets/empty-state/analytics/empty-chart-radar-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/analytics/empty-chart-radar-light.webp b/apps/web/core/assets/empty-state/analytics/empty-chart-radar-light.webp deleted file mode 100644 index 29820169..00000000 Binary files a/apps/web/core/assets/empty-state/analytics/empty-chart-radar-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/analytics/empty-table-dark.webp b/apps/web/core/assets/empty-state/analytics/empty-table-dark.webp deleted file mode 100644 index f5fcedd5..00000000 Binary files a/apps/web/core/assets/empty-state/analytics/empty-table-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/analytics/empty-table-light.webp b/apps/web/core/assets/empty-state/analytics/empty-table-light.webp deleted file mode 100644 index c9e8fec9..00000000 Binary files a/apps/web/core/assets/empty-state/analytics/empty-table-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/archived/empty-cycles-dark.webp b/apps/web/core/assets/empty-state/archived/empty-cycles-dark.webp deleted file mode 100644 index 872fb2fc..00000000 Binary files a/apps/web/core/assets/empty-state/archived/empty-cycles-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/archived/empty-cycles-light.webp b/apps/web/core/assets/empty-state/archived/empty-cycles-light.webp deleted file mode 100644 index 2db1dc4b..00000000 Binary files a/apps/web/core/assets/empty-state/archived/empty-cycles-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/archived/empty-issues-dark.webp b/apps/web/core/assets/empty-state/archived/empty-issues-dark.webp deleted file mode 100644 index c18e9462..00000000 Binary files a/apps/web/core/assets/empty-state/archived/empty-issues-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/archived/empty-issues-light.webp b/apps/web/core/assets/empty-state/archived/empty-issues-light.webp deleted file mode 100644 index d99a5017..00000000 Binary files a/apps/web/core/assets/empty-state/archived/empty-issues-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/archived/empty-modules-dark.webp b/apps/web/core/assets/empty-state/archived/empty-modules-dark.webp deleted file mode 100644 index e34bf373..00000000 Binary files a/apps/web/core/assets/empty-state/archived/empty-modules-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/archived/empty-modules-light.webp b/apps/web/core/assets/empty-state/archived/empty-modules-light.webp deleted file mode 100644 index 5caf2ea9..00000000 Binary files a/apps/web/core/assets/empty-state/archived/empty-modules-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/calendar-dark-resp.webp b/apps/web/core/assets/empty-state/cycle-issues/calendar-dark-resp.webp deleted file mode 100644 index 5f0c2197..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/calendar-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/calendar-dark.webp b/apps/web/core/assets/empty-state/cycle-issues/calendar-dark.webp deleted file mode 100644 index 312b1389..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/calendar-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/calendar-light-resp.webp b/apps/web/core/assets/empty-state/cycle-issues/calendar-light-resp.webp deleted file mode 100644 index 556a4508..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/calendar-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/calendar-light.webp b/apps/web/core/assets/empty-state/cycle-issues/calendar-light.webp deleted file mode 100644 index aef2ff17..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/calendar-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-dark-resp.webp b/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-dark-resp.webp deleted file mode 100644 index e2eda052..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-dark.webp b/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-dark.webp deleted file mode 100644 index d2a9dfbb..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-light-resp.webp b/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-light-resp.webp deleted file mode 100644 index 1a915d32..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-light.webp b/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-light.webp deleted file mode 100644 index 9dcbdd6f..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/gantt_chart-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/kanban-dark-resp.webp b/apps/web/core/assets/empty-state/cycle-issues/kanban-dark-resp.webp deleted file mode 100644 index 227dd488..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/kanban-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/kanban-dark.webp b/apps/web/core/assets/empty-state/cycle-issues/kanban-dark.webp deleted file mode 100644 index b161dbc7..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/kanban-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/kanban-light-resp.webp b/apps/web/core/assets/empty-state/cycle-issues/kanban-light-resp.webp deleted file mode 100644 index c377068c..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/kanban-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/kanban-light.webp b/apps/web/core/assets/empty-state/cycle-issues/kanban-light.webp deleted file mode 100644 index 0958f212..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/kanban-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/list-dark-resp.webp b/apps/web/core/assets/empty-state/cycle-issues/list-dark-resp.webp deleted file mode 100644 index 4088595c..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/list-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/list-dark.webp b/apps/web/core/assets/empty-state/cycle-issues/list-dark.webp deleted file mode 100644 index 7e9f8c65..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/list-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/list-light-resp.webp b/apps/web/core/assets/empty-state/cycle-issues/list-light-resp.webp deleted file mode 100644 index 862544a0..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/list-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/list-light.webp b/apps/web/core/assets/empty-state/cycle-issues/list-light.webp deleted file mode 100644 index fb01bff1..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/list-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-dark-resp.webp b/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-dark-resp.webp deleted file mode 100644 index baccb3fb..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-dark.webp b/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-dark.webp deleted file mode 100644 index 6f603619..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-light-resp.webp b/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-light-resp.webp deleted file mode 100644 index c7889d66..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-light.webp b/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-light.webp deleted file mode 100644 index 0f35b4eb..00000000 Binary files a/apps/web/core/assets/empty-state/cycle-issues/spreadsheet-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle/completed-dark.webp b/apps/web/core/assets/empty-state/cycle/completed-dark.webp deleted file mode 100644 index eebe656d..00000000 Binary files a/apps/web/core/assets/empty-state/cycle/completed-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle/completed-light.webp b/apps/web/core/assets/empty-state/cycle/completed-light.webp deleted file mode 100644 index 6c192fd3..00000000 Binary files a/apps/web/core/assets/empty-state/cycle/completed-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle/completed-no-issues-dark.webp b/apps/web/core/assets/empty-state/cycle/completed-no-issues-dark.webp deleted file mode 100644 index a187dbf5..00000000 Binary files a/apps/web/core/assets/empty-state/cycle/completed-no-issues-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle/completed-no-issues-light.webp b/apps/web/core/assets/empty-state/cycle/completed-no-issues-light.webp deleted file mode 100644 index 6009f60f..00000000 Binary files a/apps/web/core/assets/empty-state/cycle/completed-no-issues-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle/draft-dark.webp b/apps/web/core/assets/empty-state/cycle/draft-dark.webp deleted file mode 100644 index 887e2e91..00000000 Binary files a/apps/web/core/assets/empty-state/cycle/draft-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle/draft-light.webp b/apps/web/core/assets/empty-state/cycle/draft-light.webp deleted file mode 100644 index d1c88bc3..00000000 Binary files a/apps/web/core/assets/empty-state/cycle/draft-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle/upcoming-dark.webp b/apps/web/core/assets/empty-state/cycle/upcoming-dark.webp deleted file mode 100644 index 205164f4..00000000 Binary files a/apps/web/core/assets/empty-state/cycle/upcoming-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/cycle/upcoming-light.webp b/apps/web/core/assets/empty-state/cycle/upcoming-light.webp deleted file mode 100644 index 522122f4..00000000 Binary files a/apps/web/core/assets/empty-state/cycle/upcoming-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/dashboard/dark/completed-issues.svg b/apps/web/core/assets/empty-state/dashboard/dark/completed-issues.svg deleted file mode 100644 index 8c4d083f..00000000 --- a/apps/web/core/assets/empty-state/dashboard/dark/completed-issues.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/dark/issues-by-priority.svg b/apps/web/core/assets/empty-state/dashboard/dark/issues-by-priority.svg deleted file mode 100644 index 803f3a72..00000000 --- a/apps/web/core/assets/empty-state/dashboard/dark/issues-by-priority.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/dark/issues-by-state-group.svg b/apps/web/core/assets/empty-state/dashboard/dark/issues-by-state-group.svg deleted file mode 100644 index b615c313..00000000 --- a/apps/web/core/assets/empty-state/dashboard/dark/issues-by-state-group.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/dark/overdue-issues.svg b/apps/web/core/assets/empty-state/dashboard/dark/overdue-issues.svg deleted file mode 100644 index cceb3480..00000000 --- a/apps/web/core/assets/empty-state/dashboard/dark/overdue-issues.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/dark/recent-activity.svg b/apps/web/core/assets/empty-state/dashboard/dark/recent-activity.svg deleted file mode 100644 index bf723482..00000000 --- a/apps/web/core/assets/empty-state/dashboard/dark/recent-activity.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/dark/recent-collaborators-1.svg b/apps/web/core/assets/empty-state/dashboard/dark/recent-collaborators-1.svg deleted file mode 100644 index 341364f5..00000000 --- a/apps/web/core/assets/empty-state/dashboard/dark/recent-collaborators-1.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/dark/recent-collaborators-2.svg b/apps/web/core/assets/empty-state/dashboard/dark/recent-collaborators-2.svg deleted file mode 100644 index 6889f750..00000000 --- a/apps/web/core/assets/empty-state/dashboard/dark/recent-collaborators-2.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/dark/recent-collaborators-3.svg b/apps/web/core/assets/empty-state/dashboard/dark/recent-collaborators-3.svg deleted file mode 100644 index deb0e211..00000000 --- a/apps/web/core/assets/empty-state/dashboard/dark/recent-collaborators-3.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/dark/upcoming-issues.svg b/apps/web/core/assets/empty-state/dashboard/dark/upcoming-issues.svg deleted file mode 100644 index 25599450..00000000 --- a/apps/web/core/assets/empty-state/dashboard/dark/upcoming-issues.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/light/completed-issues.svg b/apps/web/core/assets/empty-state/dashboard/light/completed-issues.svg deleted file mode 100644 index 6f9c4c43..00000000 --- a/apps/web/core/assets/empty-state/dashboard/light/completed-issues.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/light/issues-by-priority.svg b/apps/web/core/assets/empty-state/dashboard/light/issues-by-priority.svg deleted file mode 100644 index 23c35d92..00000000 --- a/apps/web/core/assets/empty-state/dashboard/light/issues-by-priority.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/light/issues-by-state-group.svg b/apps/web/core/assets/empty-state/dashboard/light/issues-by-state-group.svg deleted file mode 100644 index eb327537..00000000 --- a/apps/web/core/assets/empty-state/dashboard/light/issues-by-state-group.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/light/overdue-issues.svg b/apps/web/core/assets/empty-state/dashboard/light/overdue-issues.svg deleted file mode 100644 index 1c66ddd0..00000000 --- a/apps/web/core/assets/empty-state/dashboard/light/overdue-issues.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/light/recent-activity.svg b/apps/web/core/assets/empty-state/dashboard/light/recent-activity.svg deleted file mode 100644 index 3bb67491..00000000 --- a/apps/web/core/assets/empty-state/dashboard/light/recent-activity.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/light/recent-collaborators-1.svg b/apps/web/core/assets/empty-state/dashboard/light/recent-collaborators-1.svg deleted file mode 100644 index fb77e418..00000000 --- a/apps/web/core/assets/empty-state/dashboard/light/recent-collaborators-1.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/light/recent-collaborators-2.svg b/apps/web/core/assets/empty-state/dashboard/light/recent-collaborators-2.svg deleted file mode 100644 index e25fc953..00000000 --- a/apps/web/core/assets/empty-state/dashboard/light/recent-collaborators-2.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/light/recent-collaborators-3.svg b/apps/web/core/assets/empty-state/dashboard/light/recent-collaborators-3.svg deleted file mode 100644 index e46473e8..00000000 --- a/apps/web/core/assets/empty-state/dashboard/light/recent-collaborators-3.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard/light/upcoming-issues.svg b/apps/web/core/assets/empty-state/dashboard/light/upcoming-issues.svg deleted file mode 100644 index ad303581..00000000 --- a/apps/web/core/assets/empty-state/dashboard/light/upcoming-issues.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/dashboard_empty_project.webp b/apps/web/core/assets/empty-state/dashboard_empty_project.webp deleted file mode 100644 index c1f633f6..00000000 Binary files a/apps/web/core/assets/empty-state/dashboard_empty_project.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/draft/draft-issues-empty-dark.webp b/apps/web/core/assets/empty-state/draft/draft-issues-empty-dark.webp deleted file mode 100644 index c50ed24b..00000000 Binary files a/apps/web/core/assets/empty-state/draft/draft-issues-empty-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/draft/draft-issues-empty-light.webp b/apps/web/core/assets/empty-state/draft/draft-issues-empty-light.webp deleted file mode 100644 index c6ded2b0..00000000 Binary files a/apps/web/core/assets/empty-state/draft/draft-issues-empty-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty-filters/calendar-dark.webp b/apps/web/core/assets/empty-state/empty-filters/calendar-dark.webp deleted file mode 100644 index 872be08b..00000000 Binary files a/apps/web/core/assets/empty-state/empty-filters/calendar-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty-filters/calendar-light.webp b/apps/web/core/assets/empty-state/empty-filters/calendar-light.webp deleted file mode 100644 index 50e56eb9..00000000 Binary files a/apps/web/core/assets/empty-state/empty-filters/calendar-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty-filters/gantt_chart-dark.webp b/apps/web/core/assets/empty-state/empty-filters/gantt_chart-dark.webp deleted file mode 100644 index c587d968..00000000 Binary files a/apps/web/core/assets/empty-state/empty-filters/gantt_chart-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty-filters/gantt_chart-light.webp b/apps/web/core/assets/empty-state/empty-filters/gantt_chart-light.webp deleted file mode 100644 index 8c874ea6..00000000 Binary files a/apps/web/core/assets/empty-state/empty-filters/gantt_chart-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty-filters/kanban-dark.webp b/apps/web/core/assets/empty-state/empty-filters/kanban-dark.webp deleted file mode 100644 index a368c686..00000000 Binary files a/apps/web/core/assets/empty-state/empty-filters/kanban-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty-filters/kanban-light.webp b/apps/web/core/assets/empty-state/empty-filters/kanban-light.webp deleted file mode 100644 index 50507e7e..00000000 Binary files a/apps/web/core/assets/empty-state/empty-filters/kanban-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty-filters/list-dark.webp b/apps/web/core/assets/empty-state/empty-filters/list-dark.webp deleted file mode 100644 index 6c49f29f..00000000 Binary files a/apps/web/core/assets/empty-state/empty-filters/list-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty-filters/list-light.webp b/apps/web/core/assets/empty-state/empty-filters/list-light.webp deleted file mode 100644 index bc4f2847..00000000 Binary files a/apps/web/core/assets/empty-state/empty-filters/list-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty-filters/spreadsheet-dark.webp b/apps/web/core/assets/empty-state/empty-filters/spreadsheet-dark.webp deleted file mode 100644 index 2e9ff4c9..00000000 Binary files a/apps/web/core/assets/empty-state/empty-filters/spreadsheet-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty-filters/spreadsheet-light.webp b/apps/web/core/assets/empty-state/empty-filters/spreadsheet-light.webp deleted file mode 100644 index 174b3d08..00000000 Binary files a/apps/web/core/assets/empty-state/empty-filters/spreadsheet-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty-updates-light.png b/apps/web/core/assets/empty-state/empty-updates-light.png deleted file mode 100644 index a92c0937..00000000 Binary files a/apps/web/core/assets/empty-state/empty-updates-light.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty_analytics.webp b/apps/web/core/assets/empty-state/empty_analytics.webp deleted file mode 100644 index 46174fff..00000000 Binary files a/apps/web/core/assets/empty-state/empty_analytics.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty_bar_graph.svg b/apps/web/core/assets/empty-state/empty_bar_graph.svg deleted file mode 100644 index 7742a423..00000000 --- a/apps/web/core/assets/empty-state/empty_bar_graph.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apps/web/core/assets/empty-state/empty_cycles.webp b/apps/web/core/assets/empty-state/empty_cycles.webp deleted file mode 100644 index 710ae2dc..00000000 Binary files a/apps/web/core/assets/empty-state/empty_cycles.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty_graph.svg b/apps/web/core/assets/empty-state/empty_graph.svg deleted file mode 100644 index 5eae523a..00000000 --- a/apps/web/core/assets/empty-state/empty_graph.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/empty_issues.webp b/apps/web/core/assets/empty-state/empty_issues.webp deleted file mode 100644 index e60d663d..00000000 Binary files a/apps/web/core/assets/empty-state/empty_issues.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty_modules.webp b/apps/web/core/assets/empty-state/empty_modules.webp deleted file mode 100644 index 49050b53..00000000 Binary files a/apps/web/core/assets/empty-state/empty_modules.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty_page.png b/apps/web/core/assets/empty-state/empty_page.png deleted file mode 100644 index 993774c7..00000000 Binary files a/apps/web/core/assets/empty-state/empty_page.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty_project.webp b/apps/web/core/assets/empty-state/empty_project.webp deleted file mode 100644 index ad66f096..00000000 Binary files a/apps/web/core/assets/empty-state/empty_project.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/empty_users.svg b/apps/web/core/assets/empty-state/empty_users.svg deleted file mode 100644 index 7298e9e8..00000000 --- a/apps/web/core/assets/empty-state/empty_users.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/web/core/assets/empty-state/empty_view.webp b/apps/web/core/assets/empty-state/empty_view.webp deleted file mode 100644 index aa0f5a65..00000000 Binary files a/apps/web/core/assets/empty-state/empty_view.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/epics/epics-dark.webp b/apps/web/core/assets/empty-state/epics/epics-dark.webp deleted file mode 100644 index 648392af..00000000 Binary files a/apps/web/core/assets/empty-state/epics/epics-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/epics/epics-light.webp b/apps/web/core/assets/empty-state/epics/epics-light.webp deleted file mode 100644 index f677e5d6..00000000 Binary files a/apps/web/core/assets/empty-state/epics/epics-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/epics/settings-dark.webp b/apps/web/core/assets/empty-state/epics/settings-dark.webp deleted file mode 100644 index 31931379..00000000 Binary files a/apps/web/core/assets/empty-state/epics/settings-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/epics/settings-light.webp b/apps/web/core/assets/empty-state/epics/settings-light.webp deleted file mode 100644 index 1f9596ea..00000000 Binary files a/apps/web/core/assets/empty-state/epics/settings-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/intake/filter-issue-dark.webp b/apps/web/core/assets/empty-state/intake/filter-issue-dark.webp deleted file mode 100644 index dab3eb78..00000000 Binary files a/apps/web/core/assets/empty-state/intake/filter-issue-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/intake/filter-issue-light.webp b/apps/web/core/assets/empty-state/intake/filter-issue-light.webp deleted file mode 100644 index 67167067..00000000 Binary files a/apps/web/core/assets/empty-state/intake/filter-issue-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/intake/intake-dark-resp.webp b/apps/web/core/assets/empty-state/intake/intake-dark-resp.webp deleted file mode 100644 index bf6166e6..00000000 Binary files a/apps/web/core/assets/empty-state/intake/intake-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/intake/intake-issue-dark.webp b/apps/web/core/assets/empty-state/intake/intake-issue-dark.webp deleted file mode 100644 index 0c14ce24..00000000 Binary files a/apps/web/core/assets/empty-state/intake/intake-issue-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/intake/intake-issue-light.webp b/apps/web/core/assets/empty-state/intake/intake-issue-light.webp deleted file mode 100644 index c557f5dc..00000000 Binary files a/apps/web/core/assets/empty-state/intake/intake-issue-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/intake/intake-light-resp.webp b/apps/web/core/assets/empty-state/intake/intake-light-resp.webp deleted file mode 100644 index 69a79d67..00000000 Binary files a/apps/web/core/assets/empty-state/intake/intake-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/intake/issue-detail-dark.webp b/apps/web/core/assets/empty-state/intake/issue-detail-dark.webp deleted file mode 100644 index 2a2c7063..00000000 Binary files a/apps/web/core/assets/empty-state/intake/issue-detail-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/intake/issue-detail-light.webp b/apps/web/core/assets/empty-state/intake/issue-detail-light.webp deleted file mode 100644 index a7130691..00000000 Binary files a/apps/web/core/assets/empty-state/intake/issue-detail-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/calendar-dark-resp.webp b/apps/web/core/assets/empty-state/module-issues/calendar-dark-resp.webp deleted file mode 100644 index 5e6404e7..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/calendar-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/calendar-dark.webp b/apps/web/core/assets/empty-state/module-issues/calendar-dark.webp deleted file mode 100644 index 5170f6c0..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/calendar-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/calendar-light-resp.webp b/apps/web/core/assets/empty-state/module-issues/calendar-light-resp.webp deleted file mode 100644 index 0d890af6..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/calendar-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/calendar-light.webp b/apps/web/core/assets/empty-state/module-issues/calendar-light.webp deleted file mode 100644 index 5bee9c91..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/calendar-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/gantt_chart-dark-resp.webp b/apps/web/core/assets/empty-state/module-issues/gantt_chart-dark-resp.webp deleted file mode 100644 index 90d7985a..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/gantt_chart-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/gantt_chart-dark.webp b/apps/web/core/assets/empty-state/module-issues/gantt_chart-dark.webp deleted file mode 100644 index d3821983..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/gantt_chart-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/gantt_chart-light-resp.webp b/apps/web/core/assets/empty-state/module-issues/gantt_chart-light-resp.webp deleted file mode 100644 index ccaadee8..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/gantt_chart-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/gantt_chart-light.webp b/apps/web/core/assets/empty-state/module-issues/gantt_chart-light.webp deleted file mode 100644 index e51bbeea..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/gantt_chart-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/kanban-dark-resp.webp b/apps/web/core/assets/empty-state/module-issues/kanban-dark-resp.webp deleted file mode 100644 index b447fb6c..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/kanban-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/kanban-dark.webp b/apps/web/core/assets/empty-state/module-issues/kanban-dark.webp deleted file mode 100644 index 5e978d59..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/kanban-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/kanban-light-resp.webp b/apps/web/core/assets/empty-state/module-issues/kanban-light-resp.webp deleted file mode 100644 index 2be0b8f1..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/kanban-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/kanban-light.webp b/apps/web/core/assets/empty-state/module-issues/kanban-light.webp deleted file mode 100644 index 5d30a652..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/kanban-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/list-dark-resp.webp b/apps/web/core/assets/empty-state/module-issues/list-dark-resp.webp deleted file mode 100644 index 84d92aaa..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/list-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/list-dark.webp b/apps/web/core/assets/empty-state/module-issues/list-dark.webp deleted file mode 100644 index 96e9518c..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/list-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/list-light-resp.webp b/apps/web/core/assets/empty-state/module-issues/list-light-resp.webp deleted file mode 100644 index b688add2..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/list-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/list-light.webp b/apps/web/core/assets/empty-state/module-issues/list-light.webp deleted file mode 100644 index d9b1c4c2..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/list-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/spreadsheet-dark-resp.webp b/apps/web/core/assets/empty-state/module-issues/spreadsheet-dark-resp.webp deleted file mode 100644 index afb2f1cb..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/spreadsheet-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/spreadsheet-dark.webp b/apps/web/core/assets/empty-state/module-issues/spreadsheet-dark.webp deleted file mode 100644 index 1894cfe7..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/spreadsheet-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/spreadsheet-light-resp.webp b/apps/web/core/assets/empty-state/module-issues/spreadsheet-light-resp.webp deleted file mode 100644 index 11115d4d..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/spreadsheet-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/module-issues/spreadsheet-light.webp b/apps/web/core/assets/empty-state/module-issues/spreadsheet-light.webp deleted file mode 100644 index aa3813f5..00000000 Binary files a/apps/web/core/assets/empty-state/module-issues/spreadsheet-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/notification.svg b/apps/web/core/assets/empty-state/notification.svg deleted file mode 100644 index 700a1552..00000000 --- a/apps/web/core/assets/empty-state/notification.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/apps/web/core/assets/empty-state/onboarding/analytics-dark.webp b/apps/web/core/assets/empty-state/onboarding/analytics-dark.webp deleted file mode 100644 index a83d55de..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/analytics-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/analytics-light.webp b/apps/web/core/assets/empty-state/onboarding/analytics-light.webp deleted file mode 100644 index 64a762f9..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/analytics-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/archive-dark.png b/apps/web/core/assets/empty-state/onboarding/archive-dark.png deleted file mode 100644 index 54cca36e..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/archive-dark.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/archive-light.png b/apps/web/core/assets/empty-state/onboarding/archive-light.png deleted file mode 100644 index 8530bbac..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/archive-light.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/dashboard-dark.webp b/apps/web/core/assets/empty-state/onboarding/dashboard-dark.webp deleted file mode 100644 index afa10bea..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/dashboard-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/dashboard-light.webp b/apps/web/core/assets/empty-state/onboarding/dashboard-light.webp deleted file mode 100644 index d4bce8be..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/dashboard-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/graph-dark.png b/apps/web/core/assets/empty-state/onboarding/graph-dark.png deleted file mode 100644 index e8a938d8..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/graph-dark.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/graph-light.png b/apps/web/core/assets/empty-state/onboarding/graph-light.png deleted file mode 100644 index eb48b45a..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/graph-light.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/issues-closed-dark.png b/apps/web/core/assets/empty-state/onboarding/issues-closed-dark.png deleted file mode 100644 index d4bafb28..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/issues-closed-dark.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/issues-closed-light.png b/apps/web/core/assets/empty-state/onboarding/issues-closed-light.png deleted file mode 100644 index 739acd10..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/issues-closed-light.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/members-dark.png b/apps/web/core/assets/empty-state/onboarding/members-dark.png deleted file mode 100644 index 2f8a1c87..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/members-dark.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/members-light.png b/apps/web/core/assets/empty-state/onboarding/members-light.png deleted file mode 100644 index eaa43ef9..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/members-light.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/notification-dark.png b/apps/web/core/assets/empty-state/onboarding/notification-dark.png deleted file mode 100644 index dee284ce..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/notification-dark.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/notification-light.png b/apps/web/core/assets/empty-state/onboarding/notification-light.png deleted file mode 100644 index 3065787e..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/notification-light.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/projects-dark.webp b/apps/web/core/assets/empty-state/onboarding/projects-dark.webp deleted file mode 100644 index d4f6c627..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/projects-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/projects-light.webp b/apps/web/core/assets/empty-state/onboarding/projects-light.webp deleted file mode 100644 index c475c8ff..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/projects-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/search-dark.png b/apps/web/core/assets/empty-state/onboarding/search-dark.png deleted file mode 100644 index 531081d4..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/search-dark.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/search-light.png b/apps/web/core/assets/empty-state/onboarding/search-light.png deleted file mode 100644 index 39e26366..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/search-light.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/snooze-light.png b/apps/web/core/assets/empty-state/onboarding/snooze-light.png deleted file mode 100644 index 6ccd7ab9..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/snooze-light.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/snoozed-dark.png b/apps/web/core/assets/empty-state/onboarding/snoozed-dark.png deleted file mode 100644 index c8b88fe5..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/snoozed-dark.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/workspace-active-cycles-dark.webp b/apps/web/core/assets/empty-state/onboarding/workspace-active-cycles-dark.webp deleted file mode 100644 index 68317b1b..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/workspace-active-cycles-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/workspace-active-cycles-light.webp b/apps/web/core/assets/empty-state/onboarding/workspace-active-cycles-light.webp deleted file mode 100644 index 2341a905..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/workspace-active-cycles-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/workspace-invites-dark.webp b/apps/web/core/assets/empty-state/onboarding/workspace-invites-dark.webp deleted file mode 100644 index d6e10046..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/workspace-invites-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/onboarding/workspace-invites-light.webp b/apps/web/core/assets/empty-state/onboarding/workspace-invites-light.webp deleted file mode 100644 index 123a600e..00000000 Binary files a/apps/web/core/assets/empty-state/onboarding/workspace-invites-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/activities-dark.webp b/apps/web/core/assets/empty-state/profile/activities-dark.webp deleted file mode 100644 index 1b693947..00000000 Binary files a/apps/web/core/assets/empty-state/profile/activities-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/activities-light.webp b/apps/web/core/assets/empty-state/profile/activities-light.webp deleted file mode 100644 index c287e0cd..00000000 Binary files a/apps/web/core/assets/empty-state/profile/activities-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/activity-dark.webp b/apps/web/core/assets/empty-state/profile/activity-dark.webp deleted file mode 100644 index d44e6a1d..00000000 Binary files a/apps/web/core/assets/empty-state/profile/activity-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/activity-light.webp b/apps/web/core/assets/empty-state/profile/activity-light.webp deleted file mode 100644 index 206685a4..00000000 Binary files a/apps/web/core/assets/empty-state/profile/activity-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/assigned-dark.webp b/apps/web/core/assets/empty-state/profile/assigned-dark.webp deleted file mode 100644 index 173ebe62..00000000 Binary files a/apps/web/core/assets/empty-state/profile/assigned-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/assigned-light.webp b/apps/web/core/assets/empty-state/profile/assigned-light.webp deleted file mode 100644 index 78416c92..00000000 Binary files a/apps/web/core/assets/empty-state/profile/assigned-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/created-dark.webp b/apps/web/core/assets/empty-state/profile/created-dark.webp deleted file mode 100644 index 8232ce2c..00000000 Binary files a/apps/web/core/assets/empty-state/profile/created-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/created-light.webp b/apps/web/core/assets/empty-state/profile/created-light.webp deleted file mode 100644 index 4ea037ae..00000000 Binary files a/apps/web/core/assets/empty-state/profile/created-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/issues-by-priority-dark.webp b/apps/web/core/assets/empty-state/profile/issues-by-priority-dark.webp deleted file mode 100644 index e1a71802..00000000 Binary files a/apps/web/core/assets/empty-state/profile/issues-by-priority-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/issues-by-priority-light.webp b/apps/web/core/assets/empty-state/profile/issues-by-priority-light.webp deleted file mode 100644 index 16abada6..00000000 Binary files a/apps/web/core/assets/empty-state/profile/issues-by-priority-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/issues-by-state-dark.webp b/apps/web/core/assets/empty-state/profile/issues-by-state-dark.webp deleted file mode 100644 index 82210aa8..00000000 Binary files a/apps/web/core/assets/empty-state/profile/issues-by-state-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/issues-by-state-light.webp b/apps/web/core/assets/empty-state/profile/issues-by-state-light.webp deleted file mode 100644 index 73788bb8..00000000 Binary files a/apps/web/core/assets/empty-state/profile/issues-by-state-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/subscribed-dark.webp b/apps/web/core/assets/empty-state/profile/subscribed-dark.webp deleted file mode 100644 index 26837e1a..00000000 Binary files a/apps/web/core/assets/empty-state/profile/subscribed-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/profile/subscribed-light.webp b/apps/web/core/assets/empty-state/profile/subscribed-light.webp deleted file mode 100644 index 7faf6609..00000000 Binary files a/apps/web/core/assets/empty-state/profile/subscribed-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/estimates-dark-resp.webp b/apps/web/core/assets/empty-state/project-settings/estimates-dark-resp.webp deleted file mode 100644 index 6f6a4949..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/estimates-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/estimates-dark.webp b/apps/web/core/assets/empty-state/project-settings/estimates-dark.webp deleted file mode 100644 index 35d42e52..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/estimates-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/estimates-light-resp.webp b/apps/web/core/assets/empty-state/project-settings/estimates-light-resp.webp deleted file mode 100644 index 13a29caf..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/estimates-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/estimates-light.webp b/apps/web/core/assets/empty-state/project-settings/estimates-light.webp deleted file mode 100644 index b329ea91..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/estimates-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/integrations-dark-resp.webp b/apps/web/core/assets/empty-state/project-settings/integrations-dark-resp.webp deleted file mode 100644 index f968f8f4..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/integrations-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/integrations-dark.webp b/apps/web/core/assets/empty-state/project-settings/integrations-dark.webp deleted file mode 100644 index f968f8f4..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/integrations-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/integrations-light-resp.webp b/apps/web/core/assets/empty-state/project-settings/integrations-light-resp.webp deleted file mode 100644 index 94f6ffe3..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/integrations-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/integrations-light.webp b/apps/web/core/assets/empty-state/project-settings/integrations-light.webp deleted file mode 100644 index 94f6ffe3..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/integrations-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/labels-dark-resp.webp b/apps/web/core/assets/empty-state/project-settings/labels-dark-resp.webp deleted file mode 100644 index bf23c60b..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/labels-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/labels-dark.webp b/apps/web/core/assets/empty-state/project-settings/labels-dark.webp deleted file mode 100644 index 6d41f556..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/labels-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/labels-light-resp.webp b/apps/web/core/assets/empty-state/project-settings/labels-light-resp.webp deleted file mode 100644 index d992fb1f..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/labels-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/labels-light.webp b/apps/web/core/assets/empty-state/project-settings/labels-light.webp deleted file mode 100644 index c6e70154..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/labels-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/updates-dark.png b/apps/web/core/assets/empty-state/project-settings/updates-dark.png deleted file mode 100644 index 46e27091..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/updates-dark.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project-settings/updates-light.png b/apps/web/core/assets/empty-state/project-settings/updates-light.png deleted file mode 100644 index d2e92087..00000000 Binary files a/apps/web/core/assets/empty-state/project-settings/updates-light.png and /dev/null differ diff --git a/apps/web/core/assets/empty-state/project.svg b/apps/web/core/assets/empty-state/project.svg deleted file mode 100644 index b8985490..00000000 --- a/apps/web/core/assets/empty-state/project.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/project/all-filters-dark.svg b/apps/web/core/assets/empty-state/project/all-filters-dark.svg deleted file mode 100644 index e0d69c46..00000000 --- a/apps/web/core/assets/empty-state/project/all-filters-dark.svg +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/project/all-filters-light.svg b/apps/web/core/assets/empty-state/project/all-filters-light.svg deleted file mode 100644 index 93ac4de7..00000000 --- a/apps/web/core/assets/empty-state/project/all-filters-light.svg +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/project/name-filter-dark.svg b/apps/web/core/assets/empty-state/project/name-filter-dark.svg deleted file mode 100644 index df4c2379..00000000 --- a/apps/web/core/assets/empty-state/project/name-filter-dark.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/project/name-filter-light.svg b/apps/web/core/assets/empty-state/project/name-filter-light.svg deleted file mode 100644 index ec632283..00000000 --- a/apps/web/core/assets/empty-state/project/name-filter-light.svg +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/recent_activity.svg b/apps/web/core/assets/empty-state/recent_activity.svg deleted file mode 100644 index bef318fa..00000000 --- a/apps/web/core/assets/empty-state/recent_activity.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/apps/web/core/assets/empty-state/search/all-issue-view-dark.webp b/apps/web/core/assets/empty-state/search/all-issue-view-dark.webp deleted file mode 100644 index dbc69c0a..00000000 Binary files a/apps/web/core/assets/empty-state/search/all-issue-view-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/search/all-issues-view-light.webp b/apps/web/core/assets/empty-state/search/all-issues-view-light.webp deleted file mode 100644 index 829b9737..00000000 Binary files a/apps/web/core/assets/empty-state/search/all-issues-view-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/search/archive-dark.webp b/apps/web/core/assets/empty-state/search/archive-dark.webp deleted file mode 100644 index d586be88..00000000 Binary files a/apps/web/core/assets/empty-state/search/archive-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/search/archive-light.webp b/apps/web/core/assets/empty-state/search/archive-light.webp deleted file mode 100644 index 5a79179e..00000000 Binary files a/apps/web/core/assets/empty-state/search/archive-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/search/comments-dark.webp b/apps/web/core/assets/empty-state/search/comments-dark.webp deleted file mode 100644 index d06ba7e4..00000000 Binary files a/apps/web/core/assets/empty-state/search/comments-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/search/comments-light.webp b/apps/web/core/assets/empty-state/search/comments-light.webp deleted file mode 100644 index 5a66067d..00000000 Binary files a/apps/web/core/assets/empty-state/search/comments-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/search/member-dark.webp b/apps/web/core/assets/empty-state/search/member-dark.webp deleted file mode 100644 index 20521a5d..00000000 Binary files a/apps/web/core/assets/empty-state/search/member-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/search/member-light.webp b/apps/web/core/assets/empty-state/search/member-light.webp deleted file mode 100644 index dcd38c97..00000000 Binary files a/apps/web/core/assets/empty-state/search/member-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/search/notification-dark.webp b/apps/web/core/assets/empty-state/search/notification-dark.webp deleted file mode 100644 index cb299d11..00000000 Binary files a/apps/web/core/assets/empty-state/search/notification-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/search/notification-light.webp b/apps/web/core/assets/empty-state/search/notification-light.webp deleted file mode 100644 index 55c4ffac..00000000 Binary files a/apps/web/core/assets/empty-state/search/notification-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/search/snooze-dark.webp b/apps/web/core/assets/empty-state/search/snooze-dark.webp deleted file mode 100644 index 296e797e..00000000 Binary files a/apps/web/core/assets/empty-state/search/snooze-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/search/snooze-light.webp b/apps/web/core/assets/empty-state/search/snooze-light.webp deleted file mode 100644 index 897ff359..00000000 Binary files a/apps/web/core/assets/empty-state/search/snooze-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/state_graph.svg b/apps/web/core/assets/empty-state/state_graph.svg deleted file mode 100644 index 651ea347..00000000 --- a/apps/web/core/assets/empty-state/state_graph.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/wiki/all-dark.webp b/apps/web/core/assets/empty-state/wiki/all-dark.webp deleted file mode 100644 index 81ef36de..00000000 Binary files a/apps/web/core/assets/empty-state/wiki/all-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/wiki/all-filters-dark.svg b/apps/web/core/assets/empty-state/wiki/all-filters-dark.svg deleted file mode 100644 index 037a2fd6..00000000 --- a/apps/web/core/assets/empty-state/wiki/all-filters-dark.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/wiki/all-filters-light.svg b/apps/web/core/assets/empty-state/wiki/all-filters-light.svg deleted file mode 100644 index 8ecd8d2e..00000000 --- a/apps/web/core/assets/empty-state/wiki/all-filters-light.svg +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/wiki/all-light.webp b/apps/web/core/assets/empty-state/wiki/all-light.webp deleted file mode 100644 index 02b1d889..00000000 Binary files a/apps/web/core/assets/empty-state/wiki/all-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/wiki/archived-dark.webp b/apps/web/core/assets/empty-state/wiki/archived-dark.webp deleted file mode 100644 index 64700c83..00000000 Binary files a/apps/web/core/assets/empty-state/wiki/archived-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/wiki/archived-light.webp b/apps/web/core/assets/empty-state/wiki/archived-light.webp deleted file mode 100644 index 9412f73a..00000000 Binary files a/apps/web/core/assets/empty-state/wiki/archived-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/wiki/name-filter-dark.svg b/apps/web/core/assets/empty-state/wiki/name-filter-dark.svg deleted file mode 100644 index 969a1fe6..00000000 --- a/apps/web/core/assets/empty-state/wiki/name-filter-dark.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/wiki/name-filter-light.svg b/apps/web/core/assets/empty-state/wiki/name-filter-light.svg deleted file mode 100644 index bc2465ae..00000000 --- a/apps/web/core/assets/empty-state/wiki/name-filter-light.svg +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/empty-state/wiki/private-dark.webp b/apps/web/core/assets/empty-state/wiki/private-dark.webp deleted file mode 100644 index b482f432..00000000 Binary files a/apps/web/core/assets/empty-state/wiki/private-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/wiki/private-light.webp b/apps/web/core/assets/empty-state/wiki/private-light.webp deleted file mode 100644 index e1c3af91..00000000 Binary files a/apps/web/core/assets/empty-state/wiki/private-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/wiki/public-dark.webp b/apps/web/core/assets/empty-state/wiki/public-dark.webp deleted file mode 100644 index 571bf8a9..00000000 Binary files a/apps/web/core/assets/empty-state/wiki/public-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/wiki/public-light.webp b/apps/web/core/assets/empty-state/wiki/public-light.webp deleted file mode 100644 index e0f7b7df..00000000 Binary files a/apps/web/core/assets/empty-state/wiki/public-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-draft/issue-dark.webp b/apps/web/core/assets/empty-state/workspace-draft/issue-dark.webp deleted file mode 100644 index 27653352..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-draft/issue-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-draft/issue-light.webp b/apps/web/core/assets/empty-state/workspace-draft/issue-light.webp deleted file mode 100644 index 8be274b3..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-draft/issue-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/api-tokens-dark-resp.webp b/apps/web/core/assets/empty-state/workspace-settings/api-tokens-dark-resp.webp deleted file mode 100644 index ae19eb46..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/api-tokens-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/api-tokens-dark.webp b/apps/web/core/assets/empty-state/workspace-settings/api-tokens-dark.webp deleted file mode 100644 index bddaf05d..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/api-tokens-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/api-tokens-light-resp.webp b/apps/web/core/assets/empty-state/workspace-settings/api-tokens-light-resp.webp deleted file mode 100644 index 2ec9bf8b..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/api-tokens-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/api-tokens-light.webp b/apps/web/core/assets/empty-state/workspace-settings/api-tokens-light.webp deleted file mode 100644 index ba3bc585..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/api-tokens-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/exports-dark-resp.webp b/apps/web/core/assets/empty-state/workspace-settings/exports-dark-resp.webp deleted file mode 100644 index 6417ffa3..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/exports-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/exports-dark.webp b/apps/web/core/assets/empty-state/workspace-settings/exports-dark.webp deleted file mode 100644 index b0911c90..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/exports-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/exports-light-resp.webp b/apps/web/core/assets/empty-state/workspace-settings/exports-light-resp.webp deleted file mode 100644 index 29a695f3..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/exports-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/exports-light.webp b/apps/web/core/assets/empty-state/workspace-settings/exports-light.webp deleted file mode 100644 index 5e08f21d..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/exports-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/imports-dark-resp.webp b/apps/web/core/assets/empty-state/workspace-settings/imports-dark-resp.webp deleted file mode 100644 index 70e789b4..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/imports-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/imports-dark.webp b/apps/web/core/assets/empty-state/workspace-settings/imports-dark.webp deleted file mode 100644 index 428ee978..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/imports-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/imports-light-resp.webp b/apps/web/core/assets/empty-state/workspace-settings/imports-light-resp.webp deleted file mode 100644 index 9bc95efa..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/imports-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/imports-light.webp b/apps/web/core/assets/empty-state/workspace-settings/imports-light.webp deleted file mode 100644 index 5f42180e..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/imports-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/integrations-dark-resp.webp b/apps/web/core/assets/empty-state/workspace-settings/integrations-dark-resp.webp deleted file mode 100644 index 3f9e0095..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/integrations-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/integrations-dark.webp b/apps/web/core/assets/empty-state/workspace-settings/integrations-dark.webp deleted file mode 100644 index 603a658e..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/integrations-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/integrations-light-resp.webp b/apps/web/core/assets/empty-state/workspace-settings/integrations-light-resp.webp deleted file mode 100644 index 13e08be8..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/integrations-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/integrations-light.webp b/apps/web/core/assets/empty-state/workspace-settings/integrations-light.webp deleted file mode 100644 index eb62503e..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/integrations-light.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/webhooks-dark-resp.webp b/apps/web/core/assets/empty-state/workspace-settings/webhooks-dark-resp.webp deleted file mode 100644 index 79230732..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/webhooks-dark-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/webhooks-dark.webp b/apps/web/core/assets/empty-state/workspace-settings/webhooks-dark.webp deleted file mode 100644 index 88a584eb..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/webhooks-dark.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/webhooks-light-resp.webp b/apps/web/core/assets/empty-state/workspace-settings/webhooks-light-resp.webp deleted file mode 100644 index ecb0f28a..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/webhooks-light-resp.webp and /dev/null differ diff --git a/apps/web/core/assets/empty-state/workspace-settings/webhooks-light.webp b/apps/web/core/assets/empty-state/workspace-settings/webhooks-light.webp deleted file mode 100644 index 6c76b5af..00000000 Binary files a/apps/web/core/assets/empty-state/workspace-settings/webhooks-light.webp and /dev/null differ diff --git a/apps/web/core/assets/instance-not-ready.webp b/apps/web/core/assets/instance-not-ready.webp deleted file mode 100644 index ceabbcc0..00000000 Binary files a/apps/web/core/assets/instance-not-ready.webp and /dev/null differ diff --git a/apps/web/core/assets/instance-setup-done.webp b/apps/web/core/assets/instance-setup-done.webp deleted file mode 100644 index 4773ed70..00000000 Binary files a/apps/web/core/assets/instance-setup-done.webp and /dev/null differ diff --git a/apps/web/core/assets/mac-command.svg b/apps/web/core/assets/mac-command.svg deleted file mode 100644 index 5cee4595..00000000 --- a/apps/web/core/assets/mac-command.svg +++ /dev/null @@ -1,2 +0,0 @@ - -mac-command \ No newline at end of file diff --git a/apps/web/core/assets/plane-takeoff.png b/apps/web/core/assets/plane-takeoff.png deleted file mode 100644 index 417ff829..00000000 Binary files a/apps/web/core/assets/plane-takeoff.png and /dev/null differ diff --git a/apps/web/core/assets/services/csv.svg b/apps/web/core/assets/services/csv.svg deleted file mode 100644 index adea1ddc..00000000 --- a/apps/web/core/assets/services/csv.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/apps/web/core/assets/services/excel.svg b/apps/web/core/assets/services/excel.svg deleted file mode 100644 index 86fb8e64..00000000 --- a/apps/web/core/assets/services/excel.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/apps/web/core/assets/services/jira.svg b/apps/web/core/assets/services/jira.svg deleted file mode 100644 index 5e5cebc8..00000000 --- a/apps/web/core/assets/services/jira.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/apps/web/core/assets/services/json.svg b/apps/web/core/assets/services/json.svg deleted file mode 100644 index 0fe32e27..00000000 --- a/apps/web/core/assets/services/json.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/apps/web/core/assets/users/user-1.png b/apps/web/core/assets/users/user-1.png deleted file mode 100644 index b69f539c..00000000 Binary files a/apps/web/core/assets/users/user-1.png and /dev/null differ diff --git a/apps/web/core/assets/users/user-2.png b/apps/web/core/assets/users/user-2.png deleted file mode 100644 index c5b9bc51..00000000 Binary files a/apps/web/core/assets/users/user-2.png and /dev/null differ diff --git a/apps/web/core/components/auth-screens/workspace/not-a-member.tsx b/apps/web/core/components/auth-screens/workspace/not-a-member.tsx deleted file mode 100644 index 1a3f6abb..00000000 --- a/apps/web/core/components/auth-screens/workspace/not-a-member.tsx +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import Link from "@/lib/navigation/link"; -// ui -import { Button } from "@pace/propel/button"; -// layouts -import DefaultLayout from "@/layouts/default-layout"; - -export function NotAWorkspaceMember() { - return ( - -
-
-
-

Not Authorized!

-

- You{"'"}re not a member of this workspace. Please contact the workspace admin to get an invitation or - check your pending invitations. -

-
-
- - - - - - - - - - -
-
-
-
- ); -} diff --git a/apps/web/core/components/common/latest-feature-block.tsx b/apps/web/core/components/common/latest-feature-block.tsx deleted file mode 100644 index 1c9af590..00000000 --- a/apps/web/core/components/common/latest-feature-block.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import Link from "@/lib/navigation/link"; -import { useTheme } from "next-themes"; -// pace imports -import { CHANGELOG_URL } from "@pace/constants"; -// icons -import { ThoughtsOutline } from "@makeplane/propel/icons"; -// images -import latestFeatures from "@/assets/onboarding/onboarding-pages.webp?url"; - -export function LatestFeatureBlock() { - const { resolvedTheme } = useTheme(); - - return ( - <> -
- -

- Pages gets a facelift! Write anything and use Galileo to help you start. - {/* Only the "Learn more" link goes when this installation publishes no changelog. The sentence in front of it is the announcement itself and stands on its own, so there is no reason to blank the whole block -- and the block is decoration on the sign-in screen, where a link to nowhere would be the first thing a new user clicks. */} - {CHANGELOG_URL && ( - <> - {" "} - - Learn more - - - )} -

-
-
-
- Pace work items -
-
- - ); -} diff --git a/apps/web/core/components/common/new-empty-state.tsx b/apps/web/core/components/common/new-empty-state.tsx deleted file mode 100644 index f967c51f..00000000 --- a/apps/web/core/components/common/new-empty-state.tsx +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React, { useState } from "react"; - -// ui -import { Button } from "@pace/propel/button"; - -type Props = { - title: string; - description?: React.ReactNode; - image: any; - comicBox?: { - direction: "left" | "right"; - title: string; - description: string; - extraPadding?: boolean; - }; - primaryButton?: { - icon?: any; - text: string; - onClick: () => void; - }; - disabled?: boolean; -}; - -export function NewEmptyState({ title, description, image, primaryButton, disabled = false, comicBox }: Props) { - const [isHovered, setIsHovered] = useState(false); - - const handleMouseEnter = () => { - setIsHovered(true); - }; - - const handleMouseLeave = () => { - setIsHovered(false); - }; - return ( -
-
-
-

{title}

- {description &&

{description}

} -
- {primaryButton?.text -
- -
- {primaryButton && ( - - )} - {comicBox && - isHovered && - (comicBox.direction === "right" ? ( -
-
-
-
-
-

-

{comicBox?.title}

-

{comicBox?.description}

- -
-
- ) : ( -
-
-
-
-
-

-

{comicBox?.title}

-

{comicBox?.description}

- -
-
- ))} -
-
-
-
- ); -} diff --git a/apps/web/core/components/cycles/list/cycle-list-project-group-header.tsx b/apps/web/core/components/cycles/list/cycle-list-project-group-header.tsx deleted file mode 100644 index 753058bb..00000000 --- a/apps/web/core/components/cycles/list/cycle-list-project-group-header.tsx +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React from "react"; -import { observer } from "mobx-react"; -import { Logo } from "@pace/propel/emoji-icon-picker"; -import { ChevronRightOutline } from "@makeplane/propel/icons"; -// icons -import { Row } from "@pace/ui"; -// helpers -import { cn } from "@pace/utils"; -import { useProject } from "@/hooks/store/use-project"; - -type Props = { - projectId: string; - count?: number; - showCount?: boolean; - isExpanded?: boolean; -}; - -export const CycleListProjectGroupHeader = observer(function CycleListProjectGroupHeader(props: Props) { - const { projectId, count, showCount = false, isExpanded = false } = props; - // store hooks - const { getProjectById } = useProject(); - // derived values - const project = getProjectById(projectId); - - if (!project) return null; - return ( - - -
- -
-
-
{project.name}
- {showCount &&
{`${count ?? "0"}`}
} -
-
- ); -}); diff --git a/apps/web/core/components/editor/rich-text/description-input/root.tsx b/apps/web/core/components/editor/rich-text/description-input/root.tsx index 173923d5..1eb82d12 100644 --- a/apps/web/core/components/editor/rich-text/description-input/root.tsx +++ b/apps/web/core/components/editor/rich-text/description-input/root.tsx @@ -273,7 +273,7 @@ export const DescriptionInput = observer(function DescriptionInput(props: Props) }); return asset_id; } catch (error) { - console.log("Error in uploading asset:", error); + console.error("Error in uploading asset:", error); throw new Error("Asset upload failed. Please try again later."); } }} diff --git a/apps/web/core/components/empty-state/comic-box-button.tsx b/apps/web/core/components/empty-state/comic-box-button.tsx deleted file mode 100644 index 8e33a295..00000000 --- a/apps/web/core/components/empty-state/comic-box-button.tsx +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import type { Ref } from "react"; -import { Fragment, useState } from "react"; -import { usePopper } from "react-popper"; -import { Popover } from "@headlessui/react"; -// pace imports -import { Button } from "@pace/propel/button"; - -type Props = { - label: string; - icon?: any; - title: string | undefined; - description: string | undefined; - onClick?: () => void; - disabled?: boolean; -}; - -export function ComicBoxButton(props: Props) { - const { label, icon, title, description, onClick, disabled = false } = props; - const [isHovered, setIsHovered] = useState(false); - - const handleMouseEnter = () => { - setIsHovered(true); - }; - - const handleMouseLeave = () => { - setIsHovered(false); - }; - - const [referenceElement, setReferenceElement] = useState(null); - const [popperElement, setPopperElement] = useState(); - const { styles, attributes } = usePopper(referenceElement, popperElement, { - placement: "right-end", - modifiers: [ - { - name: "offset", - options: { - offset: [0, 10], - }, - }, - ], - }); - - return ( - - - - - {isHovered && ( - -
} - style={styles.popper} - {...attributes.popper} - > -
-

{title}

-

{description}

-
- - )} - - ); -} diff --git a/apps/web/core/components/empty-state/helper.tsx b/apps/web/core/components/empty-state/helper.tsx deleted file mode 100644 index 03460f62..00000000 --- a/apps/web/core/components/empty-state/helper.tsx +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -export const getEmptyStateImagePath = (category: string, type: string, isLightMode: boolean) => - `/empty-state/${category}/${type}-${isLightMode ? "light" : "dark"}.webp`; diff --git a/apps/web/core/components/estimates/empty-screen.tsx b/apps/web/core/components/estimates/empty-screen.tsx deleted file mode 100644 index 2ebd767e..00000000 --- a/apps/web/core/components/estimates/empty-screen.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useTheme } from "next-themes"; -// pace imports -import { useTranslation } from "@pace/i18n"; -// components -import { DetailedEmptyState } from "@/components/empty-state/detailed-empty-state-root"; - -type TEstimateEmptyScreen = { - onButtonClick: () => void; -}; - -export function EstimateEmptyScreen(props: TEstimateEmptyScreen) { - // props - const { onButtonClick } = props; - const { resolvedTheme } = useTheme(); - - const { t } = useTranslation(); - - const resolvedPath = `/empty-state/project-settings/estimates-${resolvedTheme === "light" ? "light" : "dark"}.png`; - return ( - { - onButtonClick(); - }, - }} - /> - ); -} diff --git a/apps/web/core/components/estimates/estimate-search.tsx b/apps/web/core/components/estimates/estimate-search.tsx deleted file mode 100644 index 0b05f671..00000000 --- a/apps/web/core/components/estimates/estimate-search.tsx +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { observer } from "mobx-react"; - -export const EstimateSearch = observer(function EstimateSearch() { - // hooks - const {} = {}; - - return
Estimate Search
; -}); diff --git a/apps/web/core/components/exporter/export-modal.tsx b/apps/web/core/components/exporter/export-modal.tsx deleted file mode 100644 index 672f1a6f..00000000 --- a/apps/web/core/components/exporter/export-modal.tsx +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React, { useState } from "react"; -import { intersection } from "lodash-es"; -import { observer } from "mobx-react"; -import { useParams } from "@/lib/navigation"; -// types -import { useTranslation } from "@pace/i18n"; -import { Button } from "@pace/propel/button"; -import { TOAST_TYPE, setToast } from "@pace/propel/toast"; -import type { IUser, IImporterService } from "@pace/types"; -// ui -import { Checkbox } from "@makeplane/propel/components/checkbox"; -import { CustomSearchSelect, EModalPosition, EModalWidth, ModalCore } from "@pace/ui"; -// hooks -import { useProject } from "@/hooks/store/use-project"; -import { useUser } from "@/hooks/store/user"; -import { useAppRouter } from "@/hooks/use-app-router"; -// services -import { ProjectExportService } from "@pace/services"; -type Props = { - isOpen: boolean; - handleClose: () => void; - data: IImporterService | null; - user: IUser | null; - provider: string | string[]; - mutateServices: () => void; -}; - -const projectExportService = new ProjectExportService(); - -export const Exporter = observer(function Exporter(props: Props) { - const { isOpen, handleClose, user, provider, mutateServices } = props; - // states - const [exportLoading, setExportLoading] = useState(false); - const [isSelectOpen, setIsSelectOpen] = useState(false); - // router - const router = useAppRouter(); - const { workspaceSlug } = useParams(); - // store hooks - const { workspaceProjectIds, getProjectById } = useProject(); - const { projectsWithCreatePermissions } = useUser(); - const { t } = useTranslation(); - - const wsProjectIdsWithCreatePermisisons = projectsWithCreatePermissions - ? intersection(workspaceProjectIds, Object.keys(projectsWithCreatePermissions)) - : []; - - const options = wsProjectIdsWithCreatePermisisons?.map((projectId) => { - const projectDetails = getProjectById(projectId); - - return { - value: projectDetails?.id, - query: `${projectDetails?.name} ${projectDetails?.identifier}`, - content: ( -
- {projectDetails?.identifier} - {projectDetails?.name} -
- ), - }; - }); - - const [value, setValue] = React.useState([]); - const [multiple, setMultiple] = React.useState(false); - const onChange = (val: any) => { - setValue(val); - }; - - async function ExportCSVToMail() { - setExportLoading(true); - if (workspaceSlug && user && typeof provider === "string") { - const payload = { - provider: provider, - project: value, - multiple: multiple, - }; - await projectExportService - .csvExport(workspaceSlug, payload) - .then(() => { - mutateServices(); - router.push(`/${workspaceSlug}/settings/exports`); - setExportLoading(false); - setToast({ - type: TOAST_TYPE.SUCCESS, - title: t("workspace_settings.settings.exports.modal.toasts.success.title"), - message: t("workspace_settings.settings.exports.modal.toasts.success.message", { - entity: provider === "csv" ? "CSV" : provider === "xlsx" ? "Excel" : provider === "json" ? "JSON" : "", - }), - }); - }) - .catch(() => { - setExportLoading(false); - setToast({ - type: TOAST_TYPE.ERROR, - title: t("error"), - message: t("workspace_settings.settings.exports.modal.toasts.error.message"), - }); - }); - } - } - - return ( - { - if (!isSelectOpen) handleClose(); - }} - position={EModalPosition.CENTER} - width={EModalWidth.XL} - > -
-
- -

- {t("workspace_settings.settings.exports.modal.title")}{" "} - {provider === "csv" ? "CSV" : provider === "xlsx" ? "Excel" : provider === "json" ? "JSON" : ""} -

-
-
-
- onChange(val)} - options={options} - input - label={ - value && value.length > 0 - ? value - .map((projectId) => { - const projectDetails = getProjectById(projectId); - - return projectDetails?.identifier; - }) - .join(", ") - : "All projects" - } - onOpen={() => setIsSelectOpen(true)} - onClose={() => setIsSelectOpen(false)} - optionsClassName="max-w-48 sm:max-w-[532px]" - placement="bottom-end" - multiple - /> -
- -
- - -
-
-
- ); -}); diff --git a/apps/web/core/components/exporter/single-export.tsx b/apps/web/core/components/exporter/single-export.tsx deleted file mode 100644 index a8ca0415..00000000 --- a/apps/web/core/components/exporter/single-export.tsx +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useState } from "react"; -// ui -import { Button } from "@pace/propel/button"; -import type { IExportData } from "@pace/types"; -// helpers -import { getDate, renderFormattedDate } from "@pace/utils"; -// types - -type Props = { - service: IExportData; - refreshing: boolean; -}; - -export function SingleExport({ service, refreshing }: Props) { - const provider = service.provider; - - const [isLoading] = useState(false); - - const checkExpiry = (inputDateString: string) => { - const currentDate = new Date(); - const expiryDate = getDate(inputDateString); - if (!expiryDate) return false; - expiryDate.setDate(expiryDate.getDate() + 7); - return expiryDate > currentDate; - }; - - return ( -
-
-

- - Export to{" "} - - {provider === "csv" ? "CSV" : provider === "xlsx" ? "Excel" : provider === "json" ? "JSON" : ""} - {" "} - - - {refreshing ? "Refreshing..." : service.status} - -

-
- {renderFormattedDate(service.created_at)}| - Exported by {service?.initiated_by_detail?.display_name} -
-
- {checkExpiry(service.created_at) ? ( - <> - {service.status == "completed" && ( - - )} - - ) : ( -
Expired
- )} -
- ); -} diff --git a/apps/web/core/components/icons/locked-component.tsx b/apps/web/core/components/icons/locked-component.tsx deleted file mode 100644 index 14f555c6..00000000 --- a/apps/web/core/components/icons/locked-component.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { LockOutline } from "@makeplane/propel/icons"; -import { Tooltip } from "@makeplane/propel/components/tooltip"; - -export function LockedComponent(props: { toolTipContent?: string }) { - const { toolTipContent } = props; - const lockedComponent = ( -
- - Locked -
- ); - - return ( - <> - {toolTipContent ? ( - - {lockedComponent} - - ) : ( - <>{lockedComponent} - )} - - ); -} diff --git a/apps/web/core/components/inbox/content/issue-root.tsx b/apps/web/core/components/inbox/content/issue-root.tsx index 013fcad6..2e4b55e8 100644 --- a/apps/web/core/components/inbox/content/issue-root.tsx +++ b/apps/web/core/components/inbox/content/issue-root.tsx @@ -87,7 +87,7 @@ export const InboxIssueMainContent = observer(function InboxIssueMainContent(pro message: "Work item deleted successfully", }); } catch (error) { - console.log("Error in deleting work item:", error); + console.error("Error in deleting work item:", error); setToast({ title: "Error!", type: TOAST_TYPE.ERROR, diff --git a/apps/web/core/components/inbox/modals/create-modal/issue-description.tsx b/apps/web/core/components/inbox/modals/create-modal/issue-description.tsx index 4b89cf99..bcfca3d9 100644 --- a/apps/web/core/components/inbox/modals/create-modal/issue-description.tsx +++ b/apps/web/core/components/inbox/modals/create-modal/issue-description.tsx @@ -102,7 +102,7 @@ export const InboxIssueDescription = observer(function InboxIssueDescription(pro onAssetUpload?.(asset_id); return asset_id; } catch (error) { - console.log("Error in uploading work item asset:", error); + console.error("Error in uploading work item asset:", error); throw new Error("Asset upload failed. Please try again later."); } }} diff --git a/apps/web/core/components/integration/github/select-repository.tsx b/apps/web/core/components/integration/github/select-repository.tsx deleted file mode 100644 index ee6dd392..00000000 --- a/apps/web/core/components/integration/github/select-repository.tsx +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React from "react"; -import { useParams } from "@/lib/navigation"; -import useSWRInfinite from "swr/infinite"; -import type { IWorkspaceIntegration } from "@pace/types"; -// services -// ui -import { CustomSearchSelect } from "@pace/ui"; -// helpers -import { truncateText } from "@pace/utils"; -import { ProjectService } from "@pace/services"; -// types - -type Props = { - integration: IWorkspaceIntegration; - value: any; - label: string | React.ReactNode; - onChange: (repo: any) => void; - characterLimit?: number; -}; - -const projectService = new ProjectService(); - -export function SelectRepository(props: Props) { - const { integration, value, label, onChange, characterLimit = 25 } = props; - // router - const { workspaceSlug } = useParams(); - - const getKey = (pageIndex: number) => { - if (!workspaceSlug || !integration) return; - - return `${process.env.VITE_API_BASE_URL}/api/workspaces/${workspaceSlug}/workspace-integrations/${ - integration.id - }/github-repositories/?page=${++pageIndex}`; - }; - - const fetchGithubRepos = async (url: string) => { - const data = await projectService.getGithubRepositories(url); - - return data; - }; - - const { data: paginatedData, size, setSize, isValidating } = useSWRInfinite(getKey, fetchGithubRepos); - - let userRepositories = (paginatedData ?? []).map((data) => data.repositories).flat(); - userRepositories = userRepositories.filter((data) => data?.id); - - const totalCount = paginatedData && paginatedData.length > 0 ? paginatedData[0].total_count : 0; - - const options = - userRepositories.map((repo) => ({ - value: repo.id, - query: repo.full_name, - content:

{truncateText(repo.full_name, characterLimit)}

, - })) ?? []; - - if (userRepositories.length < 1) return null; - - return ( - { - const repo = userRepositories.find((repo) => repo.id === val); - - onChange(repo); - }} - label={label} - footerOption={ - <> - {userRepositories && options.length < totalCount && ( - - )} - - } - optionsClassName="w-48" - /> - ); -} diff --git a/apps/web/core/components/integration/slack/select-channel.tsx b/apps/web/core/components/integration/slack/select-channel.tsx deleted file mode 100644 index 2a54d24a..00000000 --- a/apps/web/core/components/integration/slack/select-channel.tsx +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useState, useEffect } from "react"; -import { observer } from "mobx-react"; -import { useParams } from "@/lib/navigation"; -import useSWR, { mutate } from "swr"; -// types -import type { IWorkspaceIntegration, ISlackIntegration } from "@pace/types"; -// ui -import { Skeleton } from "@pace/propel/skeleton"; -// fetch-keys -import { SLACK_CHANNEL_INFO } from "@pace/constants"; -// hooks -import { useInstance } from "@/hooks/store/use-instance"; -import useIntegrationPopup from "@/hooks/use-integration-popup"; -// services -import { AppInstallationService } from "@pace/services"; - -type Props = { - integration: IWorkspaceIntegration; -}; - -const appInstallationService = new AppInstallationService(); - -export const SelectChannel = observer(function SelectChannel({ integration }: Props) { - // store hooks - const { config } = useInstance(); - // states - const [slackChannelAvailabilityToggle, setSlackChannelAvailabilityToggle] = useState(false); - const [slackChannel, setSlackChannel] = useState(null); - - const { workspaceSlug, projectId } = useParams(); - - // FIXME: - const { startAuth } = useIntegrationPopup({ - provider: "slackChannel", - stateParams: integration.id, - // github_app_name: instance?.config?.github_client_id || "", - slack_client_id: config?.slack_client_id || "", - }); - - const { data: projectIntegration } = useSWR( - workspaceSlug && projectId && integration.id ? SLACK_CHANNEL_INFO(workspaceSlug, projectId) : null, - () => - workspaceSlug && projectId && integration.id - ? appInstallationService.getSlackChannelDetail(workspaceSlug, projectId, integration.id) - : null - ); - - useEffect(() => { - if (projectId && projectIntegration && projectIntegration.length > 0) { - const projectSlackIntegrationCheck: ISlackIntegration | undefined = projectIntegration.find( - (_slack: ISlackIntegration) => _slack.project === projectId - ); - if (projectSlackIntegrationCheck) { - setSlackChannel(() => projectSlackIntegrationCheck); - setSlackChannelAvailabilityToggle(true); - } - } - }, [projectIntegration, projectId]); - - const handleDelete = async () => { - if (!workspaceSlug || !projectId) return; - if (projectIntegration.length === 0) return; - mutate(SLACK_CHANNEL_INFO(workspaceSlug?.toString(), projectId?.toString()), (prevData: any) => { - if (!prevData) return; - return prevData.id !== integration.id; - }).then(() => { - setSlackChannelAvailabilityToggle(false); - setSlackChannel(null); - }); - appInstallationService - .removeSlackChannel(workspaceSlug, projectId, integration.id, slackChannel?.id) - .catch((err) => console.error(err)); - }; - - const handleAuth = async () => { - await startAuth(); - }; - - return ( - <> - {projectIntegration ? ( - - ) : ( - - - - )} - - ); -}); diff --git a/apps/web/core/components/issues/issue-detail/issue-activity/helper.tsx b/apps/web/core/components/issues/issue-detail/issue-activity/helper.tsx index 83bdad4e..30e5df73 100644 --- a/apps/web/core/components/issues/issue-detail/issue-activity/helper.tsx +++ b/apps/web/core/components/issues/issue-detail/issue-activity/helper.tsx @@ -138,7 +138,7 @@ export const useWorkItemCommentOperations = ( }); return res; } catch (error) { - console.log("Error in uploading comment asset:", error); + console.error("Error in uploading comment asset:", error); throw new Error(t("issue.comments.upload.error")); } }, diff --git a/apps/web/core/components/issues/issue-detail/relation-select.tsx b/apps/web/core/components/issues/issue-detail/relation-select.tsx deleted file mode 100644 index 1e892ecb..00000000 --- a/apps/web/core/components/issues/issue-detail/relation-select.tsx +++ /dev/null @@ -1,173 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React from "react"; -import { observer } from "mobx-react"; -import Link from "@/lib/navigation/link"; - -import { CloseOutline, EditOutline } from "@makeplane/propel/icons"; -// Plane -import { TOAST_TYPE, setToast } from "@pace/propel/toast"; -import { Tooltip } from "@makeplane/propel/components/tooltip"; -import type { ISearchIssueResponse } from "@pace/types"; -import { cn, generateWorkItemLink } from "@pace/utils"; -// components -import { ExistingIssuesListModal } from "@/components/issues/existing-issues-list-modal"; -// hooks -import { useIssueDetail } from "@/hooks/store/use-issue-detail"; -import { useIssues } from "@/hooks/store/use-issues"; -import { useProject } from "@/hooks/store/use-project"; -import { usePlatformOS } from "@/hooks/use-platform-os"; -// Plane web imports -import { useTimeLineRelationOptions } from "@/components/relations"; -import type { TIssueRelationTypes } from "@pace/types"; -import type { TRelationObject } from "../issue-detail-widgets/relations"; - -type TIssueRelationSelect = { - className?: string; - workspaceSlug: string; - projectId: string; - issueId: string; - relationKey: TIssueRelationTypes; - disabled?: boolean; -}; - -export const IssueRelationSelect = observer(function IssueRelationSelect(props: TIssueRelationSelect) { - const { className = "", workspaceSlug, projectId, issueId, relationKey, disabled = false } = props; - // hooks - const { getProjectById } = useProject(); - const { - createRelation, - removeRelation, - relation: { getRelationByIssueIdRelationType }, - isRelationModalOpen, - toggleRelationModal, - } = useIssueDetail(); - const { issueMap } = useIssues(); - const { isMobile } = usePlatformOS(); - const relationIssueIds = getRelationByIssueIdRelationType(issueId, relationKey); - const ISSUE_RELATION_OPTIONS = useTimeLineRelationOptions(); - - const onSubmit = async (data: ISearchIssueResponse[]) => { - if (data.length === 0) { - setToast({ - type: TOAST_TYPE.ERROR, - title: "Error!", - message: "Please select at least one work item.", - }); - return; - } - - await createRelation( - workspaceSlug, - projectId, - issueId, - relationKey, - data.map((i) => i.id) - ); - - toggleRelationModal(null, null); - }; - - if (!relationIssueIds) return null; - - const isRelationKeyModalActive = - isRelationModalOpen?.relationType === relationKey && isRelationModalOpen?.issueId === issueId; - - const currRelationOption: TRelationObject | undefined = ISSUE_RELATION_OPTIONS[relationKey]; - - return ( - <> - toggleRelationModal(null, null)} - searchParams={{ issue_relation: true, issue_id: issueId }} - handleOnSubmit={onSubmit} - workspaceLevelToggle - /> - - - - ); -}); diff --git a/apps/web/core/components/issues/issue-detail/root.tsx b/apps/web/core/components/issues/issue-detail/root.tsx index aa7c33ab..27d29978 100644 --- a/apps/web/core/components/issues/issue-detail/root.tsx +++ b/apps/web/core/components/issues/issue-detail/root.tsx @@ -95,7 +95,7 @@ export const IssueDetailRoot = observer(function IssueDetailRoot(props: TIssueDe try { await updateIssue(workspaceSlug, projectId, issueId, data); } catch (error) { - console.log("Error in updating issue:", error); + console.error("Error in updating issue:", error); setToast({ title: t("common.error.label"), type: TOAST_TYPE.ERROR, @@ -113,7 +113,7 @@ export const IssueDetailRoot = observer(function IssueDetailRoot(props: TIssueDe message: t("entity.delete.success", { entity: t("issue.label") }), }); } catch (error) { - console.log("Error in deleting issue:", error); + console.error("Error in deleting issue:", error); setToast({ title: t("common.error.label"), type: TOAST_TYPE.ERROR, @@ -125,7 +125,7 @@ export const IssueDetailRoot = observer(function IssueDetailRoot(props: TIssueDe try { await archiveIssue(workspaceSlug, projectId, issueId); } catch (error) { - console.log("Error in archiving issue:", error); + console.error("Error in archiving issue:", error); } }, addCycleToIssue: async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => { @@ -166,7 +166,7 @@ export const IssueDetailRoot = observer(function IssueDetailRoot(props: TIssueDe }); await removeFromCyclePromise; } catch (error) { - console.log("Error in removing issue from cycle:", error); + console.error("Error in removing issue from cycle:", error); } }, removeIssueFromModule: async (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => { @@ -185,7 +185,7 @@ export const IssueDetailRoot = observer(function IssueDetailRoot(props: TIssueDe }); await removeFromModulePromise; } catch (error) { - console.log("Error in removing issue from module:", error); + console.error("Error in removing issue from module:", error); } }, changeModulesInIssue: async ( diff --git a/apps/web/core/components/issues/issue-modal/components/description-editor.tsx b/apps/web/core/components/issues/issue-modal/components/description-editor.tsx index 507b8af9..51646512 100644 --- a/apps/web/core/components/issues/issue-modal/components/description-editor.tsx +++ b/apps/web/core/components/issues/issue-modal/components/description-editor.tsx @@ -221,7 +221,7 @@ export const IssueDescriptionEditor = observer(function IssueDescriptionEditor(p onAssetUpload(asset_id); return asset_id; } catch (error) { - console.log("Error in uploading issue asset:", error); + console.error("Error in uploading issue asset:", error); throw new Error("Asset upload failed. Please try again later."); } }} diff --git a/apps/web/core/components/issues/layout-quick-actions.tsx b/apps/web/core/components/issues/layout-quick-actions.tsx deleted file mode 100644 index 588a7a7e..00000000 --- a/apps/web/core/components/issues/layout-quick-actions.tsx +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { observer } from "mobx-react"; -import { TOAST_TYPE, setToast } from "@pace/propel/toast"; -import type { TContextMenuItem } from "@pace/ui"; -import { CustomMenu } from "@pace/ui"; -import { copyUrlToClipboard, cn } from "@pace/utils"; -import { useLayoutMenuItems } from "@/components/common/quick-actions-helper"; -import { MoreHorizontalOutline } from "@makeplane/propel/icons"; -import { IconButton } from "@pace/propel/icon-button"; - -type Props = { - workspaceSlug: string; - projectId: string; - storeType: "PROJECT" | "EPIC"; -}; - -export const LayoutQuickActions = observer(function LayoutQuickActions(props: Props) { - const { workspaceSlug, projectId, storeType } = props; - - const layoutLink = `${workspaceSlug}/projects/${projectId}/${storeType === "EPIC" ? "epics" : "issues"}`; - - const handleCopyLink = () => - copyUrlToClipboard(layoutLink).then(() => { - setToast({ - type: TOAST_TYPE.SUCCESS, - title: "Link copied", - message: `${storeType === "EPIC" ? "Epics" : "Work items"} link copied to clipboard.`, - }); - }); - - const handleOpenInNewTab = () => window.open(`/${layoutLink}`, "_blank"); - - const menuResult = useLayoutMenuItems({ - workspaceSlug, - projectId, - storeType, - handleCopyLink, - handleOpenInNewTab, - }); - - const MENU_ITEMS: TContextMenuItem[] = Array.isArray(menuResult) ? menuResult : menuResult.items; - const additionalModals = Array.isArray(menuResult) ? null : menuResult.modals; - - return ( - <> - {additionalModals} - } - > - {MENU_ITEMS.map((item) => { - if (item.shouldRender === false) return null; - return ( - - {item.icon && } - {item.title} - - ); - })} - - - ); -}); diff --git a/apps/web/core/components/onboarding/create-or-join-workspaces.tsx b/apps/web/core/components/onboarding/create-or-join-workspaces.tsx deleted file mode 100644 index 99ef35d8..00000000 --- a/apps/web/core/components/onboarding/create-or-join-workspaces.tsx +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useEffect, useState } from "react"; -import { observer } from "mobx-react"; -import { AlertOctagonOutline } from "@makeplane/propel/icons"; -// pace imports -import type { IWorkspaceMemberInvitation, TOnboardingSteps } from "@pace/types"; -// components -import { LogoSpinner } from "@/components/common/logo-spinner"; -// hooks -import { useUser } from "@/hooks/store/user"; -import { useInstance } from "@/hooks/store/use-instance"; -// local imports -import { CreateWorkspace } from "./create-workspace"; -import { Invitations } from "./invitations"; -import { SwitchAccountDropdown } from "./switch-account-dropdown"; - -export enum ECreateOrJoinWorkspaceViews { - WORKSPACE_CREATE = "WORKSPACE_CREATE", - WORKSPACE_JOIN = "WORKSPACE_JOIN", -} - -type Props = { - invitations: IWorkspaceMemberInvitation[]; - totalSteps: number; - stepChange: (steps: Partial) => Promise; - finishOnboarding: () => Promise; -}; - -export const CreateOrJoinWorkspaces = observer(function CreateOrJoinWorkspaces(props: Props) { - const { invitations, stepChange, finishOnboarding } = props; - // states - const [currentView, setCurrentView] = useState(null); - // store hooks - const { data: user } = useUser(); - const { config } = useInstance(); - // derived values - const isWorkspaceCreationDisabled = config?.is_workspace_creation_disabled ?? false; - - useEffect(() => { - if (invitations.length > 0) { - setCurrentView(ECreateOrJoinWorkspaceViews.WORKSPACE_JOIN); - } else { - setCurrentView(ECreateOrJoinWorkspaceViews.WORKSPACE_CREATE); - } - }, [invitations]); - - const handleNextStep = async () => { - if (!user) return; - - await finishOnboarding(); - }; - - return ( -
-
-
- {currentView === ECreateOrJoinWorkspaceViews.WORKSPACE_JOIN ? ( - setCurrentView(ECreateOrJoinWorkspaceViews.WORKSPACE_CREATE)} - /> - ) : currentView === ECreateOrJoinWorkspaceViews.WORKSPACE_CREATE ? ( - !isWorkspaceCreationDisabled ? ( - setCurrentView(ECreateOrJoinWorkspaceViews.WORKSPACE_JOIN)} - /> - ) : ( -
-
- - - You don't seem to have any invites to a workspace and your instance admin has restricted - creation of new workspaces. Please ask a workspace owner or admin to invite you to a workspace first - and come back to this screen to join. - -
-
- ) - ) : ( -
- -
- )} -
-
- -
- ); -}); diff --git a/apps/web/core/components/onboarding/invite-members.tsx b/apps/web/core/components/onboarding/invite-members.tsx deleted file mode 100644 index dd800e0e..00000000 --- a/apps/web/core/components/onboarding/invite-members.tsx +++ /dev/null @@ -1,409 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React, { useEffect, useState } from "react"; -import { observer } from "mobx-react"; -import type { - Control, - FieldArrayWithId, - UseFieldArrayRemove, - UseFormGetValues, - UseFormSetValue, - UseFormWatch, -} from "react-hook-form"; -import { Controller, useFieldArray, useForm } from "react-hook-form"; -// icons -import { usePopper } from "react-popper"; -import { AddOutline, ChevronDownOutline, CloseCircleOutline, TickOutline } from "@makeplane/propel/icons"; -import { Listbox } from "@headlessui/react"; -// pace imports -import { Field } from "@makeplane/propel/components/field"; -import { Input, InputGroup } from "@makeplane/propel/components/input"; -import type { EUserPermissions } from "@pace/constants"; -import { ROLE, ROLE_DETAILS } from "@pace/constants"; -import { useTranslation } from "@pace/i18n"; -// types -import { Button } from "@pace/propel/button"; -import { TOAST_TYPE, setToast } from "@pace/propel/toast"; -import type { IUser, IWorkspace } from "@pace/types"; -// ui -import { Spinner } from "@pace/propel/spinners"; -// services -import { WorkspaceService } from "@pace/services"; -// components -import { SwitchAccountDropdown } from "./switch-account-dropdown"; - -type Props = { - finishOnboarding: () => Promise; - totalSteps: number; - user: IUser | undefined; - workspace: IWorkspace | undefined; -}; - -type EmailRole = { - email: string; - role: EUserPermissions; - role_active: boolean; -}; - -type FormValues = { - emails: EmailRole[]; -}; - -type InviteMemberFormProps = { - index: number; - remove: UseFieldArrayRemove; - control: Control; - setValue: UseFormSetValue; - getValues: UseFormGetValues; - watch: UseFormWatch; - field: FieldArrayWithId; - fields: FieldArrayWithId[]; - errors: any; - isInvitationDisabled: boolean; - setIsInvitationDisabled: (value: boolean) => void; -}; - -// services -const workspaceService = new WorkspaceService(); -const emailRegex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i; - -const placeholderEmails = [ - "charlie.taylor@frstflt.com", - "octave.chanute@frstflt.com", - "george.spratt@frstflt.com", - "frank.coffyn@frstflt.com", - "amos.root@frstflt.com", - "edward.deeds@frstflt.com", - "charles.m.manly@frstflt.com", - "glenn.curtiss@frstflt.com", - "thomas.selfridge@frstflt.com", - "albert.zahm@frstflt.com", -]; -const InviteMemberInput = observer(function InviteMemberInput(props: InviteMemberFormProps) { - const { - control, - index, - fields, - remove, - errors, - isInvitationDisabled, - setIsInvitationDisabled, - setValue, - getValues, - watch, - } = props; - - const [referenceElement, setReferenceElement] = useState(null); - const [popperElement, setPopperElement] = useState(null); - - const { t } = useTranslation(); - - const email = watch(`emails.${index}.email`); - - const emailOnChange = (event: React.ChangeEvent) => { - if (event.target.value === "") { - const validEmail = fields.map((_, i) => emailRegex.test(getValues(`emails.${i}.email`))).includes(true); - if (validEmail) { - setIsInvitationDisabled(false); - } else { - setIsInvitationDisabled(true); - } - - if (getValues(`emails.${index}.role_active`)) { - setValue(`emails.${index}.role_active`, false); - } - } else { - if (!getValues(`emails.${index}.role_active`)) { - setValue(`emails.${index}.role_active`, true); - } - if (isInvitationDisabled && emailRegex.test(event.target.value)) { - setIsInvitationDisabled(false); - } else if (!isInvitationDisabled && !emailRegex.test(event.target.value)) { - setIsInvitationDisabled(true); - } - } - }; - - const { styles, attributes } = usePopper(referenceElement, popperElement, { - placement: "bottom-end", - modifiers: [ - { - name: "preventOverflow", - options: { - padding: 12, - }, - }, - ], - }); - - return ( -
-
-
- ( - - - { - emailOnChange(event); - onChange(event); - }} - ref={ref} - placeholder={placeholderEmails[index % placeholderEmails.length]} - autoComplete="off" - /> - - - )} - /> -
-
- ( - { - onChange(val); - setValue(`emails.${index}.role_active`, true); - }} - className="w-full flex-shrink-0 text-left" - > - - - {ROLE[value]} - - - - - - -
- {Object.entries(ROLE_DETAILS).map(([key, value]) => ( - - `cursor-pointer truncate rounded-sm px-1 py-1.5 select-none ${ - active || selected ? "bg-onboarding-background-400/40" : "" - } ${selected ? "text-primary" : "text-secondary"}` - } - > - {({ selected }) => ( -
-
-
{t(value.i18n_title)}
-
{t(value.i18n_description)}
-
- {selected && } -
- )} -
- ))} -
-
-
- )} - /> -
- {fields.length > 1 && ( - - )} -
- {email && !emailRegex.test(email) && ( -
- 🤥{" "} - That doesn{"'"}t look like an email address. -
- )} -
- ); -}); - -export function InviteMembers(props: Props) { - const { finishOnboarding, workspace } = props; - - const [isInvitationDisabled, setIsInvitationDisabled] = useState(true); - - const { - control, - watch, - getValues, - setValue, - handleSubmit, - formState: { isSubmitting, errors, isValid }, - } = useForm(); - - const { fields, append, remove } = useFieldArray({ - control, - name: "emails", - }); - - const nextStep = async () => { - await finishOnboarding(); - }; - - const onSubmit = async (formData: FormValues) => { - if (!workspace) return; - - let payload = { ...formData }; - payload = { emails: payload.emails.filter((email) => email.email !== "") }; - - await workspaceService - .inviteWorkspace(workspace.slug, { - emails: payload.emails.map((email) => ({ - email: email.email, - role: email.role, - })), - }) - .then(async () => { - setToast({ - type: TOAST_TYPE.SUCCESS, - title: "Success!", - message: "Invitations sent successfully.", - }); - await nextStep(); - }) - .catch((err) => { - setToast({ - type: TOAST_TYPE.ERROR, - title: "Error!", - message: err?.error, - }); - }); - }; - - const appendField = () => { - append({ email: "", role: 15, role_active: false }); - }; - - useEffect(() => { - if (fields.length === 0) { - append( - [ - { email: "", role: 15, role_active: false }, - { email: "", role: 15, role_active: false }, - { email: "", role: 15, role_active: false }, - ], - { - focusIndex: 0, - } - ); - } - }, [fields, append]); - - return ( -
-
-
-
-

Invite your teammates

-

- Work in plane happens best with your team. Invite them now to use Plane to its potential. -

-
-
{ - if (e.code === "Enter") e.preventDefault(); - }} - > -
-
-
Email
-
Role
-
-
- {fields.map((field, index) => ( - setIsInvitationDisabled(value)} - control={control} - errors={errors} - field={field} - fields={fields} - index={index} - remove={remove} - key={field.id} - /> - ))} -
- -
-
- - -
-
-
-
- -
- ); -} diff --git a/apps/web/core/components/onboarding/profile-setup.tsx b/apps/web/core/components/onboarding/profile-setup.tsx deleted file mode 100644 index cc03c04f..00000000 --- a/apps/web/core/components/onboarding/profile-setup.tsx +++ /dev/null @@ -1,563 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useMemo, useState } from "react"; -import { observer } from "mobx-react"; -import { Controller, useForm } from "react-hook-form"; -import { HideOutline, ShowOutline } from "@makeplane/propel/icons"; -import { Field } from "@makeplane/propel/components/field"; -import { Input, InputGroup } from "@makeplane/propel/components/input"; -import { E_PASSWORD_STRENGTH } from "@pace/constants"; -// types -import { useTranslation } from "@pace/i18n"; -import { Button } from "@pace/propel/button"; -import { TOAST_TYPE, setToast } from "@pace/propel/toast"; -import type { IUser, TUserProfile, TOnboardingSteps } from "@pace/types"; -// ui -import { Spinner } from "@pace/propel/spinners"; -import { PasswordStrengthIndicator } from "@pace/ui"; -// components -import { cn, getFileURL, getPasswordStrength, validatePersonName } from "@pace/utils"; -import { UserImageUploadModal } from "@/components/profile/user-image-upload-modal"; -// hooks -import { useUser, useUserProfile } from "@/hooks/store/user"; -// services -import { AuthService } from "@pace/services"; - -type TProfileSetupFormValues = { - first_name: string; - last_name: string; - avatar_url?: string | null; - password?: string; - confirm_password?: string; - role?: string; - use_case?: string[]; -}; - -const defaultValues: Partial = { - first_name: "", - last_name: "", - avatar_url: "", - password: undefined, - confirm_password: undefined, - role: undefined, - use_case: [], -}; - -type Props = { - user?: IUser; - totalSteps: number; - stepChange: (steps: Partial) => Promise; - finishOnboarding: () => Promise; -}; - -enum EProfileSetupSteps { - ALL = "ALL", - USER_DETAILS = "USER_DETAILS", - USER_PERSONALIZATION = "USER_PERSONALIZATION", -} - -const USER_ROLE = ["Individual contributor", "Senior Leader", "Manager", "Executive", "Freelancer", "Student"]; - -const USER_DOMAIN = [ - "Engineering", - "Product", - "Marketing", - "Sales", - "Operations", - "Legal", - "Finance", - "Human Resources", - "Project", - "Other", -]; - -const authService = new AuthService(); - -export const ProfileSetup = observer(function ProfileSetup(props: Props) { - const { user, totalSteps, stepChange, finishOnboarding } = props; - // states - const [profileSetupStep, setProfileSetupStep] = useState( - user?.is_password_autoset ? EProfileSetupSteps.USER_DETAILS : EProfileSetupSteps.ALL - ); - const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false); - const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false); - const [showPassword, setShowPassword] = useState({ - password: false, - retypePassword: false, - }); - // pace hooks - const { t } = useTranslation(); - // store hooks - const { updateCurrentUser } = useUser(); - const { updateUserProfile } = useUserProfile(); - // form info - const { - getValues, - handleSubmit, - control, - watch, - setValue, - formState: { errors, isSubmitting, isValid }, - } = useForm({ - defaultValues: { - ...defaultValues, - first_name: user?.first_name, - last_name: user?.last_name, - avatar_url: user?.avatar_url, - }, - mode: "onChange", - }); - // derived values - const userAvatar = watch("avatar_url"); - - const handleShowPassword = (key: keyof typeof showPassword) => - setShowPassword((prev) => ({ ...prev, [key]: !prev[key] })); - - const handleSetPassword = async (password: string) => { - const token = await authService.requestCSRFToken().then((data) => data?.csrf_token); - await authService.setPassword(token, { password }); - }; - - const handleSubmitProfileSetup = async (formData: TProfileSetupFormValues) => { - const userDetailsPayload: Partial = { - first_name: formData.first_name, - last_name: formData.last_name, - avatar_url: formData.avatar_url ?? undefined, - }; - const profileUpdatePayload: Partial = { - use_case: formData.use_case && formData.use_case.length > 0 ? formData.use_case.join(". ") : undefined, - role: formData.role, - }; - try { - await Promise.all([ - updateCurrentUser(userDetailsPayload), - updateUserProfile(profileUpdatePayload), - totalSteps > 2 && stepChange({ profile_complete: true }), - ]); - setToast({ - type: TOAST_TYPE.SUCCESS, - title: "Success", - message: "Profile setup completed!", - }); - // For Invited Users, they will skip all other steps and finish onboarding. - if (totalSteps <= 2) { - finishOnboarding(); - } - } catch { - setToast({ - type: TOAST_TYPE.ERROR, - title: "Error", - message: "Profile setup failed. Please try again!", - }); - } - }; - - const handleSubmitUserDetail = async (formData: TProfileSetupFormValues) => { - const userDetailsPayload: Partial = { - first_name: formData.first_name, - last_name: formData.last_name, - avatar_url: formData.avatar_url ?? undefined, - }; - try { - await Promise.all([ - updateCurrentUser(userDetailsPayload), - formData.password && handleSetPassword(formData.password), - ]).then(() => { - if (formData.password) { - } else { - setProfileSetupStep(EProfileSetupSteps.USER_PERSONALIZATION); - } - }); - } catch { - setToast({ - type: TOAST_TYPE.ERROR, - title: "Error", - message: "User details update failed. Please try again!", - }); - } - }; - - const handleSubmitUserPersonalization = async (formData: TProfileSetupFormValues) => { - const profileUpdatePayload: Partial = { - use_case: formData.use_case && formData.use_case.length > 0 ? formData.use_case.join(". ") : undefined, - role: formData.role, - }; - try { - await Promise.all([ - updateUserProfile(profileUpdatePayload), - totalSteps > 2 && stepChange({ profile_complete: true }), - ]); - setToast({ - type: TOAST_TYPE.SUCCESS, - title: "Success", - message: "Profile setup completed!", - }); - // For Invited Users, they will skip all other steps and finish onboarding. - if (totalSteps <= 2) { - finishOnboarding(); - } - } catch { - setToast({ - type: TOAST_TYPE.ERROR, - title: "Error", - message: "Profile setup failed. Please try again!", - }); - } - }; - - const onSubmit = async (formData: TProfileSetupFormValues) => { - if (!user) return; - if (profileSetupStep === EProfileSetupSteps.ALL) await handleSubmitProfileSetup(formData); - if (profileSetupStep === EProfileSetupSteps.USER_DETAILS) await handleSubmitUserDetail(formData); - if (profileSetupStep === EProfileSetupSteps.USER_PERSONALIZATION) await handleSubmitUserPersonalization(formData); - }; - - const handleDelete = (url: string | null | undefined) => { - if (!url) return; - setValue("avatar_url", ""); - }; - - // derived values - const isPasswordAlreadySetup = !user?.is_password_autoset; - const currentPassword = watch("password") || undefined; - const currentConfirmPassword = watch("confirm_password") || undefined; - - const isValidPassword = useMemo(() => { - if (currentPassword) { - if ( - currentPassword === currentConfirmPassword && - getPasswordStrength(currentPassword) === E_PASSWORD_STRENGTH.STRENGTH_VALID - ) { - return true; - } else { - return false; - } - } else { - return true; - } - }, [currentPassword, currentConfirmPassword]); - - // Check for all available fields validation and if password field is available, then checks for password validation (strength + confirmation). - // Also handles the condition for optional password i.e if password field is optional it only checks for above validation if it's not empty. - const isButtonDisabled = - !isSubmitting && isValid ? (isPasswordAlreadySetup ? false : isValidPassword ? false : true) : true; - - return ( -
-
-
- {profileSetupStep !== EProfileSetupSteps.USER_PERSONALIZATION && ( - <> - ( - setIsImageUploadModalOpen(false)} - handleRemove={async () => handleDelete(getValues("avatar_url"))} - onSuccess={(url) => { - onChange(url); - setIsImageUploadModalOpen(false); - }} - value={value && value.trim() !== "" ? value : null} - /> - )} - /> -
- -
-
-
- - ( - - - - - - )} - /> - {errors.first_name && ( - {errors.first_name.message} - )} -
-
- - ( - - - - - - )} - /> - {errors.last_name && {errors.last_name.message}} -
-
- - {/* setting up password for the first time */} - {!isPasswordAlreadySetup && ( - <> -
- - ( - - - setIsPasswordInputFocused(true)} - onBlur={() => setIsPasswordInputFocused(false)} - autoComplete="new-password" - aria-label="New password..." - /> - - - - )} - /> - -
-
- - - watch("password") ? (value === watch("password") ? true : "Passwords don't match") : true, - }} - render={({ field: { value, onChange, ref } }) => ( - - - - - - - )} - /> - {errors.confirm_password && ( - {errors.confirm_password.message} - )} -
- - )} - - )} - - {/* user role once the password is set */} - {profileSetupStep !== EProfileSetupSteps.USER_DETAILS && ( - <> -
- - ( -
- {USER_ROLE.map((userRole) => ( -
onChange(userRole)} - > - {userRole} -
- ))} -
- )} - /> - {errors.role && {errors.role.message}} -
-
- - (value && value.length > 0) || "Please select at least one option", - }} - render={({ field: { value, onChange } }) => ( -
- {USER_DOMAIN.map((userDomain) => { - const isSelected = value?.includes(userDomain) || false; - return ( -
{ - const currentValue = value || []; - if (isSelected) { - onChange(currentValue.filter((item) => item !== userDomain)); - } else { - onChange([...currentValue, userDomain]); - } - }} - > - {userDomain} -
- ); - })} -
- )} - /> - {errors.use_case && {errors.use_case.message}} -
- - )} - - -
-
- ); -}); diff --git a/apps/web/core/components/onboarding/step-indicator.tsx b/apps/web/core/components/onboarding/step-indicator.tsx deleted file mode 100644 index 218d8977..00000000 --- a/apps/web/core/components/onboarding/step-indicator.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React from "react"; -// helpers -import { cn } from "@pace/utils"; - -interface OnboardingStepIndicatorProps { - currentStep: number; - totalSteps: number; -} - -export function OnboardingStepIndicator({ currentStep, totalSteps }: OnboardingStepIndicatorProps) { - const renderIndicators = () => { - const indicators = []; - - for (let i = 0; i < totalSteps; i++) { - const isCompleted = i < currentStep; - const isActive = i === currentStep - 1; - const isFirstStep = i === 0; - const isLastStep = i === totalSteps - 1; - - indicators.push( -
- ); - } - - return indicators; - }; - - return ( -
-
- {currentStep} of {totalSteps} steps -
-
{renderIndicators()}
-
- ); -} diff --git a/apps/web/core/components/power-k/ui/pages/work-item-selection-page.tsx b/apps/web/core/components/power-k/ui/pages/work-item-selection-page.tsx deleted file mode 100644 index 9d5688d4..00000000 --- a/apps/web/core/components/power-k/ui/pages/work-item-selection-page.tsx +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useState, useEffect } from "react"; -// pace imports -// import { useTranslation } from "@pace/i18n"; -import type { TIssueEntityData, TIssueSearchResponse, TActivityEntityData } from "@pace/types"; -// import { generateWorkItemLink } from "@pace/utils"; -// components -// import { CommandPaletteEntityList } from "@/components/command-palette"; -// import { SimpleEmptyState } from "@/components/empty-state/simple-empty-state-root"; -// hooks -// import { useCommandPalette } from "@/hooks/store/use-command-palette"; -// import { usePowerK } from "@/hooks/store/use-power-k"; -// import { useAppRouter } from "@/hooks/use-app-router"; -// pace web imports -// import { IssueIdentifier } from "@/plane-web/components/issues/issue-details/issue-identifier"; -import { WorkspaceService } from "@pace/services"; - -const workspaceService = new WorkspaceService(); - -type Props = { - workspaceSlug: string | undefined; - projectId: string | undefined; - searchTerm: string; - debouncedSearchTerm: string; - isLoading: boolean; - isSearching: boolean; - resolvedPath: string; - isWorkspaceLevel?: boolean; -}; - -export function WorkItemSelectionPage(props: Props) { - const { workspaceSlug, projectId, debouncedSearchTerm, isWorkspaceLevel = false } = props; - // router - // const router = useAppRouter(); - // pace hooks - // const { t } = useTranslation(); - // store hooks - // const { togglePowerKModal } = usePowerK(); - // states - const [_recentIssues, setRecentIssues] = useState([]); - const [_issueResults, setIssueResults] = useState([]); - - // Load recent issues when component mounts - useEffect(() => { - if (!workspaceSlug) return; - - workspaceService - .fetchWorkspaceRecents(workspaceSlug.toString(), "issue") - .then((res) => - setRecentIssues(res.map((r: TActivityEntityData) => r.entity_data as TIssueEntityData).slice(0, 10)) - ) - .catch(() => setRecentIssues([])); - }, [workspaceSlug]); - - // Search issues based on search term - useEffect(() => { - if (!workspaceSlug || !debouncedSearchTerm) { - setIssueResults([]); - return; - } - - workspaceService - .searchEntity(workspaceSlug.toString(), { - count: 10, - query: debouncedSearchTerm, - query_type: ["issue"], - ...(!isWorkspaceLevel && projectId ? { project_id: projectId.toString() } : {}), - }) - // oxlint-disable-next-line promise/always-return - .then((res) => { - setIssueResults(res.issue || []); - }) - .catch(() => setIssueResults([])); - }, [debouncedSearchTerm, workspaceSlug, projectId, isWorkspaceLevel]); - - if (!workspaceSlug) return null; - - return ( - <> - {/* {searchTerm === "" ? ( - recentIssues.length > 0 ? ( - issue.id} - getLabel={(issue) => `${issue.project_identifier}-${issue.sequence_id} ${issue.name}`} - renderItem={(issue) => ( -
- {issue.project_id && ( - - )} - {issue.name} -
- )} - onSelect={(issue) => { - if (!issue.project_id) return; - togglePowerKModal(false); - router.push( - generateWorkItemLink({ - workspaceSlug: workspaceSlug.toString(), - projectId: issue.project_id, - issueId: issue.id, - projectIdentifier: issue.project_identifier, - sequenceId: issue.sequence_id, - isEpic: issue.is_epic, - }) - ); - }} - emptyText="Search for issue id or issue title" - /> - ) : ( -
Search for issue id or issue title
- ) - ) : issueResults.length > 0 ? ( - issue.id} - getLabel={(issue) => `${issue.project__identifier}-${issue.sequence_id} ${issue.name}`} - renderItem={(issue) => ( -
- {issue.project_id && issue.project__identifier && issue.sequence_id && ( - - )} - {issue.name} -
- )} - onSelect={(issue) => { - if (!issue.project_id) return; - togglePowerKModal(false); - router.push( - generateWorkItemLink({ - workspaceSlug: workspaceSlug.toString(), - projectId: issue.project_id, - issueId: issue.id, - projectIdentifier: issue.project__identifier, - sequenceId: issue.sequence_id, - }) - ); - }} - emptyText={t("command_k.empty_state.search.title") as string} - /> - ) : ( - !isLoading && - !isSearching && ( -
- -
- ) - )} */} - - ); -} diff --git a/apps/web/core/components/profile/profile-setting-content-wrapper.tsx b/apps/web/core/components/profile/profile-setting-content-wrapper.tsx deleted file mode 100644 index dd206546..00000000 --- a/apps/web/core/components/profile/profile-setting-content-wrapper.tsx +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { cn } from "@pace/utils"; -import { SidebarHamburgerToggle } from "@/components/core/sidebar/sidebar-menu-hamburger-toggle"; - -type Props = { - children: React.ReactNode; - className?: string; -}; - -export function ProfileSettingContentWrapper(props: Props) { - const { children, className = "" } = props; - return ( -
-
- -
- -
- {children} -
-
- ); -} diff --git a/apps/web/core/components/profile/user-image-upload-modal.tsx b/apps/web/core/components/profile/user-image-upload-modal.tsx index 62176f60..d8a8cbff 100644 --- a/apps/web/core/components/profile/user-image-upload-modal.tsx +++ b/apps/web/core/components/profile/user-image-upload-modal.tsx @@ -87,7 +87,7 @@ export const UserImageUploadModal = observer(function UserImageUploadModal(props } await handleRemove(); } catch (error) { - console.log("Error in uploading user asset:", error); + console.error("Error in uploading user asset:", error); } finally { setIsRemoving(false); } diff --git a/apps/web/core/components/project-states/create-update/form.tsx b/apps/web/core/components/project-states/create-update/form.tsx index 2db5d93b..f59cbe44 100644 --- a/apps/web/core/components/project-states/create-update/form.tsx +++ b/apps/web/core/components/project-states/create-update/form.tsx @@ -60,7 +60,7 @@ export function StateForm(props: TStateForm) { try { await onSubmit(formData); } catch (error) { - console.log("error", error); + console.error("error", error); } }; diff --git a/apps/web/core/components/project/integration-card.tsx b/apps/web/core/components/project/integration-card.tsx deleted file mode 100644 index e434b3f7..00000000 --- a/apps/web/core/components/project/integration-card.tsx +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useParams } from "@/lib/navigation"; -import useSWR, { mutate } from "swr"; -import { TOAST_TYPE, setToast } from "@pace/propel/toast"; -import type { IWorkspaceIntegration } from "@pace/types"; -// assets -import GithubLogo from "@/assets/logos/github-square.png?url"; -import SlackLogo from "@/assets/services/slack.png?url"; -// components -import { SelectChannel } from "@/components/integration/slack/select-channel"; -import { SelectRepository } from "@/components/integration/github/select-repository"; -// constants -import { PROJECT_GITHUB_REPOSITORY } from "@pace/constants"; -// services -import { ProjectService } from "@pace/services"; - -type Props = { - integration: IWorkspaceIntegration; -}; - -const integrationDetails: { [key: string]: any } = { - github: { - logo: GithubLogo, - description: "Select GitHub repository to enable sync.", - }, - slack: { - logo: SlackLogo, - description: "Get regular updates and control which notification you want to receive.", - }, -}; - -// services -const projectService = new ProjectService(); - -export function IntegrationCard({ integration }: Props) { - const { workspaceSlug, projectId } = useParams(); - - const { data: syncedGithubRepository } = useSWR(projectId ? PROJECT_GITHUB_REPOSITORY(projectId) : null, () => - workspaceSlug && projectId && integration - ? projectService.getProjectGithubRepository(workspaceSlug, projectId, integration.id) - : null - ); - - const handleChange = (repo: any) => { - if (!workspaceSlug || !projectId || !integration) return; - - const { - html_url, - owner: { login }, - id, - name, - } = repo; - - projectService - .syncGithubRepository(workspaceSlug, projectId, integration.id, { - name, - owner: login, - repository_id: id, - url: html_url, - }) - .then(() => { - mutate(PROJECT_GITHUB_REPOSITORY(projectId)); - - setToast({ - type: TOAST_TYPE.SUCCESS, - title: "Success!", - message: `${login}/${name} repository synced with the project successfully.`, - }); - }) - .catch((err) => { - console.error(err); - setToast({ - type: TOAST_TYPE.ERROR, - title: "Error!", - message: "Repository could not be synced with the project. Please try again.", - }); - }); - }; - - return ( - <> - {integration && ( -
-
-
- {`${integration.integration_detail.title} -
-
-

{integration.integration_detail.title}

-

- {integrationDetails[integration.integration_detail.provider].description} -

-
-
- {integration.integration_detail.provider === "github" && ( - 0 - ? `${syncedGithubRepository[0].repo_detail.owner}/${syncedGithubRepository[0].repo_detail.name}` - : null - } - label={ - syncedGithubRepository && syncedGithubRepository.length > 0 - ? `${syncedGithubRepository[0].repo_detail.owner}/${syncedGithubRepository[0].repo_detail.name}` - : "Select Repository" - } - onChange={handleChange} - /> - )} - {integration.integration_detail.provider === "slack" && } -
- )} - - ); -} diff --git a/apps/web/core/components/project/multi-select-modal.tsx b/apps/web/core/components/project/multi-select-modal.tsx deleted file mode 100644 index 80b6b673..00000000 --- a/apps/web/core/components/project/multi-select-modal.tsx +++ /dev/null @@ -1,198 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React, { useEffect, useMemo, useRef, useState } from "react"; -import { xor } from "lodash-es"; -import { observer } from "mobx-react"; -import { useTheme } from "next-themes"; -import { Combobox } from "@headlessui/react"; -// pace ui -import { useTranslation } from "@pace/i18n"; -import { Button } from "@pace/propel/button"; -import { Logo } from "@pace/propel/emoji-icon-picker"; -import { CloseOutline, SearchOutline } from "@makeplane/propel/icons"; -import { Checkbox } from "@makeplane/propel/components/checkbox"; -import { EModalPosition, EModalWidth, ModalCore } from "@pace/ui"; -import { cn } from "@pace/utils"; -// assets -import darkProjectAsset from "@/assets/empty-state/search/project-dark.webp?url"; -import lightProjectAsset from "@/assets/empty-state/search/project-light.webp?url"; -// components -import { SimpleEmptyState } from "@/components/empty-state/simple-empty-state-root"; -// hooks -import { useProject } from "@/hooks/store/use-project"; - -type Props = { - isOpen: boolean; - onClose: () => void; - selectedProjectIds: string[]; - projectIds: string[]; - onSubmit: (projectIds: string[]) => Promise; -}; - -export const ProjectMultiSelectModal = observer(function ProjectMultiSelectModal(props: Props) { - const { isOpen, onClose, selectedProjectIds: selectedProjectIdsProp, projectIds, onSubmit } = props; - // states - const [searchTerm, setSearchTerm] = useState(""); - const [selectedProjectIds, setSelectedProjectIds] = useState([]); - const [isSubmitting, setIsSubmitting] = useState(false); - // refs - const moveButtonRef = useRef(null); - // theme hook - const { resolvedTheme } = useTheme(); - // pace hooks - const { t } = useTranslation(); - // store hooks - const { getProjectById } = useProject(); - // derived values - const projectDetailsMap = useMemo( - () => new Map(projectIds.map((id) => [id, getProjectById(id)])), - [projectIds, getProjectById] - ); - const areSelectedProjectsChanged = xor(selectedProjectIds, selectedProjectIdsProp).length > 0; - const filteredProjectIds = projectIds.filter((id) => { - const project = projectDetailsMap.get(id); - const projectQuery = `${project?.identifier} ${project?.name}`.toLowerCase(); - return projectQuery.includes(searchTerm.toLowerCase()); - }); - const filteredProjectResolvedPath = resolvedTheme === "light" ? lightProjectAsset : darkProjectAsset; - - useEffect(() => { - if (isOpen) setSelectedProjectIds(selectedProjectIdsProp); - }, [isOpen, selectedProjectIdsProp]); - - const handleClose = () => { - onClose(); - setTimeout(() => { - setSearchTerm(""); - setSelectedProjectIds([]); - }, 300); - }; - - const handleSubmit = async () => { - setIsSubmitting(true); - await onSubmit(selectedProjectIds); - setIsSubmitting(false); - handleClose(); - }; - - const handleSelectedProjectChange = (val: string[]) => { - setSelectedProjectIds(val); - setSearchTerm(""); - moveButtonRef.current?.focus(); - }; - - if (!isOpen) return null; - - return ( - - -
-
- {selectedProjectIds.length > 0 && ( -
- {selectedProjectIds.map((projectId) => { - const projectDetails = projectDetailsMap.get(projectId); - if (!projectDetails) return null; - return ( -
{ - handleSelectedProjectChange(selectedProjectIds.filter((id) => id !== projectDetails.id)); - }} - > - -

- {projectDetails.identifier} -

- -
- ); - })} -
- )} - - {filteredProjectIds.length === 0 ? ( -
- -
- ) : ( -
    0, - })} - > - {filteredProjectIds.map((projectId) => { - const projectDetails = projectDetailsMap.get(projectId); - if (!projectDetails) return null; - const isProjectSelected = selectedProjectIds.includes(projectDetails.id); - return ( - - cn( - "flex w-full cursor-pointer items-center justify-between gap-2 truncate rounded-md p-2 text-secondary transition-colors select-none", - { - "bg-layer-1": active, - "text-primary": isProjectSelected, - } - ) - } - > -
    - - - - - - - {projectDetails.identifier} -

    {projectDetails.name}

    -
    -
    - ); - })} -
- )} -
-
-
- - -
-
- ); -}); diff --git a/apps/web/core/components/project/settings/member-columns.tsx b/apps/web/core/components/project/settings/member-columns.tsx index 05720c08..08b4ff85 100644 --- a/apps/web/core/components/project/settings/member-columns.tsx +++ b/apps/web/core/components/project/settings/member-columns.tsx @@ -155,7 +155,7 @@ export const AccountTypeColumn = observer(function AccountTypeColumn(props: Acco if (!workspaceSlug) return; await updateMemberRole(workspaceSlug.toString(), projectId.toString(), rowData.member.id, value).catch( (err) => { - console.log(err, "err"); + console.error("Failed to update project member role:", err); const error = err.error; const errorString = Array.isArray(error) ? error[0] : error; diff --git a/apps/web/core/components/sidebar/search-button.tsx b/apps/web/core/components/sidebar/search-button.tsx deleted file mode 100644 index 6c4fe2fe..00000000 --- a/apps/web/core/components/sidebar/search-button.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { SearchOutline } from "@makeplane/propel/icons"; -import { cn } from "@pace/utils"; - -type Props = { - isActive?: boolean; -}; - -export function SidebarSearchButton(props: Props) { - const { isActive } = props; - return ( -
- -
- ); -} diff --git a/apps/web/core/components/stickies/action-bar.tsx b/apps/web/core/components/stickies/action-bar.tsx deleted file mode 100644 index aa0ab430..00000000 --- a/apps/web/core/components/stickies/action-bar.tsx +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useRef, useState } from "react"; -import { observer } from "mobx-react"; -import { useParams } from "@/lib/navigation"; -import useSWR from "swr"; -// pace hooks -import { useOutsideClickDetector } from "@pace/hooks"; -// pace ui -import { AddOutline, CloseOutline, MultipleStickyOutline, StickyNoteOutline } from "@makeplane/propel/icons"; -import { PreviewCard, PreviewCardContent, PreviewCardTrigger } from "@makeplane/propel/components/preview-card"; -import { Tooltip } from "@makeplane/propel/components/tooltip"; -// pace utils -import { cn } from "@pace/utils"; -// hooks -import { useCommandPalette } from "@/hooks/store/use-command-palette"; -import { useSticky } from "@/hooks/use-stickies"; -// components -import { STICKY_COLORS_LIST } from "../editor/sticky-editor/color-palette"; -import { AllStickiesModal } from "./modal"; -import { StickyNote } from "./sticky"; - -export const StickyActionBar = observer(function StickyActionBar() { - // states - const [isExpanded, setIsExpanded] = useState(false); - const [newSticky, setNewSticky] = useState(false); - const [showRecentSticky, setShowRecentSticky] = useState(false); - // navigation - const { workspaceSlug } = useParams(); - // refs - const ref = useRef(null); - // store hooks - const { stickies, activeStickyId, recentStickyId, updateActiveStickyId, fetchRecentSticky, toggleShowNewSticky } = - useSticky(); - const { toggleAllStickiesModal, allStickiesModal } = useCommandPalette(); - // derived values - const recentStickyBackgroundColor = recentStickyId - ? STICKY_COLORS_LIST.find((c) => c.key === stickies[recentStickyId].background_color)?.backgroundColor - : STICKY_COLORS_LIST[0].backgroundColor; - - useSWR( - workspaceSlug ? `WORKSPACE_STICKIES_RECENT_${workspaceSlug}` : null, - workspaceSlug ? () => fetchRecentSticky(workspaceSlug.toString()) : null - ); - - useOutsideClickDetector(ref, () => { - setNewSticky(false); - setShowRecentSticky(false); - setIsExpanded(false); - }); - - const recentStickyButton = ( - - ); - - return ( -
-
- - - - {recentStickyId && - (showRecentSticky ? ( - recentStickyButton - ) : ( - - - -
- -
-
- - - ))} - - - -
- - - -
- {(newSticky || (showRecentSticky && recentStickyId)) && ( - (newSticky ? setNewSticky(false) : setShowRecentSticky(false))} - workspaceSlug={workspaceSlug.toString()} - stickyId={newSticky ? activeStickyId : recentStickyId} - /> - )} -
- - toggleAllStickiesModal(false)} /> -
- ); -}); diff --git a/apps/web/core/components/ui/loader/notification-loader.tsx b/apps/web/core/components/ui/loader/notification-loader.tsx deleted file mode 100644 index 9ebcaf73..00000000 --- a/apps/web/core/components/ui/loader/notification-loader.tsx +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { range } from "lodash-es"; - -export function NotificationsLoader() { - return ( -
- {range(3).map((i) => ( -
- -
- -
- - -
-
-
- ))} -
- ); -} diff --git a/apps/web/core/components/ui/loader/pages-loader.tsx b/apps/web/core/components/ui/loader/pages-loader.tsx deleted file mode 100644 index 8cfbf68a..00000000 --- a/apps/web/core/components/ui/loader/pages-loader.tsx +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { range } from "lodash-es"; - -export function PagesLoader() { - return ( -
-
-

Pages

-
-
- {range(5).map((i) => ( - - ))} -
-
- {range(5).map((i) => ( -
-
- - -
-
- - - - -
-
- ))} -
-
- ); -} diff --git a/apps/web/core/components/ui/markdown-to-component.tsx b/apps/web/core/components/ui/markdown-to-component.tsx deleted file mode 100644 index af66e84b..00000000 --- a/apps/web/core/components/ui/markdown-to-component.tsx +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React from "react"; -import ReactMarkdown from "react-markdown"; - -interface CustomComponentProps { - href: string; - children: React.ReactNode; -} - -type CustomComponent = React.ComponentType; - -interface Props { - markdown: string; - components?: { - a?: CustomComponent; - blockquote?: CustomComponent; - code?: CustomComponent; - del?: CustomComponent; - em?: CustomComponent; - heading?: CustomComponent; - hr?: CustomComponent; - image?: CustomComponent; - inlineCode?: CustomComponent; - link?: CustomComponent; - list?: CustomComponent; - listItem?: CustomComponent; - paragraph?: CustomComponent; - strong?: CustomComponent; - table?: CustomComponent; - tableCell?: CustomComponent; - tableHead?: CustomComponent; - tableRow?: CustomComponent; - }; - options?: any; -} - -function HeadingPrimary({ children }: { children: React.ReactNode }) { - return

{children}

; -} - -function HeadingSecondary({ children }: { children: React.ReactNode }) { - return

{children}

; -} - -function Paragraph({ children }: { children: React.ReactNode }) { - return

{children}

; -} - -function OrderedList({ children }: { children: React.ReactNode }) { - return
    {children}
; -} - -function UnorderedList({ children }: { children: React.ReactNode }) { - return
    {children}
; -} - -function Link({ href, children }: CustomComponentProps) { - return ( - - {children} - - ); -} - -export function MarkdownRenderer({ markdown, options = {} }: Props) { - const customComponents = { - h1: HeadingPrimary, - h3: HeadingSecondary, - p: Paragraph, - ol: OrderedList, - ul: UnorderedList, - a: Link, - }; - - return ( - - {markdown} - - ); -} diff --git a/apps/web/core/components/ui/profile-empty-state.tsx b/apps/web/core/components/ui/profile-empty-state.tsx deleted file mode 100644 index 09f2547e..00000000 --- a/apps/web/core/components/ui/profile-empty-state.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React from "react"; - -type Props = { - title: string; - description?: React.ReactNode; - image: any; -}; - -export function ProfileEmptyState({ title, description, image }: Props) { - return ( -
-
-
- {title} -
-
{title}
- {description &&

{description}

} -
-
- ); -} diff --git a/apps/web/core/components/workspace-notifications/notification-app-sidebar-option.tsx b/apps/web/core/components/workspace-notifications/notification-app-sidebar-option.tsx deleted file mode 100644 index 0177c334..00000000 --- a/apps/web/core/components/workspace-notifications/notification-app-sidebar-option.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { observer } from "mobx-react"; -import useSWR from "swr"; -// pace imports -import { getNumberCount } from "@pace/utils"; -// components -import { CountChip } from "@/components/common/count-chip"; -// hooks -import { useWorkspaceNotifications } from "@/hooks/store/notifications"; - -type TNotificationAppSidebarOption = { - workspaceSlug: string; -}; - -export const NotificationAppSidebarOption = observer(function NotificationAppSidebarOption( - props: TNotificationAppSidebarOption -) { - const { workspaceSlug } = props; - // hooks - const { unreadNotificationsCount, getUnreadNotificationsCount } = useWorkspaceNotifications(); - - useSWR( - workspaceSlug ? "WORKSPACE_UNREAD_NOTIFICATION_COUNT" : null, - workspaceSlug ? () => getUnreadNotificationsCount(workspaceSlug) : null - ); - - // derived values - const isMentionsEnabled = unreadNotificationsCount.mention_unread_notifications_count > 0 ? true : false; - const totalNotifications = isMentionsEnabled - ? unreadNotificationsCount.mention_unread_notifications_count - : unreadNotificationsCount.total_unread_notifications_count; - - if (totalNotifications <= 0) return <>; - - return ( -
- -
- ); -}); diff --git a/apps/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx b/apps/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx index e174e3db..8c46e9c5 100644 --- a/apps/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx +++ b/apps/web/core/components/workspace/sidebar/favorites/favorites-menu.tsx @@ -169,7 +169,6 @@ export const SidebarFavoritesMenu = observer(function SidebarFavoritesMenu() { onDrop: ({ source }) => { setIsDragging(false); const sourceId = source?.data?.id as string | undefined; - console.log({ sourceId }); if (!sourceId || !groupedFavorites[sourceId].parent) return; }, }) diff --git a/apps/web/core/components/workspace/sidebar/user-menu-item.tsx b/apps/web/core/components/workspace/sidebar/user-menu-item.tsx deleted file mode 100644 index e7a96621..00000000 --- a/apps/web/core/components/workspace/sidebar/user-menu-item.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { observer } from "mobx-react"; -import Link from "@/lib/navigation/link"; -import { useParams } from "@/lib/navigation"; -import { usePathname } from "@/lib/navigation"; -// pace imports -import { EUserPermissionsLevel } from "@pace/constants"; -import { useTranslation } from "@pace/i18n"; -import type { EUserWorkspaceRoles } from "@pace/types"; -// components -import { SidebarNavItem } from "@/components/sidebar/sidebar-navigation"; -import { NotificationAppSidebarOption } from "@/components/workspace-notifications/notification-app-sidebar-option"; -// hooks -import { useAppTheme } from "@/hooks/store/use-app-theme"; -import { useUserPermissions } from "@/hooks/store/user"; - -export interface SidebarUserMenuItemProps { - item: { - key: string; - href: string; - access: EUserWorkspaceRoles[]; - labelTranslationKey: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - Icon: any; - }; - draftIssueCount: number; -} - -export const SidebarUserMenuItem = observer(function SidebarUserMenuItem(props: SidebarUserMenuItemProps) { - const { item, draftIssueCount } = props; - // nextjs hooks - const { workspaceSlug } = useParams(); - const pathname = usePathname(); - // package hooks - const { t } = useTranslation(); - // store hooks - const { allowPermissions } = useUserPermissions(); - const { toggleSidebar } = useAppTheme(); - - const isActive = pathname === item.href; - - if (item.key === "drafts" && draftIssueCount === 0) return null; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - if (!allowPermissions(item.access as any, EUserPermissionsLevel.WORKSPACE, workspaceSlug.toString())) return null; - - const handleLinkClick = () => { - if (window.innerWidth < 768) { - toggleSidebar(); - } - }; - - return ( - - -
- -

{t(item.labelTranslationKey)}

-
- {item.key === "notifications" && } -
- - ); -}); diff --git a/apps/web/core/components/workspace/sidebar/user-menu.tsx b/apps/web/core/components/workspace/sidebar/user-menu.tsx deleted file mode 100644 index 1cd923b9..00000000 --- a/apps/web/core/components/workspace/sidebar/user-menu.tsx +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React from "react"; -import { observer } from "mobx-react"; -import { useParams } from "@/lib/navigation"; -// pace imports -import { PiChatLogo } from "@pace/propel/icons"; -import { DashboardsOutline, DraftsOutline, HomeOutline, YourWorkOutline } from "@makeplane/propel/icons"; -import { EUserWorkspaceRoles } from "@pace/types"; -// hooks -import { useUserPermissions, useUser } from "@/hooks/store/user"; -// local imports -import { SidebarUserMenuItem } from "./user-menu-item"; - -export const SidebarUserMenu = observer(function SidebarUserMenu() { - // navigation - const { workspaceSlug } = useParams(); - // store hooks - const { workspaceUserInfo } = useUserPermissions(); - const { data: currentUser } = useUser(); - - const SIDEBAR_USER_MENU_ITEMS = [ - { - key: "home", - labelTranslationKey: "sidebar.home", - href: `/${workspaceSlug.toString()}/`, - access: [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER, EUserWorkspaceRoles.GUEST], - Icon: HomeOutline, - }, - { - key: "dashboards", - labelTranslationKey: "workspace_dashboards", - href: `/${workspaceSlug.toString()}/dashboards/`, - access: [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER], - Icon: DashboardsOutline, - }, - { - key: "your-work", - labelTranslationKey: "sidebar.your_work", - href: `/${workspaceSlug.toString()}/profile/${currentUser?.id}/`, - access: [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER], - Icon: YourWorkOutline, - }, - { - key: "drafts", - labelTranslationKey: "sidebar.drafts", - href: `/${workspaceSlug.toString()}/drafts/`, - access: [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER], - Icon: DraftsOutline, - }, - { - key: "pi-chat", - labelTranslationKey: "sidebar.pi_chat", - href: `/${workspaceSlug.toString()}/pi-chat/`, - access: [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER, EUserWorkspaceRoles.GUEST], - Icon: PiChatLogo, - }, - ]; - - const draftIssueCount = workspaceUserInfo[workspaceSlug.toString()]?.draft_issue_count; - - return ( -
- {SIDEBAR_USER_MENU_ITEMS.map((item) => ( - - ))} -
- ); -}); diff --git a/apps/web/core/components/workspace/sidebar/workspace-menu-header.tsx b/apps/web/core/components/workspace/sidebar/workspace-menu-header.tsx deleted file mode 100644 index 5cde6f90..00000000 --- a/apps/web/core/components/workspace/sidebar/workspace-menu-header.tsx +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useState, useRef } from "react"; -import { observer } from "mobx-react"; -import { useParams } from "@/lib/navigation"; -import { useRouter } from "@/lib/navigation"; -import { ArchiveOutline, ChevronRightOutline, MoreHorizontalOutline, SettingsOutline } from "@makeplane/propel/icons"; -import { Disclosure } from "@headlessui/react"; -// pace imports -import { EUserPermissionsLevel } from "@pace/constants"; -import { useOutsideClickDetector } from "@pace/hooks"; -import { useTranslation } from "@pace/i18n"; -import { EUserWorkspaceRoles } from "@pace/types"; -import { CustomMenu } from "@pace/ui"; -import { cn } from "@pace/utils"; -// store hooks -import { useUserPermissions } from "@/hooks/store/user"; - -export type SidebarWorkspaceMenuHeaderProps = { - isWorkspaceMenuOpen: boolean; - toggleWorkspaceMenu: (value: boolean) => void; -}; - -export const SidebarWorkspaceMenuHeader = observer(function SidebarWorkspaceMenuHeader( - props: SidebarWorkspaceMenuHeaderProps -) { - const { isWorkspaceMenuOpen, toggleWorkspaceMenu } = props; - // state - const [isMenuActive, setIsMenuActive] = useState(false); - // refs - const actionSectionRef = useRef(null); - // hooks - const { workspaceSlug } = useParams(); - const router = useRouter(); - const { allowPermissions } = useUserPermissions(); - const { t } = useTranslation(); - - useOutsideClickDetector(actionSectionRef, () => setIsMenuActive(false)); - - // TODO: fix types - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const isAdmin = allowPermissions([EUserWorkspaceRoles.ADMIN] as any, EUserPermissionsLevel.WORKSPACE); - - return ( -
- toggleWorkspaceMenu(!isWorkspaceMenuOpen)} - > - {t("common.workspace")} - - { - setIsMenuActive(!isMenuActive); - }} - > - - - } - className={cn( - "pointer-events-none z-20 my-auto flex h-full flex-shrink-0 items-center opacity-0 group-hover/workspace-button:pointer-events-auto group-hover/workspace-button:opacity-100", - { - "pointer-events-auto opacity-100": isMenuActive, - } - )} - customButtonClassName="grid place-items-center" - placement="bottom-start" - > - router.push(`/${workspaceSlug}/projects/archives`)}> -
- - {t("archives")} -
-
- - {isAdmin && ( - router.push(`/${workspaceSlug}/settings`)}> -
- - {t("settings")} -
-
- )} -
- toggleWorkspaceMenu(!isWorkspaceMenuOpen)} - > - {" "} - - - - -
- ); -}); diff --git a/apps/web/core/components/workspace/sidebar/workspace-menu-item.tsx b/apps/web/core/components/workspace/sidebar/workspace-menu-item.tsx deleted file mode 100644 index 473449e7..00000000 --- a/apps/web/core/components/workspace/sidebar/workspace-menu-item.tsx +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { observer } from "mobx-react"; -import Link from "@/lib/navigation/link"; -import { useParams } from "@/lib/navigation"; -import { usePathname } from "@/lib/navigation"; -// pace imports -import { EUserPermissionsLevel } from "@pace/constants"; -import { useTranslation } from "@pace/i18n"; -import type { EUserWorkspaceRoles } from "@pace/types"; -import { cn } from "@pace/utils"; -// components -import { SidebarNavItem } from "@/components/sidebar/sidebar-navigation"; -// hooks -import { useAppTheme } from "@/hooks/store/use-app-theme"; -import { useUserPermissions } from "@/hooks/store/user"; -// pace web imports -import { UpgradeBadge } from "@/components/workspace/upgrade-badge"; - -export type SidebarWorkspaceMenuItemProps = { - item: { - labelTranslationKey: string; - key: string; - href: string; - Icon: any; - access: EUserWorkspaceRoles[]; - }; -}; - -export const SidebarWorkspaceMenuItem = observer(function SidebarWorkspaceMenuItem( - props: SidebarWorkspaceMenuItemProps -) { - const { item } = props; - - const { t } = useTranslation(); - // nextjs hooks - const pathname = usePathname(); - const { workspaceSlug } = useParams(); - const { allowPermissions } = useUserPermissions(); - // store hooks - const { toggleSidebar } = useAppTheme(); - - const handleLinkClick = () => { - if (window.innerWidth < 768) { - toggleSidebar(); - } - }; - - if (!allowPermissions(item.access as any, EUserPermissionsLevel.WORKSPACE, workspaceSlug.toString())) { - return null; - } - - const isActive = item.href === pathname; - - return ( - handleLinkClick()}> - -
- -

{t(item.labelTranslationKey)}

-
-
- -
-
- - ); -}); diff --git a/apps/web/core/components/workspace/sidebar/workspace-menu.tsx b/apps/web/core/components/workspace/sidebar/workspace-menu.tsx deleted file mode 100644 index e0f8a8a4..00000000 --- a/apps/web/core/components/workspace/sidebar/workspace-menu.tsx +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import React from "react"; -import { observer } from "mobx-react"; -import { useParams } from "@/lib/navigation"; -import { Disclosure, Transition } from "@headlessui/react"; -// pace imports -import { AnalyticsOutline, CyclesOutline, ProjectsOutline, ViewsOutline } from "@makeplane/propel/icons"; -import { EUserWorkspaceRoles } from "@pace/types"; -// hooks -import useLocalStorage from "@/hooks/use-local-storage"; -// local imports -import { SidebarWorkspaceMenuHeader } from "./workspace-menu-header"; -import { SidebarWorkspaceMenuItem } from "./workspace-menu-item"; - -export const SidebarWorkspaceMenu = observer(function SidebarWorkspaceMenu() { - // router params - const { workspaceSlug } = useParams(); - // local storage - const { setValue: toggleWorkspaceMenu, storedValue } = useLocalStorage("is_workspace_menu_open", true); - // derived values - const isWorkspaceMenuOpen = !!storedValue; - - const SIDEBAR_WORKSPACE_MENU_ITEMS = [ - { - key: "projects", - labelTranslationKey: "sidebar.projects", - href: `/${workspaceSlug}/projects/`, - access: [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER, EUserWorkspaceRoles.GUEST], - Icon: ProjectsOutline, - }, - { - key: "views", - labelTranslationKey: "sidebar.views", - href: `/${workspaceSlug}/workspace-views/all-issues/`, - access: [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER, EUserWorkspaceRoles.GUEST], - Icon: ViewsOutline, - }, - { - key: "active-cycles", - labelTranslationKey: "sidebar.cycles", - href: `/${workspaceSlug}/active-cycles/`, - access: [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER], - Icon: CyclesOutline, - }, - { - key: "analytics", - labelTranslationKey: "sidebar.analytics", - href: `/${workspaceSlug}/analytics/`, - access: [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER], - Icon: AnalyticsOutline, - }, - ]; - - return ( - - - - {isWorkspaceMenuOpen && ( - - {SIDEBAR_WORKSPACE_MENU_ITEMS.map((item) => ( - - ))} - - )} - - - ); -}); diff --git a/apps/web/core/components/workspace/workspace-image-upload-modal.tsx b/apps/web/core/components/workspace/workspace-image-upload-modal.tsx index ddef63c4..2dbd8622 100644 --- a/apps/web/core/components/workspace/workspace-image-upload-modal.tsx +++ b/apps/web/core/components/workspace/workspace-image-upload-modal.tsx @@ -76,7 +76,7 @@ export const WorkspaceImageUploadModal = observer(function WorkspaceImageUploadM updateWorkspaceLogo(workspaceSlug.toString(), asset_url); onSuccess(asset_url); } catch (error: any) { - console.log("error", error); + console.error("error", error); setToast({ type: TOAST_TYPE.ERROR, title: "Error", @@ -100,7 +100,7 @@ export const WorkspaceImageUploadModal = observer(function WorkspaceImageUploadM await handleRemove(); handleClose(); } catch (error) { - console.log("Error in removing workspace asset:", error); + console.error("Error in removing workspace asset:", error); } finally { setIsRemoving(false); } diff --git a/apps/web/core/hooks/store/estimates/use-project-estimate.ts b/apps/web/core/hooks/store/estimates/use-project-estimate.ts index 08b54822..0fdbf689 100644 --- a/apps/web/core/hooks/store/estimates/use-project-estimate.ts +++ b/apps/web/core/hooks/store/estimates/use-project-estimate.ts @@ -12,7 +12,7 @@ import type { IProjectEstimateStore } from "@/store/estimates/project-estimate.s export const useProjectEstimates = (): IProjectEstimateStore => { const context = useContext(StoreContext); - if (context === undefined) throw new Error("useProjectPage must be used within StoreProvider"); + if (context === undefined) throw new Error("useProjectEstimates must be used within StoreProvider"); return context.projectEstimate; }; diff --git a/apps/web/core/hooks/store/use-calendar-view.ts b/apps/web/core/hooks/store/use-calendar-view.ts index cc117403..11a6c185 100644 --- a/apps/web/core/hooks/store/use-calendar-view.ts +++ b/apps/web/core/hooks/store/use-calendar-view.ts @@ -12,6 +12,6 @@ import type { ICalendarStore } from "@/store/issue/issue-calendar-view.store"; export const useCalendarView = (): ICalendarStore => { const context = useContext(StoreContext); - if (context === undefined) throw new Error("useLabel must be used within StoreProvider"); + if (context === undefined) throw new Error("useCalendarView must be used within StoreProvider"); return context.issue.issueCalendarView; }; diff --git a/apps/web/core/hooks/store/use-dashboard.ts b/apps/web/core/hooks/store/use-dashboard.ts deleted file mode 100644 index eaba6c5a..00000000 --- a/apps/web/core/hooks/store/use-dashboard.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useContext } from "react"; -// mobx store -import { StoreContext } from "@/lib/store-context"; -// types -import type { IDashboardStore } from "@/store/dashboard.store"; - -export const useDashboard = (): IDashboardStore => { - const context = useContext(StoreContext); - if (context === undefined) throw new Error("useDashboard must be used within StoreProvider"); - return context.dashboard; -}; diff --git a/apps/web/core/hooks/store/use-favorite.ts b/apps/web/core/hooks/store/use-favorite.ts index 788ec946..b336e848 100644 --- a/apps/web/core/hooks/store/use-favorite.ts +++ b/apps/web/core/hooks/store/use-favorite.ts @@ -11,6 +11,6 @@ import type { IFavoriteStore } from "@/store/favorite.store"; export const useFavorite = (): IFavoriteStore => { const context = useContext(StoreContext); - if (context === undefined) throw new Error("useFavorites must be used within StoreProvider"); + if (context === undefined) throw new Error("useFavorite must be used within StoreProvider"); return context.favorite; }; diff --git a/apps/web/core/hooks/store/use-home.ts b/apps/web/core/hooks/store/use-home.ts index 3012ea73..477d3c1a 100644 --- a/apps/web/core/hooks/store/use-home.ts +++ b/apps/web/core/hooks/store/use-home.ts @@ -12,6 +12,6 @@ import type { IHomeStore } from "@/store/workspace/home"; export const useHome = (): IHomeStore => { const context = useContext(StoreContext); - if (context === undefined) throw new Error("useDashboard must be used within StoreProvider"); + if (context === undefined) throw new Error("useHome must be used within StoreProvider"); return context.workspaceRoot.home; }; diff --git a/apps/web/core/hooks/store/use-inbox-issues.ts b/apps/web/core/hooks/store/use-inbox-issues.ts deleted file mode 100644 index bdd1ebe8..00000000 --- a/apps/web/core/hooks/store/use-inbox-issues.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { useContext } from "react"; -// mobx store -import { StoreContext } from "@/lib/store-context"; -import type { IInboxIssueStore } from "@/store/inbox/inbox-issue.store"; - -export const useInboxIssues = (inboxIssueId: string): IInboxIssueStore => { - const context = useContext(StoreContext); - if (context === undefined) throw new Error("useInboxIssues must be used within StoreProvider"); - return context.projectInbox.getIssueInboxByIssueId(inboxIssueId); -}; diff --git a/apps/web/core/hooks/store/use-kanban-view.ts b/apps/web/core/hooks/store/use-kanban-view.ts index 4ebdcd01..b1a5414f 100644 --- a/apps/web/core/hooks/store/use-kanban-view.ts +++ b/apps/web/core/hooks/store/use-kanban-view.ts @@ -12,6 +12,6 @@ import type { IIssueKanBanViewStore } from "@/store/issue/issue-kanban-view.stor export const useKanbanView = (): IIssueKanBanViewStore => { const context = useContext(StoreContext); - if (context === undefined) throw new Error("useLabel must be used within StoreProvider"); + if (context === undefined) throw new Error("useKanbanView must be used within StoreProvider"); return context.issue.issueKanBanView; }; diff --git a/apps/web/core/hooks/use-debounced-duplicate-issues.tsx b/apps/web/core/hooks/use-debounced-duplicate-issues.tsx deleted file mode 100644 index afd5367d..00000000 --- a/apps/web/core/hooks/use-debounced-duplicate-issues.tsx +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import type { TDeDupeIssue } from "@pace/types"; - -export const useDebouncedDuplicateIssues = ( - _workspaceSlug: string | undefined, - _workspaceId: string | undefined, - _projectId: string | undefined, - _formData: { name: string | undefined; description_html?: string | undefined; issueId?: string | undefined } -) => { - const duplicateIssues: TDeDupeIssue[] = []; - - return { duplicateIssues }; -}; diff --git a/apps/web/core/hooks/use-multiple-select.ts b/apps/web/core/hooks/use-multiple-select.ts index 2c060297..93026615 100644 --- a/apps/web/core/hooks/use-multiple-select.ts +++ b/apps/web/core/hooks/use-multiple-select.ts @@ -185,7 +185,6 @@ export const useMultipleSelect = (props: Props) => { if (forceAction) { if (forceAction === "force-add") { - console.log("force adding"); updateSelectedEntityDetails(entityDetails, "add"); handleActiveEntityChange(entityDetails, shouldScroll); } diff --git a/apps/web/core/store/cycle.store.ts b/apps/web/core/store/cycle.store.ts index 3974275a..3a371596 100644 --- a/apps/web/core/store/cycle.store.ts +++ b/apps/web/core/store/cycle.store.ts @@ -604,7 +604,7 @@ export class CycleStore implements ICycleStore { this.fetchCycleDetails(workspaceSlug, projectId, cycleId); return response; } catch (error) { - console.log("Failed to patch cycle from cycle store"); + console.error("Failed to patch cycle from cycle store"); this.fetchAllCycles(workspaceSlug, projectId); this.fetchActiveCycle(workspaceSlug, projectId); throw error; diff --git a/apps/web/core/store/dashboard.store.ts b/apps/web/core/store/dashboard.store.ts deleted file mode 100644 index 2bc5e06d..00000000 --- a/apps/web/core/store/dashboard.store.ts +++ /dev/null @@ -1,291 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { set } from "lodash-es"; -import { action, computed, makeObservable, observable, runInAction } from "mobx"; -import { computedFn } from "mobx-utils"; -// types -import type { - THomeDashboardResponse, - TWidget, - TWidgetFiltersFormData, - TWidgetStatsResponse, - TWidgetKeys, - TWidgetStatsRequestParams, -} from "@pace/types"; -// services -import { DashboardService } from "@pace/services"; -// pace web store -import type { CoreRootStore } from "./root.store"; - -export interface IDashboardStore { - // error states - widgetStatsError: { [workspaceSlug: string]: Record> }; - // observables - homeDashboardId: string | null; - widgetDetails: { [workspaceSlug: string]: Record }; - // { - // workspaceSlug: { - // dashboardId: TWidget[] - // } - // } - widgetStats: { [workspaceSlug: string]: Record> }; - // { - // workspaceSlug: { - // dashboardId: { - // widgetKey: TWidgetStatsResponse; - // } - // } - // } - // computed - homeDashboardWidgets: TWidget[] | undefined; - // computed actions - getWidgetDetails: (workspaceSlug: string, dashboardId: string, widgetKey: TWidgetKeys) => TWidget | undefined; - getWidgetStats: (workspaceSlug: string, dashboardId: string, widgetKey: TWidgetKeys) => T | undefined; - getWidgetStatsError: (workspaceSlug: string, dashboardId: string, widgetKey: TWidgetKeys) => any | null; - // actions - fetchHomeDashboardWidgets: (workspaceSlug: string) => Promise; - fetchWidgetStats: ( - workspaceSlug: string, - dashboardId: string, - params: TWidgetStatsRequestParams - ) => Promise; - updateDashboardWidget: ( - workspaceSlug: string, - dashboardId: string, - widgetId: string, - data: Partial - ) => Promise; - updateDashboardWidgetFilters: ( - workspaceSlug: string, - dashboardId: string, - widgetId: string, - data: TWidgetFiltersFormData - ) => Promise; -} - -export class DashboardStore implements IDashboardStore { - // error states - widgetStatsError: { [workspaceSlug: string]: Record> } = {}; - // observables - homeDashboardId: string | null = null; - widgetDetails: { [workspaceSlug: string]: Record } = {}; - widgetStats: { [workspaceSlug: string]: Record> } = {}; - // stores - routerStore; - issueStore; - // services - dashboardService; - - constructor(_rootStore: CoreRootStore) { - makeObservable(this, { - // error states - widgetStatsError: observable, - // observables - homeDashboardId: observable.ref, - widgetDetails: observable, - widgetStats: observable, - // computed - homeDashboardWidgets: computed, - // fetch actions - fetchHomeDashboardWidgets: action, - fetchWidgetStats: action, - // update actions - updateDashboardWidget: action, - updateDashboardWidgetFilters: action, - }); - - // router store - this.routerStore = _rootStore.router; - this.issueStore = _rootStore.issue.issues; - // services - this.dashboardService = new DashboardService(); - } - - /** - * @description get home dashboard widgets - * @returns {TWidget[] | undefined} - */ - get homeDashboardWidgets() { - const workspaceSlug = this.routerStore.workspaceSlug; - if (!workspaceSlug) return undefined; - const { homeDashboardId, widgetDetails } = this; - return homeDashboardId ? widgetDetails?.[workspaceSlug]?.[homeDashboardId] : undefined; - } - - /** - * @description get widget details - * @param {string} workspaceSlug - * @param {string} dashboardId - * @param {TWidgetKeys} widgetKey - * @returns {TWidget | undefined} - */ - getWidgetDetails = computedFn((workspaceSlug: string, dashboardId: string, widgetKey: TWidgetKeys) => { - const widgets = this.widgetDetails?.[workspaceSlug]?.[dashboardId]; - if (!widgets) return undefined; - return widgets.find((widget) => widget.key === widgetKey); - }); - - /** - * @description get widget stats - * @param {string} workspaceSlug - * @param {string} dashboardId - * @param {TWidgetKeys} widgetKey - * @returns {T | undefined} - */ - getWidgetStats = (workspaceSlug: string, dashboardId: string, widgetKey: TWidgetKeys): T | undefined => - (this.widgetStats?.[workspaceSlug]?.[dashboardId]?.[widgetKey] as unknown as T) ?? undefined; - - /** - * @description get widget stats error - * @param {string} workspaceSlug - * @param {string} dashboardId - * @param {TWidgetKeys} widgetKey - * @returns {any | null} - */ - getWidgetStatsError = (workspaceSlug: string, dashboardId: string, widgetKey: TWidgetKeys) => - this.widgetStatsError?.[workspaceSlug]?.[dashboardId]?.[widgetKey] ?? null; - - /** - * @description fetch home dashboard details and widgets - * @param {string} workspaceSlug - * @returns {Promise} - */ - fetchHomeDashboardWidgets = async (workspaceSlug: string): Promise => { - try { - const response = await this.dashboardService.getHomeWidgets(workspaceSlug); - - runInAction(() => { - this.homeDashboardId = response.dashboard.id; - set(this.widgetDetails, [workspaceSlug, response.dashboard.id], response.widgets); - }); - - return response; - } catch (error) { - runInAction(() => { - this.homeDashboardId = null; - }); - - throw error; - } - }; - - /** - * @description fetch widget stats - * @param {string} workspaceSlug - * @param {string} dashboardId - * @param {TWidgetStatsRequestParams} widgetKey - * @returns widget stats - */ - fetchWidgetStats = async (workspaceSlug: string, dashboardId: string, params: TWidgetStatsRequestParams) => - this.dashboardService - .getWidgetStats(workspaceSlug, dashboardId, params) - .then((res: any) => { - runInAction(() => { - if (res.issues) this.issueStore.addIssue(res.issues); - set(this.widgetStats, [workspaceSlug, dashboardId, params.widget_key], res); - set(this.widgetStatsError, [workspaceSlug, dashboardId, params.widget_key], null); - }); - return res; - }) - .catch((error) => { - runInAction(() => { - set(this.widgetStatsError, [workspaceSlug, dashboardId, params.widget_key], error); - }); - - throw error; - }); - - /** - * @description update dashboard widget - * @param {string} dashboardId - * @param {string} widgetId - * @param {Partial} data - * @returns updated widget - */ - updateDashboardWidget = async ( - workspaceSlug: string, - dashboardId: string, - widgetId: string, - data: Partial - ): Promise => { - // find all widgets in dashboard - const widgets = this.widgetDetails?.[workspaceSlug]?.[dashboardId]; - if (!widgets) throw new Error("Dashboard not found"); - // find widget index - const widgetIndex = widgets.findIndex((widget) => widget.id === widgetId); - // get original widget - const originalWidget = { ...widgets[widgetIndex] }; - if (widgetIndex === -1) throw new Error("Widget not found"); - - try { - runInAction(() => { - this.widgetDetails[workspaceSlug][dashboardId][widgetIndex] = { - ...widgets[widgetIndex], - ...data, - }; - }); - const response = await this.dashboardService.updateWidget(dashboardId, widgetId, data); - return response; - } catch (error) { - // revert changes - runInAction(() => { - this.widgetDetails[workspaceSlug][dashboardId][widgetIndex] = originalWidget; - }); - throw error; - } - }; - - /** - * @description update dashboard widget filters - * @param {string} dashboardId - * @param {string} widgetId - * @param {TWidgetFiltersFormData} data - * @returns updated widget - */ - updateDashboardWidgetFilters = async ( - workspaceSlug: string, - dashboardId: string, - widgetId: string, - data: TWidgetFiltersFormData - ): Promise => { - const widgetDetails = this.getWidgetDetails(workspaceSlug, dashboardId, data.widgetKey); - if (!widgetDetails) throw new Error("Widget not found"); - try { - const updatedWidget = { - ...widgetDetails, - widget_filters: { - ...widgetDetails.widget_filters, - ...data.filters, - }, - }; - // update widget details optimistically - runInAction(() => { - set( - this.widgetDetails, - [workspaceSlug, dashboardId], - this.widgetDetails?.[workspaceSlug]?.[dashboardId]?.map((w) => (w.id === widgetId ? updatedWidget : w)) - ); - }); - const response = await this.updateDashboardWidget(workspaceSlug, dashboardId, widgetId, { - filters: { - ...widgetDetails.widget_filters, - ...data.filters, - }, - }).then((res) => res); - - return response; - } catch (error) { - // revert changes - runInAction(() => { - this.widgetDetails[workspaceSlug][dashboardId] = this.widgetDetails?.[workspaceSlug]?.[dashboardId]?.map((w) => - w.id === widgetId ? widgetDetails : w - ); - }); - throw error; - } - }; -} diff --git a/apps/web/core/store/issue/archived/filter.store.ts b/apps/web/core/store/issue/archived/filter.store.ts index 89a3161f..51ee1160 100644 --- a/apps/web/core/store/issue/archived/filter.store.ts +++ b/apps/web/core/store/issue/archived/filter.store.ts @@ -187,7 +187,7 @@ export class ArchivedIssuesFilter extends IssueFilterHelperStore implements IArc } ); } catch (error) { - console.log("error while updating rich filters", error); + console.error("error while updating rich filters", error); throw error; } }; diff --git a/apps/web/core/store/issue/cycle/filter.store.ts b/apps/web/core/store/issue/cycle/filter.store.ts index 66c5726b..990ebf28 100644 --- a/apps/web/core/store/issue/cycle/filter.store.ts +++ b/apps/web/core/store/issue/cycle/filter.store.ts @@ -198,7 +198,7 @@ export class CycleIssuesFilter extends IssueFilterHelperStore implements ICycleI rich_filters: filters, }); } catch (error) { - console.log("error while updating rich filters", error); + console.error("error while updating rich filters", error); throw error; } }; diff --git a/apps/web/core/store/issue/issue-details/comment-reaction.store.ts b/apps/web/core/store/issue/issue-details/comment-reaction.store.ts index aa3a28a2..408052b0 100644 --- a/apps/web/core/store/issue/issue-details/comment-reaction.store.ts +++ b/apps/web/core/store/issue/issue-details/comment-reaction.store.ts @@ -123,7 +123,7 @@ export class IssueCommentReactionStore implements IIssueCommentReactionStore { return response; } catch (error) { - console.log("error", error); + console.error("error", error); throw error; } }; @@ -163,7 +163,7 @@ export class IssueCommentReactionStore implements IIssueCommentReactionStore { return response; } catch (error) { - console.log("error", error); + console.error("error", error); throw error; } }; diff --git a/apps/web/core/store/issue/issue-gantt-view.store.ts b/apps/web/core/store/issue/issue-gantt-view.store.ts deleted file mode 100644 index 62ccb5b8..00000000 --- a/apps/web/core/store/issue/issue-gantt-view.store.ts +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { action, makeObservable, observable, runInAction } from "mobx"; -import { computedFn } from "mobx-utils"; -// helpers -import type { ChartDataType, TGanttViews } from "@pace/types"; -import { currentViewDataWithView } from "@/components/gantt-chart/data"; -// types - -export interface IGanttStore { - // observables - currentView: TGanttViews; - currentViewData: ChartDataType | undefined; - activeBlockId: string | null; - renderView: any; - // computed functions - isBlockActive: (blockId: string) => boolean; - // actions - updateCurrentView: (view: TGanttViews) => void; - updateCurrentViewData: (data: ChartDataType | undefined) => void; - updateActiveBlockId: (blockId: string | null) => void; - updateRenderView: (data: any[]) => void; -} - -export class GanttStore implements IGanttStore { - // observables - currentView: TGanttViews = "month"; - currentViewData: ChartDataType | undefined = undefined; - activeBlockId: string | null = null; - renderView: any[] = []; - - constructor() { - makeObservable(this, { - // observables - currentView: observable.ref, - currentViewData: observable, - activeBlockId: observable.ref, - renderView: observable, - // actions - updateCurrentView: action.bound, - updateCurrentViewData: action.bound, - updateActiveBlockId: action.bound, - updateRenderView: action.bound, - }); - - this.initGantt(); - } - - /** - * @description check if block is active - * @param {string} blockId - */ - isBlockActive = computedFn((blockId: string): boolean => this.activeBlockId === blockId); - - /** - * @description update current view - * @param {TGanttViews} view - */ - updateCurrentView = (view: TGanttViews) => { - this.currentView = view; - }; - - /** - * @description update current view data - * @param {ChartDataType | undefined} data - */ - updateCurrentViewData = (data: ChartDataType | undefined) => { - this.currentViewData = data; - }; - - /** - * @description update active block - * @param {string | null} block - */ - updateActiveBlockId = (blockId: string | null) => { - this.activeBlockId = blockId; - }; - - /** - * @description update render view - * @param {any[]} data - */ - updateRenderView = (data: any[]) => { - this.renderView = data; - }; - - /** - * @description initialize gantt chart with month view - */ - initGantt = () => { - const newCurrentViewData = currentViewDataWithView(this.currentView); - - runInAction(() => { - this.currentViewData = newCurrentViewData; - }); - }; -} diff --git a/apps/web/core/store/issue/module/filter.store.ts b/apps/web/core/store/issue/module/filter.store.ts index 26123f24..1d436857 100644 --- a/apps/web/core/store/issue/module/filter.store.ts +++ b/apps/web/core/store/issue/module/filter.store.ts @@ -203,7 +203,7 @@ export class ModuleIssuesFilter extends IssueFilterHelperStore implements IModul rich_filters: filters, }); } catch (error) { - console.log("error while updating rich filters", error); + console.error("error while updating rich filters", error); throw error; } }; diff --git a/apps/web/core/store/issue/profile/filter.store.ts b/apps/web/core/store/issue/profile/filter.store.ts index 1af40103..00656c20 100644 --- a/apps/web/core/store/issue/profile/filter.store.ts +++ b/apps/web/core/store/issue/profile/filter.store.ts @@ -179,7 +179,7 @@ export class ProfileIssuesFilter extends IssueFilterHelperStore implements IProf } ); } catch (error) { - console.log("error while updating rich filters", error); + console.error("error while updating rich filters", error); throw error; } }; diff --git a/apps/web/core/store/issue/project-views/filter.store.ts b/apps/web/core/store/issue/project-views/filter.store.ts index 87169e4c..ed08747e 100644 --- a/apps/web/core/store/issue/project-views/filter.store.ts +++ b/apps/web/core/store/issue/project-views/filter.store.ts @@ -178,7 +178,7 @@ export class ProjectViewIssuesFilter extends IssueFilterHelperStore implements I const viewDetails = await this.issueFilterService.getViewDetails(workspaceSlug, projectId, viewId); this.mutateFilters(workspaceSlug, viewId, viewDetails); } catch (error) { - console.log("error while fetching project view filters", error); + console.error("error while fetching project view filters", error); throw error; } }; @@ -206,7 +206,7 @@ export class ProjectViewIssuesFilter extends IssueFilterHelperStore implements I "mutation" ); } catch (error) { - console.log("error while updating rich filters", error); + console.error("error while updating rich filters", error); throw error; } }; diff --git a/apps/web/core/store/issue/project/filter.store.ts b/apps/web/core/store/issue/project/filter.store.ts index eadc2c49..eef0c9a6 100644 --- a/apps/web/core/store/issue/project/filter.store.ts +++ b/apps/web/core/store/issue/project/filter.store.ts @@ -186,7 +186,7 @@ export class ProjectIssuesFilter extends IssueFilterHelperStore implements IProj rich_filters: filters, }); } catch (error) { - console.log("error while updating rich filters", error); + console.error("error while updating rich filters", error); throw error; } }; diff --git a/apps/web/core/store/issue/workspace-draft/filter.store.ts b/apps/web/core/store/issue/workspace-draft/filter.store.ts index 6c19794f..fcf6d582 100644 --- a/apps/web/core/store/issue/workspace-draft/filter.store.ts +++ b/apps/web/core/store/issue/workspace-draft/filter.store.ts @@ -185,7 +185,7 @@ export class WorkspaceDraftIssuesFilter extends IssueFilterHelperStore implement } ); } catch (error) { - console.log("error while updating rich filters", error); + console.error("error while updating rich filters", error); throw error; } }; diff --git a/apps/web/core/store/issue/workspace/filter.store.ts b/apps/web/core/store/issue/workspace/filter.store.ts index e9128a47..78a09f8c 100644 --- a/apps/web/core/store/issue/workspace/filter.store.ts +++ b/apps/web/core/store/issue/workspace/filter.store.ts @@ -206,7 +206,7 @@ export class WorkspaceIssuesFilter extends IssueFilterHelperStore implements IWo this.rootIssueStore.workspaceIssues.fetchIssuesWithExistingPagination(workspaceSlug, viewId, "mutation"); } catch (error) { - console.log("error while updating rich filters", error); + console.error("error while updating rich filters", error); throw error; } }; diff --git a/apps/web/core/store/label.store.ts b/apps/web/core/store/label.store.ts index 56e81041..abba65c7 100644 --- a/apps/web/core/store/label.store.ts +++ b/apps/web/core/store/label.store.ts @@ -220,7 +220,7 @@ export class LabelStore implements ILabelStore { const response = await this.issueLabelService.patchIssueLabel(workspaceSlug, projectId, labelId, data); return response; } catch (error) { - console.log("Failed to update label from project store"); + console.error("Failed to update label from project store"); runInAction(() => { set(this.labelMap, [labelId], originalLabel); }); diff --git a/apps/web/core/store/project/project.store.ts b/apps/web/core/store/project/project.store.ts index 1d1b9227..e77585ec 100644 --- a/apps/web/core/store/project/project.store.ts +++ b/apps/web/core/store/project/project.store.ts @@ -320,7 +320,7 @@ export class ProjectStore implements IProjectStore { }); return projectsResponse; } catch (error) { - console.log("Failed to fetch project from workspace store"); + console.error("Failed to fetch project from workspace store"); this.loader = "loaded"; throw error; } @@ -349,7 +349,7 @@ export class ProjectStore implements IProjectStore { }); return projectsResponse; } catch (error) { - console.log("Failed to fetch project from workspace store"); + console.error("Failed to fetch project from workspace store"); this.loader = "loaded"; throw error; } @@ -369,7 +369,7 @@ export class ProjectStore implements IProjectStore { }); return response; } catch (error) { - console.log("Error while fetching project details", error); + console.error("Error while fetching project details", error); throw error; } }; @@ -393,7 +393,7 @@ export class ProjectStore implements IProjectStore { }); return response; } catch (error) { - console.log("Failed to fetch project analytics count", error); + console.error("Failed to fetch project analytics count", error); throw error; } }; @@ -469,7 +469,7 @@ export class ProjectStore implements IProjectStore { }); return response; } catch (error) { - console.log("Failed to add project to favorite"); + console.error("Failed to add project to favorite"); runInAction(() => { set(this.projectMap, [projectId, "is_favorite"], false); }); @@ -494,7 +494,7 @@ export class ProjectStore implements IProjectStore { return response; } catch (error) { - console.log("Failed to add project to favorite"); + console.error("Failed to remove project from favorites"); runInAction(() => { set(this.projectMap, [projectId, "is_favorite"], true); }); @@ -521,7 +521,7 @@ export class ProjectStore implements IProjectStore { runInAction(() => { set(this.projectMap, [projectId, "sort_order"], currentProjectSortOrder); }); - console.log("Failed to update sort order of the projects"); + console.error("Failed to update sort order of the projects"); throw error; } }; @@ -538,7 +538,7 @@ export class ProjectStore implements IProjectStore { this.processProjectAfterCreation(workspaceSlug, response); return response; } catch (error) { - console.log("Failed to create project from project store"); + console.error("Failed to create project from project store"); throw error; } }; @@ -563,7 +563,7 @@ export class ProjectStore implements IProjectStore { }); return response; } catch (error) { - console.log("Failed to create project from project store"); + console.error("Failed to update project from project store"); runInAction(() => { set(this.projectMap, [projectId], projectDetails); this.isUpdatingProject = false; @@ -588,7 +588,7 @@ export class ProjectStore implements IProjectStore { delete this.rootStore.user.permission.workspaceProjectsPermissions[workspaceSlug][projectId]; }); } catch (error) { - console.log("Failed to delete project from project store"); + console.error("Failed to delete project from project store"); throw error; } }; @@ -609,7 +609,7 @@ export class ProjectStore implements IProjectStore { }); }) .catch((error) => { - console.log("Failed to archive project from project store"); + console.error("Failed to archive project from project store"); throw error; }); }; @@ -629,7 +629,7 @@ export class ProjectStore implements IProjectStore { }); }) .catch((error) => { - console.log("Failed to restore project from project store"); + console.error("Failed to restore project from project store"); throw error; }); }; diff --git a/apps/web/core/store/root.store.ts b/apps/web/core/store/root.store.ts index 60ff0818..e13bd2cb 100644 --- a/apps/web/core/store/root.store.ts +++ b/apps/web/core/store/root.store.ts @@ -26,8 +26,6 @@ import type { ICycleStore } from "./cycle.store"; import { CycleStore } from "./cycle.store"; import type { ICycleFilterStore } from "./cycle-filter.store"; import { CycleFilterStore } from "./cycle-filter.store"; -import type { IDashboardStore } from "./dashboard.store"; -import { DashboardStore } from "./dashboard.store"; import type { IEditorAssetStore } from "./editor/asset.store"; import { EditorAssetStore } from "./editor/asset.store"; import type { IProjectEstimateStore } from "./estimates/project-estimate.store"; @@ -85,7 +83,6 @@ export class CoreRootStore { issue: IIssueRootStore; state: IStateStore; label: ILabelStore; - dashboard: IDashboardStore; analytics: IAnalyticsStore; projectPages: IProjectPageStore; router: IRouterStore; @@ -122,7 +119,6 @@ export class CoreRootStore { this.issue = new IssueRootStore(this); this.state = new StateStore(this); this.label = new LabelStore(this); - this.dashboard = new DashboardStore(this); this.multipleSelect = new MultipleSelectStore(); this.projectInbox = new ProjectInboxStore(this); this.projectPages = new ProjectPageStore(this); @@ -157,7 +153,6 @@ export class CoreRootStore { this.issue = new IssueRootStore(this); this.state = new StateStore(this); this.label = new LabelStore(this); - this.dashboard = new DashboardStore(this); this.projectInbox = new ProjectInboxStore(this); this.projectPages = new ProjectPageStore(this); this.multipleSelect = new MultipleSelectStore(); diff --git a/apps/web/core/store/sticky/sticky.store.ts b/apps/web/core/store/sticky/sticky.store.ts index 03e232e7..963b0df8 100644 --- a/apps/web/core/store/sticky/sticky.store.ts +++ b/apps/web/core/store/sticky/sticky.store.ts @@ -221,7 +221,7 @@ export class StickyStore implements IStickyStore { this.recentStickyId = this.workspaceStickies[workspaceSlug][0]; await this.stickyService.deleteSticky(workspaceSlug, id); } catch (e) { - console.log(e); + console.error(e); this.stickies[id] = sticky; } }; diff --git a/apps/web/core/store/user/index.ts b/apps/web/core/store/user/index.ts index ed998403..41c947c5 100644 --- a/apps/web/core/store/user/index.ts +++ b/apps/web/core/store/user/index.ts @@ -226,7 +226,7 @@ export class UserStore implements IUserStore { if (this.data) set(this.data, ["is_password_autoset"], false); return user; } catch (error) { - console.log(error); + console.error("Failed to change password:", error); throw error; } }; diff --git a/apps/web/google.d.ts b/apps/web/google.d.ts deleted file mode 100644 index 0a8bf469..00000000 --- a/apps/web/google.d.ts +++ /dev/null @@ -1,91 +0,0 @@ -// google.d.ts - -interface IdConfiguration { - client_id: string; - auto_select?: boolean; - callback: (handleCredentialResponse: CredentialResponse) => void; - login_uri?: string; - native_callback?: (...args: any[]) => void; - cancel_on_tap_outside?: boolean; - prompt_parent_id?: string; - nonce?: string; - context?: string; - state_cookie_domain?: string; - ux_mode?: "popup" | "redirect"; - allowed_parent_origin?: string | string[]; - intermediate_iframe_close_callback?: (...args: any[]) => void; -} - -interface CredentialResponse { - credential?: string; - select_by?: - | "auto" - | "user" - | "user_1tap" - | "user_2tap" - | "btn" - | "btn_confirm" - | "brn_add_session" - | "btn_confirm_add_session"; - clientId?: string; -} - -interface GsiButtonConfiguration { - type: "standard" | "icon"; - theme?: "outline" | "filled_blue" | "filled_black"; - size?: "large" | "medium" | "small"; - text?: "signin_with" | "signup_with" | "continue_with"; - shape?: "rectangular" | "pill" | "circle" | "square"; - logo_alignment?: "left" | "center"; - width?: number; - local?: string; -} - -interface PromptMomentNotification { - isDisplayMoment: () => boolean; - isDisplayed: () => boolean; - isNotDisplayed: () => boolean; - getNotDisplayedReason: () => - | "browser_not_supported" - | "invalid_client" - | "missing_client_id" - | "opt_out_or_no_session" - | "secure_http_required" - | "suppressed_by_user" - | "unregistered_origin" - | "unknown_reason"; - isSkippedMoment: () => boolean; - getSkippedReason: () => "auto_cancel" | "user_cancel" | "tap_outside" | "issuing_failed"; - isDismissedMoment: () => boolean; - getDismissedReason: () => "credential_returned" | "cancel_called" | "flow_restarted"; - getMomentType: () => "display" | "skipped" | "dismissed"; -} - -interface RevocationResponse { - successful: boolean; - error: string; -} - -interface Credential { - id: string; - password: string; -} - -interface Google { - accounts: { - id: { - initialize: (input: IdConfiguration) => void; - prompt: (momentListener?: (res: PromptMomentNotification) => void) => void; - renderButton: (parent: HTMLElement, options: GsiButtonConfiguration) => void; - disableAutoSelect: () => void; - storeCredential: (credentials: Credential, callback: () => void) => void; - cancel: () => void; - onGoogleLibraryLoad: () => void; - revoke: (hint: string, callback: (done: RevocationResponse) => void) => void; - }; - }; -} - -interface Window { - google?: Google; -} diff --git a/apps/web/helpers/dashboard.helper.ts b/apps/web/helpers/dashboard.helper.ts deleted file mode 100644 index d97e1582..00000000 --- a/apps/web/helpers/dashboard.helper.ts +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { endOfMonth, endOfWeek, endOfYear, startOfMonth, startOfWeek, startOfYear } from "date-fns"; -// helpers -// types -import { DURATION_FILTER_OPTIONS, EDurationFilters } from "@pace/constants"; -import type { TIssuesListTypes } from "@pace/types"; -// constants -import { renderFormattedDate, renderFormattedPayloadDate } from "@pace/utils"; - -// -------------------- DEPRECATED -------------------- - -/** - * @description returns date range based on the duration filter - * @param duration - */ -export const getCustomDates = (duration: EDurationFilters, customDates: string[]): string => { - const today = new Date(); - let firstDay, lastDay; - - switch (duration) { - case EDurationFilters.NONE: - return ""; - case EDurationFilters.TODAY: - firstDay = renderFormattedPayloadDate(today); - lastDay = renderFormattedPayloadDate(today); - return `${firstDay};after,${lastDay};before`; - case EDurationFilters.THIS_WEEK: - firstDay = renderFormattedPayloadDate(startOfWeek(today)); - lastDay = renderFormattedPayloadDate(endOfWeek(today)); - return `${firstDay};after,${lastDay};before`; - case EDurationFilters.THIS_MONTH: - firstDay = renderFormattedPayloadDate(startOfMonth(today)); - lastDay = renderFormattedPayloadDate(endOfMonth(today)); - return `${firstDay};after,${lastDay};before`; - case EDurationFilters.THIS_YEAR: - firstDay = renderFormattedPayloadDate(startOfYear(today)); - lastDay = renderFormattedPayloadDate(endOfYear(today)); - return `${firstDay};after,${lastDay};before`; - case EDurationFilters.CUSTOM: - return customDates.join(","); - } -}; - -/** - * @description returns redirection filters for the issues list - * @param type - */ -export const getRedirectionFilters = (type: TIssuesListTypes): string => { - const today = renderFormattedPayloadDate(new Date()); - - const filterParams = - type === "pending" - ? "?state_group=backlog,unstarted,started" - : type === "upcoming" - ? `?target_date=${today};after` - : type === "overdue" - ? `?target_date=${today};before` - : "?state_group=completed"; - - return filterParams; -}; - -/** - * @description returns the tab key based on the duration filter - * @param duration - * @param tab - */ -export const getTabKey = (duration: EDurationFilters, tab: TIssuesListTypes | undefined): TIssuesListTypes => { - if (!tab) return "completed"; - - if (tab === "completed") return tab; - - if (duration === "none") return "pending"; - else { - if (["upcoming", "overdue"].includes(tab)) return tab; - else return "upcoming"; - } -}; - -/** - * @description returns the label for the duration filter dropdown - * @param duration - * @param customDates - */ -export const getDurationFilterDropdownLabel = (duration: EDurationFilters, customDates: string[]): string => { - if (duration !== "custom") return DURATION_FILTER_OPTIONS.find((option) => option.key === duration)?.label ?? ""; - else { - const afterDate = customDates.find((date) => date.includes("after"))?.split(";")[0]; - const beforeDate = customDates.find((date) => date.includes("before"))?.split(";")[0]; - - if (afterDate && beforeDate) return `${renderFormattedDate(afterDate)} - ${renderFormattedDate(beforeDate)}`; - else if (afterDate) return `After ${renderFormattedDate(afterDate)}`; - else if (beforeDate) return `Before ${renderFormattedDate(beforeDate)}`; - else return ""; - } -}; diff --git a/apps/web/helpers/emoji.helper.tsx b/apps/web/helpers/emoji.helper.tsx deleted file mode 100644 index 55edd2ca..00000000 --- a/apps/web/helpers/emoji.helper.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -/** - * Renders an emoji or icon - * @param {string | { name: string; color: string }} emoji - The emoji or icon to render - * @returns {React.ReactNode} The rendered emoji or icon - */ -export const renderEmoji = ( - emoji: - | string - | { - name: string; - color: string; - } -): React.ReactNode => { - if (!emoji) return; - - if (typeof emoji === "object") - return ( - - {emoji.name} - - ); - else return isNaN(parseInt(emoji)) ? emoji : String.fromCodePoint(parseInt(emoji)); -}; diff --git a/apps/web/helpers/graph.helper.ts b/apps/web/helpers/graph.helper.ts deleted file mode 100644 index 055df63d..00000000 --- a/apps/web/helpers/graph.helper.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -// ------------ DEPRECATED (Use re-charts and its helpers instead) ------------ - -export const generateYAxisTickValues = (data: number[]) => { - if (!data || !Array.isArray(data) || data.length === 0) return []; - - const minValue = 0; - const maxValue = Math.max(...data); - - const valueRange = maxValue - minValue; - - let tickInterval = 1; - - if (valueRange < 10) tickInterval = 1; - else if (valueRange < 20) tickInterval = 2; - else if (valueRange < 50) tickInterval = 5; - else tickInterval = (Math.ceil(valueRange / 100) * 100) / 10; - - const tickValues: number[] = []; - let tickValue = minValue; - while (tickValue <= maxValue) { - tickValues.push(tickValue); - tickValue += tickInterval; - } - - return tickValues; -}; diff --git a/apps/web/helpers/react-hook-form.helper.ts b/apps/web/helpers/react-hook-form.helper.ts deleted file mode 100644 index da9a9fc6..00000000 --- a/apps/web/helpers/react-hook-form.helper.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import type { FieldError, FieldValues } from "react-hook-form"; - -/** - * Get a nested error from a form's errors object - * @param errors - The form's errors object - * @param path - The path to the error - * @returns The error or undefined if not found - */ -export const getNestedError = (errors: T, path: string): FieldError | undefined => { - const keys = path.split("."); - let current: unknown = errors; - - for (const key of keys) { - if (current && typeof current === "object" && key in current) { - current = (current as Record)[key]; - } else { - return undefined; - } - } - - // Check if the final value is a FieldError - if (current && typeof current === "object" && "message" in current) { - return current as FieldError; - } - - return undefined; -}; diff --git a/apps/web/package.json b/apps/web/package.json index 467f9329..aaa518d1 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,6 +1,6 @@ { "name": "web", - "version": "1.4.42", + "version": "1.4.43", "private": true, "license": "AGPL-3.0", "type": "module", @@ -55,7 +55,6 @@ "react-dom": "catalog:", "react-dropzone": "catalog:", "react-hook-form": "catalog:", - "react-markdown": "catalog:", "react-masonry-component": "catalog:", "react-pdf-html": "catalog:", "react-popper": "catalog:", diff --git a/package.json b/package.json index 24b89691..4b65980b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pace", - "version": "1.4.42", + "version": "1.4.43", "private": true, "description": "Project management that keeps pace with the work", "license": "AGPL-3.0", diff --git a/packages/codemods/package.json b/packages/codemods/package.json index b1d5e61c..824c9684 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -1,6 +1,6 @@ { "name": "@pace/codemods", - "version": "1.4.42", + "version": "1.4.43", "private": true, "scripts": { "check:format": "oxfmt --check .", diff --git a/packages/constants/package.json b/packages/constants/package.json index a72cd1ab..4a27cbc2 100644 --- a/packages/constants/package.json +++ b/packages/constants/package.json @@ -1,6 +1,6 @@ { "name": "@pace/constants", - "version": "1.4.42", + "version": "1.4.43", "private": true, "license": "AGPL-3.0", "type": "module", diff --git a/packages/constants/src/fetch-keys.ts b/packages/constants/src/fetch-keys.ts index c291fdc3..ccdaaec8 100644 --- a/packages/constants/src/fetch-keys.ts +++ b/packages/constants/src/fetch-keys.ts @@ -4,7 +4,7 @@ * See the LICENSE file for details. */ -import type { EUserPermissions, IJiraMetadata } from "@pace/types"; +import type { EUserPermissions } from "@pace/types"; const paramsToKey = (params: any) => { const { @@ -68,17 +68,11 @@ export const WORKSPACE_LABELS = (workspaceSlug: string) => `WORKSPACE_LABELS_${w export const WORKSPACE_ESTIMATES = (workspaceSlug: string) => `WORKSPACE_ESTIMATES_${workspaceSlug.toUpperCase()}`; -export const WORKSPACE_WORKFLOW_STATES = (workspaceSlug: string) => - `WORKSPACE_WORKFLOW_STATES_${workspaceSlug.toUpperCase()}`; - export const WORKSPACE_INVITATION = (invitationId: string) => `WORKSPACE_INVITATION_${invitationId}`; export const WORKSPACE_MEMBER_ME_INFORMATION = (workspaceSlug: string) => `WORKSPACE_MEMBER_ME_INFORMATION_${workspaceSlug.toUpperCase()}`; -export const WORKSPACE_MEMBER_ACTIVITY = (workspaceSlug: string) => - `WORKSPACE_MEMBER_ACTIVITY_${workspaceSlug.toUpperCase()}`; - export const WORKSPACE_PROJECTS_ROLES_INFORMATION = (workspaceSlug: string) => `WORKSPACE_PROJECTS_ROLES_INFORMATION_${workspaceSlug.toUpperCase()}`; @@ -95,8 +89,6 @@ export const WORKSPACE_PROJECT_NAVIGATION_PREFERENCES = (workspaceSlug: string) export const PROJECT_GITHUB_REPOSITORY = (projectId: string) => `PROJECT_GITHUB_REPOSITORY_${projectId.toUpperCase()}`; // cycles -export const WORKSPACE_ACTIVE_CYCLES_LIST = (workspaceSlug: string, cursor: string, per_page: string) => - `WORKSPACE_ACTIVE_CYCLES_LIST_${workspaceSlug.toUpperCase()}_${cursor.toUpperCase()}_${per_page.toUpperCase()}`; export const CYCLE_ISSUES_WITH_PARAMS = (cycleId: string, params?: any) => { if (!params) return `CYCLE_ISSUES_WITH_PARAMS_${cycleId.toUpperCase()}`; @@ -105,8 +97,6 @@ export const CYCLE_ISSUES_WITH_PARAMS = (cycleId: string, params?: any) => { return `CYCLE_ISSUES_WITH_PARAMS_${cycleId.toUpperCase()}_${paramsKey.toUpperCase()}`; }; -export const USER_ACTIVITY = (params: { cursor?: string }) => `USER_ACTIVITY_${params?.cursor}`; - // Issues export const ISSUE_DETAILS = (issueId: string) => `ISSUE_DETAILS_${issueId.toUpperCase()}`; @@ -115,24 +105,10 @@ export const APP_INTEGRATIONS = "APP_INTEGRATIONS"; export const WORKSPACE_INTEGRATIONS = (workspaceSlug: string) => `WORKSPACE_INTEGRATIONS_${workspaceSlug.toUpperCase()}`; -export const JIRA_IMPORTER_DETAIL = (workspaceSlug: string, params: IJiraMetadata) => { - const { api_token, cloud_hostname, email, project_key } = params; - - return `JIRA_IMPORTER_DETAIL_${workspaceSlug.toUpperCase()}_${api_token}_${cloud_hostname}_${email}_${project_key}`; -}; - -//import-export -export const IMPORTER_SERVICES_LIST = (workspaceSlug: string) => - `IMPORTER_SERVICES_LIST_${workspaceSlug.toUpperCase()}`; - //export export const EXPORT_SERVICES_LIST = (workspaceSlug: string, cursor: string, per_page: string) => `EXPORTER_SERVICES_LIST_${workspaceSlug.toUpperCase()}_${cursor.toUpperCase()}_${per_page.toUpperCase()}`; -// github-importer -export const GITHUB_REPOSITORY_INFO = (workspaceSlug: string, repoName: string) => - `GITHUB_REPO_INFO_${workspaceSlug.toString().toUpperCase()}_${repoName.toUpperCase()}`; - // slack-project-integration export const SLACK_CHANNEL_INFO = (workspaceSlug: string, projectId: string) => `SLACK_CHANNEL_INFO_${workspaceSlug.toString().toUpperCase()}_${projectId.toUpperCase()}`; @@ -153,12 +129,6 @@ export const USER_PROFILE_PROJECT_SEGREGATION = (workspaceSlug: string, userId: // api-tokens export const API_TOKENS_LIST = `API_TOKENS_LIST`; -// marketplace -export const APPLICATIONS_LIST = (workspaceSlug: string) => `APPLICATIONS_LIST_${workspaceSlug.toUpperCase()}`; -export const APPLICATION_DETAILS = (applicationId: string) => `APPLICATION_DETAILS_${applicationId.toUpperCase()}`; -export const APPLICATION_BY_CLIENT_ID = (clientId: string) => `APPLICATION_BY_CLIENT_ID_${clientId.toUpperCase()}`; -export const APPLICATION_CATEGORIES_LIST = () => `APPLICATION_CATEGORIES_LIST`; - // project level keys export const PROJECT_DETAILS = (_workspaceSlug: string, projectId: string) => `PROJECT_DETAILS_${projectId.toString().toUpperCase()}`; @@ -192,15 +162,3 @@ export const PROJECT_VIEWS = (projectId: string, projectRole: EUserPermissions | export const PROJECT_MEMBER_PREFERENCES = (projectId: string, projectRole: EUserPermissions | undefined) => `PROJECT_MEMBER_PREFERENCES_${projectId.toString().toUpperCase()}_${projectRole}`; - -export const PROJECT_WORKFLOWS = (projectId: string, projectRole: EUserPermissions | undefined) => - `PROJECT_WORKFLOWS_${projectId.toString().toUpperCase()}_${projectRole}`; - -export const EPICS_PROPERTIES_AND_OPTIONS = (projectId: string, projectRole: EUserPermissions | undefined) => - `EPICS_PROPERTIES_AND_OPTIONS_${projectId.toString().toUpperCase()}_${projectRole}`; - -export const WORK_ITEM_TYPES_PROPERTIES_AND_OPTIONS = (projectId: string, projectRole: EUserPermissions | undefined) => - `WORK_ITEM_TYPES_PROPERTIES_AND_OPTIONS_${projectId.toString().toUpperCase()}_${projectRole}`; - -export const PROJECT_MILESTONES = (projectId: string, projectRole: EUserPermissions | undefined) => - `PROJECT_MILESTONES_${projectId.toString().toUpperCase()}_${projectRole}`; diff --git a/packages/constants/src/metadata.ts b/packages/constants/src/metadata.ts index bd633a2b..6db1199e 100644 --- a/packages/constants/src/metadata.ts +++ b/packages/constants/src/metadata.ts @@ -5,19 +5,5 @@ */ export const SITE_NAME = "Pace | Simple, extensible, open-source project management tool."; -export const SITE_TITLE = "Pace | Simple, extensible, open-source project management tool."; export const SITE_DESCRIPTION = "Open-source project management tool to manage work items, cycles, and product roadmaps easily"; -export const SITE_KEYWORDS = - "software development, plan, ship, software, accelerate, code management, release management, project management, work items tracking, agile, scrum, kanban, collaboration"; -export const SITE_URL = "https://pace.yldm.ai/"; -export const TWITTER_USER_NAME = "Pace | Simple, extensible, open-source project management tool."; - -// Pace Sites Metadata -export const SPACE_SITE_NAME = "Pace Publish | Make your Pace boards and roadmaps public with just one click."; -export const SPACE_SITE_TITLE = "Pace Publish | Make your Pace boards public with one click"; -export const SPACE_SITE_DESCRIPTION = "Pace Publish is a customer feedback management tool built on Pace"; -export const SPACE_SITE_KEYWORDS = - "software development, customer feedback, software, accelerate, code management, release management, project management, work items tracking, agile, scrum, kanban, collaboration"; -export const SPACE_SITE_URL = "https://pace.yldm.ai/"; -export const SPACE_TWITTER_USER_NAME = ""; diff --git a/packages/constants/src/user.ts b/packages/constants/src/user.ts index 7b65c93f..e747539e 100644 --- a/packages/constants/src/user.ts +++ b/packages/constants/src/user.ts @@ -4,17 +4,6 @@ * See the LICENSE file for details. */ -export enum EAuthenticationPageType { - STATIC = "STATIC", - NOT_AUTHENTICATED = "NOT_AUTHENTICATED", - AUTHENTICATED = "AUTHENTICATED", -} - -export enum EInstancePageType { - PRE_SETUP = "PRE_SETUP", - POST_SETUP = "POST_SETUP", -} - export enum EUserStatus { ERROR = "ERROR", AUTHENTICATION_NOT_DONE = "AUTHENTICATION_NOT_DONE", @@ -39,27 +28,3 @@ export enum EUserPermissions { GUEST = 5, } export type TUserPermissions = EUserPermissions; - -export type TUserAllowedPermissionsObject = { - create: TUserPermissions[]; - update: TUserPermissions[]; - delete: TUserPermissions[]; - read: TUserPermissions[]; -}; -export type TUserAllowedPermissions = { - workspace: { - [key: string]: Partial; - }; - project: { - [key: string]: Partial; - }; -}; - -export const USER_ALLOWED_PERMISSIONS: TUserAllowedPermissions = { - workspace: { - dashboard: { - read: [EUserPermissions.ADMIN, EUserPermissions.MEMBER, EUserPermissions.GUEST], - }, - }, - project: {}, -}; diff --git a/packages/editor/package.json b/packages/editor/package.json index d284a731..808cff97 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,6 +1,6 @@ { "name": "@pace/editor", - "version": "1.4.42", + "version": "1.4.43", "private": true, "description": "Core Editor that powers Pace", "keywords": [ diff --git a/packages/hooks/package.json b/packages/hooks/package.json index 22de95a7..338ad769 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@pace/hooks", - "version": "1.4.42", + "version": "1.4.43", "private": true, "description": "React hooks that are shared across multiple apps internally", "license": "AGPL-3.0", diff --git a/packages/i18n/package.json b/packages/i18n/package.json index dfe7c608..8b288d0e 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@pace/i18n", - "version": "1.4.42", + "version": "1.4.43", "private": true, "description": "I18n shared across multiple apps internally", "license": "AGPL-3.0", @@ -19,6 +19,7 @@ "generate:types": "tsx scripts/generate-types.ts", "sync:check": "tsx scripts/sync-check.ts", "check:sync": "tsx scripts/sync-check.ts --ci", + "unused:check": "tsx scripts/unused-check.ts", "check:lint": "oxlint --max-warnings=3 .", "check:types": "pnpm run generate:types && tsc --noEmit", "check:format": "oxfmt --check .", diff --git a/packages/i18n/scripts/lib/source-scan.ts b/packages/i18n/scripts/lib/source-scan.ts new file mode 100644 index 00000000..e5971bf9 --- /dev/null +++ b/packages/i18n/scripts/lib/source-scan.ts @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +import fs from "node:fs"; +import path from "node:path"; +import { LOCALES_DIR } from "./locale-io.js"; + +/** Repo root, derived from the locales directory so the two move together if the package is ever relocated. */ +export const REPO_ROOT = path.resolve(LOCALES_DIR, "../../../.."); + +// Only the extensions that can call `t()`. Widening this is tempting -- the Go API, the SQL migrations and the webmanifest all contain strings that happen to equal a key -- but every match measured outside .ts/.tsx was a database column (`avatar`, `workspaces`, `background_color`, `label_name`) rather than a translation lookup, so they would only launder dead keys into looking alive. +const SOURCE_EXTENSIONS = new Set([".ts", ".tsx"]); + +const SKIPPED_DIRECTORIES = new Set([ + "node_modules", + "build", + "dist", + ".react-router", + ".turbo", + ".next", + ".vite", + "coverage", +]); + +// Written by `generate:types`. It spells every key in the catalogue as a string literal, so scanning it would report the entire catalogue as referenced. It is gitignored, but it exists on any machine that has run a build. +const SKIPPED_FILES = new Set(["keys.generated.ts"]); + +/** Every .ts/.tsx file under `dir`, skipping build output and the generated key union. */ +export function collectSourceFiles(dir: string, out: string[] = []): string[] { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const entryPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + if (SKIPPED_DIRECTORIES.has(entry.name)) continue; + // The locale JSON is the thing being checked, not a reference to it. + if (entryPath === LOCALES_DIR) continue; + collectSourceFiles(entryPath, out); + } else if (SOURCE_EXTENSIONS.has(path.extname(entry.name)) && !SKIPPED_FILES.has(entry.name)) { + out.push(entryPath); + } + } + return out; +} + +// Single-line string literals in all three quote styles, backticks only when the template has no interpolation. Anything containing a backslash is skipped rather than unescaped: no translation key contains one, so the only cost is ignoring literals that could never be keys. +const LITERAL_PATTERNS = [/"([^"\\\n]+)"/g, /'([^'\\\n]+)'/g, /`([^`\\\n$]+)`/g]; + +/** + * Yields every string literal in a source file, not just the arguments of `t(...)`. + * + * Keys reach `t` indirectly often enough -- through a label map, a strength-message table, a `labelKey` prop -- that matching on the call site would miss exactly the cases hardest to spot by eye. The same resolution therefore backs both the eager-namespace check (which asks "is this key loaded?") and the unused-key report (which asks "does anyone name this key?"), so neither can be more naive than the other. + * + * Duplicates are yielded; callers are expected to be resolving against a key set anyway. + */ +export function* collectStringLiterals(source: string): Generator { + for (const pattern of LITERAL_PATTERNS) { + for (const [, literal] of source.matchAll(pattern)) { + yield literal; + } + } +} + +// The literal head of an interpolated template, e.g. `admin.page.titles.${page}` -> "admin.page.titles.". +const TEMPLATE_PREFIX_PATTERN = /`([^`\\\n$]*)\$\{/g; + +/** + * Yields the static prefix of every interpolated template literal that could plausibly name a key subtree. + * + * A key built at runtime -- `translate(`admin.page.titles.${page}`)` in apps/admin/helpers/page-title.ts is the live example -- has no literal anywhere, so a literal scan alone would call the whole subtree dead. Requiring a dot in the prefix is what keeps this from matching every `${}` in the codebase; prefixes that name nothing are simply never consulted. + */ +export function* collectTemplatePrefixes(source: string): Generator { + for (const [, prefix] of source.matchAll(TEMPLATE_PREFIX_PATTERN)) { + if (prefix.includes(".")) { + yield prefix; + } + } +} diff --git a/packages/i18n/scripts/sync-check.ts b/packages/i18n/scripts/sync-check.ts index e0d264a7..0f0bdc87 100644 --- a/packages/i18n/scripts/sync-check.ts +++ b/packages/i18n/scripts/sync-check.ts @@ -12,6 +12,7 @@ import fs from "node:fs"; import path from "node:path"; import type { LocaleData } from "./lib/locale-io.js"; import { LOCALES_DIR, listLocales, loadLocale } from "./lib/locale-io.js"; +import { REPO_ROOT, collectSourceFiles, collectStringLiterals } from "./lib/source-scan.js"; import { ADMIN_NAMESPACES } from "../src/constants/namespaces.js"; // --------------------------------------------------------------------------- @@ -135,7 +136,7 @@ interface EagerNamespaceScope { // Apps that download fewer than all namespaces before their first render. Anything absent here loads every namespace and cannot go out of range. const EAGER_NAMESPACE_SCOPES: EagerNamespaceScope[] = [ - { app: "admin", dir: path.resolve(LOCALES_DIR, "../../../../apps/admin"), namespaces: ADMIN_NAMESPACES }, + { app: "admin", dir: path.resolve(REPO_ROOT, "apps/admin"), namespaces: ADMIN_NAMESPACES }, ]; interface OutOfScopeKey { @@ -144,27 +145,12 @@ interface OutOfScopeKey { file: string; } -const SOURCE_EXTENSIONS = new Set([".ts", ".tsx"]); -const SKIPPED_DIRECTORIES = new Set(["node_modules", "build", "dist", ".react-router", ".turbo"]); - -function collectSourceFiles(dir: string, out: string[] = []): string[] { - for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { - if (entry.isDirectory()) { - if (SKIPPED_DIRECTORIES.has(entry.name)) continue; - collectSourceFiles(path.join(dir, entry.name), out); - } else if (SOURCE_EXTENSIONS.has(path.extname(entry.name))) { - out.push(path.join(dir, entry.name)); - } - } - return out; -} - /** * Finds translation keys an app references but will not have loaded. * * Narrowing the eager namespace set is what keeps the admin console from downloading twenty-seven namespaces it has no screens for, but it removes the safety net that made any key resolve from anywhere: i18next answers an unloaded lookup with the key itself, silently, so the failure would be a raw `admin.page.titles.general` painted into the UI rather than an error. This turns that into a build failure. * - * Every double-quoted string literal in the app is considered, not just the arguments of `t(...)`. Keys reach `t` indirectly often enough -- through a label map, a strength-message table, a `labelKey` prop -- that matching on the call site would miss exactly the cases hardest to spot by eye. + * Every string literal in the app is considered, not just the arguments of `t(...)` -- see `collectStringLiterals`, which `unused-check.ts` resolves keys with as well so the two cannot disagree about what counts as a reference. */ function findOutOfScopeKeys(enData: LocaleData, scope: EagerNamespaceScope): OutOfScopeKey[] { const eager = new Set(scope.namespaces); @@ -180,7 +166,7 @@ function findOutOfScopeKeys(enData: LocaleData, scope: EagerNamespaceScope): Out const found = new Map(); for (const file of collectSourceFiles(scope.dir)) { const source = fs.readFileSync(file, "utf-8"); - for (const [, literal] of source.matchAll(/"([^"\\\n]+)"/g)) { + for (const literal of collectStringLiterals(source)) { const owners = keyOwners.get(literal); if (!owners || owners.some((ns) => eager.has(ns))) continue; if (!found.has(literal)) { diff --git a/packages/i18n/scripts/unused-check.ts b/packages/i18n/scripts/unused-check.ts new file mode 100644 index 00000000..d6c59b83 --- /dev/null +++ b/packages/i18n/scripts/unused-check.ts @@ -0,0 +1,194 @@ +/** + * Copyright (c) 2023-present Plane Software, Inc. and contributors + * SPDX-License-Identifier: AGPL-3.0-only + * See the LICENSE file for details. + */ + +// Usage: +// tsx packages/i18n/scripts/unused-check.ts # Report every unused key, always exit 0 +// tsx packages/i18n/scripts/unused-check.ts --summary # Counts and per-namespace totals only +// tsx packages/i18n/scripts/unused-check.ts --max=2400 # Exit 1 when the count climbs past a ratchet +// tsx packages/i18n/scripts/unused-check.ts --strict # Exit 1 if any key is unused (same as --max=0) +// +// Advisory by design. Unlike sync-check's other checks -- which compare one machine-readable set against another and are right or wrong -- this one infers intent from string literals, so it is a heuristic and can be wrong in both directions. Failing CI on it by default would break every PR that adds a label map on the day it is added, which is why the only exit-1 paths are opt-in. + +import fs from "node:fs"; +import path from "node:path"; +import { loadLocale } from "./lib/locale-io.js"; +import { REPO_ROOT, collectSourceFiles, collectStringLiterals, collectTemplatePrefixes } from "./lib/source-scan.js"; + +// Everything that can call `t()`. The Go API in apps/api cannot -- it has no access to the catalogue -- so it is covered only incidentally by living under apps/. +const SCAN_ROOTS = ["apps", "packages"]; + +/** Format a number with commas (e.g. 7712 -> "7,712"). */ +function fmt(n: number): string { + return n.toLocaleString("en-US"); +} + +interface ScanResult { + /** Keys named by a string literal somewhere in the scanned tree. */ + referenced: Set; + /** Keys with no literal, but under a prefix some interpolated template builds at runtime. */ + dynamic: Map; + /** Keys with neither signal. */ + unused: string[]; + /** Template prefixes that actually cover at least one key, for the reader to audit. */ + usedPrefixes: Map; + filesScanned: number; +} + +function scan(enKeys: Set): ScanResult { + const files: string[] = []; + for (const root of SCAN_ROOTS) { + collectSourceFiles(path.resolve(REPO_ROOT, root), files); + } + + const referenced = new Set(); + const prefixes = new Set(); + + for (const file of files) { + const source = fs.readFileSync(file, "utf-8"); + for (const literal of collectStringLiterals(source)) { + if (enKeys.has(literal)) referenced.add(literal); + } + for (const prefix of collectTemplatePrefixes(source)) { + prefixes.add(prefix); + } + } + + // Two signals, deliberately ordered: a literal is direct evidence, a prefix only says "something in this subtree is assembled at runtime". Keeping them apart is what lets a reviewer treat the prefix-covered keys as off-limits without treating them as proven live. + const dynamic = new Map(); + const unused: string[] = []; + const usedPrefixes = new Map(); + + const prefixList = [...prefixes]; + for (const key of [...enKeys].toSorted()) { + if (referenced.has(key)) continue; + const prefix = prefixList.find((p) => key.startsWith(p)); + if (prefix) { + dynamic.set(key, prefix); + usedPrefixes.set(prefix, (usedPrefixes.get(prefix) ?? 0) + 1); + } else { + unused.push(key); + } + } + + return { referenced, dynamic, unused, usedPrefixes, filesScanned: files.length }; +} + +/** Group keys by the namespace file they live in, so a whole dead namespace is visible as one line. */ +function groupByNamespace(keys: string[], owners: Map): Map { + const counts = new Map(); + for (const key of keys) { + for (const ns of owners.get(key) ?? []) { + counts.set(ns, (counts.get(ns) ?? 0) + 1); + } + } + return counts; +} + +/** Group keys by their first dot-segment, which is how a dead feature (`sso.`, `automations.`) shows up. */ +function groupByTopLevel(keys: string[]): Map { + const counts = new Map(); + for (const key of keys) { + const top = key.split(".")[0]!; + counts.set(top, (counts.get(top) ?? 0) + 1); + } + return counts; +} + +function parseMax(argv: string[]): number | undefined { + if (argv.includes("--strict")) return 0; + const flag = argv.find((a) => a.startsWith("--max=")); + if (!flag) return undefined; + const value = Number.parseInt(flag.slice("--max=".length), 10); + if (!Number.isInteger(value) || value < 0) { + console.error(`ERROR: --max expects a non-negative integer, got "${flag.slice("--max=".length)}"`); + process.exit(1); + } + return value; +} + +function main() { + const summaryOnly = process.argv.includes("--summary"); + const max = parseMax(process.argv); + + const enData = loadLocale("en"); + + const keyOwners = new Map(); + const namespaceTotals = new Map(); + for (const ns of enData.namespaces) { + namespaceTotals.set(ns.name, ns.keys.size); + for (const key of ns.keys) { + const owners = keyOwners.get(key); + if (owners) owners.push(ns.name); + else keyOwners.set(key, [ns.name]); + } + } + + const result = scan(enData.allKeys); + const total = enData.allKeys.size; + const share = total > 0 ? (result.unused.length / total) * 100 : 0; + + console.log("\n=== Unused Key Report ===\n"); + console.log( + ` scanned ${fmt(result.filesScanned)} source files under ${SCAN_ROOTS.map((r) => `${r}/`).join(", ")}` + ); + console.log(` en ${fmt(total)} keys`); + console.log(` referenced ${fmt(result.referenced.size)} named by a string literal`); + console.log(` dynamic ${fmt(result.dynamic.size)} reachable only through a template-literal prefix`); + console.log(` UNUSED ${fmt(result.unused.length)} (${share.toFixed(1)}% of en) — no literal, no prefix\n`); + + if (result.usedPrefixes.size > 0) { + console.log("KEYS BUILT AT RUNTIME (counted as used — do not delete these without reading the call site):"); + for (const [prefix, count] of [...result.usedPrefixes].toSorted((a, b) => b[1] - a[1])) { + console.log(` ${String(count).padStart(5)} ${prefix}\${...}`); + } + console.log(); + } + + const byNamespace = groupByNamespace(result.unused, keyOwners); + if (byNamespace.size > 0) { + console.log("UNUSED BY NAMESPACE:"); + for (const [ns, count] of [...byNamespace].toSorted((a, b) => b[1] - a[1])) { + const nsTotal = namespaceTotals.get(ns) ?? 0; + const pct = nsTotal > 0 ? ((count / nsTotal) * 100).toFixed(0) : "0"; + console.log(` ${String(count).padStart(5)} of ${String(nsTotal).padEnd(5)} (${pct.padStart(3)}%) ${ns}.json`); + } + console.log(); + } + + const byTopLevel = groupByTopLevel(result.unused); + if (byTopLevel.size > 0) { + console.log("UNUSED BY TOP-LEVEL PREFIX (>= 10 keys):"); + for (const [top, count] of [...byTopLevel].toSorted((a, b) => b[1] - a[1])) { + if (count < 10) continue; + console.log(` ${String(count).padStart(5)} ${top}`); + } + console.log(); + } + + if (!summaryOnly && result.unused.length > 0) { + console.log("UNUSED KEYS:"); + for (const key of result.unused) { + console.log(` - ${key} (${(keyOwners.get(key) ?? []).join(", ")})`); + } + console.log(); + } + + console.log( + "This is a heuristic, not a fact: a key is called unused when no string literal and no interpolated template prefix in apps/ or packages/ names it. It can be wrong in both directions — a key assembled from parts the prefix scan does not model reads as unused, and a key that happens to equal an unrelated literal reads as used. Before deleting anything, prefer whole feature subtrees whose feature does not exist in this repo over scattered individual keys, confirm the prefix appears nowhere in apps/, and remember that deleting from `en` means deleting the same key from all twenty locales under the rules in the translate skill." + ); + + if (max !== undefined && result.unused.length > max) { + console.log(`\nFAIL: ${fmt(result.unused.length)} unused keys exceeds the --max=${fmt(max)} ratchet.`); + process.exit(1); + } +} + +try { + main(); +} catch (err) { + console.error("Unused check failed:", err); + process.exit(1); +} diff --git a/packages/i18n/src/core/instance.ts b/packages/i18n/src/core/instance.ts index 17410093..a390d274 100644 --- a/packages/i18n/src/core/instance.ts +++ b/packages/i18n/src/core/instance.ts @@ -23,6 +23,10 @@ const EAGER_NAMESPACES: readonly TNamespace[] = export const i18nInstance: I18nInstance = i18n.createInstance(); // The plugin registration and the `init` below run at import time, which is the whole contract of this module: importing @pace/i18n anywhere is what configures the instance. That is why packages/i18n deliberately has no `sideEffects: false` in its package.json, unlike the pure-data packages around it -- marking it pure would let a bundler drop this module when a consumer only reads a re-exported constant from the barrel, and the failure would be an unconfigured i18next at runtime rather than a build error. +// +// `../locales` resolves through a symlink that is committed to git, and the build depends on it. tsdown does not rewrite this template specifier, so the emitted dist/index.js contains it verbatim and the app's bundler resolves it relative to dist/ -- that is packages/i18n/locales, not the src/locales where the JSON actually lives. What bridges the two is `packages/i18n/locales -> src/locales`, a mode 120000 entry in the index since the first commit (`git ls-files -s packages/i18n/locales`). Nothing copies the JSON into dist, and package.json exports no `./locales/*`, so those 600 files enter the bundle graph through a path the manifest does not describe. +// +// Consequences worth knowing before touching this line, the tsdown entry layout, or the `../` depth: a clone without symlink support (Windows without `core.symlinks`) and any change that alters how deep dist/index.js sits both break every namespace fetch, and i18next answers an unresolvable lookup with the key itself -- so the symptom is raw `issue.title` strings painted into a UI that never logs an error, the same failure mode ./translate.ts documents at length for its `meta` exports. i18nInstance .use(ICU) .use(initReactI18next) diff --git a/packages/propel/package.json b/packages/propel/package.json index 7b2f91f3..af113e6f 100644 --- a/packages/propel/package.json +++ b/packages/propel/package.json @@ -1,6 +1,6 @@ { "name": "@pace/propel", - "version": "1.4.42", + "version": "1.4.43", "private": true, "license": "AGPL-3.0", "type": "module", diff --git a/packages/services/package.json b/packages/services/package.json index e38a8a02..fd29baa9 100644 --- a/packages/services/package.json +++ b/packages/services/package.json @@ -1,6 +1,6 @@ { "name": "@pace/services", - "version": "1.4.42", + "version": "1.4.43", "private": true, "license": "AGPL-3.0", "type": "module", diff --git a/packages/services/src/cycle/cycle-analytics.service.ts b/packages/services/src/cycle/cycle-analytics.service.ts deleted file mode 100644 index 38ef4af7..00000000 --- a/packages/services/src/cycle/cycle-analytics.service.ts +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { API_BASE_URL } from "@pace/constants"; -import type { TCycleDistribution, TProgressSnapshot, TCycleEstimateDistribution } from "@pace/types"; -import { APIService } from "../api.service"; - -/** - * Service class for managing cycles within a workspace and project context. - * Extends APIService to handle HTTP requests to the cycle-related endpoints. - * @extends {APIService} - */ -export class CycleAnalyticsService extends APIService { - constructor(BASE_URL?: string) { - super(BASE_URL || API_BASE_URL); - } - - /** - * Retrieves analytics for active cycles in a workspace. - * @param {string} workspaceSlug - The workspace identifier - * @param {string} projectId - The project identifier - * @param {string} cycleId - The cycle identifier - * @param {string} [analytic_type="points"] - The type of analytics to retrieve - * @returns {Promise} The cycle analytics data - * @throws {Error} If the request fails - */ - async workspaceActiveCyclesAnalytics( - workspaceSlug: string, - projectId: string, - cycleId: string, - analytic_type: string = "points" - ): Promise { - return this.get( - `/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/analytics?type=${analytic_type}` - ) - .then((res) => res?.data) - .catch((err) => { - throw err?.response?.data; - }); - } - - /** - * Retrieves progress data for active cycles. - * @param {string} workspaceSlug - The workspace identifier - * @param {string} projectId - The project identifier - * @param {string} cycleId - The cycle identifier - * @returns {Promise} The cycle progress data - * @throws {Error} If the request fails - */ - async workspaceActiveCyclesProgress( - workspaceSlug: string, - projectId: string, - cycleId: string - ): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/progress/`) - .then((res) => res?.data) - .catch((err) => { - throw err?.response?.data; - }); - } - - /** - * Retrieves advanced progress data for active cycles (Pro feature). - * @param {string} workspaceSlug - The workspace identifier - * @param {string} projectId - The project identifier - * @param {string} cycleId - The cycle identifier - * @returns {Promise} The detailed cycle progress data - * @throws {Error} If the request fails - */ - async workspaceActiveCyclesProgressPro( - workspaceSlug: string, - projectId: string, - cycleId: string - ): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-progress/`) - .then((res) => res?.data) - .catch((err) => { - throw err?.response?.data; - }); - } -} diff --git a/packages/services/src/cycle/cycle-operations.service.ts b/packages/services/src/cycle/cycle-operations.service.ts deleted file mode 100644 index ae503f8e..00000000 --- a/packages/services/src/cycle/cycle-operations.service.ts +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { API_BASE_URL } from "@pace/constants"; -import { APIService } from "../api.service"; - -export class CycleOperationsService extends APIService { - constructor(BASE_URL?: string) { - super(BASE_URL || API_BASE_URL); - } - - /** - * Adds a cycle to user favorites. - * @param {string} workspaceSlug - The workspace identifier - * @param {string} projectId - The project identifier - * @param {{cycle: string}} data - The favorite cycle data - * @returns {Promise} The response data - * @throws {Error} If the request fails - */ - async addToFavorites( - workspaceSlug: string, - projectId: string, - data: { - cycle: string; - } - ): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-cycles/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Removes a cycle from user favorites. - * @param {string} workspaceSlug - The workspace identifier - * @param {string} projectId - The project identifier - * @param {string} cycleId - The cycle identifier - * @returns {Promise} The removal response - * @throws {Error} If the request fails - */ - async removeFromFavorites(workspaceSlug: string, projectId: string, cycleId: string): Promise { - return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-cycles/${cycleId}/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Transfers issues between cycles. - * @param {string} workspaceSlug - The workspace identifier - * @param {string} projectId - The project identifier - * @param {string} cycleId - The source cycle identifier - * @param {{new_cycle_id: string}} data - The target cycle data - * @returns {Promise} The transfer response - * @throws {Error} If the request fails - */ - async transferIssues( - workspaceSlug: string, - projectId: string, - cycleId: string, - data: { - new_cycle_id: string; - } - ): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/transfer-issues/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } -} diff --git a/packages/services/src/cycle/index.ts b/packages/services/src/cycle/index.ts index d53702a1..55353357 100644 --- a/packages/services/src/cycle/index.ts +++ b/packages/services/src/cycle/index.ts @@ -4,8 +4,6 @@ * See the LICENSE file for details. */ -export * from "./cycle-analytics.service"; export * from "./cycle-archive.service"; -export * from "./cycle-operations.service"; export * from "./cycle.service"; export * from "./sites-cycle.service"; diff --git a/packages/services/src/dashboard/dashboard.service.ts b/packages/services/src/dashboard/dashboard.service.ts deleted file mode 100644 index 84abe32d..00000000 --- a/packages/services/src/dashboard/dashboard.service.ts +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { API_BASE_URL } from "@pace/constants"; -import type { THomeDashboardResponse, TWidget, TWidgetStatsResponse, TWidgetStatsRequestParams } from "@pace/types"; -import { APIService } from "../api.service"; -// helpers -// types - -export class DashboardService extends APIService { - constructor() { - super(API_BASE_URL); - } - - async getHomeWidgets(workspaceSlug: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/dashboard/`, { - params: { - dashboard_type: "home", - }, - }) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - async getWidgetStats( - workspaceSlug: string, - dashboardId: string, - params: TWidgetStatsRequestParams - ): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/dashboard/${dashboardId}/`, { - params, - }) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - async retrieve(dashboardId: string): Promise { - return this.get(`/api/dashboard/${dashboardId}/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - async updateWidget(dashboardId: string, widgetId: string, data: Partial): Promise { - return this.patch(`/api/dashboard/${dashboardId}/widgets/${widgetId}/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } -} diff --git a/packages/services/src/dashboard/index.ts b/packages/services/src/dashboard/index.ts deleted file mode 100644 index 52a2e867..00000000 --- a/packages/services/src/dashboard/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -export * from "./dashboard.service"; diff --git a/packages/services/src/index.ts b/packages/services/src/index.ts index e23ed816..34c7bcf2 100644 --- a/packages/services/src/index.ts +++ b/packages/services/src/index.ts @@ -9,7 +9,6 @@ export * from "./ai"; export * from "./analytics"; export * from "./auth"; export * from "./cycle"; -export * from "./dashboard"; export * from "./developer"; export * from "./file"; export * from "./instance"; diff --git a/packages/services/src/instance/app-config.service.ts b/packages/services/src/instance/app-config.service.ts deleted file mode 100644 index cfe698a6..00000000 --- a/packages/services/src/instance/app-config.service.ts +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -// services -import { API_BASE_URL } from "@pace/constants"; -import { APIService } from "../api.service"; -// helper -// types -// FIXME: -// import { TAppConfig } from "@pace/types"; - -export class AppConfigService extends APIService { - constructor() { - super(API_BASE_URL); - } - - async envConfig(): Promise { - return this.get("/api/configs/", { - headers: { "Content-Type": "application/json" }, - }) - .then((response) => response.data) - .catch((error) => { - throw error?.response?.data; - }); - } -} diff --git a/packages/services/src/instance/index.ts b/packages/services/src/instance/index.ts index 90333746..5296407a 100644 --- a/packages/services/src/instance/index.ts +++ b/packages/services/src/instance/index.ts @@ -4,6 +4,5 @@ * See the LICENSE file for details. */ -export * from "./app-config.service"; export * from "./instance.service"; export * from "./timezone.service"; diff --git a/packages/services/src/module/index.ts b/packages/services/src/module/index.ts index 210c3ab1..4fe1d7d1 100644 --- a/packages/services/src/module/index.ts +++ b/packages/services/src/module/index.ts @@ -4,8 +4,6 @@ * See the LICENSE file for details. */ -export * from "./link.service"; export * from "./module-archive.service"; export * from "./module.service"; -export * from "./operations.service"; export * from "./sites-module.service"; diff --git a/packages/services/src/module/link.service.ts b/packages/services/src/module/link.service.ts deleted file mode 100644 index 7811cf52..00000000 --- a/packages/services/src/module/link.service.ts +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -// types -import type { ILinkDetails, ModuleLink } from "@pace/types"; -// services -import { APIService } from "../api.service"; - -/** - * Service class for handling module link related operations. - * Extends the base APIService class to interact with module link endpoints. - */ -export class ModuleLinkService extends APIService { - /** - * Creates an instance of ModuleLinkService. - * @param {string} baseURL - The base URL for the API endpoints - */ - - /** - * Creates a new module link. - * @param {string} workspaceSlug - The unique identifier for the workspace - * @param {string} projectId - The unique identifier for the project - * @param {string} moduleId - The unique identifier for the module - * @param {Partial} data - The module link data to be created - * @returns {Promise} The created module link details - * @throws {Error} When the API request fails - */ - async create( - workspaceSlug: string, - projectId: string, - moduleId: string, - data: Partial - ): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response; - }); - } - - /** - * Updates an existing module link. - * @param {string} workspaceSlug - The unique identifier for the workspace - * @param {string} projectId - The unique identifier for the project - * @param {string} moduleId - The unique identifier for the module - * @param {string} linkId - The unique identifier for the link to update - * @param {Partial} data - The module link data to be updated - * @returns {Promise} The updated module link details - * @throws {Error} When the API request fails - */ - async update( - workspaceSlug: string, - projectId: string, - moduleId: string, - linkId: string, - data: Partial - ): Promise { - return this.patch( - `/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/${linkId}/`, - data - ) - .then((response) => response?.data) - .catch((error) => { - throw error?.response; - }); - } - - /** - * Deletes a module link. - * @param {string} workspaceSlug - The unique identifier for the workspace - * @param {string} projectId - The unique identifier for the project - * @param {string} moduleId - The unique identifier for the module - * @param {string} linkId - The unique identifier for the link to delete - * @returns {Promise} Response data from the server - * @throws {Error} When the API request fails - */ - async destroy(workspaceSlug: string, projectId: string, moduleId: string, linkId: string): Promise { - return this.delete( - `/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/${linkId}/` - ) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } -} diff --git a/packages/services/src/module/operations.service.ts b/packages/services/src/module/operations.service.ts deleted file mode 100644 index 5d29926f..00000000 --- a/packages/services/src/module/operations.service.ts +++ /dev/null @@ -1,148 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -// types -// import type { IModule, ILinkDetails, ModuleLink, TIssuesResponse } from "@pace/types"; -// services -import { APIService } from "../api.service"; - -export class ModuleOperationService extends APIService { - /** - * Add issues to a module - * @param {string} workspaceSlug - The slug of the workspace - * @param {string} projectId - The ID of the project - * @param {string} moduleId - The ID of the module - * @param {object} data - The data to be sent in the request body - * @param {string[]} data.issues - The IDs of the issues to be added - * @returns {Promise} - */ - async addIssuesToModule( - workspaceSlug: string, - projectId: string, - moduleId: string, - data: { issues: string[] } - ): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/issues/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Add modules to an issue - * @param {string} workspaceSlug - The slug of the workspace - * @param {string} projectId - The ID of the project - * @param {string} issueId - The ID of the issue - * @param {object} data - The data to be sent in the request body - * @param {string[]} data.modules - The IDs of the modules to be added - * @param {string[]} [data.removed_modules] - The IDs of the modules to be removed - * @returns {Promise} - */ - async addModulesToIssue( - workspaceSlug: string, - projectId: string, - issueId: string, - data: { modules: string[]; removed_modules?: string[] } - ): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/modules/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Remove issues from a module - * @param {string} workspaceSlug - The slug of the workspace - * @param {string} projectId - The ID of the project - * @param {string} moduleId - The ID of the module - * @param {string[]} issueIds - The IDs of the issues to be removed - * @returns {Promise} - */ - async removeIssuesFromModuleBulk( - workspaceSlug: string, - projectId: string, - moduleId: string, - issueIds: string[] - ): Promise { - const promiseDataUrls: any = []; - issueIds.forEach((issueId) => { - promiseDataUrls.push( - this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/issues/${issueId}/`) - ); - }); - await Promise.all(promiseDataUrls) - .then((response) => response) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Remove modules from an issue - * @param {string} workspaceSlug - The slug of the workspace - * @param {string} projectId - The ID of the project - * @param {string} issueId - The ID of the issue - * @param {string[]} moduleIds - The IDs of the modules to be removed - * @returns {Promise} - */ - async removeModulesFromIssueBulk( - workspaceSlug: string, - projectId: string, - issueId: string, - moduleIds: string[] - ): Promise { - const promiseDataUrls: any = []; - moduleIds.forEach((moduleId) => { - promiseDataUrls.push( - this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/issues/${issueId}/`) - ); - }); - await Promise.all(promiseDataUrls) - .then((response) => response) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Add a module to favorites - * @param {string} workspaceSlug - The slug of the workspace - * @param {string} projectId - The ID of the project - * @param {object} data - The data to be sent in the request body - * @param {string} data.module - The ID of the module to be added - * @returns {Promise} - */ - async addModuleToFavorites( - workspaceSlug: string, - projectId: string, - data: { - module: string; - } - ): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-modules/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Remove a module from favorites - * @param {string} workspaceSlug - The slug of the workspace - * @param {string} projectId - The ID of the project - * @param {string} moduleId - The ID of the module to be removed - * @returns {Promise} - */ - async removeModuleFromFavorites(workspaceSlug: string, projectId: string, moduleId: string): Promise { - return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-favorite-modules/${moduleId}/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } -} diff --git a/packages/services/src/project/index.ts b/packages/services/src/project/index.ts index fa5384c0..72636736 100644 --- a/packages/services/src/project/index.ts +++ b/packages/services/src/project/index.ts @@ -14,5 +14,4 @@ export * from "./project-publish.service"; export * from "./project-state.service"; export * from "./project.service"; export * from "./sites-publish.service"; -export * from "./view.service"; export * from "./workspace-view.service"; diff --git a/packages/services/src/project/view.service.ts b/packages/services/src/project/view.service.ts deleted file mode 100644 index 5c2f847c..00000000 --- a/packages/services/src/project/view.service.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -// pace imports -import { API_BASE_URL } from "@pace/constants"; -// api services -import { APIService } from "../api.service"; - -export class ProjectViewService extends APIService { - /** - * Creates an instance of ProjectViewService - * @param {string} baseUrl - The base URL for API requests - */ - constructor(BASE_URL?: string) { - super(BASE_URL || API_BASE_URL); - } -} diff --git a/packages/services/src/user/favorite.service.ts b/packages/services/src/user/favorite.service.ts deleted file mode 100644 index 6eee2a88..00000000 --- a/packages/services/src/user/favorite.service.ts +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { API_BASE_URL } from "@pace/constants"; -import type { IFavorite } from "@pace/types"; -import { APIService } from "../api.service"; - -/** - * Service class for managing user favorites - * Handles operations for adding, updating, removing, and retrieving user favorites within a workspace - * @extends {APIService} - */ -export class UserFavoriteService extends APIService { - constructor(BASE_URL?: string) { - super(BASE_URL || API_BASE_URL); - } - - /** - * Adds a new item to user favorites - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @param {Partial} data - Favorite item data to be added - * @returns {Promise} Promise resolving to the created favorite item - * @throws {Error} If the API request fails - */ - async add(workspaceSlug: string, data: Partial): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/user-favorites/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response; - }); - } - - /** - * Updates an existing favorite item - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @param {string} favoriteId - The unique identifier for the favorite item - * @param {Partial} data - Updated favorite item data - * @returns {Promise} Promise resolving to the updated favorite item - * @throws {Error} If the API request fails - */ - async update(workspaceSlug: string, favoriteId: string, data: Partial): Promise { - return this.patch(`/api/workspaces/${workspaceSlug}/user-favorites/${favoriteId}/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response; - }); - } - - /** - * Removes an item from user favorites - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @param {string} favoriteId - The unique identifier for the favorite item to remove - * @returns {Promise} Promise resolving when the favorite item is removed - * @throws {Error} If the API request fails - */ - async remove(workspaceSlug: string, favoriteId: string): Promise { - return this.delete(`/api/workspaces/${workspaceSlug}/user-favorites/${favoriteId}/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response; - }); - } - - /** - * Retrieves all favorite items for a user in a workspace - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @returns {Promise} Promise resolving to array of favorite items - * @throws {Error} If the API request fails - * @remarks This method includes the 'all' parameter to retrieve all favorites - */ - async list(workspaceSlug: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/user-favorites/`, { - params: { - all: true, - }, - }) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Retrieves grouped favorite items for a specific favorite in a workspace - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @param {string} favoriteId - The unique identifier for the favorite item to get grouped items for - * @returns {Promise} Promise resolving to array of grouped favorite items - * @throws {Error} If the API request fails - */ - async groupedList(workspaceSlug: string, favoriteId: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/user-favorites/${favoriteId}/group/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } -} diff --git a/packages/services/src/user/index.ts b/packages/services/src/user/index.ts index f6fd9d4f..df4aea26 100644 --- a/packages/services/src/user/index.ts +++ b/packages/services/src/user/index.ts @@ -4,7 +4,6 @@ * See the LICENSE file for details. */ -export * from "./favorite.service"; export * from "./sites-member.service"; export * from "./sticky.service"; export * from "./user.service"; diff --git a/packages/services/src/workspace/index.ts b/packages/services/src/workspace/index.ts index 41def323..e4e50473 100644 --- a/packages/services/src/workspace/index.ts +++ b/packages/services/src/workspace/index.ts @@ -6,9 +6,6 @@ export * from "./app-installation.service"; export * from "./instance-workspace.service"; -export * from "./invitation.service"; -export * from "./member.service"; export * from "./notification.service"; -export * from "./view.service"; export * from "./workspace-draft.service"; export * from "./workspace.service"; diff --git a/packages/services/src/workspace/invitation.service.ts b/packages/services/src/workspace/invitation.service.ts deleted file mode 100644 index a21458b1..00000000 --- a/packages/services/src/workspace/invitation.service.ts +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { API_BASE_URL } from "@pace/constants"; -import type { IWorkspaceMemberInvitation, IWorkspaceBulkInviteFormData, IWorkspaceMember } from "@pace/types"; -import { APIService } from "../api.service"; - -/** - * Service class for managing workspace invitations - * Handles operations related to inviting users to workspaces and managing invitations - * @extends {APIService} - */ -export class WorkspaceInvitationService extends APIService { - constructor(BASE_URL?: string) { - super(BASE_URL || API_BASE_URL); - } - - /** - * Retrieves all workspace invitations for the current user - * @returns {Promise} Promise resolving to array of workspace invitations - * @throws {Error} If the API request fails - */ - async userInvitations(): Promise { - return this.get("/api/users/me/workspaces/invitations/") - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Retrieves all invitations for a specific workspace - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @returns {Promise} Promise resolving to array of workspace invitations - * @throws {Error} If the API request fails - */ - async workspaceInvitations(workspaceSlug: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/invitations/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Sends bulk invitations to users for a workspace - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @param {IWorkspaceBulkInviteFormData} data - Bulk invitation data containing user information - * @returns {Promise} Promise resolving to the invitation response - * @throws {Error} If the API request fails - */ - async invite(workspaceSlug: string, data: IWorkspaceBulkInviteFormData): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/invitations/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Update Invitation - * @param workspaceSlug - * @param invitationId - * @param data - * @returns - */ - async update(workspaceSlug: string, invitationId: string, data: Partial): Promise { - return this.patch(`/api/workspaces/${workspaceSlug}/invitations/${invitationId}/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Delete Workspace invitation - * @param workspaceSlug - * @param invitationId - * @returns - */ - async destroy(workspaceSlug: string, invitationId: string): Promise { - return this.delete(`/api/workspaces/${workspaceSlug}/invitations/${invitationId}/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Accepts an invitation to join a workspace - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @param {string} invitationId - The unique identifier for the invitation - * @param {any} data - Additional data required for joining the workspace - * @returns {Promise} Promise resolving to the join response - * @throws {Error} If the API request fails - */ - async join(workspaceSlug: string, invitationId: string, data: any): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/invitations/${invitationId}/join/`, data, { - headers: {}, - }) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Accepts multiple workspace invitations at once - * @param {any} data - Data containing information about invitations to accept - * @returns {Promise} Promise resolving to the bulk join response - * @throws {Error} If the API request fails - */ - async joinMany(data: any): Promise { - return this.post("/api/users/me/workspaces/invitations/", data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } -} diff --git a/packages/services/src/workspace/member.service.ts b/packages/services/src/workspace/member.service.ts deleted file mode 100644 index ff341e15..00000000 --- a/packages/services/src/workspace/member.service.ts +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { API_BASE_URL } from "@pace/constants"; -import type { IWorkspaceMemberMe, IWorkspaceMember, IUserProjectsRole } from "@pace/types"; -import { APIService } from "../api.service"; - -/** - * Service class for managing workspace members - * Handles operations related to workspace membership, including member information, - * updates, deletions, and role management - * @extends {APIService} - */ -export class WorkspaceMemberService extends APIService { - /** - * Creates an instance of WorkspaceMemberService - * @param {string} baseUrl - The base URL for API requests - */ - constructor(BASE_URL?: string) { - super(BASE_URL || API_BASE_URL); - } - - /** - * Retrieves current user's information for a specific workspace - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @returns {Promise} Promise resolving to current user's workspace member information - * @throws {Error} If the API request fails - */ - async myInfo(workspaceSlug: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/workspace-members/me/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response; - }); - } - - /** - * Retrieves all members of a specific workspace - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @returns {Promise} Promise resolving to array of workspace members - * @throws {Error} If the API request fails - */ - async list(workspaceSlug: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/members/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Updates a workspace member's information - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @param {string} memberId - The unique identifier for the member - * @param {Partial} data - Updated member data - * @returns {Promise} Promise resolving to the updated member information - * @throws {Error} If the API request fails - */ - async update(workspaceSlug: string, memberId: string, data: Partial): Promise { - return this.patch(`/api/workspaces/${workspaceSlug}/members/${memberId}/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Removes a member from a workspace - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @param {string} memberId - The unique identifier for the member to remove - * @returns {Promise} Promise resolving to the deletion response - * @throws {Error} If the API request fails - */ - async destroy(workspaceSlug: string, memberId: string): Promise { - return this.delete(`/api/workspaces/${workspaceSlug}/members/${memberId}/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - /** - * Retrieves the current user's project roles within a workspace - * @param {string} workspaceSlug - The unique slug identifier for the workspace - * @returns {Promise} Promise resolving to user's project roles - * @throws {Error} If the API request fails - */ - async getWorkspaceUserProjectsRole(workspaceSlug: string): Promise { - return this.get(`/api/users/me/workspaces/${workspaceSlug}/project-roles/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } -} diff --git a/packages/services/src/workspace/view.service.ts b/packages/services/src/workspace/view.service.ts deleted file mode 100644 index 4c149439..00000000 --- a/packages/services/src/workspace/view.service.ts +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { API_BASE_URL } from "@pace/constants"; -import type { IWorkspaceView, TIssuesResponse } from "@pace/types"; -import { APIService } from "../api.service"; - -export class WorkspaceViewService extends APIService { - /** - * Creates an instance of WorkspaceViewService - * @param {string} baseUrl - The base URL for API requests - */ - constructor(BASE_URL?: string) { - super(BASE_URL || API_BASE_URL); - } - - async create(workspaceSlug: string, data: Partial): Promise { - return this.post(`/api/workspaces/${workspaceSlug}/views/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - async update(workspaceSlug: string, viewId: string, data: Partial): Promise { - return this.patch(`/api/workspaces/${workspaceSlug}/views/${viewId}/`, data) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - async destroy(workspaceSlug: string, viewId: string): Promise { - return this.delete(`/api/workspaces/${workspaceSlug}/views/${viewId}/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - async list(workspaceSlug: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/views/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - async retrieve(workspaceSlug: string, viewId: string): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/views/${viewId}/`) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } - - async getViewIssues(workspaceSlug: string, params: any, config = {}): Promise { - return this.get( - `/api/workspaces/${workspaceSlug}/issues/`, - { - params, - }, - config - ) - .then((response) => response?.data) - .catch((error) => { - throw error?.response?.data; - }); - } -} diff --git a/packages/shared-state/package.json b/packages/shared-state/package.json index eecb2866..0a1a9b76 100644 --- a/packages/shared-state/package.json +++ b/packages/shared-state/package.json @@ -1,6 +1,6 @@ { "name": "@pace/shared-state", - "version": "1.4.42", + "version": "1.4.43", "private": true, "description": "Shared state shared across multiple apps internally", "license": "AGPL-3.0", diff --git a/packages/shared-state/src/store/user.store.ts b/packages/shared-state/src/store/user.store.ts deleted file mode 100644 index b288d25a..00000000 --- a/packages/shared-state/src/store/user.store.ts +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { makeObservable, observable } from "mobx"; -import type { IWorkspaceStore } from "./workspace.store"; - -export interface IUserStore { - user: any; - workspaces: Map; - isLoading: boolean; - error: any; -} - -export class UserStore implements IUserStore { - user: any = null; - workspaces: Map = new Map(); - isLoading: boolean = false; - error: any = null; - - constructor() { - makeObservable(this, { - user: observable.ref, - workspaces: observable, - isLoading: observable.ref, - error: observable.ref, - }); - } -} - -// userStore.ts - -// class UserStore { -// user: User | null = null; -// workspaces: Workspace[] = []; -// isLoading = false; -// error: string | null = null; -// private indexedDBService: IndexedDBService; - -// constructor() { -// makeAutoObservable(this); -// this.indexedDBService = new IndexedDBService(); -// this.init(); -// } - -// private async init() { -// try { -// await this.indexedDBService.init(); -// await this.loadWorkspacesFromIndexedDB(); -// } catch (error) { -// runInAction(() => { -// this.error = "Failed to initialize store"; -// console.error("Store initialization error:", error); -// }); -// } -// } - -// setUser(user: User | null) { -// this.user = user; -// } - -// async loadWorkspacesFromIndexedDB() { -// try { -// const workspaces = await this.indexedDBService.getWorkspaces(); -// runInAction(() => { -// this.workspaces = workspaces; -// }); -// } catch (error) { -// runInAction(() => { -// this.error = "Failed to load workspaces from IndexedDB"; -// console.error("Load workspaces error:", error); -// }); -// } -// } - -// async fetchAndSyncWorkspaces() { -// this.isLoading = true; -// this.error = null; - -// try { -// // Simulate API call to fetch workspaces -// const response = await fetch("/api/workspaces"); -// const workspaces = await response.json(); - -// // Save to IndexedDB -// await this.indexedDBService.saveWorkspaces(workspaces); - -// // Update MobX store -// runInAction(() => { -// this.workspaces = workspaces; -// this.isLoading = false; -// }); -// } catch (error) { -// runInAction(() => { -// this.error = "Failed to fetch workspaces"; -// this.isLoading = false; -// console.error("Fetch workspaces error:", error); -// }); -// } -// } - -// // Additional methods for workspace management -// async addWorkspace(workspace: Omit) { -// this.isLoading = true; -// this.error = null; - -// try { -// // Simulate API call to create workspace -// const response = await fetch("/api/workspaces", { -// method: "POST", -// body: JSON.stringify(workspace), -// }); -// const newWorkspace = await response.json(); - -// // Update local storage and state -// const updatedWorkspaces = [...this.workspaces, newWorkspace]; -// await this.indexedDBService.saveWorkspaces(updatedWorkspaces); - -// runInAction(() => { -// this.workspaces.push(newWorkspace); -// this.isLoading = false; -// }); -// } catch (error) { -// runInAction(() => { -// this.error = "Failed to add workspace"; -// this.isLoading = false; -// console.error("Add workspace error:", error); -// }); -// } -// } - -// logout() { -// this.user = null; -// this.workspaces = []; -// // Optionally clear IndexedDB data -// this.indexedDBService.init().then(() => { -// this.indexedDBService.saveWorkspaces([]); -// }); -// } -// } diff --git a/packages/shared-state/src/store/workspace.store.ts b/packages/shared-state/src/store/workspace.store.ts deleted file mode 100644 index 74521cb6..00000000 --- a/packages/shared-state/src/store/workspace.store.ts +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -import { makeObservable, observable } from "mobx"; - -export interface IWorkspaceStore { - id: string; - name: string; - createdAt: string; - updatedAt: string; -} - -export class WorkspaceStore implements IWorkspaceStore { - id: string; - name: string; - createdAt: string; - updatedAt: string; - - constructor(data: IWorkspaceStore) { - makeObservable(this, { - id: observable.ref, - name: observable.ref, - createdAt: observable.ref, - updatedAt: observable.ref, - }); - this.id = data.id; - this.name = data.name; - this.createdAt = data.createdAt; - this.updatedAt = data.updatedAt; - } -} diff --git a/packages/tailwind-config/package.json b/packages/tailwind-config/package.json index a101482c..8a5cb175 100644 --- a/packages/tailwind-config/package.json +++ b/packages/tailwind-config/package.json @@ -1,6 +1,6 @@ { "name": "@pace/tailwind-config", - "version": "1.4.42", + "version": "1.4.43", "private": true, "description": "common tailwind configuration across monorepo", "license": "AGPL-3.0", diff --git a/packages/types/package.json b/packages/types/package.json index 1f04b183..38ddbc59 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@pace/types", - "version": "1.4.42", + "version": "1.4.43", "private": true, "license": "AGPL-3.0", "type": "module", diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index ed43cc22..0c40a8e9 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@pace/typescript-config", - "version": "1.4.42", + "version": "1.4.43", "private": true, "license": "AGPL-3.0", "files": [ diff --git a/packages/ui/package.json b/packages/ui/package.json index 97bb5397..3125215f 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@pace/ui", - "version": "1.4.42", + "version": "1.4.43", "private": true, "description": "UI components shared across multiple apps internally", "license": "AGPL-3.0", diff --git a/packages/utils/package.json b/packages/utils/package.json index d8d2bd27..d0070cd9 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@pace/utils", - "version": "1.4.42", + "version": "1.4.43", "private": true, "description": "Helper functions shared across multiple apps internally", "license": "AGPL-3.0", diff --git a/packages/utils/src/tlds.ts b/packages/utils/src/tlds.ts deleted file mode 100644 index 6890a429..00000000 --- a/packages/utils/src/tlds.ts +++ /dev/null @@ -1,1447 +0,0 @@ -/** - * Copyright (c) 2023-present Plane Software, Inc. and contributors - * SPDX-License-Identifier: AGPL-3.0-only - * See the LICENSE file for details. - */ - -export default [ - "aaa", - "aarp", - "abb", - "abbott", - "abbvie", - "abc", - "able", - "abogado", - "abudhabi", - "ac", - "academy", - "accenture", - "accountant", - "accountants", - "aco", - "actor", - "ad", - "ads", - "adult", - "ae", - "aeg", - "aero", - "aetna", - "af", - "afl", - "africa", - "ag", - "agakhan", - "agency", - "ai", - "aig", - "airbus", - "airforce", - "airtel", - "akdn", - "al", - "alibaba", - "alipay", - "allfinanz", - "allstate", - "ally", - "alsace", - "alstom", - "am", - "amazon", - "americanexpress", - "americanfamily", - "amex", - "amfam", - "amica", - "amsterdam", - "analytics", - "android", - "anquan", - "anz", - "ao", - "aol", - "apartments", - "app", - "apple", - "aq", - "aquarelle", - "ar", - "arab", - "aramco", - "archi", - "army", - "arpa", - "art", - "arte", - "as", - "asda", - "asia", - "associates", - "at", - "athleta", - "attorney", - "au", - "auction", - "audi", - "audible", - "audio", - "auspost", - "author", - "auto", - "autos", - "aw", - "aws", - "ax", - "axa", - "az", - "azure", - "ba", - "baby", - "baidu", - "banamex", - "band", - "bank", - "bar", - "barcelona", - "barclaycard", - "barclays", - "barefoot", - "bargains", - "baseball", - "basketball", - "bauhaus", - "bayern", - "bb", - "bbc", - "bbt", - "bbva", - "bcg", - "bcn", - "bd", - "be", - "beats", - "beauty", - "beer", - "berlin", - "best", - "bestbuy", - "bet", - "bf", - "bg", - "bh", - "bharti", - "bi", - "bible", - "bid", - "bike", - "bing", - "bingo", - "bio", - "biz", - "bj", - "black", - "blackfriday", - "blockbuster", - "blog", - "bloomberg", - "blue", - "bm", - "bms", - "bmw", - "bn", - "bnpparibas", - "bo", - "boats", - "boehringer", - "bofa", - "bom", - "bond", - "boo", - "book", - "booking", - "bosch", - "bostik", - "boston", - "bot", - "boutique", - "box", - "br", - "bradesco", - "bridgestone", - "broadway", - "broker", - "brother", - "brussels", - "bs", - "bt", - "build", - "builders", - "business", - "buy", - "buzz", - "bv", - "bw", - "by", - "bz", - "bzh", - "ca", - "cab", - "cafe", - "cal", - "call", - "calvinklein", - "cam", - "camera", - "camp", - "canon", - "capetown", - "capital", - "capitalone", - "car", - "caravan", - "cards", - "care", - "career", - "careers", - "cars", - "casa", - "case", - "cash", - "casino", - "cat", - "catering", - "catholic", - "cba", - "cbn", - "cbre", - "cc", - "cd", - "center", - "ceo", - "cern", - "cf", - "cfa", - "cfd", - "cg", - "ch", - "chanel", - "channel", - "charity", - "chase", - "chat", - "cheap", - "chintai", - "christmas", - "chrome", - "church", - "ci", - "cipriani", - "circle", - "cisco", - "citadel", - "citi", - "citic", - "city", - "ck", - "cl", - "claims", - "cleaning", - "click", - "clinic", - "clinique", - "clothing", - "cloud", - "club", - "clubmed", - "cm", - "cn", - "co", - "coach", - "codes", - "coffee", - "college", - "cologne", - "com", - "commbank", - "community", - "company", - "compare", - "computer", - "comsec", - "condos", - "construction", - "consulting", - "contact", - "contractors", - "cooking", - "cool", - "coop", - "corsica", - "country", - "coupon", - "coupons", - "courses", - "cpa", - "cr", - "credit", - "creditcard", - "creditunion", - "cricket", - "crown", - "crs", - "cruise", - "cruises", - "cu", - "cuisinella", - "cv", - "cw", - "cx", - "cy", - "cymru", - "cyou", - "cz", - "dad", - "dance", - "data", - "date", - "dating", - "datsun", - "day", - "dclk", - "dds", - "de", - "deal", - "dealer", - "deals", - "degree", - "delivery", - "dell", - "deloitte", - "delta", - "democrat", - "dental", - "dentist", - "desi", - "design", - "dev", - "dhl", - "diamonds", - "diet", - "digital", - "direct", - "directory", - "discount", - "discover", - "dish", - "diy", - "dj", - "dk", - "dm", - "dnp", - "do", - "docs", - "doctor", - "dog", - "domains", - "dot", - "download", - "drive", - "dtv", - "dubai", - "dunlop", - "dupont", - "durban", - "dvag", - "dvr", - "dz", - "earth", - "eat", - "ec", - "eco", - "edeka", - "edu", - "education", - "ee", - "eg", - "email", - "emerck", - "energy", - "engineer", - "engineering", - "enterprises", - "epson", - "equipment", - "er", - "ericsson", - "erni", - "es", - "esq", - "estate", - "et", - "eu", - "eurovision", - "eus", - "events", - "exchange", - "expert", - "exposed", - "express", - "extraspace", - "fage", - "fail", - "fairwinds", - "faith", - "family", - "fan", - "fans", - "farm", - "farmers", - "fashion", - "fast", - "fedex", - "feedback", - "ferrari", - "ferrero", - "fi", - "fidelity", - "fido", - "film", - "final", - "finance", - "financial", - "fire", - "firestone", - "firmdale", - "fish", - "fishing", - "fit", - "fitness", - "fj", - "fk", - "flickr", - "flights", - "flir", - "florist", - "flowers", - "fly", - "fm", - "fo", - "foo", - "food", - "football", - "ford", - "forex", - "forsale", - "forum", - "foundation", - "fox", - "fr", - "free", - "fresenius", - "frl", - "frogans", - "frontier", - "ftr", - "fujitsu", - "fun", - "fund", - "furniture", - "futbol", - "fyi", - "ga", - "gal", - "gallery", - "gallo", - "gallup", - "game", - "games", - "gap", - "garden", - "gay", - "gb", - "gbiz", - "gd", - "gdn", - "ge", - "gea", - "gent", - "genting", - "george", - "gf", - "gg", - "ggee", - "gh", - "gi", - "gift", - "gifts", - "gives", - "giving", - "gl", - "glass", - "gle", - "global", - "globo", - "gm", - "gmail", - "gmbh", - "gmo", - "gmx", - "gn", - "godaddy", - "gold", - "goldpoint", - "golf", - "goo", - "goodyear", - "goog", - "google", - "gop", - "got", - "gov", - "gp", - "gq", - "gr", - "grainger", - "graphics", - "gratis", - "green", - "gripe", - "grocery", - "group", - "gs", - "gt", - "gu", - "gucci", - "guge", - "guide", - "guitars", - "guru", - "gw", - "gy", - "hair", - "hamburg", - "hangout", - "haus", - "hbo", - "hdfc", - "hdfcbank", - "health", - "healthcare", - "help", - "helsinki", - "here", - "hermes", - "hiphop", - "hisamitsu", - "hitachi", - "hiv", - "hk", - "hkt", - "hm", - "hn", - "hockey", - "holdings", - "holiday", - "homedepot", - "homegoods", - "homes", - "homesense", - "honda", - "horse", - "hospital", - "host", - "hosting", - "hot", - "hotels", - "hotmail", - "house", - "how", - "hr", - "hsbc", - "ht", - "hu", - "hughes", - "hyatt", - "hyundai", - "ibm", - "icbc", - "ice", - "icu", - "id", - "ie", - "ieee", - "ifm", - "ikano", - "il", - "im", - "imamat", - "imdb", - "immo", - "immobilien", - "in", - "inc", - "industries", - "infiniti", - "info", - "ing", - "ink", - "institute", - "insurance", - "insure", - "int", - "international", - "intuit", - "investments", - "io", - "ipiranga", - "iq", - "ir", - "irish", - "is", - "ismaili", - "ist", - "istanbul", - "it", - "itau", - "itv", - "jaguar", - "java", - "jcb", - "je", - "jeep", - "jetzt", - "jewelry", - "jio", - "jll", - "jm", - "jmp", - "jnj", - "jo", - "jobs", - "joburg", - "jot", - "joy", - "jp", - "jpmorgan", - "jprs", - "juegos", - "juniper", - "kaufen", - "kddi", - "ke", - "kerryhotels", - "kerryproperties", - "kfh", - "kg", - "kh", - "ki", - "kia", - "kids", - "kim", - "kindle", - "kitchen", - "kiwi", - "km", - "kn", - "koeln", - "komatsu", - "kosher", - "kp", - "kpmg", - "kpn", - "kr", - "krd", - "kred", - "kuokgroup", - "kw", - "ky", - "kyoto", - "kz", - "la", - "lacaixa", - "lamborghini", - "lamer", - "land", - "landrover", - "lanxess", - "lasalle", - "lat", - "latino", - "latrobe", - "law", - "lawyer", - "lb", - "lc", - "lds", - "lease", - "leclerc", - "lefrak", - "legal", - "lego", - "lexus", - "lgbt", - "li", - "lidl", - "life", - "lifeinsurance", - "lifestyle", - "lighting", - "like", - "lilly", - "limited", - "limo", - "lincoln", - "link", - "live", - "living", - "lk", - "llc", - "llp", - "loan", - "loans", - "locker", - "locus", - "lol", - "london", - "lotte", - "lotto", - "love", - "lpl", - "lplfinancial", - "lr", - "ls", - "lt", - "ltd", - "ltda", - "lu", - "lundbeck", - "luxe", - "luxury", - "lv", - "ly", - "ma", - "madrid", - "maif", - "maison", - "makeup", - "man", - "management", - "mango", - "map", - "market", - "marketing", - "markets", - "marriott", - "marshalls", - "mattel", - "mba", - "mc", - "mckinsey", - "md", - "me", - "med", - "media", - "meet", - "melbourne", - "meme", - "memorial", - "men", - "menu", - "merckmsd", - "mg", - "mh", - "miami", - "microsoft", - "mil", - "mini", - "mint", - "mit", - "mitsubishi", - "mk", - "ml", - "mlb", - "mls", - "mm", - "mma", - "mn", - "mo", - "mobi", - "mobile", - "moda", - "moe", - "moi", - "mom", - "monash", - "money", - "monster", - "mormon", - "mortgage", - "moscow", - "moto", - "motorcycles", - "mov", - "movie", - "mp", - "mq", - "mr", - "ms", - "msd", - "mt", - "mtn", - "mtr", - "mu", - "museum", - "music", - "mv", - "mw", - "mx", - "my", - "mz", - "na", - "nab", - "nagoya", - "name", - "navy", - "nba", - "nc", - "ne", - "nec", - "net", - "netbank", - "netflix", - "network", - "neustar", - "new", - "news", - "next", - "nextdirect", - "nexus", - "nf", - "nfl", - "ng", - "ngo", - "nhk", - "ni", - "nico", - "nike", - "nikon", - "ninja", - "nissan", - "nissay", - "nl", - "no", - "nokia", - "norton", - "now", - "nowruz", - "nowtv", - "np", - "nr", - "nra", - "nrw", - "ntt", - "nu", - "nyc", - "nz", - "obi", - "observer", - "office", - "okinawa", - "olayan", - "olayangroup", - "ollo", - "om", - "omega", - "one", - "ong", - "onl", - "online", - "ooo", - "open", - "oracle", - "orange", - "org", - "organic", - "origins", - "osaka", - "otsuka", - "ott", - "ovh", - "pa", - "page", - "panasonic", - "paris", - "pars", - "partners", - "parts", - "party", - "pay", - "pccw", - "pe", - "pet", - "pf", - "pfizer", - "pg", - "ph", - "pharmacy", - "phd", - "philips", - "phone", - "photo", - "photography", - "photos", - "physio", - "pics", - "pictet", - "pictures", - "pid", - "pin", - "ping", - "pink", - "pioneer", - "pizza", - "pk", - "pl", - "place", - "play", - "playstation", - "plumbing", - "plus", - "pm", - "pn", - "pnc", - "pohl", - "poker", - "politie", - "porn", - "post", - "pr", - "praxi", - "press", - "prime", - "pro", - "prod", - "productions", - "prof", - "progressive", - "promo", - "properties", - "property", - "protection", - "pru", - "prudential", - "ps", - "pt", - "pub", - "pw", - "pwc", - "py", - "qa", - "qpon", - "quebec", - "quest", - "racing", - "radio", - "re", - "read", - "realestate", - "realtor", - "realty", - "recipes", - "red", - "redumbrella", - "rehab", - "reise", - "reisen", - "reit", - "reliance", - "ren", - "rent", - "rentals", - "repair", - "report", - "republican", - "rest", - "restaurant", - "review", - "reviews", - "rexroth", - "rich", - "richardli", - "ricoh", - "ril", - "rio", - "rip", - "ro", - "rocks", - "rodeo", - "rogers", - "room", - "rs", - "rsvp", - "ru", - "rugby", - "ruhr", - "run", - "rw", - "rwe", - "ryukyu", - "sa", - "saarland", - "safe", - "safety", - "sakura", - "sale", - "salon", - "samsclub", - "samsung", - "sandvik", - "sandvikcoromant", - "sanofi", - "sap", - "sarl", - "sas", - "save", - "saxo", - "sb", - "sbi", - "sbs", - "sc", - "scb", - "schaeffler", - "schmidt", - "scholarships", - "school", - "schule", - "schwarz", - "science", - "scot", - "sd", - "se", - "search", - "seat", - "secure", - "security", - "seek", - "select", - "sener", - "services", - "seven", - "sew", - "sex", - "sexy", - "sfr", - "sg", - "sh", - "shangrila", - "sharp", - "shell", - "shia", - "shiksha", - "shoes", - "shop", - "shopping", - "shouji", - "show", - "si", - "silk", - "sina", - "singles", - "site", - "sj", - "sk", - "ski", - "skin", - "sky", - "skype", - "sl", - "sling", - "sm", - "smart", - "smile", - "sn", - "sncf", - "so", - "soccer", - "social", - "softbank", - "software", - "sohu", - "solar", - "solutions", - "song", - "sony", - "soy", - "spa", - "space", - "sport", - "spot", - "sr", - "srl", - "ss", - "st", - "stada", - "staples", - "star", - "statebank", - "statefarm", - "stc", - "stcgroup", - "stockholm", - "storage", - "store", - "stream", - "studio", - "study", - "style", - "su", - "sucks", - "supplies", - "supply", - "support", - "surf", - "surgery", - "suzuki", - "sv", - "swatch", - "swiss", - "sx", - "sy", - "sydney", - "systems", - "sz", - "tab", - "taipei", - "talk", - "taobao", - "target", - "tatamotors", - "tatar", - "tattoo", - "tax", - "taxi", - "tc", - "tci", - "td", - "tdk", - "team", - "tech", - "technology", - "tel", - "temasek", - "tennis", - "teva", - "tf", - "tg", - "th", - "thd", - "theater", - "theatre", - "tiaa", - "tickets", - "tienda", - "tips", - "tires", - "tirol", - "tj", - "tjmaxx", - "tjx", - "tk", - "tkmaxx", - "tl", - "tm", - "tmall", - "tn", - "to", - "today", - "tokyo", - "tools", - "top", - "toray", - "toshiba", - "total", - "tours", - "town", - "toyota", - "toys", - "tr", - "trade", - "trading", - "training", - "travel", - "travelers", - "travelersinsurance", - "trust", - "trv", - "tt", - "tube", - "tui", - "tunes", - "tushu", - "tv", - "tvs", - "tw", - "tz", - "ua", - "ubank", - "ubs", - "ug", - "uk", - "unicom", - "university", - "uno", - "uol", - "ups", - "us", - "uy", - "uz", - "va", - "vacations", - "vana", - "vanguard", - "vc", - "ve", - "vegas", - "ventures", - "verisign", - "vermögensberater", - "vermögensberatung", - "versicherung", - "vet", - "vg", - "vi", - "viajes", - "video", - "vig", - "viking", - "villas", - "vin", - "vip", - "virgin", - "visa", - "vision", - "viva", - "vivo", - "vlaanderen", - "vn", - "vodka", - "volvo", - "vote", - "voting", - "voto", - "voyage", - "vu", - "wales", - "walmart", - "walter", - "wang", - "wanggou", - "watch", - "watches", - "weather", - "weatherchannel", - "webcam", - "weber", - "website", - "wed", - "wedding", - "weibo", - "weir", - "wf", - "whoswho", - "wien", - "wiki", - "williamhill", - "win", - "windows", - "wine", - "winners", - "wme", - "wolterskluwer", - "woodside", - "work", - "works", - "world", - "wow", - "ws", - "wtc", - "wtf", - "xbox", - "xerox", - "xihuan", - "xin", - "xxx", - "xyz", - "yachts", - "yahoo", - "yamaxun", - "yandex", - "ye", - "yodobashi", - "yoga", - "yokohama", - "you", - "youtube", - "yt", - "yun", - "za", - "zappos", - "zara", - "zero", - "zip", - "zm", - "zone", - "zuerich", - "zw", - "ελ", - "ευ", - "бг", - "бел", - "дети", - "ею", - "католик", - "ком", - "мкд", - "мон", - "москва", - "онлайн", - "орг", - "рус", - "рф", - "сайт", - "срб", - "укр", - "қаз", - "հայ", - "ישראל", - "קום", - "ابوظبي", - "ارامكو", - "الاردن", - "البحرين", - "الجزائر", - "السعودية", - "العليان", - "المغرب", - "امارات", - "ایران", - "بارت", - "بازار", - "بيتك", - "بھارت", - "تونس", - "سودان", - "سورية", - "شبكة", - "عراق", - "عرب", - "عمان", - "فلسطين", - "قطر", - "كاثوليك", - "كوم", - "مصر", - "مليسيا", - "موريتانيا", - "موقع", - "همراه", - "پاکستان", - "ڀارت", - "कॉम", - "नेट", - "भारत", - "भारतम्", - "भारोत", - "संगठन", - "বাংলা", - "ভারত", - "ভাৰত", - "ਭਾਰਤ", - "ભારત", - "ଭାରତ", - "இந்தியா", - "இலங்கை", - "சிங்கப்பூர்", - "భారత్", - "ಭಾರತ", - "ഭാരതം", - "ලංකා", - "คอม", - "ไทย", - "ລາວ", - "გე", - "みんな", - "アマゾン", - "クラウド", - "グーグル", - "コム", - "ストア", - "セール", - "ファッション", - "ポイント", - "世界", - "中信", - "中国", - "中國", - "中文网", - "亚马逊", - "企业", - "佛山", - "信息", - "健康", - "八卦", - "公司", - "公益", - "台湾", - "台灣", - "商城", - "商店", - "商标", - "嘉里", - "嘉里大酒店", - "在线", - "大拿", - "天主教", - "娱乐", - "家電", - "广东", - "微博", - "慈善", - "我爱你", - "手机", - "招聘", - "政务", - "政府", - "新加坡", - "新闻", - "时尚", - "書籍", - "机构", - "淡马锡", - "游戏", - "澳門", - "点看", - "移动", - "组织机构", - "网址", - "网店", - "网站", - "网络", - "联通", - "谷歌", - "购物", - "通販", - "集团", - "電訊盈科", - "飞利浦", - "食品", - "餐厅", - "香格里拉", - "香港", - "닷넷", - "닷컴", - "삼성", - "한국", -]; diff --git a/packages/utils/src/url.test.ts b/packages/utils/src/url.test.ts index 1c13c96d..c32ffc00 100644 --- a/packages/utils/src/url.test.ts +++ b/packages/utils/src/url.test.ts @@ -9,7 +9,6 @@ import { describe, expect, it } from "vitest"; import { ensureTrailingSlash, extractHostname, - extractTLD, formatURLForDisplay, isLocalhost, isValidIPv4, @@ -128,19 +127,6 @@ describe("validateIPAddress", () => { }); }); -describe("extractTLD", () => { - it("returns a known suffix", () => { - expect(extractTLD("https://a.example.com/x")).toBe("com"); - expect(extractTLD("a.co.uk")).toBe("uk"); - }); - - it("returns nothing when there is no known suffix to find", () => { - for (const input of ["nope", "a.invalidtld", ".com", "example.", ""]) { - expect(extractTLD(input), input).toBe(""); - } - }); -}); - describe("formatURLForDisplay", () => { it("shows the host of a url", () => { expect(formatURLForDisplay("https://pace.example/x?y=1")).toBe("pace.example"); diff --git a/packages/utils/src/url.ts b/packages/utils/src/url.ts index 84fa7a7a..a3f06538 100644 --- a/packages/utils/src/url.ts +++ b/packages/utils/src/url.ts @@ -4,14 +4,7 @@ * See the LICENSE file for details. */ -import tlds from "./tlds"; - -const PROTOCOL_REGEX = /^[a-zA-Z]+:\/\//; -const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; const LOCALHOST_ADDRESSES = new Set(["localhost", "127.0.0.1", "0.0.0.0"]); -const HTTP_PROTOCOL = "http://"; -const MAILTO_PROTOCOL = "mailto:"; -const DEFAULT_PROTOCOL = HTTP_PROTOCOL; // IPv4 regex - matches 0.0.0.0 to 255.255.255.255 const IPV4_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; // IPv6 regex - comprehensive pattern for all IPv6 formats @@ -121,151 +114,6 @@ export function formatURLForDisplay(url: string): string { } } -/** - * Extracts and validates the TLD (Top Level Domain) from a URL string. - * - * @param {string} urlString - The string to extract TLD from - * @returns {string} The valid TLD if found, empty string otherwise - * - * @description - * The function performs the following steps: - * 1. Basic validation (rejects empty strings, strings starting/ending with dots) - * 2. URL component cleaning: - * - Removes protocol (if present) - * - Removes auth credentials (if present) - * - Removes path component (everything after '/') - * - Removes query parameters (everything after '?') - * - Removes hash fragments (everything after '#') - * - Removes port numbers (everything after ':') - * 3. Validates the TLD against a list of known TLDs - */ - -export function extractTLD(urlString: string): string { - if (!urlString || urlString.startsWith(".") || urlString.endsWith(".")) { - return ""; - } - - const hostname = extractHostname(urlString); - const hostnameParts = hostname.split("."); - - if (hostnameParts.length >= 2) { - const potentialTLD = hostnameParts[hostnameParts.length - 1].toLowerCase(); - return tlds.includes(potentialTLD) ? potentialTLD : ""; - } - return ""; -} - -/** - * Interface representing the cleaned components of a URL. - * @interface IURLComponents - * @property {string} protocol - The URL protocol (e.g., 'http', 'https'), if protocol is not present, Always contains the actual protocol used. - * @property {string} subdomain - The subdomain part of the URL (e.g., 'blog' in 'blog.example.com') - * @property {string} rootDomain - The root domain name (e.g., 'example' in 'blog.example.com') - * @property {string} tld - The top-level domain (e.g., 'com', 'org') - * @property {string} pathname - The URL path excluding search params and hash, empty if pathname is '/' - * @property {URL} full - The original URL object with all native URL properties - */ -export interface IURLComponents { - protocol: string; - subdomain: string; - rootDomain: string; - tld: string; - pathname: string; - full: URL; -} - -/** - * Process a URL object to extract its components - */ -export function processURL(url: URL): IURLComponents { - const protocol = url.protocol.slice(0, -1); - const hostnameParts = url.hostname.split("."); - - let subdomain = ""; - let rootDomain = ""; - let tld = ""; - - if (hostnameParts.length === 1) { - rootDomain = hostnameParts[0]; // For cases like 'localhost' - } else if (hostnameParts.length >= 2) { - tld = hostnameParts[hostnameParts.length - 1]; - rootDomain = hostnameParts[hostnameParts.length - 2]; - - if (hostnameParts.length > 2) { - subdomain = hostnameParts.slice(0, -2).join("."); - } - } - - return { - protocol, - subdomain, - rootDomain, - tld, - pathname: url.pathname === "/" ? "" : url.pathname, - full: url, - }; -} - -/** - * Extracts components from a URL object or string. - * - * @param {URL | string} url - The URL object or string to extract components from - * @returns {IURLComponents | undefined} URL components or undefined if invalid - * - * @example - * // With URL object - * const url = new URL('https://blog.example.com/posts'); - * extractURLComponents(url); - * - * // With string - * extractURLComponents('blog.example.com/posts'); - * - * // Example output: - * // { - * // protocol: 'https', // empty string if protocol is not present - * // subdomain: 'blog', - * // rootDomain: 'example', - * // tld: 'com', - * // pathname: 'posts', - * // full: URL {} // The parsed URL object - * // } - */ -export function extractURLComponents(url: URL | string): IURLComponents | undefined { - // If URL object is passed directly - if (typeof url !== "string") { - return processURL(url); - } - - // Handle empty strings - if (!url || url.trim() === "") return undefined; - - // Input length validation for security - if (url.length > 2048) return undefined; - - const urlLower = url.toLowerCase(); - - try { - // 1. Handle web URLs with protocols (including mailto, http, https, ftp, etc.) - if (PROTOCOL_REGEX.test(urlLower) || urlLower.startsWith(MAILTO_PROTOCOL)) { - return processURL(new URL(url)); - } - - // 2. Check if it's an email address - if (EMAIL_REGEX.test(urlLower)) { - return processURL(new URL(`${MAILTO_PROTOCOL}${url}`)); - } - - // 3. URL without protocol but valid domain or IP address or TLD - if (isLocalhost(urlLower) || isValidIPv4(urlLower) || isValidIPv6(urlLower) || extractTLD(urlLower)) { - return processURL(new URL(`${DEFAULT_PROTOCOL}${urlLower}`)); - } - - return undefined; - } catch (_error) { - return undefined; - } -} - /** * Validates that a next_path parameter is safe for redirection. * Only allows relative paths starting with "/" to prevent open redirect vulnerabilities. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c623184c..5767eb0c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -324,9 +324,6 @@ catalogs: react-i18next: specifier: 16.6.6 version: 16.6.6 - react-markdown: - specifier: ^10.1.0 - version: 10.1.0 react-masonry-component: specifier: ^6.3.0 version: 6.3.0 @@ -884,9 +881,6 @@ importers: react-hook-form: specifier: 'catalog:' version: 7.84.0(react@19.2.8) - react-markdown: - specifier: 'catalog:' - version: 10.1.0(@types/react@19.2.17)(react@19.2.8) react-masonry-component: specifier: 'catalog:' version: 6.3.0(react@19.2.8) @@ -4370,9 +4364,6 @@ packages: '@types/esrecurse@4.3.1': resolution: {integrity: sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==} - '@types/estree-jsx@1.0.5': - resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} - '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -4454,9 +4445,6 @@ packages: '@types/semver@7.7.1': resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} - '@types/unist@2.0.11': - resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -4907,9 +4895,6 @@ packages: character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - character-reference-invalid@2.0.1: - resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -5564,9 +5549,6 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - estree-util-is-identifier-name@3.0.0: - resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} - estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} @@ -5913,9 +5895,6 @@ packages: hast-util-to-html@9.0.5: resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} - hast-util-to-jsx-runtime@2.3.6: - resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} - hast-util-to-mdast@10.1.2: resolution: {integrity: sha512-FiCRI7NmOvM4y+f5w32jPRzcxDIz+PUqDwEqn1A+1q2cdp3B8Gx7aVrXORdOKjMNDQsD1ogOr896+0jJHW1EFQ==} @@ -5969,9 +5948,6 @@ packages: html-parse-stringify@3.0.1: resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} - html-url-attributes@3.0.1: - resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} - html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} @@ -6079,9 +6055,6 @@ packages: resolution: {integrity: sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w==} engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} - inline-style-parser@0.2.7: - resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} - internmap@2.0.3: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} @@ -6093,12 +6066,6 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - is-alphabetical@2.0.1: - resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} - - is-alphanumerical@2.0.1: - resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -6110,9 +6077,6 @@ packages: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} - is-decimal@2.0.1: - resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} @@ -6142,9 +6106,6 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-hexadecimal@2.0.1: - resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - is-inside-container@1.0.0: resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} engines: {node: '>=14.16'} @@ -6610,15 +6571,6 @@ packages: mdast-util-gfm@3.1.0: resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} - mdast-util-mdx-expression@2.0.1: - resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} - - mdast-util-mdx-jsx@3.2.0: - resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} - - mdast-util-mdxjs-esm@2.0.1: - resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} - mdast-util-phrasing@4.1.0: resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} @@ -7063,9 +7015,6 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - parse-entities@4.0.2: - resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} - parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -7474,12 +7423,6 @@ packages: react-is@19.2.8: resolution: {integrity: sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ==} - react-markdown@10.1.0: - resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==} - peerDependencies: - '@types/react': 19.2.17 - react: 19.2.8 - react-masonry-component@6.3.0: resolution: {integrity: sha512-4ZI78nxMfCpU5yQiS6Rup07Ju++YzcOGAyvbMcl2GfpZTw8GRwT548lkKr0PJarNicRV1qE2D/NiT26UPg1T7A==} peerDependencies: @@ -7621,9 +7564,6 @@ packages: remark-parse@11.0.0: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} - remark-rehype@11.1.2: - resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==} - remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} @@ -7939,12 +7879,6 @@ packages: peerDependencies: webpack: 5.104.1 - style-to-js@1.1.21: - resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==} - - style-to-object@1.0.14: - resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -11004,10 +10938,6 @@ snapshots: '@types/esrecurse@4.3.1': {} - '@types/estree-jsx@1.0.5': - dependencies: - '@types/estree': 1.0.8 - '@types/estree@1.0.8': {} '@types/hast@3.0.4': @@ -11087,8 +11017,6 @@ snapshots: '@types/semver@7.7.1': {} - '@types/unist@2.0.11': {} - '@types/unist@3.0.3': {} '@types/use-sync-external-store@0.0.6': {} @@ -11591,8 +11519,6 @@ snapshots: character-entities@2.0.2: {} - character-reference-invalid@2.0.1: {} - check-error@2.1.1: {} chokidar@3.6.0: @@ -12243,8 +12169,6 @@ snapshots: estraverse@5.3.0: {} - estree-util-is-identifier-name@3.0.0: {} - estree-walker@2.0.2: {} estree-walker@3.0.3: @@ -12659,26 +12583,6 @@ snapshots: stringify-entities: 4.0.4 zwitch: 2.0.4 - hast-util-to-jsx-runtime@2.3.6: - dependencies: - '@types/estree': 1.0.8 - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - comma-separated-tokens: 2.0.3 - devlop: 1.1.0 - estree-util-is-identifier-name: 3.0.0 - hast-util-whitespace: 3.0.0 - mdast-util-mdx-expression: 2.0.1 - mdast-util-mdx-jsx: 3.2.0 - mdast-util-mdxjs-esm: 2.0.1 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - style-to-js: 1.1.21 - unist-util-position: 5.0.0 - vfile-message: 4.0.3 - transitivePeerDependencies: - - supports-color - hast-util-to-mdast@10.1.2: dependencies: '@types/hast': 3.0.4 @@ -12754,8 +12658,6 @@ snapshots: dependencies: void-elements: 3.1.0 - html-url-attributes@3.0.1: {} - html-void-elements@3.0.0: {} html-webpack-plugin@5.6.4(webpack@5.104.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.28.1)(postcss@8.5.25)): @@ -12862,8 +12764,6 @@ snapshots: ini@7.0.0: {} - inline-style-parser@0.2.7: {} - internmap@2.0.3: {} intl-messageformat@10.7.16: @@ -12875,13 +12775,6 @@ snapshots: ipaddr.js@1.9.1: {} - is-alphabetical@2.0.1: {} - - is-alphanumerical@2.0.1: - dependencies: - is-alphabetical: 2.0.1 - is-decimal: 2.0.1 - is-arrayish@0.2.1: {} is-binary-path@2.1.0: @@ -12892,8 +12785,6 @@ snapshots: dependencies: hasown: 2.0.4 - is-decimal@2.0.1: {} - is-docker@2.2.1: {} is-docker@3.0.0: {} @@ -12912,8 +12803,6 @@ snapshots: dependencies: is-extglob: 2.1.1 - is-hexadecimal@2.0.1: {} - is-inside-container@1.0.0: dependencies: is-docker: 3.0.0 @@ -13387,45 +13276,6 @@ snapshots: transitivePeerDependencies: - supports-color - mdast-util-mdx-expression@2.0.1: - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-mdx-jsx@3.2.0: - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - parse-entities: 4.0.2 - stringify-entities: 4.0.4 - unist-util-stringify-position: 4.0.0 - vfile-message: 4.0.3 - transitivePeerDependencies: - - supports-color - - mdast-util-mdxjs-esm@2.0.1: - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - mdast-util-phrasing@4.1.0: dependencies: '@types/mdast': 4.0.4 @@ -14061,16 +13911,6 @@ snapshots: dependencies: callsites: 3.1.0 - parse-entities@4.0.2: - dependencies: - '@types/unist': 2.0.11 - character-entities-legacy: 3.0.0 - character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.2.0 - is-alphanumerical: 2.0.1 - is-decimal: 2.0.1 - is-hexadecimal: 2.0.1 - parse-json@5.2.0: dependencies: '@babel/code-frame': 7.29.7 @@ -14557,24 +14397,6 @@ snapshots: react-is@19.2.8: {} - react-markdown@10.1.0(@types/react@19.2.17)(react@19.2.8): - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@types/react': 19.2.17 - devlop: 1.1.0 - hast-util-to-jsx-runtime: 2.3.6 - html-url-attributes: 3.0.1 - mdast-util-to-hast: 13.2.1 - react: 19.2.8 - remark-parse: 11.0.0 - remark-rehype: 11.1.2 - unified: 11.0.5 - unist-util-visit: 5.0.0 - vfile: 6.0.3 - transitivePeerDependencies: - - supports-color - react-masonry-component@6.3.0(react@19.2.8): dependencies: create-react-class: 15.7.0 @@ -14758,14 +14580,6 @@ snapshots: transitivePeerDependencies: - supports-color - remark-rehype@11.1.2: - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - mdast-util-to-hast: 13.2.1 - unified: 11.0.5 - vfile: 6.0.3 - remark-stringify@11.0.0: dependencies: '@types/mdast': 4.0.4 @@ -15158,14 +14972,6 @@ snapshots: dependencies: webpack: 5.104.1(@swc/core@1.13.5(@swc/helpers@0.5.17))(esbuild@0.28.1)(postcss@8.5.25) - style-to-js@1.1.21: - dependencies: - style-to-object: 1.0.14 - - style-to-object@1.0.14: - dependencies: - inline-style-parser: 0.2.7 - supports-color@7.2.0: dependencies: has-flag: 4.0.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 31292be2..9db2cbc6 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -120,7 +120,6 @@ catalog: "react-i18next": "16.6.6" # No package.json declares react-is; the entry exists for the `react-is: "catalog:"` override below, which is what keeps recharts, react-popper and the rest on one copy alongside the single React. "react-is": "^19.2.8" - "react-markdown": "^10.1.0" "react-masonry-component": "^6.3.0" "react-pdf-html": "^2.1.2" "react-popper": "^2.3.0"