Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/constants/src/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export const WORKSPACE_SETTINGS = {
},
"api-tokens": {
key: "api-tokens",
i18n_label: "workspace_settings.settings.webhooks.title",
i18n_label: "workspace_settings.settings.api_tokens.title",
href: `/settings/api-tokens`,
access: [EUserWorkspaceRoles.ADMIN],
highlight: (pathname: string, baseUrl: string) =>
Expand Down
127 changes: 119 additions & 8 deletions packages/i18n/src/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,17 @@
"no_labels_yet": "No labels yet",
"ideal": "Ideal",
"current": "Current",
"no_matching_members": "No matching members",
"leaving": "Leaving",
"removing": "Removing",
"leave": "Leave",
"refreshing": "Refreshing",
"refresh_status": "Refresh status",
"prev": "Prev",
"next": "Next",
"re_generating": "Re-generating",
"re_generate": "Re-generate",
"re_generate_key": "Re-generate key",

"project_view": {
"sort_by": {
Expand Down Expand Up @@ -895,24 +906,124 @@

"workspace_settings": {
"label": "Workspace settings",
"key_created": "Key created",
"copy_key": "Copy and save this secret key in Plane Pages. You can't see this key after you hit Close. A CSV file containing the key has been downloaded.",
"token_copied": "Token copied to clipboard.",
"settings": {
"general": {
"title": "General"
"title": "General",
"upload_logo": "Upload logo",
"edit_logo": "Edit logo",
"name": "Workspace name",
"company_size": "Company size",
"url": "Workspace URL",
"update_workspace" : "Update workspace",
"delete_workspace" : "Delete workspace",
"delete_workspace_description" : "When deleting a workspace, all of the data and resources within that workspace will be permanently removed and cannot be recovered.",
"delete_btn": "Delete my workspace",
"errors": {
"name": {
"required": "Name is required",
"max_length": "Workspace name should not exceed 80 characters"
},
"company_size": {
"required": "Company size is required"
}
}
},
"members": {
"title": "Members"
"title": "Members",
"add_member": "Add member",
"invitations_sent_successfully": "Invitations sent successfully",
"leave_confirmation": "Are you sure you want to leave the workspace? You will no longer have access to this workspace. This action cannot be undone.",
"details":{
"full_name":"Full name",
"display_name":"Display name",
"email_address":"Email address",
"account_type":"Account type",
"authentication":"Authentication",
"joining_date":"Joining date"
}
},
"billing-and-plans": {
"title": "Billing & Plans"
"billing_and_plans": {
"title": "Billing & Plans",
"current_plan":"Current plan",
"free_plan":"You are currently using the free plan",
"view_plans":"View plans"
},
"exports": {
"title": "Exports"
"title": "Exports",
"exporting": "Exporting",
"previous_exports": "Previous exports",
"export_separate_files" : "Export the data into separate files",
"modal": {
"title": "Export to",
"toasts": {
"success": {
"title": "Export successful",
"message": "You will be able to download the exported {entity} from the previous export."
},
"error": {
"title": "Export failed",
"message": "Export was unsuccessful. Please try again."
}
}
}
},
"webhooks": {
"title": "Webhooks"
"title": "Webhooks",
"add_webhook": "Add webhook",
"modal": {
"title": "Create webhook",
"details": "Webhook details",
"payload": "Payload URL",
"question": "Which events would you like to trigger this webhook?" ,
"error": "URL is required"
},
"secret_key": {
"title": "Secret key",
"message": "Generate a token to sign-in to the webhook payload"
},
"toasts": {
"created": {
"title": "Webhook created",
"message": "The webhook has been successfully created"
},
"not_created": {
"title": "Webhook not created",
"message": "The webhook could not be created"
},
"updated": {
"title": "Webhook updated",
"message": "The webhook has been successfully updated"
},
"not_updated": {
"title": "Webhook not updated",
"message": "The webhook could not be updated"
},
"removed": {
"title": "Webhook removed",
"message": "The webhook has been successfully removed"
},
"not_removed": {
"title": "Webhook not removed",
"message": "The webhook could not be removed"
},
"secret_key_copied": {
"message": "Secret key copied to clipboard."
},
"secret_key_not_copied": {
"message": "Error occurred while copying secret key."
}
}
},
"api-tokens": {
"title": "API Tokens"
"api_tokens": {
"title": "API Tokens",
"add_token": "Add API token",
"create_token": "Create token",
"never_expires": "Never expires",
"generate_token": "Generate token",
"generating": "Generating"
}
},
"empty_state": {
Expand Down
12 changes: 7 additions & 5 deletions web/app/[workspaceSlug]/(projects)/settings/api-tokens/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ const ApiTokensPage = observer(() => {
workspaceSlug && canPerformWorkspaceAdminActions ? apiTokenService.getApiTokens(workspaceSlug.toString()) : null
);

const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - API Tokens` : undefined;
const pageTitle = currentWorkspace?.name
? `${currentWorkspace.name} - ${t("workspace_settings.settings.api_tokens.title")}`
: undefined;

if (workspaceUserInfo && !canPerformWorkspaceAdminActions) {
return <NotAuthorizedView section="settings" />;
Expand All @@ -61,9 +63,9 @@ const ApiTokensPage = observer(() => {
{tokens.length > 0 ? (
<>
<div className="flex items-center justify-between border-b border-custom-border-200 pb-3.5">
<h3 className="text-xl font-medium">API tokens</h3>
<h3 className="text-xl font-medium">{t("workspace_settings.settings.api_tokens.title")}</h3>
<Button variant="primary" onClick={() => setIsCreateTokenModalOpen(true)}>
Add API token
{t("workspace_settings.settings.api_tokens.add_token")}
</Button>
</div>
<div>
Expand All @@ -75,9 +77,9 @@ const ApiTokensPage = observer(() => {
) : (
<div className="flex h-full w-full flex-col">
<div className="flex items-center justify-between gap-4 border-b border-custom-border-200 pb-3.5">
<h3 className="text-xl font-medium">API tokens</h3>
<h3 className="text-xl font-medium">{t("workspace_settings.settings.api_tokens.title")}</h3>
<Button variant="primary" onClick={() => setIsCreateTokenModalOpen(true)}>
Add API token
{t("workspace_settings.settings.api_tokens.add_token")}
</Button>
</div>
<div className="h-full w-full flex items-center justify-center">
Expand Down
8 changes: 6 additions & 2 deletions web/app/[workspaceSlug]/(projects)/settings/exports/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { observer } from "mobx-react";
// components
import { useTranslation } from "@plane/i18n";
import { NotAuthorizedView } from "@/components/auth-screens";
import { PageHead } from "@/components/core";
import ExportGuide from "@/components/exporter/guide";
Expand All @@ -15,13 +16,16 @@ const ExportsPage = observer(() => {
// store hooks
const { workspaceUserInfo, allowPermissions } = useUserPermissions();
const { currentWorkspace } = useWorkspace();
const { t } = useTranslation();

// derived values
const canPerformWorkspaceMemberActions = allowPermissions(
[EUserPermissions.ADMIN, EUserPermissions.MEMBER],
EUserPermissionsLevel.WORKSPACE
);
const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Exports` : undefined;
const pageTitle = currentWorkspace?.name
? `${currentWorkspace.name} - ${t("workspace_settings.settings.exports.title")}`
: undefined;

// if user is not authorized to view this page
if (workspaceUserInfo && !canPerformWorkspaceMemberActions) {
Expand All @@ -37,7 +41,7 @@ const ExportsPage = observer(() => {
})}
>
<div className="flex items-center border-b border-custom-border-100 pb-3.5">
<h3 className="text-xl font-medium">Exports</h3>
<h3 className="text-xl font-medium">{t("workspace_settings.settings.exports.title")}</h3>
</div>
<ExportGuide />
</div>
Expand Down
12 changes: 7 additions & 5 deletions web/app/[workspaceSlug]/(projects)/settings/members/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useParams } from "next/navigation";
import { Search } from "lucide-react";
// types
import { MEMBER_INVITED } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { IWorkspaceBulkInviteFormData } from "@plane/types";
// ui
import { Button, TOAST_TYPE, setToast } from "@plane/ui";
Expand Down Expand Up @@ -34,6 +35,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
workspace: { inviteMembersToWorkspace },
} = useMember();
const { currentWorkspace } = useWorkspace();
const { t } = useTranslation();

// derived values
const canPerformWorkspaceAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.WORKSPACE);
Expand Down Expand Up @@ -62,7 +64,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
setToast({
type: TOAST_TYPE.SUCCESS,
title: "Success!",
message: "Invitations sent successfully.",
message: t("workspace_settings.settings.members.invitations_sent_successfully"),
});
})
.catch((err) => {
Expand All @@ -80,7 +82,7 @@ const WorkspaceMembersSettingsPage = observer(() => {
setToast({
type: TOAST_TYPE.ERROR,
title: "Error!",
message: `${err.error ?? "Something went wrong. Please try again."}`,
message: `${err.error ?? t("something_went_wrong_please_try_again")}`,
});
});
};
Expand All @@ -107,20 +109,20 @@ const WorkspaceMembersSettingsPage = observer(() => {
})}
>
<div className="flex justify-between gap-4 pb-3.5 items-start ">
<h4 className="text-xl font-medium">Members</h4>
<h4 className="text-xl font-medium">{t("workspace_settings.settings.members.title")}</h4>
<div className="ml-auto flex items-center gap-1.5 rounded-md border border-custom-border-200 bg-custom-background-100 px-2.5 py-1.5">
<Search className="h-3.5 w-3.5 text-custom-text-400" />
<input
className="w-full max-w-[234px] border-none bg-transparent text-sm outline-none placeholder:text-custom-text-400"
placeholder="Search..."
placeholder={`${t("search")}...`}
value={searchQuery}
autoFocus
onChange={(e) => setSearchQuery(e.target.value)}
/>
</div>
{canPerformWorkspaceAdminActions && (
<Button variant="primary" size="sm" onClick={() => setInviteModal(true)}>
Add member
{t("workspace_settings.settings.members.add_member")}
</Button>
)}
</div>
Expand Down
2 changes: 1 addition & 1 deletion web/app/[workspaceSlug]/(projects)/settings/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const WorkspaceSettingsSidebar = observer(() => {
return (
<div className="flex w-[280px] flex-col gap-6">
<div className="flex flex-col gap-2">
<span className="text-xs font-semibold text-custom-sidebar-text-400">SETTINGS</span>
<span className="text-xs font-semibold text-custom-sidebar-text-400 uppercase">{t("settings")}</span>
<div className="flex w-full flex-col gap-1">
{WORKSPACE_SETTINGS_LINKS.map(
(link) =>
Expand Down
12 changes: 7 additions & 5 deletions web/app/[workspaceSlug]/(projects)/settings/webhooks/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ const WebhooksListPage = observer(() => {
workspaceSlug && canPerformWorkspaceAdminActions ? () => fetchWebhooks(workspaceSlug.toString()) : null
);

const pageTitle = currentWorkspace?.name ? `${currentWorkspace.name} - Webhooks` : undefined;
const pageTitle = currentWorkspace?.name
? `${currentWorkspace.name} - ${t("workspace_settings.settings.webhooks.title")}`
: undefined;

// clear secret key when modal is closed.
useEffect(() => {
Expand Down Expand Up @@ -67,19 +69,19 @@ const WebhooksListPage = observer(() => {
{Object.keys(webhooks).length > 0 ? (
<div className="flex h-full w-full flex-col">
<div className="flex items-center justify-between gap-4 border-b border-custom-border-200 pb-3.5">
<div className="text-xl font-medium">Webhooks</div>
<div className="text-xl font-medium">{t("workspace_settings.settings.webhooks.title")}</div>
<Button variant="primary" size="sm" onClick={() => setShowCreateWebhookModal(true)}>
Add webhook
{t("workspace_settings.settings.webhooks.add_webhook")}
</Button>
</div>
<WebhooksList />
</div>
) : (
<div className="flex h-full w-full flex-col">
<div className="flex items-center justify-between gap-4 border-b border-custom-border-200 pb-3.5">
<div className="text-xl font-medium">Webhooks</div>
<div className="text-xl font-medium">{t("workspace_settings.settings.webhooks.title")}</div>
<Button variant="primary" size="sm" onClick={() => setShowCreateWebhookModal(true)}>
Add webhook
{t("workspace_settings.settings.webhooks.add_webhook")}
</Button>
</div>
<div className="h-full w-full flex items-center justify-center">
Expand Down
38 changes: 22 additions & 16 deletions web/ce/components/workspace/billing/root.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
import { MARKETING_PRICING_PAGE_LINK } from "@plane/constants";
import { useTranslation } from "@plane/i18n";
import { Button } from "@plane/ui";

export const BillingRoot = () => (
<section className="w-full overflow-y-auto">
<div>
<div className="flex items-center border-b border-custom-border-100 pb-3.5">
<h3 className="text-xl font-medium">Billing and Plans</h3>
</div>
</div>
<div className="py-6">
export const BillingRoot = () => {
const { t } = useTranslation();
return (
<section className="w-full overflow-y-auto">
<div>
<h4 className="text-md mb-1 leading-6">Current plan</h4>
<p className="mb-3 text-sm text-custom-text-200">You are currently using the free plan</p>
<a href={MARKETING_PRICING_PAGE_LINK} target="_blank" rel="noreferrer">
<Button variant="neutral-primary">View plans</Button>
</a>
<div className="flex items-center border-b border-custom-border-100 pb-3.5">
<h3 className="text-xl font-medium">{t("workspace_settings.settings.billing_and_plans.title")}</h3>
</div>
</div>
<div className="py-6">
<div>
<h4 className="text-md mb-1 leading-6">{t("workspace_settings.settings.billing_and_plans.current_plan")}</h4>
<p className="mb-3 text-sm text-custom-text-200">
{t("workspace_settings.settings.billing_and_plans.free_plan")}
</p>
<a href={MARKETING_PRICING_PAGE_LINK} target="_blank" rel="noreferrer">
<Button variant="neutral-primary">{t("workspace_settings.settings.billing_and_plans.view_plans")}</Button>
</a>
</div>
</div>
</div>
</section>
);
</section>
);
};
Loading
Loading