diff --git a/apps/admin/app/(all)/(dashboard)/general/form.tsx b/apps/admin/app/(all)/(dashboard)/general/form.tsx
index 9c6b7c62..03923ab1 100644
--- a/apps/admin/app/(all)/(dashboard)/general/form.tsx
+++ b/apps/admin/app/(all)/(dashboard)/general/form.tsx
@@ -11,6 +11,7 @@ import { UsageOutline } from "@makeplane/propel/icons";
import { Button } from "@makeplane/propel/components/button";
import { Input } from "@makeplane/propel/components/input";
import { Switch } from "@makeplane/propel/components/switch";
+import { DOCS_URL, externalLink } from "@pace/constants";
import type { IInstance, IInstanceAdmin } from "@pace/types";
// components
import { ControllerInput } from "@/components/common/controller-input";
@@ -19,6 +20,8 @@ import { TOAST_TYPE, setToast } from "@/providers/toast";
import { useTranslation } from "@pace/i18n";
import { useInstance } from "@/hooks/store";
+const telemetryPolicyLink = externalLink(DOCS_URL, "/self-hosting/telemetry");
+
export interface IGeneralConfigurationForm {
instance: IInstance;
instanceAdmins: IInstanceAdmin[];
@@ -113,16 +116,23 @@ export const GeneralConfigurationForm = observer(function GeneralConfigurationFo
{t("admin.general.telemetry.description")}
- No PII is collected.This anonymized data is used to understand how you use Plane and build new features
- in line with{" "}
-
- our Telemetry Policy.
-
+ {/* The sentence carries the actual disclosure -- no PII, anonymous, used for feature work -- so it stays either way. What goes with the link is the clause that cites the policy document: naming a Telemetry Policy the reader cannot open claims a document this installation may not publish. Upstream this page linked developers.plane.so, and the docs site is the closest equivalent a fork configures. */}
+ {telemetryPolicyLink ? (
+ <>
+ No PII is collected. This anonymized data is used to understand how you use Plane and build new
+ features in line with{" "}
+
+ our Telemetry Policy.
+
+ >
+ ) : (
+ "No PII is collected. This anonymized data is used to understand how you use Plane and build new features."
+ )}
diff --git a/apps/admin/app/(all)/(dashboard)/sidebar-help-section.tsx b/apps/admin/app/(all)/(dashboard)/sidebar-help-section.tsx
index e9f86053..8a154933 100644
--- a/apps/admin/app/(all)/(dashboard)/sidebar-help-section.tsx
+++ b/apps/admin/app/(all)/(dashboard)/sidebar-help-section.tsx
@@ -8,7 +8,7 @@ import { useState, useRef } from "react";
import { observer } from "mobx-react";
import Link from "@/app/hooks/link";
import { Transition } from "@headlessui/react";
-import { WEB_BASE_URL } from "@pace/constants";
+import { DOCS_URL, FORUM_URL, WEB_BASE_URL } from "@pace/constants";
// pace internal packages
import { Tooltip } from "@makeplane/propel/components/tooltip";
import { LanguageSwitcher } from "@/components/common/language-switcher";
@@ -27,15 +27,16 @@ import { useInstance, useTheme } from "@/hooks/store";
// assets
// `name` holds a translation key, not text: this list lives outside the component and so cannot call the translation hook. The keys are resolved where the options are rendered, below.
+// Entries whose href is empty are dropped: the documentation and forum sites are per-installation configuration and this fork ships without either, so the alternative is a menu entry that navigates nowhere.
const helpOptions = [
{
name: "admin.nav.documentation",
- href: "https://pace.yldm.ai/docs/",
+ href: DOCS_URL,
Icon: PagesOutline,
},
{
name: "admin.nav.forum",
- href: "https://pace.yldm.ai/forum",
+ href: FORUM_URL,
Icon: ChatOutline,
},
{
@@ -43,7 +44,7 @@ const helpOptions = [
href: "https://github.com/makeplane/plane/issues/new/choose",
Icon: Github,
},
-];
+].filter((option) => !!option.href);
export const AdminSidebarHelpSection = observer(function AdminSidebarHelpSection() {
// i18n
diff --git a/apps/admin/core/components/instance/setup-form.tsx b/apps/admin/core/components/instance/setup-form.tsx
index 7ccec888..786318b3 100644
--- a/apps/admin/core/components/instance/setup-form.tsx
+++ b/apps/admin/core/components/instance/setup-form.tsx
@@ -9,7 +9,7 @@ import { useSearchParams } from "@/app/hooks/navigation";
// icons
import { HideOutline, ShowOutline } from "@makeplane/propel/icons";
// pace internal packages
-import { API_BASE_URL, E_PASSWORD_STRENGTH } from "@pace/constants";
+import { API_BASE_URL, DOCS_URL, E_PASSWORD_STRENGTH, externalLink } from "@pace/constants";
import { Button } from "@makeplane/propel/components/button";
import { Checkbox } from "@makeplane/propel/components/checkbox";
import { Input, InputGroup } from "@makeplane/propel/components/input";
@@ -25,6 +25,8 @@ import { useTranslation } from "@pace/i18n";
// service initialization
const authService = new AuthService();
+const telemetryPolicyLink = externalLink(DOCS_URL, "/self-hosting/telemetry");
+
// error codes
enum EErrorCodes {
INSTANCE_NOT_CONFIGURED = "INSTANCE_NOT_CONFIGURED",
@@ -354,15 +356,21 @@ export function InstanceSetupForm() {
/>
diff --git a/apps/admin/package.json b/apps/admin/package.json
index 98e777ed..e3be06b7 100644
--- a/apps/admin/package.json
+++ b/apps/admin/package.json
@@ -1,6 +1,6 @@
{
"name": "admin",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"description": "Admin UI for Pace",
"license": "AGPL-3.0",
diff --git a/apps/api/internal/worker/seeds/issues.json b/apps/api/internal/worker/seeds/issues.json
index 61006e57..e2cd06bb 100644
--- a/apps/api/internal/worker/seeds/issues.json
+++ b/apps/api/internal/worker/seeds/issues.json
@@ -30,8 +30,8 @@
"id": 3,
"name": "2. Invite your team 🤜🤛",
"sequence_id": 3,
- "description_html": "
Let's get your teammates on board!
First, you'll need to invite them to your workspace before they can join specific projects:
Click on your workspace name in the top-left corner, then select Settings from the dropdown.
Head over to the Members tab - this is your user management hub. Click Add member on the top right.
Enter your teammate's email address. Select a role for them (Admin, Member or Guest) that determines what they can do in the workspace.
Your team member will get an email invite. Once they've joined your workspace, you can add them to specific projects.
To do this, go to your project's Settings page.
Find the Members section, select your teammate, and assign them a project role - this controls what they can do within just this project.
",
- "description_stripped": "Let's get your teammates on board!First, you'll need to invite them to your workspace before they can join specific projects:Click on your workspace name in the top-left corner, then select Settings from the dropdown.Head over to the Members tab - this is your user management hub. Click Add member on the top right.Enter your teammate's email address. Select a role for them (Admin, Member or Guest) that determines what they can do in the workspace.Your team member will get an email invite. Once they've joined your workspace, you can add them to specific projects.To do this, go to your project's Settings page.Find the Members section, select your teammate, and assign them a project role - this controls what they can do within just this project.That's it!To learn more about user management, see Manage users and roles.",
+ "description_html": "
Let's get your teammates on board!
First, you'll need to invite them to your workspace before they can join specific projects:
Click on your workspace name in the top-left corner, then select Settings from the dropdown.
Head over to the Members tab - this is your user management hub. Click Add member on the top right.
Enter your teammate's email address. Select a role for them (Admin, Member or Guest) that determines what they can do in the workspace.
Your team member will get an email invite. Once they've joined your workspace, you can add them to specific projects.
To do this, go to your project's Settings page.
Find the Members section, select your teammate, and assign them a project role - this controls what they can do within just this project.
That's it!
",
+ "description_stripped": "Let's get your teammates on board!First, you'll need to invite them to your workspace before they can join specific projects:Click on your workspace name in the top-left corner, then select Settings from the dropdown.Head over to the Members tab - this is your user management hub. Click Add member on the top right.Enter your teammate's email address. Select a role for them (Admin, Member or Guest) that determines what they can do in the workspace.Your team member will get an email invite. Once they've joined your workspace, you can add them to specific projects.To do this, go to your project's Settings page.Find the Members section, select your teammate, and assign them a project role - this controls what they can do within just this project.That's it!",
"sort_order": 3000,
"state_id": 1,
"labels": [],
@@ -44,8 +44,8 @@
"id": 4,
"name": "3. Create and assign Work Items ✏️",
"sequence_id": 4,
- "description_html": "
A work item is the fundamental building block of your project. Think of these as the actionable tasks that move your project forward.
Ready to add something to your project's to-do list? Here's how:
Click the Add work item button in the top-right corner of the Work Items page.
Give your task a clear title and add any details in the description.
Set up the essentials:
Assign it to a team member (or yourself!)
Choose a priority level
Add start and due dates if there's a timeline
Tip: Save time by using the keyboard shortcut C from anywhere in your project to quickly create a new work item!
Want to dive deeper into all the things you can do with work items? Check out our documentation.
",
- "description_stripped": "A work item is the fundamental building block of your project. Think of these as the actionable tasks that move your project forward.Ready to add something to your project's to-do list? Here's how:Click the Add work item button in the top-right corner of the Work Items page.Give your task a clear title and add any details in the description.Set up the essentials:Assign it to a team member (or yourself!)Choose a priority levelAdd start and due dates if there's a timelineTip: Save time by using the keyboard shortcut C from anywhere in your project to quickly create a new work item!Want to dive deeper into all the things you can do with work items? Check out our documentation.",
+ "description_html": "
A work item is the fundamental building block of your project. Think of these as the actionable tasks that move your project forward.
Ready to add something to your project's to-do list? Here's how:
Click the Add work item button in the top-right corner of the Work Items page.
Give your task a clear title and add any details in the description.
Set up the essentials:
Assign it to a team member (or yourself!)
Choose a priority level
Add start and due dates if there's a timeline
Tip: Save time by using the keyboard shortcut C from anywhere in your project to quickly create a new work item!
",
+ "description_stripped": "A work item is the fundamental building block of your project. Think of these as the actionable tasks that move your project forward.Ready to add something to your project's to-do list? Here's how:Click the Add work item button in the top-right corner of the Work Items page.Give your task a clear title and add any details in the description.Set up the essentials:Assign it to a team member (or yourself!)Choose a priority levelAdd start and due dates if there's a timelineTip: Save time by using the keyboard shortcut C from anywhere in your project to quickly create a new work item!",
"sort_order": 4000,
"state_id": 3,
"labels": [2],
@@ -58,8 +58,8 @@
"id": 5,
"name": "4. Visualize your work 🔮",
"sequence_id": 5,
- "description_html": "
Pace offers multiple ways to look at your work items depending on what you need to see. Let's explore how to change views and customize them!
Switch between layouts
Look at the top toolbar in your project. You'll see several layout icons.
Click any of these icons to instantly switch between layouts.
Tip: Different layouts work best for different needs. Try Board view for tracking progress, Calendar for deadline management, and Gantt for timeline planning! See Layouts for more info.
Filter and display options
Need to focus on specific work?
Click the Filters dropdown in the toolbar. Select criteria and choose which items to show.
Click the Display dropdown to tailor how the information appears in your layout
Created the perfect setup? Save it for later by clicking the the Save View button.
Access saved views anytime from the Views section in your sidebar.
",
- "description_stripped": "Pace offers multiple ways to look at your work items depending on what you need to see. Let's explore how to change views and customize them!Switch between layoutsLook at the top toolbar in your project. You'll see several layout icons.Click any of these icons to instantly switch between layouts.Tip: Different layouts work best for different needs. Try Board view for tracking progress, Calendar for deadline management, and Gantt for timeline planning! See Layouts for more info.Filter and display optionsNeed to focus on specific work?Click the Filters dropdown in the toolbar. Select criteria and choose which items to show.Click the Display dropdown to tailor how the information appears in your layoutCreated the perfect setup? Save it for later by clicking the the Save View button.Access saved views anytime from the Views section in your sidebar.",
+ "description_html": "
Pace offers multiple ways to look at your work items depending on what you need to see. Let's explore how to change views and customize them!
Switch between layouts
Look at the top toolbar in your project. You'll see several layout icons.
Click any of these icons to instantly switch between layouts.
Tip: Different layouts work best for different needs. Try Board view for tracking progress, Calendar for deadline management, and Gantt for timeline planning!
Filter and display options
Need to focus on specific work?
Click the Filters dropdown in the toolbar. Select criteria and choose which items to show.
Click the Display dropdown to tailor how the information appears in your layout
Created the perfect setup? Save it for later by clicking the the Save View button.
Access saved views anytime from the Views section in your sidebar.
",
+ "description_stripped": "Pace offers multiple ways to look at your work items depending on what you need to see. Let's explore how to change views and customize them!Switch between layoutsLook at the top toolbar in your project. You'll see several layout icons.Click any of these icons to instantly switch between layouts.Tip: Different layouts work best for different needs. Try Board view for tracking progress, Calendar for deadline management, and Gantt for timeline planning!Filter and display optionsNeed to focus on specific work?Click the Filters dropdown in the toolbar. Select criteria and choose which items to show.Click the Display dropdown to tailor how the information appears in your layoutCreated the perfect setup? Save it for later by clicking the the Save View button.Access saved views anytime from the Views section in your sidebar.",
"sort_order": 5000,
"state_id": 3,
"labels": [],
@@ -72,8 +72,8 @@
"id": 6,
"name": "5. Use Cycles to time box tasks 🗓️",
"sequence_id": 6,
- "description_html": "
A Cycle in Pace is like a sprint - a dedicated timeframe where your team focuses on completing specific work items. It helps you break down your project into manageable chunks with clear start and end dates so everyone knows what to work on and when it needs to be done.
Setup Cycles
Go to the Cycles section in your project (you can find it in the left sidebar)
Click the Add cycle button in the top-right corner
Enter details and set the start and end dates for your cycle.
Click Create cycle and you're ready to go!
Add existing work items to the Cycle or create new ones.
Tip: To create a new Cycle quickly, just press Q from anywhere in your project!
",
- "description_stripped": "A Cycle in Pace is like a sprint - a dedicated timeframe where your team focuses on completing specific work items. It helps you break down your project into manageable chunks with clear start and end dates so everyone knows what to work on and when it needs to be done.Setup CyclesGo to the Cycles section in your project (you can find it in the left sidebar)Click the Add cycle button in the top-right cornerEnter details and set the start and end dates for your cycle.Click Create cycle and you're ready to go!Add existing work items to the Cycle or create new ones.Tip: To create a new Cycle quickly, just press Q from anywhere in your project!Want to learn more?Starting and stopping cyclesTransferring work items between cyclesTracking progress with chartsCheck out our detailed documentation for everything you need to know!",
+ "description_html": "
A Cycle in Pace is like a sprint - a dedicated timeframe where your team focuses on completing specific work items. It helps you break down your project into manageable chunks with clear start and end dates so everyone knows what to work on and when it needs to be done.
Setup Cycles
Go to the Cycles section in your project (you can find it in the left sidebar)
Click the Add cycle button in the top-right corner
Enter details and set the start and end dates for your cycle.
Click Create cycle and you're ready to go!
Add existing work items to the Cycle or create new ones.
Tip: To create a new Cycle quickly, just press Q from anywhere in your project!
",
+ "description_stripped": "A Cycle in Pace is like a sprint - a dedicated timeframe where your team focuses on completing specific work items. It helps you break down your project into manageable chunks with clear start and end dates so everyone knows what to work on and when it needs to be done.Setup CyclesGo to the Cycles section in your project (you can find it in the left sidebar)Click the Add cycle button in the top-right cornerEnter details and set the start and end dates for your cycle.Click Create cycle and you're ready to go!Add existing work items to the Cycle or create new ones.Tip: To create a new Cycle quickly, just press Q from anywhere in your project!",
"sort_order": 6000,
"state_id": 1,
"labels": [2],
diff --git a/apps/api/internal/worker/workspace_seed.go b/apps/api/internal/worker/workspace_seed.go
index 2f68db38..3c50667c 100644
--- a/apps/api/internal/worker/workspace_seed.go
+++ b/apps/api/internal/worker/workspace_seed.go
@@ -22,6 +22,8 @@ import (
const WorkspaceSeedTask = "plane.bgtasks.workspace_seed_task.workspace_seed"
// The seed data itself, copied from plane/seeds/data and diffed against it by CI.
+//
+// issues.json deviates from upstream on purpose: the documentation links its prose carried pointed at docs.plane.so, which this fork does not run, and nothing here interpolates configuration -- the files are embedded and unmarshalled as they stand -- so the sentences that existed only to carry those links were dropped instead of a templating pass being invented for four of them. Everything the prose actually teaches is still there.
var (
//go:embed seeds/projects.json
projectSeedJSON []byte
diff --git a/apps/space/app/error.tsx b/apps/space/app/error.tsx
index 4428e787..fb976c7e 100644
--- a/apps/space/app/error.tsx
+++ b/apps/space/app/error.tsx
@@ -4,9 +4,36 @@
* See the LICENSE file for details.
*/
+// pace imports
+import { FORUM_URL, SUPPORT_EMAIL } from "@pace/constants";
// ui
import { Button } from "@pace/propel/button";
+// Where to send crash details is per-installation configuration, and this fork ships with neither a support address nor a forum. The whole request for details goes when there is no channel to ask for them on -- asking someone to write to an address that does not exist wastes the one moment they were willing to help -- and the wording follows whichever channel is left so the sentence stays grammatical on its own.
+function ReportDetailsSentence() {
+ if (!SUPPORT_EMAIL && !FORUM_URL) return null;
+
+ const supportLink = SUPPORT_EMAIL ? (
+
+ {SUPPORT_EMAIL}
+
+ ) : null;
+ const forumLink = FORUM_URL ? (
+
+ Forum
+
+ ) : null;
+
+ return (
+ <>
+ {" "}
+ If you have more details, please {supportLink ? <>write to {supportLink}> : null}
+ {supportLink && forumLink ? " or " : null}
+ {forumLink ? <>post on our {forumLink}> : null}.
+ >
+ );
+}
+
function ErrorPage() {
const handleRetry = () => {
window.location.reload();
@@ -18,21 +45,8 @@ function ErrorPage() {
Yikes! That doesn{"'"}t look good.
- That crashed Plane, pun intended. No worries, though. Our engineers have been notified. If you have more
- details, please write to{" "}
-
- support@yldm.ai
- {" "}
- or on our{" "}
-
- Forum
-
- .
+ That crashed Plane, pun intended. No worries, though. Our engineers have been notified.
+
diff --git a/apps/space/core/components/account/terms-and-conditions.tsx b/apps/space/core/components/account/terms-and-conditions.tsx
index b389a903..c49f1c9f 100644
--- a/apps/space/core/components/account/terms-and-conditions.tsx
+++ b/apps/space/core/components/account/terms-and-conditions.tsx
@@ -4,21 +4,26 @@
* See the LICENSE file for details.
*/
+import { PRIVACY_POLICY_URL, TERMS_OF_SERVICE_URL } from "@pace/constants";
+
type Props = {
isSignUp?: boolean;
};
export function TermsAndConditions(props: Props) {
const { isSignUp = false } = props;
+ // Nothing is claimed when this installation publishes neither document. Telling someone they agreed to terms that are not reachable is worse than saying nothing, and the previous links pointed at paths this deployment does not serve.
+ if (!TERMS_OF_SERVICE_URL || !PRIVACY_POLICY_URL) return null;
+
return (
{isSignUp ? "By creating an account" : "By signing in"}, you agree to our{" \n"}
-
+ Terms of Service{" "}
and{" "}
-
+ Privacy Policy
{"."}
diff --git a/apps/space/package.json b/apps/space/package.json
index ab5f5504..f773d059 100644
--- a/apps/space/package.json
+++ b/apps/space/package.json
@@ -1,6 +1,6 @@
{
"name": "space",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"license": "AGPL-3.0",
"type": "module",
diff --git a/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx
index ec4d8af5..e8ad363f 100644
--- a/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx
+++ b/apps/web/app/(all)/[workspaceSlug]/(settings)/settings/projects/page.tsx
@@ -8,6 +8,7 @@ import { observer } from "mobx-react";
import Link from "@/app/hooks/link";
import { useTheme } from "next-themes";
// pace imports
+import { MARKETING_SITE_URL } from "@pace/constants";
import { Button, getButtonStyling } from "@pace/propel/button";
import { cn } from "@pace/utils";
// assets
@@ -31,9 +32,12 @@ function ProjectSettingsPage() {
need to get things done.
-
- Learn more about projects
-
+ {/* This was the marketing site's front page upstream, and the domain rename turned it into a link from the app back to the app's own root. It is dropped when there is no marketing site configured; the primary action next to it is the one that actually does something here. */}
+ {MARKETING_SITE_URL && (
+
+ Learn more about projects
+
+ )}
diff --git a/apps/web/app/(all)/workspace-invitations/page.tsx b/apps/web/app/(all)/workspace-invitations/page.tsx
index cabc3eb8..2e5d5ac6 100644
--- a/apps/web/app/(all)/workspace-invitations/page.tsx
+++ b/apps/web/app/(all)/workspace-invitations/page.tsx
@@ -19,7 +19,7 @@ import {
import { LogoSpinner } from "@/components/common/logo-spinner";
import { EmptySpace, EmptySpaceItem } from "@/components/ui/empty-space";
// constants
-import { WORKSPACE_INVITATION } from "@pace/constants";
+import { FORUM_URL, WORKSPACE_INVITATION } from "@pace/constants";
// helpers
import { EPageTypes } from "@/helpers/authentication.helper";
// hooks
@@ -118,11 +118,10 @@ function WorkspaceInvitationPage() {
)}
-
+ {/* The community entry is the forum, which this fork does not run at a known address. The list keeps its other entries, so dropping this one leaves the page with somewhere to go. */}
+ {FORUM_URL && (
+
+ )}
)
) : (
diff --git a/apps/web/app/error/prod.tsx b/apps/web/app/error/prod.tsx
index e60ce108..de0b6f49 100644
--- a/apps/web/app/error/prod.tsx
+++ b/apps/web/app/error/prod.tsx
@@ -6,6 +6,7 @@
import { useTheme } from "next-themes";
// pace imports
+import { STATUS_URL, SUPPORT_EMAIL } from "@pace/constants";
import { Button } from "@pace/propel/button";
// assets
import maintenanceModeDarkModeImage from "@/app/assets/instance/maintenance-mode-dark.svg?url";
@@ -13,18 +14,19 @@ import maintenanceModeLightModeImage from "@/app/assets/instance/maintenance-mod
// layouts
import DefaultLayout from "@/layouts/default-layout";
+// Both entries are dropped when this installation has not configured them. The previous defaults were upstream's, carried through a domain rename: pace-status.yldm.ai does not resolve at all, and offering a dead status page on the screen a user reaches *because* something broke is worse than offering nothing.
const linkMap = [
- {
+ SUPPORT_EMAIL && {
key: "mail_to",
label: "Contact Support",
- value: "mailto:support@yldm.ai",
+ value: `mailto:${SUPPORT_EMAIL}`,
},
- {
+ STATUS_URL && {
key: "status",
label: "Status Page",
- value: "https://pace-status.yldm.ai/",
+ value: STATUS_URL,
},
-];
+].filter(Boolean) as { key: string; label: string; value: string }[];
// Production Error Component
interface ProdErrorComponentProps {
diff --git a/apps/web/core/components/account/terms-and-conditions.tsx b/apps/web/core/components/account/terms-and-conditions.tsx
index 242e67c0..1444b0eb 100644
--- a/apps/web/core/components/account/terms-and-conditions.tsx
+++ b/apps/web/core/components/account/terms-and-conditions.tsx
@@ -6,7 +6,7 @@
import React from "react";
import Link from "@/app/hooks/link";
-import { EAuthModes } from "@pace/constants";
+import { EAuthModes, PRIVACY_POLICY_URL, TERMS_OF_SERVICE_URL } from "@pace/constants";
interface TermsAndConditionsProps {
authType?: EAuthModes;
@@ -14,8 +14,8 @@ interface TermsAndConditionsProps {
// Constants for better maintainability
const LEGAL_LINKS = {
- termsOfService: "https://pace.yldm.ai/legals/terms-and-conditions",
- privacyPolicy: "https://pace.yldm.ai/legals/privacy-policy",
+ termsOfService: TERMS_OF_SERVICE_URL,
+ privacyPolicy: PRIVACY_POLICY_URL,
} as const;
const MESSAGES = {
@@ -33,6 +33,9 @@ function LegalLink({ href, children }: { href: string; children: React.ReactNode
}
export function TermsAndConditions({ authType = EAuthModes.SIGN_IN }: TermsAndConditionsProps) {
+ // Nothing is claimed when this installation publishes neither document. Telling someone they agreed to terms that are not reachable is worse than saying nothing, and the previous links pointed at paths this deployment does not serve.
+ if (!LEGAL_LINKS.termsOfService || !LEGAL_LINKS.privacyPolicy) return null;
+
return (
diff --git a/apps/web/core/components/common/latest-feature-block.tsx b/apps/web/core/components/common/latest-feature-block.tsx
index 9acbc057..f2d6506c 100644
--- a/apps/web/core/components/common/latest-feature-block.tsx
+++ b/apps/web/core/components/common/latest-feature-block.tsx
@@ -6,6 +6,8 @@
import Link from "@/app/hooks/link";
import { useTheme } from "next-themes";
+// pace imports
+import { CHANGELOG_URL } from "@pace/constants";
// icons
import { ThoughtsOutline } from "@makeplane/propel/icons";
// images
@@ -19,10 +21,16 @@ export function LatestFeatureBlock() {
- Pages gets a facelift! Write anything and use Galileo to help you start.{" "}
-
- Learn more
-
+ 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
+
+ >
+ )}
Estimates have gone through a change, these are the estimates you had in your older versions which
- were not in use. Read more about them
-
- here.
-
+ were not in use.
+ {/* The sentence above already says what the archived list is, so the pointer at the documentation is the only part that goes when there is no documentation site configured. The path is the one upstream used on docs.plane.so, relative to whichever docs site this installation sets. */}
+ {archivedEstimatesDocsLink && (
+ <>
+ {" "}
+ Read more about them
+
+ here.
+
+ >
+ )}
>
}
variant="h6"
diff --git a/apps/web/core/components/global/product-updates/fallback.tsx b/apps/web/core/components/global/product-updates/fallback.tsx
index 7ba53852..631f0294 100644
--- a/apps/web/core/components/global/product-updates/fallback.tsx
+++ b/apps/web/core/components/global/product-updates/fallback.tsx
@@ -4,6 +4,7 @@
* See the LICENSE file for details.
*/
+import { CHANGELOG_URL } from "@pace/constants";
import { EmptyStateDetailed } from "@pace/propel/empty-state";
type TProductUpdatesFallbackProps = {
@@ -14,10 +15,10 @@ type TProductUpdatesFallbackProps = {
export function ProductUpdatesFallback(props: TProductUpdatesFallbackProps) {
const { description, variant } = props;
// derived values
- const changelogUrl =
- variant === "cloud"
- ? "https://pace.yldm.ai/changelog?category=cloud"
- : "https://pace.yldm.ai/changelog?category=self-hosted";
+ // The empty state stays either way, since it is what this modal shows when the updates feed could not be read. Only the button goes when there is no changelog to send anybody to: this screen is already an apology, and a second dead end on top of it is worse than none.
+ const changelogUrl = CHANGELOG_URL
+ ? `${CHANGELOG_URL}?category=${variant === "cloud" ? "cloud" : "self-hosted"}`
+ : "";
return (
);
diff --git a/apps/web/core/components/global/product-updates/footer.tsx b/apps/web/core/components/global/product-updates/footer.tsx
index 66d15baa..98bb2796 100644
--- a/apps/web/core/components/global/product-updates/footer.tsx
+++ b/apps/web/core/components/global/product-updates/footer.tsx
@@ -4,6 +4,8 @@
* See the LICENSE file for details.
*/
+import { Fragment } from "react";
+import { CHANGELOG_URL, DOCS_URL, FORUM_URL, MARKETING_PAGES_PAGE_LINK, SUPPORT_EMAIL } from "@pace/constants";
import { useTranslation } from "@pace/i18n";
// ui
import { getButtonStyling } from "@pace/propel/button";
@@ -11,65 +13,51 @@ import { PaceLogo } from "@pace/propel/icons";
// helpers
import { cn } from "@pace/utils";
+const LINK_CLASSNAME = "text-13 text-secondary underline-offset-1 outline-none hover:text-primary hover:underline";
+
export function ProductUpdatesFooter() {
const { t } = useTranslation();
+ // Every destination in this row is a separate site that a self-hosted installation may not have, so the row is built from whichever of them is configured instead of being written out link by link. The dot separator is drawn before each link except the first, because separators written between fixed links leave a dangling dot the moment one of those links stops rendering.
+ const links = [
+ { key: "docs", label: t("docs"), href: DOCS_URL },
+ { key: "changelog", label: t("full_changelog"), href: CHANGELOG_URL },
+ { key: "support", label: t("support"), href: SUPPORT_EMAIL ? `mailto:${SUPPORT_EMAIL}` : "" },
+ { key: "forum", label: "Forum", href: FORUM_URL },
+ ].filter((link) => !!link.href);
+
+ // Nothing here is part of the changelog itself, so with no configured link left there is no footer to draw -- only its margins.
+ if (links.length === 0 && !MARKETING_PAGES_PAGE_LINK) return null;
+
return (
);
}
diff --git a/apps/web/core/components/license/modal/card/plan-upgrade.tsx b/apps/web/core/components/license/modal/card/plan-upgrade.tsx
index 864e0a11..2d2f4092 100644
--- a/apps/web/core/components/license/modal/card/plan-upgrade.tsx
+++ b/apps/web/core/components/license/modal/card/plan-upgrade.tsx
@@ -25,7 +25,12 @@ export type PlanUpgradeCardProps = {
verticalFeatureList?: boolean;
extraFeatures?: string | React.ReactNode;
renderTrialButton?: (props: { productId: string | undefined; priceId: string | undefined }) => React.ReactNode;
- handleCheckout: (params: TCheckoutParams) => void;
+ /**
+ * Omit this to offer the sales contact instead of a checkout button.
+ *
+ * A self-hosted installation has no billing service of its own to check out against -- upstream sent buyers to the vendor's cloud app for that, which this fork has no equivalent of -- so nothing passes it today. It stays a supported prop because wiring up a real checkout is exactly what would make it reachable again.
+ */
+ handleCheckout?: (params: TCheckoutParams) => void;
isSelfHosted: boolean;
isTrialAllowed: boolean;
};
@@ -51,7 +56,7 @@ export const PlanUpgradeCard = observer(function PlanUpgradeCard(props: PlanUpgr
const yearlyDiscount = calculateYearlyDiscount(monthlyPriceDetails.price, yearlyPriceDetails.price);
const prices = [monthlyPriceDetails, yearlyPriceDetails];
- if (!product?.is_active) {
+ if (!product?.is_active || !handleCheckout) {
return (
{
+ const href = SUBSCRIPTION_WEBPAGE_URLS[planVariant];
+ if (!href) return null;
+ return (
+
- }
- handleCheckout={handleRedirection}
+ extraFeatures={renderFullFeaturesLink(EProductSubscriptionEnum.ENTERPRISE)}
isSelfHosted={!!isSelfHosted}
isTrialAllowed={!!isTrialAllowed}
/>
diff --git a/apps/web/core/components/power-k/config/help-commands.ts b/apps/web/core/components/power-k/config/help-commands.ts
index 59b1a146..a1ae7b43 100644
--- a/apps/web/core/components/power-k/config/help-commands.ts
+++ b/apps/web/core/components/power-k/config/help-commands.ts
@@ -5,6 +5,8 @@
*/
import { ChatOutline, DocumentationOutline, Github, RocketOutline } from "@makeplane/propel/icons";
+// pace imports
+import { DOCS_URL, FORUM_URL } from "@pace/constants";
// components
import type { TPowerKCommandConfig } from "@/components/power-k/core/types";
// hooks
@@ -37,10 +39,10 @@ export const usePowerKHelpCommands = (): TPowerKCommandConfig[] => {
i18n_title: "power_k.help_actions.open_plane_documentation",
icon: DocumentationOutline,
action: () => {
- window.open("https://pace.yldm.ai/docs/", "_blank", "noopener,noreferrer");
+ window.open(DOCS_URL, "_blank", "noopener,noreferrer");
},
isEnabled: () => true,
- isVisible: () => true,
+ isVisible: () => !!DOCS_URL,
closeOnSelect: true,
},
{
@@ -50,10 +52,10 @@ export const usePowerKHelpCommands = (): TPowerKCommandConfig[] => {
i18n_title: "power_k.help_actions.join_forum",
icon: ChatOutline,
action: () => {
- window.open("https://pace.yldm.ai/forum", "_blank", "noopener,noreferrer");
+ window.open(FORUM_URL, "_blank", "noopener,noreferrer");
},
isEnabled: () => true,
- isVisible: () => true,
+ isVisible: () => !!FORUM_URL,
closeOnSelect: true,
},
{
diff --git a/apps/web/core/components/workspace/billing/comparison/plan-detail.tsx b/apps/web/core/components/workspace/billing/comparison/plan-detail.tsx
index c95641e5..f4f256f2 100644
--- a/apps/web/core/components/workspace/billing/comparison/plan-detail.tsx
+++ b/apps/web/core/components/workspace/billing/comparison/plan-detail.tsx
@@ -6,7 +6,7 @@
import { observer } from "mobx-react";
// pace imports
-import { SUBSCRIPTION_REDIRECTION_URLS, SUBSCRIPTION_WITH_BILLING_FREQUENCY, TALK_TO_SALES_URL } from "@pace/constants";
+import { SUBSCRIPTION_WITH_BILLING_FREQUENCY, TALK_TO_SALES_URL } from "@pace/constants";
import { useTranslation } from "@pace/i18n";
import { Button } from "@pace/propel/button";
import type { TBillingFrequency } from "@pace/types";
@@ -40,12 +40,9 @@ export const PlanDetail = observer(function PlanDetail(props: TPlanDetailProps)
? planDetail.monthlyPriceSecondaryDescription
: planDetail.yearlyPriceSecondaryDescription;
+ // There is no self-serve upgrade for a self-hosted installation to send a buyer to, so the only destination this button ever has is whatever sales contact the installation configures. It is not rendered when there is none, rather than opening a page that does not exist.
const handleRedirection = () => {
- const frequency = billingFrequency ?? "year";
- // Get the redirection URL based on the subscription type and billing frequency
- const redirectUrl = SUBSCRIPTION_REDIRECTION_URLS[subscriptionType][frequency] ?? TALK_TO_SALES_URL;
- // Open the URL in a new tab
- window.open(redirectUrl, "_blank");
+ window.open(TALK_TO_SALES_URL, "_blank");
};
return (
@@ -95,11 +92,13 @@ export const PlanDetail = observer(function PlanDetail(props: TPlanDetailProps)
)}
{/* Subscription button */}
-
-
-
+ {TALK_TO_SALES_URL && (
+
+
+
+ )}
);
});
diff --git a/apps/web/core/components/workspace/billing/comparison/plans.tsx b/apps/web/core/components/workspace/billing/comparison/plans.tsx
index bd7e1e66..95599cc1 100644
--- a/apps/web/core/components/workspace/billing/comparison/plans.tsx
+++ b/apps/web/core/components/workspace/billing/comparison/plans.tsx
@@ -5,6 +5,7 @@
*/
import { ChatOutline, MailOutline } from "@makeplane/propel/icons";
+import { TALK_TO_SALES_URL } from "@pace/constants";
import { EProductSubscriptionEnum } from "@pace/types";
// pace imports
import { cn } from "@pace/utils";
@@ -1234,16 +1235,16 @@ export const PLANS_COMPARISON_LIST: TPlansComparisonDetails[] = [
{
title: "SLA",
description: (
+ // The claim that tiers can be requested holds whether or not there is a sales page to request them on, so the phrase stays as plain text when this installation has configured no such page and only the link goes.
<>
Get business-friendly SLAs with higher plans. SLAs are by priority of work item and tiers{" "}
-
- can be requested
-
+ {TALK_TO_SALES_URL ? (
+
+ can be requested
+
+ ) : (
+ "can be requested"
+ )}
.
>
),
diff --git a/apps/web/core/components/workspace/sidebar/help-section/root.tsx b/apps/web/core/components/workspace/sidebar/help-section/root.tsx
index f0135753..8f96edfe 100644
--- a/apps/web/core/components/workspace/sidebar/help-section/root.tsx
+++ b/apps/web/core/components/workspace/sidebar/help-section/root.tsx
@@ -7,6 +7,7 @@
import React, { useState } from "react";
import { observer } from "mobx-react";
import { HelpOutline, PagesOutline, UserOutline } from "@makeplane/propel/icons";
+import { DOCS_URL, FORUM_URL, SUPPORT_EMAIL } from "@pace/constants";
import { useTranslation } from "@pace/i18n";
// ui
import { CustomMenu } from "@pace/ui";
@@ -46,19 +47,24 @@ export const HelpMenuRoot = observer(function HelpMenuRoot() {
maxHeight="lg"
closeOnSelect
>
- window.open("https://pace.yldm.ai/docs", "_blank")}>
-
-
-
+ {/* The documentation site, the support address and the forum are all per-installation configuration this fork ships empty, and each entry is dropped when its own is missing: a menu row whose only job is to open a link has nothing to do without one. The divider goes with them, so the menu does not open on a rule with nothing above it. */}
+ {DOCS_URL && (
+ window.open(DOCS_URL, "_blank")}>
+
diff --git a/apps/web/package.json b/apps/web/package.json
index 19f3d4f9..08ee07aa 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -1,6 +1,6 @@
{
"name": "web",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"license": "AGPL-3.0",
"type": "module",
diff --git a/package.json b/package.json
index 76351b08..fa3dbd24 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "pace",
- "version": "1.4.37",
+ "version": "1.4.38",
"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 f3403674..eff21b10 100644
--- a/packages/codemods/package.json
+++ b/packages/codemods/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/codemods",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"scripts": {
"check:format": "oxfmt --check .",
diff --git a/packages/constants/package.json b/packages/constants/package.json
index 75f7f8c3..6b7e5f02 100644
--- a/packages/constants/package.json
+++ b/packages/constants/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/constants",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"license": "AGPL-3.0",
"type": "module",
diff --git a/packages/constants/src/endpoints.ts b/packages/constants/src/endpoints.ts
index 68496c5a..150fb0e4 100644
--- a/packages/constants/src/endpoints.ts
+++ b/packages/constants/src/endpoints.ts
@@ -23,11 +23,35 @@ export const LIVE_URL = encodeURI(`${LIVE_BASE_URL}${LIVE_BASE_PATH}`);
export const WEB_BASE_URL = process.env.VITE_WEB_BASE_URL || "";
export const WEB_BASE_PATH = process.env.VITE_WEB_BASE_PATH || "";
export const WEB_URL = encodeURI(`${WEB_BASE_URL}${WEB_BASE_PATH}`);
-// This installation's own website, which is where "powered by" and the like point.
+// This installation's own website, which is where "powered by" and the like point. The app's own public home is a real destination, so this one keeps a default.
export const WEBSITE_URL = process.env.VITE_WEBSITE_URL || "https://pace.yldm.ai";
// Whoever runs this installation, not upstream. Left empty rather than guessed: every message that uses it already falls back to "administrator" when it is, and mailing support@yldm.ai about an account on someone else's fork helps nobody. Set VITE_SUPPORT_EMAIL to fill it in.
export const SUPPORT_EMAIL = process.env.VITE_SUPPORT_EMAIL || "";
-// marketing links
-export const MARKETING_PRICING_PAGE_LINK = "https://pace.yldm.ai/pricing";
-export const MARKETING_CONTACT_US_PAGE_LINK = "https://pace.yldm.ai/contact";
-export const MARKETING_PLANE_ONE_PAGE_LINK = "https://pace.yldm.ai/one";
+// The four hosts below are separate sites upstream -- a marketing site, docs.plane.so, forum.plane.so and a status page -- and this fork has no equivalent of any of them at a known address. They are empty by default for the same reason SUPPORT_EMAIL is, and the rule for using one is the same: when it is empty, do not render the link at all. Do NOT fall back to WEBSITE_URL. That is exactly what the domain rename did, and because the web app's root route is the dynamic `:workspaceSlug` segment, a marketing path sent to the app's own domain does not even land on a router 404 -- `/pricing` is read as a workspace named "pricing" and fails as a missing workspace, while a deeper path like `/upgrade/pro/self-hosted` matches nothing and 404s outright.
+export const MARKETING_SITE_URL = process.env.VITE_MARKETING_SITE_URL || "";
+export const DOCS_URL = process.env.VITE_DOCS_URL || "";
+export const FORUM_URL = process.env.VITE_FORUM_URL || "";
+export const STATUS_URL = process.env.VITE_STATUS_URL || "";
+
+/**
+ * Builds a link to a page on one of the optional external sites above, and returns "" when that site is not configured.
+ *
+ * Callers must treat "" as "there is no such page here" and omit the link, rather than rendering an anchor with an empty href -- which navigates to the current page and reads as a broken control.
+ */
+export const externalLink = (siteUrl: string, path = ""): string =>
+ siteUrl ? `${siteUrl.replace(/\/$/, "")}${path}` : "";
+
+// This installation's own terms and privacy policy. They default to the marketing site's conventional paths when one is configured, and are overridable on their own because legal documents are often published somewhere else entirely.
+//
+// When these are empty the sign-in and sign-up screens drop the whole "you understand and agree to our Terms of Service and Privacy Policy" sentence rather than keeping the claim and dropping the links: an installation that publishes no terms should not be telling people they agreed to them.
+export const TERMS_OF_SERVICE_URL =
+ process.env.VITE_TERMS_OF_SERVICE_URL || externalLink(MARKETING_SITE_URL, "/legals/terms-and-conditions");
+export const PRIVACY_POLICY_URL =
+ process.env.VITE_PRIVACY_POLICY_URL || externalLink(MARKETING_SITE_URL, "/legals/privacy-policy");
+
+// marketing links, empty unless VITE_MARKETING_SITE_URL is set
+export const MARKETING_PRICING_PAGE_LINK = externalLink(MARKETING_SITE_URL, "/pricing");
+export const MARKETING_CONTACT_US_PAGE_LINK = externalLink(MARKETING_SITE_URL, "/contact");
+export const MARKETING_PLANE_ONE_PAGE_LINK = externalLink(MARKETING_SITE_URL, "/one");
+export const MARKETING_PAGES_PAGE_LINK = externalLink(MARKETING_SITE_URL, "/pages");
+export const CHANGELOG_URL = externalLink(MARKETING_SITE_URL, "/changelog");
diff --git a/packages/constants/src/payment.ts b/packages/constants/src/payment.ts
index b67a339f..0e0e805a 100644
--- a/packages/constants/src/payment.ts
+++ b/packages/constants/src/payment.ts
@@ -4,8 +4,10 @@
* See the LICENSE file for details.
*/
-import type { IPaymentProduct, TBillingFrequency, TProductBillingFrequency } from "@pace/types";
+import type { IPaymentProduct, TProductBillingFrequency } from "@pace/types";
import { EProductSubscriptionEnum } from "@pace/types";
+// local imports
+import { MARKETING_SITE_URL, externalLink } from "./endpoints";
/**
* Default billing frequency for each product subscription type
@@ -115,45 +117,22 @@ export const PLANE_COMMUNITY_PRODUCTS: Record = {
};
/**
- * URL for the "Talk to Sales" page where users can contact sales team
+ * URL for the "Talk to Sales" page where users can contact sales team.
+ *
+ * Empty unless VITE_MARKETING_SITE_URL is configured, and every caller must omit its link when it is — see the comment on MARKETING_SITE_URL in endpoints.ts.
*/
-export const TALK_TO_SALES_URL = "https://pace.yldm.ai/talk-to-sales";
-
-/**
- * Mapping of subscription types to their respective upgrade/redirection URLs based on billing frequency
- * Used for self-hosted installations to redirect users to appropriate upgrade pages
- */
-export const SUBSCRIPTION_REDIRECTION_URLS: Record> = {
- [EProductSubscriptionEnum.FREE]: {
- month: TALK_TO_SALES_URL,
- year: TALK_TO_SALES_URL,
- },
- [EProductSubscriptionEnum.ONE]: {
- month: TALK_TO_SALES_URL,
- year: TALK_TO_SALES_URL,
- },
- [EProductSubscriptionEnum.PRO]: {
- month: "https://pace.yldm.ai/upgrade/pro/self-hosted?plan=month",
- year: "https://pace.yldm.ai/upgrade/pro/self-hosted?plan=year",
- },
- [EProductSubscriptionEnum.BUSINESS]: {
- month: "https://pace.yldm.ai/upgrade/business/self-hosted?plan=month",
- year: "https://pace.yldm.ai/upgrade/business/self-hosted?plan=year",
- },
- [EProductSubscriptionEnum.ENTERPRISE]: {
- month: TALK_TO_SALES_URL,
- year: TALK_TO_SALES_URL,
- },
-};
+export const TALK_TO_SALES_URL = externalLink(MARKETING_SITE_URL, "/talk-to-sales");
/**
* Mapping of subscription types to their respective marketing webpage URLs
* Used to direct users to learn more about each plan's features and pricing
+ *
+ * There is deliberately no counterpart for the paid upgrade flow. Upstream, a self-hosted installation sent buyers to the vendor's own cloud app (app.plane.so/upgrade/...) to buy a licence, and this fork has no such service -- so a checkout redirect here has nowhere to go and the CTA that used it is gone rather than pointing somewhere that 404s.
*/
export const SUBSCRIPTION_WEBPAGE_URLS: Record = {
[EProductSubscriptionEnum.FREE]: TALK_TO_SALES_URL,
[EProductSubscriptionEnum.ONE]: TALK_TO_SALES_URL,
- [EProductSubscriptionEnum.PRO]: "https://pace.yldm.ai/pro",
- [EProductSubscriptionEnum.BUSINESS]: "https://pace.yldm.ai/business",
- [EProductSubscriptionEnum.ENTERPRISE]: "https://pace.yldm.ai/business",
+ [EProductSubscriptionEnum.PRO]: externalLink(MARKETING_SITE_URL, "/pro"),
+ [EProductSubscriptionEnum.BUSINESS]: externalLink(MARKETING_SITE_URL, "/business"),
+ [EProductSubscriptionEnum.ENTERPRISE]: externalLink(MARKETING_SITE_URL, "/business"),
};
diff --git a/packages/editor/package.json b/packages/editor/package.json
index 7b788abb..e3aab465 100644
--- a/packages/editor/package.json
+++ b/packages/editor/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/editor",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"description": "Core Editor that powers Pace",
"keywords": [
diff --git a/packages/hooks/package.json b/packages/hooks/package.json
index 473a9032..7db38f89 100644
--- a/packages/hooks/package.json
+++ b/packages/hooks/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/hooks",
- "version": "1.4.37",
+ "version": "1.4.38",
"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 a91ad628..5c179910 100644
--- a/packages/i18n/package.json
+++ b/packages/i18n/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/i18n",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"description": "I18n shared across multiple apps internally",
"license": "AGPL-3.0",
diff --git a/packages/propel/package.json b/packages/propel/package.json
index 1ded20e1..5cf9843f 100644
--- a/packages/propel/package.json
+++ b/packages/propel/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/propel",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"license": "AGPL-3.0",
"type": "module",
diff --git a/packages/services/package.json b/packages/services/package.json
index 50521f6d..f0af3409 100644
--- a/packages/services/package.json
+++ b/packages/services/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/services",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"license": "AGPL-3.0",
"type": "module",
diff --git a/packages/shared-state/package.json b/packages/shared-state/package.json
index 0d1345bd..98cd1e7c 100644
--- a/packages/shared-state/package.json
+++ b/packages/shared-state/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/shared-state",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"description": "Shared state shared across multiple apps internally",
"license": "AGPL-3.0",
diff --git a/packages/tailwind-config/package.json b/packages/tailwind-config/package.json
index a79110b3..35406e35 100644
--- a/packages/tailwind-config/package.json
+++ b/packages/tailwind-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/tailwind-config",
- "version": "1.4.37",
+ "version": "1.4.38",
"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 74ff7b95..4f252210 100644
--- a/packages/types/package.json
+++ b/packages/types/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/types",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"license": "AGPL-3.0",
"type": "module",
diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json
index 8c662206..1df10826 100644
--- a/packages/typescript-config/package.json
+++ b/packages/typescript-config/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/typescript-config",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"license": "AGPL-3.0",
"files": [
diff --git a/packages/ui/package.json b/packages/ui/package.json
index ebef813a..8f128831 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/ui",
- "version": "1.4.37",
+ "version": "1.4.38",
"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 005c36a0..274f4cc1 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -1,6 +1,6 @@
{
"name": "@pace/utils",
- "version": "1.4.37",
+ "version": "1.4.38",
"private": true,
"description": "Helper functions shared across multiple apps internally",
"license": "AGPL-3.0",
diff --git a/turbo.json b/turbo.json
index af116bd3..4ada0888 100644
--- a/turbo.json
+++ b/turbo.json
@@ -14,8 +14,12 @@
"VITE_API_BASE_PATH",
"VITE_API_BASE_URL",
"VITE_APP_VERSION",
+ "VITE_DOCS_URL",
+ "VITE_FORUM_URL",
"VITE_LIVE_BASE_PATH",
"VITE_LIVE_BASE_URL",
+ "VITE_MARKETING_SITE_URL",
+ "VITE_PRIVACY_POLICY_URL",
"VITE_SENTRY_DSN",
"VITE_SENTRY_ENVIRONMENT",
"VITE_SENTRY_PROFILES_SAMPLE_RATE",
@@ -25,7 +29,9 @@
"VITE_SENTRY_TRACES_SAMPLE_RATE",
"VITE_SPACE_BASE_PATH",
"VITE_SPACE_BASE_URL",
+ "VITE_STATUS_URL",
"VITE_SUPPORT_EMAIL",
+ "VITE_TERMS_OF_SERVICE_URL",
"VITE_WEB_BASE_PATH",
"VITE_WEB_BASE_URL",
"VITE_WEBSITE_URL"