mirror of
https://github.com/penpot/penpot.git
synced 2025-07-13 21:57:17 +02:00
🐛 Add fixes for subscription design review (#6751)
* 🐛 Fix from subscription design review * 📎 Fixes PR feedback
This commit is contained in:
parent
67ca8ccb22
commit
1f42f032fc
24 changed files with 556 additions and 511 deletions
|
@ -2,11 +2,13 @@
|
||||||
{
|
{
|
||||||
"~:id": "~uf88e52d7-2b77-81fd-8006-23413fafe56c",
|
"~:id": "~uf88e52d7-2b77-81fd-8006-23413fafe56c",
|
||||||
"~:name": "The Alpaca team",
|
"~:name": "The Alpaca team",
|
||||||
|
"~:total-editors": 3,
|
||||||
"~:total-members": 3
|
"~:total-members": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"~:id": "~u81be1d05-a07b-81d5-8006-3e728bea76fb",
|
"~:id": "~u81be1d05-a07b-81d5-8006-3e728bea76fb",
|
||||||
"~:name": "The Quokka team",
|
"~:name": "The Quokka team",
|
||||||
|
"~:total-editors": 1,
|
||||||
"~:total-members": 1
|
"~:total-members": 1
|
||||||
}
|
}
|
||||||
]
|
]
|
|
@ -49,7 +49,7 @@
|
||||||
"~:fullname": "Chewbacca",
|
"~:fullname": "Chewbacca",
|
||||||
"~:is-owner": false,
|
"~:is-owner": false,
|
||||||
"~:modified-at": "~m1713533116365",
|
"~:modified-at": "~m1713533116365",
|
||||||
"~:can-edit": false,
|
"~:can-edit": true,
|
||||||
"~:is-active": true,
|
"~:is-active": true,
|
||||||
"~:id": "~u4b2c3d4e-2345-6789-8002-bcdefabcdefa",
|
"~:id": "~u4b2c3d4e-2345-6789-8002-bcdefabcdefa",
|
||||||
"~:profile-id": "~u4b2c3d4e-2345-6789-8002-bcdefabcdefa",
|
"~:profile-id": "~u4b2c3d4e-2345-6789-8002-bcdefabcdefa",
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
"~:fullname": "R2-D2",
|
"~:fullname": "R2-D2",
|
||||||
"~:is-owner": false,
|
"~:is-owner": false,
|
||||||
"~:modified-at": "~m1713533116365",
|
"~:modified-at": "~m1713533116365",
|
||||||
"~:can-edit": false,
|
"~:can-edit": true,
|
||||||
"~:is-active": true,
|
"~:is-active": true,
|
||||||
"~:id": "~u6d4e5f6a-4567-8901-8004-defabcdefabc",
|
"~:id": "~u6d4e5f6a-4567-8901-8004-defabcdefabc",
|
||||||
"~:profile-id": "~u6d4e5f6a-4567-8901-8004-defabcdefabc",
|
"~:profile-id": "~u6d4e5f6a-4567-8901-8004-defabcdefabc",
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
"~:fullname": "C-3PO",
|
"~:fullname": "C-3PO",
|
||||||
"~:is-owner": false,
|
"~:is-owner": false,
|
||||||
"~:modified-at": "~m1713533116365",
|
"~:modified-at": "~m1713533116365",
|
||||||
"~:can-edit": false,
|
"~:can-edit": true,
|
||||||
"~:is-active": true,
|
"~:is-active": true,
|
||||||
"~:id": "~u7e5f6a7b-5678-9012-8005-efabcdefabcd",
|
"~:id": "~u7e5f6a7b-5678-9012-8005-efabcdefabcd",
|
||||||
"~:profile-id": "~u7e5f6a7b-5678-9012-8005-efabcdefabcd",
|
"~:profile-id": "~u7e5f6a7b-5678-9012-8005-efabcdefabcd",
|
||||||
|
@ -119,7 +119,7 @@
|
||||||
"~:fullname": "Yoda",
|
"~:fullname": "Yoda",
|
||||||
"~:is-owner": false,
|
"~:is-owner": false,
|
||||||
"~:modified-at": "~m1713533116365",
|
"~:modified-at": "~m1713533116365",
|
||||||
"~:can-edit": false,
|
"~:can-edit": true,
|
||||||
"~:is-active": true,
|
"~:is-active": true,
|
||||||
"~:id": "~u9a7b8c9d-7890-1234-8007-abcdefabcdef",
|
"~:id": "~u9a7b8c9d-7890-1234-8007-abcdefabcdef",
|
||||||
"~:profile-id": "~u9a7b8c9d-7890-1234-8007-abcdefabcdef",
|
"~:profile-id": "~u9a7b8c9d-7890-1234-8007-abcdefabcdef",
|
||||||
|
|
|
@ -26,5 +26,19 @@
|
||||||
"~:id": "~uc7ce0794-0992-8105-8004-38e630f29a9b",
|
"~:id": "~uc7ce0794-0992-8105-8004-38e630f29a9b",
|
||||||
"~:profile-id": "~uf56647eb-19a7-8115-8003-b6bc939ecd1b",
|
"~:profile-id": "~uf56647eb-19a7-8115-8003-b6bc939ecd1b",
|
||||||
"~:created-at": "~m1713533116365"
|
"~:created-at": "~m1713533116365"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"~:is-admin": false,
|
||||||
|
"~:email": "luke@example.com",
|
||||||
|
"~:team-id": "~udd33ff88-f4e5-8033-8003-8096cc07bdf3",
|
||||||
|
"~:name": "Luke Skywalker",
|
||||||
|
"~:fullname": "Luke Skywalker",
|
||||||
|
"~:is-owner": false,
|
||||||
|
"~:modified-at": "~m1713533116365",
|
||||||
|
"~:can-edit": true,
|
||||||
|
"~:is-active": true,
|
||||||
|
"~:id": "~u123456789-0000-0000-0000-abcdefabcdef",
|
||||||
|
"~:profile-id": "~u123456789-0000-0000-0000-abcdefabcdef",
|
||||||
|
"~:created-at": "~m1713533116365"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -26,5 +26,19 @@
|
||||||
"~:id": "~uc7ce0794-0992-8105-8004-38e630f29a9b",
|
"~:id": "~uc7ce0794-0992-8105-8004-38e630f29a9b",
|
||||||
"~:profile-id": "~uf56647eb-19a7-8115-8003-b6bc939ecd1b",
|
"~:profile-id": "~uf56647eb-19a7-8115-8003-b6bc939ecd1b",
|
||||||
"~:created-at": "~m1713533116365"
|
"~:created-at": "~m1713533116365"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"~:is-admin": false,
|
||||||
|
"~:email": "luke@example.com",
|
||||||
|
"~:team-id": "~udd33ff88-f4e5-8033-8003-8096cc07bdf3",
|
||||||
|
"~:name": "Luke Skywalker",
|
||||||
|
"~:fullname": "Luke Skywalker",
|
||||||
|
"~:is-owner": false,
|
||||||
|
"~:modified-at": "~m1713533116365",
|
||||||
|
"~:can-edit": true,
|
||||||
|
"~:is-active": true,
|
||||||
|
"~:id": "~u123456789-0000-0000-0000-abcdefabcdef",
|
||||||
|
"~:profile-id": "~u123456789-0000-0000-0000-abcdefabcdef",
|
||||||
|
"~:created-at": "~m1713533116365"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"~:features": {
|
|
||||||
"~#set": [
|
|
||||||
"layout/grid",
|
|
||||||
"styles/v2",
|
|
||||||
"fdata/pointer-map",
|
|
||||||
"fdata/objects-map",
|
|
||||||
"components/v2",
|
|
||||||
"fdata/shape-data-type"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"~:permissions": {
|
|
||||||
"~:type": "~:owner",
|
|
||||||
"~:is-owner": true,
|
|
||||||
"~:is-admin": true,
|
|
||||||
"~:can-edit": true
|
|
||||||
},
|
|
||||||
"~:name": "Default",
|
|
||||||
"~:modified-at": "~m1713533116375",
|
|
||||||
"~:id": "~uc7ce0794-0992-8105-8004-38e630f40f6d",
|
|
||||||
"~:created-at": "~m1713533116375",
|
|
||||||
"~:is-default": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"~:features": {
|
|
||||||
"~#set": [
|
|
||||||
"layout/grid",
|
|
||||||
"styles/v2",
|
|
||||||
"fdata/pointer-map",
|
|
||||||
"fdata/objects-map",
|
|
||||||
"components/v2",
|
|
||||||
"fdata/shape-data-type"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"~:permissions": {
|
|
||||||
"~:type": "~:owner",
|
|
||||||
"~:is-owner": true,
|
|
||||||
"~:is-admin": true,
|
|
||||||
"~:can-edit": true
|
|
||||||
},
|
|
||||||
"~:subscription": {
|
|
||||||
"~:type": "unlimited",
|
|
||||||
"~:status": "paused"
|
|
||||||
},
|
|
||||||
"~:name": "Second team",
|
|
||||||
"~:modified-at": "~m1701164272671",
|
|
||||||
"~:id": "~udd33ff88-f4e5-8033-8003-8096cc07bdf3",
|
|
||||||
"~:created-at": "~m1701164272671",
|
|
||||||
"~:is-default": false
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,31 +1,30 @@
|
||||||
import { expect } from "@playwright/test";
|
import { expect } from "@playwright/test";
|
||||||
import { BaseWebSocketPage } from "./BaseWebSocketPage";
|
import { DashboardPage } from "./DashboardPage";
|
||||||
|
|
||||||
export class SubscriptionProfilePage extends BaseWebSocketPage {
|
export class SubscriptionProfilePage extends DashboardPage {
|
||||||
static async init(page) {
|
static async init(page) {
|
||||||
await BaseWebSocketPage.initWebSockets(page);
|
await DashboardPage.initWebSockets(page);
|
||||||
|
|
||||||
await BaseWebSocketPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-owned-teams",
|
"get-owned-teams",
|
||||||
"subscription/get-owned-teams.json",
|
"subscription/get-owned-teams.json",
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(page) {
|
constructor(page) {
|
||||||
super(page);
|
super(page);
|
||||||
|
|
||||||
this.mainHeading = page.getByRole('heading', { name: 'Subscription', level: 2 });
|
this.mainHeading = page.getByRole("heading", {
|
||||||
|
name: "Subscription",
|
||||||
|
level: 2,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToSubscriptions() {
|
async goToSubscriptions() {
|
||||||
await this.page.goto(
|
await this.page.goto(`#/settings/subscriptions`);
|
||||||
`#/settings/subscriptions`,
|
|
||||||
);
|
|
||||||
await expect(this.mainHeading).toBeVisible();
|
await expect(this.mainHeading).toBeVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SubscriptionProfilePage;
|
export default SubscriptionProfilePage;
|
||||||
|
|
|
@ -317,3 +317,5 @@ export class WorkspacePage extends BaseWebSocketPage {
|
||||||
.click(clickOptions);
|
.click(clickOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default WorkspacePage;
|
|
@ -1,14 +1,18 @@
|
||||||
import { test, expect } from "@playwright/test";
|
import { test, expect } from "@playwright/test";
|
||||||
import DashboardPage from "../pages/DashboardPage";
|
import DashboardPage from "../pages/DashboardPage";
|
||||||
import { WorkspacePage } from "../pages/WorkspacePage";
|
|
||||||
import { SubscriptionProfilePage } from "../pages/SubscriptionProfilePage";
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await DashboardPage.init(page);
|
||||||
|
await DashboardPage.mockConfigFlags(page, [
|
||||||
|
"enable-subscriptions",
|
||||||
|
"disable-onboarding",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
test.describe("Subscriptions: dashboard", () => {
|
test.describe("Subscriptions: dashboard", () => {
|
||||||
test("Team with unlimited subscription has specific icon in menu", async ({
|
test("Team with unlimited subscription has specific icon in menu", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
await DashboardPage.init(page);
|
|
||||||
await DashboardPage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-profile",
|
"get-profile",
|
||||||
|
@ -45,8 +49,6 @@ test.describe("Subscriptions: dashboard", () => {
|
||||||
test("The Unlimited subscription has its name in the sidebar dropdown", async ({
|
test("The Unlimited subscription has its name in the sidebar dropdown", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
await DashboardPage.init(page);
|
|
||||||
await DashboardPage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-profile",
|
"get-profile",
|
||||||
|
@ -79,12 +81,10 @@ test.describe("Subscriptions: dashboard", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe("Subscriptions: Team members and invitations", () => {
|
test.describe("Subscriptions: team members and invitations", () => {
|
||||||
test("Team settings has susbscription name and no manage subscription link when is member", async ({
|
test("Team settings has susbscription name and no manage subscription link when is member", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
await DashboardPage.init(page);
|
|
||||||
await DashboardPage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-profile",
|
"get-profile",
|
||||||
|
@ -132,8 +132,6 @@ test.describe("Subscriptions: Team members and invitations", () => {
|
||||||
test("Team settings has susbscription name and manage subscription link when is owner", async ({
|
test("Team settings has susbscription name and manage subscription link when is owner", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
await DashboardPage.init(page);
|
|
||||||
await DashboardPage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-profile",
|
"get-profile",
|
||||||
|
@ -188,8 +186,6 @@ test.describe("Subscriptions: Team members and invitations", () => {
|
||||||
test("Members tab has warning message when team has more members than subscriptions. Subscribe link is shown for owners.", async ({
|
test("Members tab has warning message when team has more members than subscriptions. Subscribe link is shown for owners.", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
await DashboardPage.init(page);
|
|
||||||
await DashboardPage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-profile",
|
"get-profile",
|
||||||
|
@ -235,8 +231,6 @@ test.describe("Subscriptions: Team members and invitations", () => {
|
||||||
test("Members tab has warning message when team has more members than subscriptions. Contact to owner is shown for members.", async ({
|
test("Members tab has warning message when team has more members than subscriptions. Contact to owner is shown for members.", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
await DashboardPage.init(page);
|
|
||||||
await DashboardPage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-profile",
|
"get-profile",
|
||||||
|
@ -282,8 +276,6 @@ test.describe("Subscriptions: Team members and invitations", () => {
|
||||||
test("Members tab has warning message when has professional subscription and more than 8 members.", async ({
|
test("Members tab has warning message when has professional subscription and more than 8 members.", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
await DashboardPage.init(page);
|
|
||||||
await DashboardPage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-profile",
|
"get-profile",
|
||||||
|
@ -330,11 +322,9 @@ test.describe("Subscriptions: Team members and invitations", () => {
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Invitations tab has warning message when subscription is expired", async ({
|
test("Invitations tab has warning message when team has more members than subscriptions", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
await DashboardPage.init(page);
|
|
||||||
await DashboardPage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-profile",
|
"get-profile",
|
||||||
|
@ -352,7 +342,7 @@ test.describe("Subscriptions: Team members and invitations", () => {
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-teams",
|
"get-teams",
|
||||||
"subscription/get-teams-unlimited-subscription-expired-owner.json",
|
"subscription/get-teams-unlimited-subscription-owner.json",
|
||||||
);
|
);
|
||||||
|
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
|
@ -382,7 +372,7 @@ test.describe("Subscriptions: Team members and invitations", () => {
|
||||||
await expect(page.getByTestId("cta")).toBeVisible();
|
await expect(page.getByTestId("cta")).toBeVisible();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByText(
|
page.getByText(
|
||||||
"Looks like your team has grown! Your plan includes seats, but you're now using more than that.",
|
"Looks like your team has grown! Your plan includes 2 seats, but you're now using 3",
|
||||||
),
|
),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
@ -390,8 +380,6 @@ test.describe("Subscriptions: Team members and invitations", () => {
|
||||||
test("Invitations tab has warning message when has professional subscription and more than 8 members.", async ({
|
test("Invitations tab has warning message when has professional subscription and more than 8 members.", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
await DashboardPage.init(page);
|
|
||||||
await DashboardPage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-profile",
|
"get-profile",
|
||||||
|
@ -409,7 +397,7 @@ test.describe("Subscriptions: Team members and invitations", () => {
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
page,
|
page,
|
||||||
"get-teams",
|
"get-teams",
|
||||||
"subscription/get-teams-unlimited-subscription-expired-owner.json",
|
"subscription/get-teams-unlimited-subscription-owner.json",
|
||||||
);
|
);
|
||||||
|
|
||||||
await DashboardPage.mockRPC(
|
await DashboardPage.mockRPC(
|
||||||
|
@ -439,274 +427,8 @@ test.describe("Subscriptions: Team members and invitations", () => {
|
||||||
await expect(page.getByTestId("cta")).toBeVisible();
|
await expect(page.getByTestId("cta")).toBeVisible();
|
||||||
await expect(
|
await expect(
|
||||||
page.getByText(
|
page.getByText(
|
||||||
"Looks like your team has grown! Your plan includes seats, but you're now using more than that.",
|
"Looks like your team has grown! Your plan includes 2 seats, but you're now using 9",
|
||||||
),
|
),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe("Subscriptions: workspace", () => {
|
|
||||||
test("Unlimited team should have 'Power up your plan' link in main menu", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await WorkspacePage.init(page);
|
|
||||||
await WorkspacePage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
|
|
||||||
const workspacePage = new WorkspacePage(page);
|
|
||||||
await workspacePage.setupEmptyFile();
|
|
||||||
|
|
||||||
await WorkspacePage.mockRPC(
|
|
||||||
page,
|
|
||||||
"get-profile",
|
|
||||||
"subscription/get-profile-unlimited-subscription.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
await workspacePage.mockRPC(
|
|
||||||
"push-audit-events",
|
|
||||||
"workspace/audit-event-empty.json",
|
|
||||||
);
|
|
||||||
await workspacePage.goToWorkspace();
|
|
||||||
await page.getByRole("button", { name: "Main menu" }).click();
|
|
||||||
|
|
||||||
await expect(page.getByText("Power up your plan")).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Enterprise team should not have 'Power up your plan' link in main menu", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await WorkspacePage.init(page);
|
|
||||||
await WorkspacePage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
|
|
||||||
const workspacePage = new WorkspacePage(page);
|
|
||||||
await workspacePage.setupEmptyFile();
|
|
||||||
|
|
||||||
await WorkspacePage.mockRPC(
|
|
||||||
page,
|
|
||||||
"get-profile",
|
|
||||||
"subscription/get-profile-enterprise-subscription.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
await workspacePage.mockRPC(
|
|
||||||
"push-audit-events",
|
|
||||||
"workspace/audit-event-empty.json",
|
|
||||||
);
|
|
||||||
await workspacePage.goToWorkspace();
|
|
||||||
await page.getByRole("button", { name: "Main menu" }).click();
|
|
||||||
|
|
||||||
await expect(page.getByText("Power up your plan")).not.toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Professional team should have 7 days autosaved versions", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await WorkspacePage.init(page);
|
|
||||||
await WorkspacePage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
|
|
||||||
const workspacePage = new WorkspacePage(page);
|
|
||||||
await workspacePage.setupEmptyFile();
|
|
||||||
|
|
||||||
await workspacePage.mockRPC(
|
|
||||||
"push-audit-events",
|
|
||||||
"workspace/audit-event-empty.json",
|
|
||||||
);
|
|
||||||
await workspacePage.goToWorkspace();
|
|
||||||
|
|
||||||
await workspacePage.mockRPC(
|
|
||||||
"get-file-snapshots?file-id=*",
|
|
||||||
"workspace/versions-snapshot-1.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
await page.getByLabel("History").click();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByText("Autosaved versions will be kept for 7 days."),
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Unlimited team should have 30 days autosaved versions", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await WorkspacePage.init(page);
|
|
||||||
await WorkspacePage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
|
|
||||||
const workspacePage = new WorkspacePage(page);
|
|
||||||
await workspacePage.setupEmptyFile();
|
|
||||||
|
|
||||||
await WorkspacePage.mockRPC(
|
|
||||||
page,
|
|
||||||
"get-profile",
|
|
||||||
"subscription/get-profile-unlimited-subscription.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
await WorkspacePage.mockRPC(
|
|
||||||
page,
|
|
||||||
"get-teams",
|
|
||||||
"subscription/get-teams-unlimited-one-team.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
await workspacePage.mockRPC(
|
|
||||||
"push-audit-events",
|
|
||||||
"workspace/audit-event-empty.json",
|
|
||||||
);
|
|
||||||
await workspacePage.goToWorkspace();
|
|
||||||
|
|
||||||
await workspacePage.mockRPC(
|
|
||||||
"get-file-snapshots?file-id=*",
|
|
||||||
"workspace/versions-snapshot-1.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
await page.getByLabel("History").click();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByText("Autosaved versions will be kept for 30 days."),
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Unlimited team should have 90 days autosaved versions", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await WorkspacePage.init(page);
|
|
||||||
await WorkspacePage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
|
|
||||||
const workspacePage = new WorkspacePage(page);
|
|
||||||
await workspacePage.setupEmptyFile();
|
|
||||||
|
|
||||||
await WorkspacePage.mockRPC(
|
|
||||||
page,
|
|
||||||
"get-profile",
|
|
||||||
"subscription/get-profile-enterprise-subscription.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
await WorkspacePage.mockRPC(
|
|
||||||
page,
|
|
||||||
"get-teams",
|
|
||||||
"subscription/get-teams-enterprise-one-team.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
await workspacePage.mockRPC(
|
|
||||||
"push-audit-events",
|
|
||||||
"workspace/audit-event-empty.json",
|
|
||||||
);
|
|
||||||
await workspacePage.goToWorkspace();
|
|
||||||
|
|
||||||
await workspacePage.mockRPC(
|
|
||||||
"get-file-snapshots?file-id=*",
|
|
||||||
"workspace/versions-snapshot-1.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
await page.getByLabel("History").click();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByText("Autosaved versions will be kept for 90 days."),
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test.describe("Subscriptions: profile", () => {
|
|
||||||
test("When subscription is professional there is no manage subscription link", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await SubscriptionProfilePage.init(page);
|
|
||||||
await SubscriptionProfilePage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
|
|
||||||
await SubscriptionProfilePage.mockRPC(
|
|
||||||
page,
|
|
||||||
"get-profile",
|
|
||||||
"logged-in-user/get-profile-logged-in.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
const subscriptionProfilePage = new SubscriptionProfilePage(page);
|
|
||||||
|
|
||||||
await subscriptionProfilePage.goToSubscriptions();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole("button", { name: "Manage your subscription" }),
|
|
||||||
).not.toBeVisible();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole("heading", { name: "Other Penpot plans", level: 3 }),
|
|
||||||
).toBeVisible();
|
|
||||||
|
|
||||||
await expect(page.getByText("$7")).toBeVisible();
|
|
||||||
|
|
||||||
await expect(page.getByText("$950")).toBeVisible();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole("button", { name: "Try it free for 14 days" }).first(),
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("When subscription is unlimited there is manage subscription link", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await SubscriptionProfilePage.init(page);
|
|
||||||
await SubscriptionProfilePage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
|
|
||||||
await SubscriptionProfilePage.mockRPC(
|
|
||||||
page,
|
|
||||||
"get-profile",
|
|
||||||
"subscription/get-profile-unlimited-subscription.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
const subscriptionProfilePage = new SubscriptionProfilePage(page);
|
|
||||||
|
|
||||||
await subscriptionProfilePage.goToSubscriptions();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole("button", { name: "Manage your subscription" }),
|
|
||||||
).toBeVisible();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole("heading", { name: "Other Penpot plans", level: 3 }),
|
|
||||||
).toBeVisible();
|
|
||||||
|
|
||||||
await expect(page.getByText("$0")).toBeVisible();
|
|
||||||
|
|
||||||
await expect(page.getByText("$950")).toBeVisible();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole("button", { name: "Try it free for 14 days" }).first(),
|
|
||||||
).not.toBeVisible();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole("button", { name: "Subscribe" }).first(),
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("When subscription is enteprise there is manage subscription link", async ({
|
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
await SubscriptionProfilePage.init(page);
|
|
||||||
await SubscriptionProfilePage.mockConfigFlags(page, ["enable-subscriptions"]);
|
|
||||||
|
|
||||||
await SubscriptionProfilePage.mockRPC(
|
|
||||||
page,
|
|
||||||
"get-profile",
|
|
||||||
"subscription/get-profile-enterprise-subscription.json",
|
|
||||||
);
|
|
||||||
|
|
||||||
const subscriptionProfilePage = new SubscriptionProfilePage(page);
|
|
||||||
|
|
||||||
await subscriptionProfilePage.goToSubscriptions();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole("button", { name: "Manage your subscription" }),
|
|
||||||
).toBeVisible();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole("heading", { name: "Other Penpot plans", level: 3 }),
|
|
||||||
).toBeVisible();
|
|
||||||
|
|
||||||
await expect(page.getByText("$0")).toBeVisible();
|
|
||||||
|
|
||||||
await expect(page.getByText("$7")).toBeVisible();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole("button", { name: "Try it free for 14 days" }).first(),
|
|
||||||
).not.toBeVisible();
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
page.getByRole("button", { name: "Subscribe" }).first(),
|
|
||||||
).toBeVisible();
|
|
||||||
});
|
|
||||||
});
|
|
111
frontend/playwright/ui/specs/subscriptions-profile.spec.js
Normal file
111
frontend/playwright/ui/specs/subscriptions-profile.spec.js
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
import { test, expect } from "@playwright/test";
|
||||||
|
import SubscriptionProfilePage from "../pages/SubscriptionProfilePage";
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await SubscriptionProfilePage.init(page);
|
||||||
|
|
||||||
|
await SubscriptionProfilePage.mockConfigFlags(page, [
|
||||||
|
"enable-subscriptions",
|
||||||
|
"disable-onboarding",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe("Subscriptions: profile", () => {
|
||||||
|
test("When subscription is professional there is no manage subscription link", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await SubscriptionProfilePage.mockRPC(
|
||||||
|
page,
|
||||||
|
"get-profile",
|
||||||
|
"logged-in-user/get-profile-logged-in.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
const subscriptionProfilePage = new SubscriptionProfilePage(page);
|
||||||
|
|
||||||
|
await subscriptionProfilePage.goToSubscriptions();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole("button", { name: "Manage your subscription" }),
|
||||||
|
).not.toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole("heading", { name: "Other Penpot plans", level: 3 }),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(page.getByText("$7")).toBeVisible();
|
||||||
|
|
||||||
|
await expect(page.getByText("$950")).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole("button", { name: "Try it free for 14 days" }).first(),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("When subscription is unlimited there is manage subscription link", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await SubscriptionProfilePage.mockRPC(
|
||||||
|
page,
|
||||||
|
"get-profile",
|
||||||
|
"subscription/get-profile-unlimited-subscription.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
const subscriptionProfilePage = new SubscriptionProfilePage(page);
|
||||||
|
|
||||||
|
await subscriptionProfilePage.goToSubscriptions();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole("button", { name: "Manage your subscription" }),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole("heading", { name: "Other Penpot plans", level: 3 }),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(page.getByText("$0")).toBeVisible();
|
||||||
|
|
||||||
|
await expect(page.getByText("$950")).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole("button", { name: "Try it free for 14 days" }).first(),
|
||||||
|
).not.toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole("button", { name: "Subscribe" }).first(),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("When subscription is enteprise there is manage subscription link", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await SubscriptionProfilePage.mockRPC(
|
||||||
|
page,
|
||||||
|
"get-profile",
|
||||||
|
"subscription/get-profile-enterprise-subscription.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
const subscriptionProfilePage = new SubscriptionProfilePage(page);
|
||||||
|
|
||||||
|
await subscriptionProfilePage.goToSubscriptions();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole("button", { name: "Manage your subscription" }),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole("heading", { name: "Other Penpot plans", level: 3 }),
|
||||||
|
).toBeVisible();
|
||||||
|
|
||||||
|
await expect(page.getByText("$0")).toBeVisible();
|
||||||
|
|
||||||
|
await expect(page.getByText("$7")).toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole("button", { name: "Try it free for 14 days" }).first(),
|
||||||
|
).not.toBeVisible();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByRole("button", { name: "Subscribe" }).first(),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
152
frontend/playwright/ui/specs/subscriptions-workspace.spec.js
Normal file
152
frontend/playwright/ui/specs/subscriptions-workspace.spec.js
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
import { test, expect } from "@playwright/test";
|
||||||
|
import WorkspacePage from "../pages/WorkspacePage";
|
||||||
|
|
||||||
|
test.beforeEach(async ({ page }) => {
|
||||||
|
await WorkspacePage.init(page);
|
||||||
|
await WorkspacePage.mockConfigFlags(page, [
|
||||||
|
"enable-subscriptions",
|
||||||
|
"disable-onboarding",
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.describe("Subscriptions: workspace", () => {
|
||||||
|
test("Unlimited team should have 'Power up your plan' link in main menu", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const workspacePage = new WorkspacePage(page);
|
||||||
|
await workspacePage.setupEmptyFile();
|
||||||
|
|
||||||
|
await WorkspacePage.mockRPC(
|
||||||
|
page,
|
||||||
|
"get-profile",
|
||||||
|
"subscription/get-profile-unlimited-subscription.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
await workspacePage.mockRPC(
|
||||||
|
"push-audit-events",
|
||||||
|
"workspace/audit-event-empty.json",
|
||||||
|
);
|
||||||
|
await workspacePage.goToWorkspace();
|
||||||
|
await page.getByRole("button", { name: "Main menu" }).click();
|
||||||
|
|
||||||
|
await expect(page.getByText("Power up your plan")).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Enterprise team should not have 'Power up your plan' link in main menu", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const workspacePage = new WorkspacePage(page);
|
||||||
|
await workspacePage.setupEmptyFile();
|
||||||
|
|
||||||
|
await WorkspacePage.mockRPC(
|
||||||
|
page,
|
||||||
|
"get-profile",
|
||||||
|
"subscription/get-profile-enterprise-subscription.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
await workspacePage.mockRPC(
|
||||||
|
"push-audit-events",
|
||||||
|
"workspace/audit-event-empty.json",
|
||||||
|
);
|
||||||
|
await workspacePage.goToWorkspace();
|
||||||
|
await page.getByRole("button", { name: "Main menu" }).click();
|
||||||
|
|
||||||
|
await expect(page.getByText("Power up your plan")).not.toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Professional team should have 7 days autosaved versions", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const workspacePage = new WorkspacePage(page);
|
||||||
|
await workspacePage.setupEmptyFile();
|
||||||
|
|
||||||
|
await workspacePage.mockRPC(
|
||||||
|
"push-audit-events",
|
||||||
|
"workspace/audit-event-empty.json",
|
||||||
|
);
|
||||||
|
await workspacePage.goToWorkspace();
|
||||||
|
|
||||||
|
await workspacePage.mockRPC(
|
||||||
|
"get-file-snapshots?file-id=*",
|
||||||
|
"workspace/versions-snapshot-1.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.getByLabel("History").click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText("Autosaved versions will be kept for 7 days."),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Unlimited team should have 30 days autosaved versions", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const workspacePage = new WorkspacePage(page);
|
||||||
|
await workspacePage.setupEmptyFile();
|
||||||
|
|
||||||
|
await WorkspacePage.mockRPC(
|
||||||
|
page,
|
||||||
|
"get-profile",
|
||||||
|
"subscription/get-profile-unlimited-subscription.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
await WorkspacePage.mockRPC(
|
||||||
|
page,
|
||||||
|
"get-teams",
|
||||||
|
"subscription/get-teams-unlimited-one-team.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
await workspacePage.mockRPC(
|
||||||
|
"push-audit-events",
|
||||||
|
"workspace/audit-event-empty.json",
|
||||||
|
);
|
||||||
|
await workspacePage.goToWorkspace();
|
||||||
|
|
||||||
|
await workspacePage.mockRPC(
|
||||||
|
"get-file-snapshots?file-id=*",
|
||||||
|
"workspace/versions-snapshot-1.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.getByLabel("History").click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText("Autosaved versions will be kept for 30 days."),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Unlimited team should have 90 days autosaved versions", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const workspacePage = new WorkspacePage(page);
|
||||||
|
await workspacePage.setupEmptyFile();
|
||||||
|
|
||||||
|
await WorkspacePage.mockRPC(
|
||||||
|
page,
|
||||||
|
"get-profile",
|
||||||
|
"subscription/get-profile-enterprise-subscription.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
await WorkspacePage.mockRPC(
|
||||||
|
page,
|
||||||
|
"get-teams",
|
||||||
|
"subscription/get-teams-enterprise-one-team.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
await workspacePage.mockRPC(
|
||||||
|
"push-audit-events",
|
||||||
|
"workspace/audit-event-empty.json",
|
||||||
|
);
|
||||||
|
await workspacePage.goToWorkspace();
|
||||||
|
|
||||||
|
await workspacePage.mockRPC(
|
||||||
|
"get-file-snapshots?file-id=*",
|
||||||
|
"workspace/versions-snapshot-1.json",
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.getByLabel("History").click();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
page.getByText("Autosaved versions will be kept for 90 days."),
|
||||||
|
).toBeVisible();
|
||||||
|
});
|
||||||
|
});
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 63 KiB |
|
@ -132,7 +132,7 @@
|
||||||
[:> team-members-page* {:team team :profile profile}]
|
[:> team-members-page* {:team team :profile profile}]
|
||||||
|
|
||||||
:dashboard-invitations
|
:dashboard-invitations
|
||||||
[:> team-invitations-page* {:team team}]
|
[:> team-invitations-page* {:team team :profile profile}]
|
||||||
|
|
||||||
:dashboard-webhooks
|
:dashboard-webhooks
|
||||||
[:> webhooks-page* {:team team}]
|
[:> webhooks-page* {:team team}]
|
||||||
|
|
|
@ -75,10 +75,15 @@
|
||||||
:has-dropdown true}])
|
:has-dropdown true}])
|
||||||
|
|
||||||
"enterprise"
|
"enterprise"
|
||||||
[:> cta-power-up*
|
(if subscription-is-trial
|
||||||
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
|
[:> cta-power-up*
|
||||||
:top-description (tr "subscription.dashboard.power-up.enterprise-plan")
|
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
|
||||||
:has-dropdown false}])))
|
:top-description (tr "subscription.dashboard.power-up.enterprise-trial.top-title")
|
||||||
|
:has-dropdown false}]
|
||||||
|
[:> cta-power-up*
|
||||||
|
{:top-title (tr "subscription.dashboard.power-up.your-subscription")
|
||||||
|
:top-description (tr "subscription.dashboard.power-up.enterprise-plan")
|
||||||
|
:has-dropdown false}]))))
|
||||||
|
|
||||||
(mf/defc team*
|
(mf/defc team*
|
||||||
[{:keys [is-owner team]}]
|
[{:keys [is-owner team]}]
|
||||||
|
@ -137,12 +142,13 @@
|
||||||
[{:keys [banner-is-expanded team profile]}]
|
[{:keys [banner-is-expanded team profile]}]
|
||||||
(let [subscription (:subscription team)
|
(let [subscription (:subscription team)
|
||||||
subscription-name (:type subscription)
|
subscription-name (:type subscription)
|
||||||
subscription-is-trial (= "trialing" (:status subscription))
|
|
||||||
is-owner (:is-owner (:permissions team))
|
is-owner (:is-owner (:permissions team))
|
||||||
|
|
||||||
email-owner (:email (some #(when (:is-owner %) %) (:members team)))
|
email-owner (:email (some #(when (:is-owner %) %) (:members team)))
|
||||||
mail-to-owner (str "<a href=\"" "mailto:" email-owner "\">" email-owner "</a>")
|
mail-to-owner (str "<a href=\"" "mailto:" email-owner "\">" email-owner "</a>")
|
||||||
go-to-subscription (dm/str (u/join cf/public-uri "#/settings/subscriptions"))
|
go-to-subscription (dm/str (u/join cf/public-uri "#/settings/subscriptions"))
|
||||||
|
seats (-> profile :props :subscription :quantity)
|
||||||
|
editors (count (filterv :can-edit (:members team)))
|
||||||
|
|
||||||
link
|
link
|
||||||
(if is-owner
|
(if is-owner
|
||||||
|
@ -151,30 +157,25 @@
|
||||||
|
|
||||||
cta-title
|
cta-title
|
||||||
(cond
|
(cond
|
||||||
(= "professional" subscription-name)
|
(and (= "professional" subscription-name) (>= editors 8))
|
||||||
(tr "subscription.dashboard.cta.professional-plan-designed")
|
(tr "subscription.dashboard.cta.professional-plan-designed")
|
||||||
|
|
||||||
subscription-is-trial
|
(and (= "unlimited" subscription-name) (< seats editors))
|
||||||
(tr "subscription.dashboard.cta.trial-plan-designed")
|
(tr "subscription.dashboard.cta.unlimited-many-editors" seats editors))
|
||||||
|
|
||||||
(= "unlimited" subscription-name)
|
|
||||||
(tr "subscription.dashboard.cta.unlimited-many-editors" (:quantity (:subscription (:props profile)))))
|
|
||||||
|
|
||||||
cta-message
|
cta-message
|
||||||
(cond
|
(cond
|
||||||
(and (= "professional" subscription-name) is-owner)
|
(and (= "professional" subscription-name) (>= editors 8) is-owner)
|
||||||
(tr "subscription.dashboard.cta.upgrade-to-unlimited-enterprise-owner" link)
|
(tr "subscription.dashboard.cta.upgrade-to-unlimited-enterprise-owner" link)
|
||||||
|
|
||||||
(and (= "professional" subscription-name) (not is-owner))
|
(and (= "professional" subscription-name) (>= editors 8) (not is-owner))
|
||||||
(tr "subscription.dashboard.cta.upgrade-to-unlimited-enterprise-member" link)
|
(tr "subscription.dashboard.cta.upgrade-to-unlimited-enterprise-member" link)
|
||||||
|
|
||||||
(and subscription-is-trial is-owner)
|
(and (= "unlimited" subscription-name) (< seats editors) is-owner)
|
||||||
(tr "subscription.dashboard.cta.upgrade-to-full-access-owner" link)
|
(tr "subscription.dashboard.cta.upgrade-more-seats-owner" link)
|
||||||
|
|
||||||
(and subscription-is-trial (not is-owner))
|
(and (= "unlimited" subscription-name) (< seats editors) (not is-owner))
|
||||||
(tr "subscription.dashboard.cta.upgrade-to-full-access-member" link)
|
(tr "subscription.dashboard.cta.upgrade-more-seats-member" link))]
|
||||||
(and (= "unlimited" subscription-name) (not subscription-is-trial))
|
|
||||||
(tr "subscription.dashboard.cta.upgrade-to-unlimited-enterprise-owner-more-seats" link))]
|
|
||||||
|
|
||||||
[:> cta* {:class (stl/css-case ::members-cta-full-width banner-is-expanded :members-cta (not banner-is-expanded)) :title cta-title}
|
[:> cta* {:class (stl/css-case ::members-cta-full-width banner-is-expanded :members-cta (not banner-is-expanded)) :title cta-title}
|
||||||
[:> i18n/tr-html*
|
[:> i18n/tr-html*
|
||||||
|
@ -184,18 +185,24 @@
|
||||||
|
|
||||||
(defn show-subscription-members-main-banner?
|
(defn show-subscription-members-main-banner?
|
||||||
[team profile]
|
[team profile]
|
||||||
(or
|
(let [seats (-> profile :props :subscription :quantity)
|
||||||
(and (= (:type (:subscription team)) "professional") (>= (count (:members team)) 8))
|
editors (count (filter :can-edit (:members team)))]
|
||||||
(and
|
(or
|
||||||
(= (:type (:subscription team)) "unlimited")
|
(and (= (:type (:subscription team)) "professional")
|
||||||
(not (= (:status (:subscription team)) "trialing"))
|
(> editors 8))
|
||||||
(>= (count (:members team)) (:quantity (:subscription (:props profile))))
|
(and
|
||||||
(:is-owner (:permissions team)))
|
(= (:type (:subscription team)) "unlimited")
|
||||||
(= (:status (:subscription team)) "paused")))
|
(>= editors 8)
|
||||||
|
(< seats editors)))))
|
||||||
|
|
||||||
|
(defn show-subscription-members-small-banner?
|
||||||
|
[team profile]
|
||||||
|
(let [seats (-> profile :props :subscription :quantity)
|
||||||
|
editors (count (filterv :can-edit (:members team)))]
|
||||||
|
(or
|
||||||
|
(and (= (:type (:subscription team)) "professional")
|
||||||
|
(= editors 8))
|
||||||
|
(and (= (:type (:subscription team)) "unlimited")
|
||||||
|
(< editors 8)
|
||||||
|
(< seats editors)))))
|
||||||
|
|
||||||
(defn show-subscription-invitations-main-banner?
|
|
||||||
[team]
|
|
||||||
(or
|
|
||||||
(and (= (:type (:subscription team)) "professional")
|
|
||||||
(>= (count (:members team)) 8))
|
|
||||||
(= (:status (:subscription team)) "paused")))
|
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
padding-block-start: var(--sp-m);
|
padding-block-start: var(--sp-m);
|
||||||
}
|
}
|
||||||
.cta-bottom-section .content {
|
.cta-bottom-section .content {
|
||||||
@include t.use-typography("body-small");
|
@include t.use-typography("body-medium");
|
||||||
@include buttonStyle;
|
@include buttonStyle;
|
||||||
color: var(--color-foreground-secondary);
|
color: var(--color-foreground-secondary);
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -62,12 +62,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.cta-title {
|
.cta-title {
|
||||||
@include t.use-typography("title-small");
|
@include t.use-typography("body-small");
|
||||||
margin-block-end: var(--sp-xs);
|
margin-block-end: var(--sp-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cta-text {
|
.cta-text {
|
||||||
@include t.use-typography("body-small");
|
@include t.use-typography("title-small");
|
||||||
}
|
}
|
||||||
|
|
||||||
.cta-bottom-section .content a {
|
.cta-bottom-section .content a {
|
||||||
|
@ -96,15 +96,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.team-text {
|
.team-text {
|
||||||
@include t.use-typography("body-large");
|
@include t.use-typography("title-medium");
|
||||||
color: var(--color-foreground-primary);
|
color: var(--color-foreground-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.manage-subscription-link {
|
.manage-subscription-link {
|
||||||
@include buttonStyle;
|
@include buttonStyle;
|
||||||
@include t.use-typography("body-small");
|
@include t.use-typography("body-medium");
|
||||||
color: var(--color-accent-tertiary);
|
color: var(--color-accent-tertiary);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin-block-start: -8px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,8 +113,16 @@
|
||||||
@extend .button-icon;
|
@extend .button-icon;
|
||||||
background: var(--color-background-primary);
|
background: var(--color-background-primary);
|
||||||
stroke: var(--color-foreground-secondary);
|
stroke: var(--color-foreground-secondary);
|
||||||
border-radius: var(--sp-xs);
|
border-radius: 6px;
|
||||||
border: $b-1 solid var(--color-foreground-secondary);
|
border: 1.75px solid var(--color-foreground-secondary);
|
||||||
|
stroke-width: 2.25px;
|
||||||
|
width: var(--sp-xl);
|
||||||
|
height: var(--sp-xl);
|
||||||
|
|
||||||
|
svg {
|
||||||
|
block-size: var(--sp-m);
|
||||||
|
inline-size: var(--sp-m);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-item {
|
.menu-item {
|
||||||
|
@ -136,6 +145,10 @@
|
||||||
margin-block-start: var(--sp-s);
|
margin-block-start: var(--sp-s);
|
||||||
margin-inline-start: $s-68;
|
margin-inline-start: $s-68;
|
||||||
max-width: $s-200;
|
max-width: $s-200;
|
||||||
|
|
||||||
|
.cta-title {
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.members-cta-full-width {
|
.members-cta-full-width {
|
||||||
|
@ -148,5 +161,6 @@
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: var(--color-accent-primary);
|
color: var(--color-accent-primary);
|
||||||
|
overflow-wrap: break-word;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
[app.main.ui.dashboard.subscription :refer [team*
|
[app.main.ui.dashboard.subscription :refer [team*
|
||||||
members-cta*
|
members-cta*
|
||||||
show-subscription-members-main-banner?
|
show-subscription-members-main-banner?
|
||||||
show-subscription-invitations-main-banner?]]
|
show-subscription-members-small-banner?]]
|
||||||
[app.main.ui.dashboard.team-form]
|
[app.main.ui.dashboard.team-form]
|
||||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
|
@ -551,12 +551,11 @@
|
||||||
[:> team-members*
|
[:> team-members*
|
||||||
{:profile profile
|
{:profile profile
|
||||||
:team team}]
|
:team team}]
|
||||||
|
|
||||||
(when (and
|
(when (and
|
||||||
(contains? cfg/flags :subscriptions)
|
(contains? cfg/flags :subscriptions)
|
||||||
(or
|
(show-subscription-members-small-banner? team profile))
|
||||||
(and (= (:type (:subscription team)) "professional") (< (count (:members team)) 8))
|
[:> members-cta* {:banner-is-expanded false :team team :profile profile}])]])
|
||||||
(= (:status (:subscription team)) "trialing")))
|
|
||||||
[:> members-cta* {:banner-is-expanded false :team team}])]])
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; INVITATIONS SECTION
|
;; INVITATIONS SECTION
|
||||||
|
@ -804,7 +803,7 @@
|
||||||
|
|
||||||
(mf/defc team-invitations-page*
|
(mf/defc team-invitations-page*
|
||||||
{::mf/props :obj}
|
{::mf/props :obj}
|
||||||
[{:keys [team]}]
|
[{:keys [team profile]}]
|
||||||
|
|
||||||
(mf/with-effect [team]
|
(mf/with-effect [team]
|
||||||
(dom/set-html-title
|
(dom/set-html-title
|
||||||
|
@ -821,16 +820,14 @@
|
||||||
:team team}]
|
:team team}]
|
||||||
[:section {:class (stl/css-case
|
[:section {:class (stl/css-case
|
||||||
:dashboard-team-invitations true
|
:dashboard-team-invitations true
|
||||||
:dashboard-top-cta (show-subscription-invitations-main-banner? team))}
|
:dashboard-top-cta (show-subscription-members-main-banner? team profile))}
|
||||||
(when (and (contains? cfg/flags :subscriptions)
|
(when (and (contains? cfg/flags :subscriptions)
|
||||||
(show-subscription-invitations-main-banner? team))
|
(show-subscription-members-main-banner? team profile))
|
||||||
[:> members-cta* {:banner-is-expanded true :team team}])
|
[:> members-cta* {:banner-is-expanded true :team team :profile profile}])
|
||||||
[:> invitation-section* {:team team}]
|
[:> invitation-section* {:team team}]
|
||||||
(when (and (contains? cfg/flags :subscriptions)
|
(when (and (contains? cfg/flags :subscriptions)
|
||||||
(or
|
(show-subscription-members-small-banner? team profile))
|
||||||
(and (= (:type (:subscription team)) "professional") (< (count (:members team)) 8))
|
[:> members-cta* {:banner-is-expanded false :team team :profile profile}])]])
|
||||||
(= (:status (:subscription team)) "trialing")))
|
|
||||||
[:> members-cta* {:banner-is-expanded false :team team}])]])
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; WEBHOOKS SECTION
|
;; WEBHOOKS SECTION
|
||||||
|
|
|
@ -107,6 +107,8 @@ $grayish-red: #bfbfbf;
|
||||||
--color-token-border: #{$aqua-400};
|
--color-token-border: #{$aqua-400};
|
||||||
--color-token-accent: #{$aqua-600};
|
--color-token-accent: #{$aqua-600};
|
||||||
--color-token-foreground: #{$aqua-800};
|
--color-token-foreground: #{$aqua-800};
|
||||||
|
|
||||||
|
--color-badge-premium: #{$orange-500};
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.default) {
|
:global(.default) {
|
||||||
|
@ -148,4 +150,6 @@ $grayish-red: #bfbfbf;
|
||||||
--color-token-border: #{$violet-700};
|
--color-token-border: #{$violet-700};
|
||||||
--color-token-accent: #{$violet-600};
|
--color-token-accent: #{$violet-600};
|
||||||
--color-token-foreground: #{$violet-300};
|
--color-token-foreground: #{$violet-300};
|
||||||
|
|
||||||
|
--color-badge-premium: #{$orange-200};
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
(def ^:svg-id logo-error-screen "logo-error-screen")
|
(def ^:svg-id logo-error-screen "logo-error-screen")
|
||||||
(def ^:svg-id login-illustration "login-illustration")
|
(def ^:svg-id login-illustration "login-illustration")
|
||||||
(def ^:svg-id logo-subscription "logo-subscription")
|
(def ^:svg-id logo-subscription "logo-subscription")
|
||||||
|
(def ^:svg-id logo-subscription-light "logo-subscription-light")
|
||||||
(def ^:svg-id marketing-arrows "marketing-arrows")
|
(def ^:svg-id marketing-arrows "marketing-arrows")
|
||||||
(def ^:svg-id marketing-exchange "marketing-exchange")
|
(def ^:svg-id marketing-exchange "marketing-exchange")
|
||||||
(def ^:svg-id marketing-file "marketing-file")
|
(def ^:svg-id marketing-file "marketing-file")
|
||||||
|
|
|
@ -18,4 +18,6 @@
|
||||||
|
|
||||||
.cta-title {
|
.cta-title {
|
||||||
color: var(--color-foreground-primary);
|
color: var(--color-foreground-primary);
|
||||||
|
line-height: 1.2;
|
||||||
|
margin-block-end: var(--sp-m);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
(def ^:icon logo-error-screen (icon-xref :logo-error-screen))
|
(def ^:icon logo-error-screen (icon-xref :logo-error-screen))
|
||||||
(def ^:icon login-illustration (icon-xref :login-illustration))
|
(def ^:icon login-illustration (icon-xref :login-illustration))
|
||||||
(def ^:icon logo-subscription (icon-xref :logo-subscription))
|
(def ^:icon logo-subscription (icon-xref :logo-subscription))
|
||||||
|
(def ^:icon logo-subscription-light (icon-xref :logo-subscription-light))
|
||||||
|
|
||||||
(def ^:icon brand-openid (icon-xref :brand-openid))
|
(def ^:icon brand-openid (icon-xref :brand-openid))
|
||||||
(def ^:icon brand-github (icon-xref :brand-github))
|
(def ^:icon brand-github (icon-xref :brand-github))
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.common.math :as mth]
|
||||||
[app.main.data.event :as ev]
|
[app.main.data.event :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
[app.main.data.profile :as du]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.main.router :as rt]
|
[app.main.router :as rt]
|
||||||
|
@ -18,12 +20,23 @@
|
||||||
|
|
||||||
(mf/defc plan-card*
|
(mf/defc plan-card*
|
||||||
{::mf/props :obj}
|
{::mf/props :obj}
|
||||||
[{:keys [card-title card-title-icon price-value price-period benefits-title benefits cta-text cta-link cta-text-trial cta-link-trial cta-text-with-icon cta-link-with-icon]}]
|
[{:keys [card-title
|
||||||
|
card-title-icon
|
||||||
|
price-value price-period
|
||||||
|
benefits-title benefits
|
||||||
|
cta-text
|
||||||
|
cta-link
|
||||||
|
cta-text-trial
|
||||||
|
cta-link-trial
|
||||||
|
cta-text-with-icon
|
||||||
|
cta-link-with-icon
|
||||||
|
editors]}]
|
||||||
[:div {:class (stl/css :plan-card)}
|
[:div {:class (stl/css :plan-card)}
|
||||||
[:div {:class (stl/css :plan-card-header)}
|
[:div {:class (stl/css :plan-card-header)}
|
||||||
[:div {:class (stl/css :plan-card-title-container)}
|
[:div {:class (stl/css :plan-card-title-container)}
|
||||||
(when card-title-icon [:span {:class (stl/css :plan-title-icon)} card-title-icon])
|
(when card-title-icon [:span {:class (stl/css :plan-title-icon)} card-title-icon])
|
||||||
[:h4 {:class (stl/css :plan-card-title)} card-title]]
|
[:h4 {:class (stl/css :plan-card-title)} card-title]
|
||||||
|
(when editors [:span {:class (stl/css :plan-editors)} (tr "subscription.settings.editors" editors)])]
|
||||||
(when (and price-value price-period)
|
(when (and price-value price-period)
|
||||||
[:div {:class (stl/css :plan-price)}
|
[:div {:class (stl/css :plan-price)}
|
||||||
[:span {:class (stl/css :plan-price-value)} price-value]
|
[:span {:class (stl/css :plan-price-value)} price-value]
|
||||||
|
@ -45,7 +58,7 @@
|
||||||
::mf/register-as :management-dialog}
|
::mf/register-as :management-dialog}
|
||||||
[{:keys [subscription-name teams subscribe-to-trial]}]
|
[{:keys [subscription-name teams subscribe-to-trial]}]
|
||||||
|
|
||||||
(let [min-members* (mf/use-state (or (some->> teams (map :total-members) (apply max)) 1))
|
(let [min-members* (mf/use-state (or (some->> teams (map :total-editors) (apply max)) 1))
|
||||||
min-members (deref min-members*)
|
min-members (deref min-members*)
|
||||||
formatted-subscription-name (if subscribe-to-trial
|
formatted-subscription-name (if subscribe-to-trial
|
||||||
(if (= subscription-name "unlimited")
|
(if (= subscription-name "unlimited")
|
||||||
|
@ -75,7 +88,7 @@
|
||||||
returnUrl (js/encodeURIComponent current-href)
|
returnUrl (js/encodeURIComponent current-href)
|
||||||
href (dm/str "payments/subscriptions/create?type=enterprise&returnUrl=" returnUrl)]
|
href (dm/str "payments/subscriptions/create?type=enterprise&returnUrl=" returnUrl)]
|
||||||
(st/emit! (rt/nav-raw :href href))))))
|
(st/emit! (rt/nav-raw :href href))))))
|
||||||
handle-accept-dialog (mf/use-callback
|
handle-accept-dialog (mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (ptk/event ::ev/event {::ev/name "open-subscription-management"
|
(st/emit! (ptk/event ::ev/event {::ev/name "open-subscription-management"
|
||||||
::ev/origin "profile"
|
::ev/origin "profile"
|
||||||
|
@ -85,7 +98,7 @@
|
||||||
href (dm/str "payments/subscriptions/show?returnUrl=" returnUrl)]
|
href (dm/str "payments/subscriptions/show?returnUrl=" returnUrl)]
|
||||||
(st/emit! (rt/nav-raw :href href)))
|
(st/emit! (rt/nav-raw :href href)))
|
||||||
(modal/hide!)))
|
(modal/hide!)))
|
||||||
handle-close-dialog (mf/use-callback
|
handle-close-dialog (mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (ptk/event ::ev/event {::ev/name "close-subscription-modal"}))
|
(st/emit! (ptk/event ::ev/event {::ev/name "close-subscription-modal"}))
|
||||||
(modal/hide!)))]
|
(modal/hide!)))]
|
||||||
|
@ -103,7 +116,7 @@
|
||||||
[:ul {:class (stl/css :teams-list)}
|
[:ul {:class (stl/css :teams-list)}
|
||||||
(for [team (js->clj teams :keywordize-keys true)]
|
(for [team (js->clj teams :keywordize-keys true)]
|
||||||
[:li {:key (dm/str (:id team)) :class (stl/css :team-name)}
|
[:li {:key (dm/str (:id team)) :class (stl/css :team-name)}
|
||||||
(:name team) (tr "subscription.settings.management.dialog.members" (:total-members team))])]]
|
(:name team) (tr "subscription.settings.management.dialog.members" (:total-editors team))])]]
|
||||||
[:div {:class (stl/css :modal-text)}
|
[:div {:class (stl/css :modal-text)}
|
||||||
(tr "subscription.settings.management.dialog.no-teams")])
|
(tr "subscription.settings.management.dialog.no-teams")])
|
||||||
|
|
||||||
|
@ -117,8 +130,14 @@
|
||||||
:type "number"
|
:type "number"
|
||||||
:value min-members
|
:value min-members
|
||||||
:min 1
|
:min 1
|
||||||
|
:max 1000
|
||||||
:on-change #(let [new-value (js/parseInt (.. % -target -value))]
|
:on-change #(let [new-value (js/parseInt (.. % -target -value))]
|
||||||
(reset! min-members* (if (or (js/isNaN new-value) (zero? new-value)) 1 (max 1 new-value))))}]]
|
(reset! min-members*
|
||||||
|
(let [v (cond
|
||||||
|
(or (mth/nan? new-value) (zero? new-value)) 1
|
||||||
|
(> new-value 1000) 1000
|
||||||
|
:else (max 1 new-value))]
|
||||||
|
v)))}]]
|
||||||
[:div {:class (stl/css :editors-cost)}
|
[:div {:class (stl/css :editors-cost)}
|
||||||
[:span {:class (stl/css :modal-text-small)}
|
[:span {:class (stl/css :modal-text-small)}
|
||||||
(tr "subscription.settings.management.dialog.price-month" min-members)]
|
(tr "subscription.settings.management.dialog.price-month" min-members)]
|
||||||
|
@ -150,7 +169,8 @@
|
||||||
::mf/register-as :subscription-success}
|
::mf/register-as :subscription-success}
|
||||||
[{:keys [subscription-name]}]
|
[{:keys [subscription-name]}]
|
||||||
|
|
||||||
(let [handle-close-dialog (mf/use-callback
|
(let [profile (mf/deref refs/profile)
|
||||||
|
handle-close-dialog (mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (ptk/event ::ev/event {::ev/name "subscription-success"}))
|
(st/emit! (ptk/event ::ev/event {::ev/name "subscription-success"}))
|
||||||
(modal/hide!)))]
|
(modal/hide!)))]
|
||||||
|
@ -160,7 +180,9 @@
|
||||||
[:button {:class (stl/css :close-btn) :on-click handle-close-dialog} i/close]
|
[:button {:class (stl/css :close-btn) :on-click handle-close-dialog} i/close]
|
||||||
[:div {:class (stl/css :modal-success-content)}
|
[:div {:class (stl/css :modal-success-content)}
|
||||||
[:div {:class (stl/css :modal-start)}
|
[:div {:class (stl/css :modal-start)}
|
||||||
i/logo-subscription]
|
(if (= "light" (:theme profile))
|
||||||
|
i/logo-subscription-light
|
||||||
|
i/logo-subscription)]
|
||||||
|
|
||||||
[:div {:class (stl/css :modal-end)}
|
[:div {:class (stl/css :modal-end)}
|
||||||
[:div {:class (stl/css :modal-title)} (tr "subscription.settings.sucess.dialog.title" subscription-name)]
|
[:div {:class (stl/css :modal-title)} (tr "subscription.settings.sucess.dialog.title" subscription-name)]
|
||||||
|
@ -178,6 +200,7 @@
|
||||||
[{:keys [profile]}]
|
[{:keys [profile]}]
|
||||||
(let [route (mf/deref refs/route)
|
(let [route (mf/deref refs/route)
|
||||||
params (:params route)
|
params (:params route)
|
||||||
|
params-subscription (:subscription (:query params))
|
||||||
show-subscription-success-modal (and (:query params)
|
show-subscription-success-modal (and (:query params)
|
||||||
(or (= (:subscription (:query params)) "subscribed-to-penpot-unlimited")
|
(or (= (:subscription (:query params)) "subscribed-to-penpot-unlimited")
|
||||||
(= (:subscription (:query params)) "subscribed-to-penpot-enterprise")))
|
(= (:subscription (:query params)) "subscribed-to-penpot-enterprise")))
|
||||||
|
@ -221,11 +244,19 @@
|
||||||
(mf/with-effect []
|
(mf/with-effect []
|
||||||
(dom/set-html-title (tr "subscription.labels")))
|
(dom/set-html-title (tr "subscription.labels")))
|
||||||
|
|
||||||
(when show-subscription-success-modal
|
(mf/with-effect [show-subscription-success-modal subscription]
|
||||||
(st/emit! (modal/show :subscription-success
|
(when show-subscription-success-modal
|
||||||
{:subscription-name (if (= (:subscription (:query params)) "subscribed-to-penpot-unlimited")
|
(st/emit!
|
||||||
(tr "subscription.settings.unlimited-trial-modal")
|
(modal/show :subscription-success
|
||||||
(tr "subscription.settings.enterprise-trial-modal"))})))
|
{:subscription-name (if (= params-subscription "subscribed-to-penpot-unlimited")
|
||||||
|
(tr "subscription.settings.unlimited-trial")
|
||||||
|
(tr "subscription.settings.enterprise-trial"))})
|
||||||
|
(du/update-profile-props {:subscription
|
||||||
|
(assoc subscription :type (if (= params-subscription "subscribed-to-penpot-unlimited")
|
||||||
|
"unlimited"
|
||||||
|
"enterprise"))})
|
||||||
|
(rt/nav :settings-subscription {} {::rt/replace true}))))
|
||||||
|
|
||||||
[:section {:class (stl/css :dashboard-section)}
|
[:section {:class (stl/css :dashboard-section)}
|
||||||
[:div {:class (stl/css :dashboard-content)}
|
[:div {:class (stl/css :dashboard-content)}
|
||||||
[:h2 {:class (stl/css :title-section)} (tr "subscription.labels")]
|
[:h2 {:class (stl/css :title-section)} (tr "subscription.labels")]
|
||||||
|
@ -251,7 +282,8 @@
|
||||||
:cta-text (tr "subscription.settings.manage-your-subscription")
|
:cta-text (tr "subscription.settings.manage-your-subscription")
|
||||||
:cta-link go-to-payments
|
:cta-link go-to-payments
|
||||||
:cta-text-trial (tr "subscription.settings.add-payment-to-continue")
|
:cta-text-trial (tr "subscription.settings.add-payment-to-continue")
|
||||||
:cta-link-trial go-to-payments}]
|
:cta-link-trial go-to-payments
|
||||||
|
:editors (-> profile :props :subscription :quantity)}]
|
||||||
|
|
||||||
[:> plan-card* {:card-title (tr "subscription.settings.unlimited")
|
[:> plan-card* {:card-title (tr "subscription.settings.unlimited")
|
||||||
:card-title-icon i/character-u
|
:card-title-icon i/character-u
|
||||||
|
@ -260,17 +292,27 @@
|
||||||
(tr "subscription.settings.unlimited.bill"),
|
(tr "subscription.settings.unlimited.bill"),
|
||||||
(tr "subscription.settings.unlimited.storage")]
|
(tr "subscription.settings.unlimited.storage")]
|
||||||
:cta-text (tr "subscription.settings.manage-your-subscription")
|
:cta-text (tr "subscription.settings.manage-your-subscription")
|
||||||
:cta-link go-to-payments}])
|
:cta-link go-to-payments
|
||||||
|
:editors (-> profile :props :subscription :quantity)}])
|
||||||
|
|
||||||
"enterprise"
|
"enterprise"
|
||||||
[:> plan-card* {:card-title (tr "subscription.settings.enterprise")
|
(if subscription-is-trial
|
||||||
:card-title-icon i/character-e
|
[:> plan-card* {:card-title (tr "subscription.settings.enterprise-trial")
|
||||||
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
|
:card-title-icon i/character-e
|
||||||
:benefits [(tr "subscription.settings.enterprise.support"),
|
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
|
||||||
(tr "subscription.settings.enterprise.security"),
|
:benefits [(tr "subscription.settings.enterprise.support"),
|
||||||
(tr "subscription.settings.enterprise.logs")]
|
(tr "subscription.settings.enterprise.security"),
|
||||||
:cta-text (tr "subscription.settings.manage-your-subscription")
|
(tr "subscription.settings.enterprise.logs")]
|
||||||
:cta-link go-to-payments}])
|
:cta-text (tr "subscription.settings.manage-your-subscription")
|
||||||
|
:cta-link go-to-payments}]
|
||||||
|
[:> plan-card* {:card-title (tr "subscription.settings.enterprise")
|
||||||
|
:card-title-icon i/character-e
|
||||||
|
:benefits-title (tr "subscription.settings.benefits.all-professional-benefits")
|
||||||
|
:benefits [(tr "subscription.settings.enterprise.support"),
|
||||||
|
(tr "subscription.settings.enterprise.security"),
|
||||||
|
(tr "subscription.settings.enterprise.logs")]
|
||||||
|
:cta-text (tr "subscription.settings.manage-your-subscription")
|
||||||
|
:cta-link go-to-payments}]))
|
||||||
|
|
||||||
[:div {:class (stl/css :membership-container)}
|
[:div {:class (stl/css :membership-container)}
|
||||||
(when subscription-member [:div {:class (stl/css :membership)}
|
(when subscription-member [:div {:class (stl/css :membership)}
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.subscription-member {
|
.subscription-member {
|
||||||
stroke: #fdcd79ff;
|
stroke: var(--color-badge-premium);
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-section {
|
.title-section {
|
||||||
|
@ -106,6 +106,13 @@
|
||||||
color: var(--color-foreground-primary);
|
color: var(--color-foreground-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.plan-editors {
|
||||||
|
@include t.use-typography("body-medium");
|
||||||
|
align-self: end;
|
||||||
|
color: var(--color-foreground-primary);
|
||||||
|
margin-block-end: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.plan-price-period {
|
.plan-price-period {
|
||||||
@include t.use-typography("body-small");
|
@include t.use-typography("body-small");
|
||||||
color: var(--color-foreground-primary);
|
color: var(--color-foreground-primary);
|
||||||
|
@ -126,7 +133,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.cta-button {
|
.cta-button {
|
||||||
@include t.use-typography("body-small");
|
@include t.use-typography("body-medium");
|
||||||
@include buttonStyle;
|
@include buttonStyle;
|
||||||
color: var(--color-accent-tertiary);
|
color: var(--color-accent-tertiary);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
[app.util.time :as dt]
|
[app.util.time :as dt]
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
|
[lambdaisland.uri :as u]
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
@ -41,6 +42,18 @@
|
||||||
(= subscription-name "enterprise") 90
|
(= subscription-name "enterprise") 90
|
||||||
:else 7)))
|
:else 7)))
|
||||||
|
|
||||||
|
(defn get-versions-warning-subtext
|
||||||
|
[team]
|
||||||
|
(let [is-owner? (-> team :permissions :is-owner)
|
||||||
|
email-owner (:email (some #(when (:is-owner %) %) (:members team)))
|
||||||
|
go-to-subscription (dm/str (u/join cfg/public-uri "#/settings/subscriptions"))]
|
||||||
|
|
||||||
|
(if (contains? cfg/flags :subscriptions)
|
||||||
|
(if is-owner?
|
||||||
|
(tr "subscription.workspace.versions.warning.subtext-owner" go-to-subscription)
|
||||||
|
(tr "subscription.workspace.versions.warning.subtext-member" email-owner email-owner))
|
||||||
|
(tr "workspace.versions.warning.subtext" "support@penpot.app"))))
|
||||||
|
|
||||||
(defn group-snapshots
|
(defn group-snapshots
|
||||||
[data]
|
[data]
|
||||||
(->> (concat
|
(->> (concat
|
||||||
|
@ -369,5 +382,4 @@
|
||||||
[:> i18n/tr-html*
|
[:> i18n/tr-html*
|
||||||
{:tag-name "div"
|
{:tag-name "div"
|
||||||
:class (stl/css :cta)
|
:class (stl/css :cta)
|
||||||
:content (tr "workspace.versions.warning.subtext"
|
:content (get-versions-warning-subtext team)}]]])]))
|
||||||
"mailto:support@penpot.app")}]]])]))
|
|
||||||
|
|
|
@ -4281,27 +4281,10 @@ msgstr ""
|
||||||
"The Professional plan is designed for teams of up to 8 editors (owner, "
|
"The Professional plan is designed for teams of up to 8 editors (owner, "
|
||||||
"admin, and editor)."
|
"admin, and editor)."
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:157
|
|
||||||
msgid "subscription.dashboard.cta.trial-plan-designed"
|
|
||||||
msgstr ""
|
|
||||||
"The Unlimited (trial) plan is designed for teams of more than 8 editors "
|
|
||||||
"(owner, admin, and editor)."
|
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:160
|
#: src/app/main/ui/dashboard/subscription.cljs:160
|
||||||
msgid "subscription.dashboard.cta.unlimited-many-editors"
|
msgid "subscription.dashboard.cta.unlimited-many-editors"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Looks like your team has grown! Your plan includes %s seats, but you're now "
|
"Looks like your team has grown! Your plan includes %s seats, but you're now using %s"
|
||||||
"using more than that."
|
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:174
|
|
||||||
#, markdown
|
|
||||||
msgid "subscription.dashboard.cta.upgrade-to-full-access-member"
|
|
||||||
msgstr "Unlock full access forever. Contact with the team owner: %s"
|
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:171
|
|
||||||
#, markdown
|
|
||||||
msgid "subscription.dashboard.cta.upgrade-to-full-access-owner"
|
|
||||||
msgstr "Unlock full access forever. [Subscribe now.](%s)"
|
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:168
|
#: src/app/main/ui/dashboard/subscription.cljs:168
|
||||||
#, markdown
|
#, markdown
|
||||||
|
@ -4315,12 +4298,16 @@ msgstr ""
|
||||||
msgid "subscription.dashboard.cta.upgrade-to-unlimited-enterprise-owner"
|
msgid "subscription.dashboard.cta.upgrade-to-unlimited-enterprise-owner"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Get more editors, more storage, and more autosaved versions with the "
|
"Get more editors, more storage, and more autosaved versions with the "
|
||||||
"Unlimited or Enterprise plan. [Subscribe now.](%s)"
|
"Unlimited or Enterprise plan. [Subscribe now.|target:self](%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:176
|
#: src/app/main/ui/dashboard/subscription.cljs:176
|
||||||
#, markdown
|
#, markdown
|
||||||
msgid "subscription.dashboard.cta.upgrade-to-unlimited-enterprise-owner-more-seats"
|
msgid "subscription.dashboard.cta.upgrade-more-seats-owner"
|
||||||
msgstr "Please upgrade to match your usage. [Subscribe now.](%s)"
|
msgstr "Please upgrade to match your usage. [Subscribe now.|target:self](%s)"
|
||||||
|
|
||||||
|
#, markdown
|
||||||
|
msgid "subscription.dashboard.cta.upgrade-more-seats-member"
|
||||||
|
msgstr "Please upgrade to match your usage. Contact with the team owner: %s"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:80
|
#: src/app/main/ui/dashboard/subscription.cljs:80
|
||||||
msgid "subscription.dashboard.power-up.enterprise-plan"
|
msgid "subscription.dashboard.power-up.enterprise-plan"
|
||||||
|
@ -4336,7 +4323,7 @@ msgstr "Advanced security, activity logs, dedicated support and more."
|
||||||
msgid "subscription.dashboard.power-up.professional.bottom-description"
|
msgid "subscription.dashboard.power-up.professional.bottom-description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Get extra editors and storage, file backup and more with the Unlimited "
|
"Get extra editors and storage, file backup and more with the Unlimited "
|
||||||
"plan[Power up](%s)"
|
"plan[Power up|target:self](%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:59
|
#: src/app/main/ui/dashboard/subscription.cljs:59
|
||||||
msgid "subscription.dashboard.power-up.professional.top-title"
|
msgid "subscription.dashboard.power-up.professional.top-title"
|
||||||
|
@ -4350,7 +4337,7 @@ msgstr "Subscribe"
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:68
|
#: src/app/main/ui/dashboard/subscription.cljs:68
|
||||||
#, markdown
|
#, markdown
|
||||||
msgid "subscription.dashboard.power-up.trial.bottom-description"
|
msgid "subscription.dashboard.power-up.trial.bottom-description"
|
||||||
msgstr "Enjoying your trial? Unlock full access forever.[Subscribe](%s)"
|
msgstr "Enjoying your trial? Unlock full access forever.[Subscribe|target:self](%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:62
|
#: src/app/main/ui/dashboard/subscription.cljs:62
|
||||||
#, unused
|
#, unused
|
||||||
|
@ -4365,12 +4352,15 @@ msgstr "Unlimited plan (trial)"
|
||||||
msgid "subscription.dashboard.power-up.unlimited-plan"
|
msgid "subscription.dashboard.power-up.unlimited-plan"
|
||||||
msgstr "Unlimited plan"
|
msgstr "Unlimited plan"
|
||||||
|
|
||||||
|
msgid "subscription.dashboard.power-up.enterprise-trial.top-title"
|
||||||
|
msgstr "Enterprise plan (trial)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:74
|
#: src/app/main/ui/dashboard/subscription.cljs:74
|
||||||
#, markdown
|
#, markdown
|
||||||
msgid "subscription.dashboard.power-up.unlimited.bottom-description"
|
msgid "subscription.dashboard.power-up.unlimited.bottom-description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Get advanced security, activity logs, dedicated support and more. Take a "
|
"Get advanced security, activity logs, dedicated support and more. Take a "
|
||||||
"look to the[Enterprise plan.](%s)"
|
"look to the[Enterprise plan.|target:self](%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:70
|
#: src/app/main/ui/dashboard/subscription.cljs:70
|
||||||
#, unused
|
#, unused
|
||||||
|
@ -4423,10 +4413,6 @@ msgstr "Enterprise"
|
||||||
msgid "subscription.settings.enterprise-trial"
|
msgid "subscription.settings.enterprise-trial"
|
||||||
msgstr "Enterprise (trial)"
|
msgstr "Enterprise (trial)"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:228
|
|
||||||
msgid "subscription.settings.enterprise-trial-modal"
|
|
||||||
msgstr "Enterprise trial"
|
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:271, src/app/main/ui/settings/subscription.cljs:320
|
#: src/app/main/ui/settings/subscription.cljs:271, src/app/main/ui/settings/subscription.cljs:320
|
||||||
msgid "subscription.settings.enterprise.logs"
|
msgid "subscription.settings.enterprise.logs"
|
||||||
msgstr "Activity logs"
|
msgstr "Activity logs"
|
||||||
|
@ -4479,7 +4465,7 @@ msgstr "Apply %s to your teams"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:282
|
#: src/app/main/ui/settings/subscription.cljs:282
|
||||||
msgid "subscription.settings.member-since"
|
msgid "subscription.settings.member-since"
|
||||||
msgstr "Penpot member since %s"
|
msgstr "Penpot member since: %s"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:295, src/app/main/ui/settings/subscription.cljs:309, src/app/main/ui/settings/subscription.cljs:323
|
#: src/app/main/ui/settings/subscription.cljs:295, src/app/main/ui/settings/subscription.cljs:309, src/app/main/ui/settings/subscription.cljs:323
|
||||||
msgid "subscription.settings.more-information"
|
msgid "subscription.settings.more-information"
|
||||||
|
@ -4517,6 +4503,9 @@ msgstr "Unlimited teams of up to 8 editors"
|
||||||
msgid "subscription.settings.section-plan"
|
msgid "subscription.settings.section-plan"
|
||||||
msgstr "Your subscription"
|
msgstr "Your subscription"
|
||||||
|
|
||||||
|
msgid "subscription.settings.editors"
|
||||||
|
msgstr "(x %s editors)"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:145
|
#: src/app/main/ui/settings/subscription.cljs:145
|
||||||
msgid "subscription.settings.start-trial"
|
msgid "subscription.settings.start-trial"
|
||||||
msgstr "Start free trial"
|
msgstr "Start free trial"
|
||||||
|
@ -4542,7 +4531,7 @@ msgstr "You are %s!"
|
||||||
#: src/app/main/ui/settings/subscription.cljs:278
|
#: src/app/main/ui/settings/subscription.cljs:278
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "subscription.settings.support-us-since"
|
msgid "subscription.settings.support-us-since"
|
||||||
msgstr "You've been supporting us with this plan since %s"
|
msgstr "You've been supporting us with this plan since: %s"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:307, src/app/main/ui/settings/subscription.cljs:321
|
#: src/app/main/ui/settings/subscription.cljs:307, src/app/main/ui/settings/subscription.cljs:321
|
||||||
msgid "subscription.settings.try-it-free"
|
msgid "subscription.settings.try-it-free"
|
||||||
|
@ -4561,10 +4550,6 @@ msgstr "Unlimited"
|
||||||
msgid "subscription.settings.unlimited-trial"
|
msgid "subscription.settings.unlimited-trial"
|
||||||
msgstr "Unlimited (trial)"
|
msgstr "Unlimited (trial)"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:227
|
|
||||||
msgid "subscription.settings.unlimited-trial-modal"
|
|
||||||
msgstr "Unlimited trial"
|
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:249, src/app/main/ui/settings/subscription.cljs:260, src/app/main/ui/settings/subscription.cljs:305
|
#: src/app/main/ui/settings/subscription.cljs:249, src/app/main/ui/settings/subscription.cljs:260, src/app/main/ui/settings/subscription.cljs:305
|
||||||
msgid "subscription.settings.unlimited.bill"
|
msgid "subscription.settings.unlimited.bill"
|
||||||
msgstr "Capped monthly bill"
|
msgstr "Capped monthly bill"
|
||||||
|
@ -7866,6 +7851,18 @@ msgstr ""
|
||||||
"If you'd like to increase this limit, write to us at "
|
"If you'd like to increase this limit, write to us at "
|
||||||
"[support@penpot.app](%s)"
|
"[support@penpot.app](%s)"
|
||||||
|
|
||||||
|
#, markdown
|
||||||
|
msgid "subscription.workspace.versions.warning.subtext-owner"
|
||||||
|
msgstr ""
|
||||||
|
"If you'd like to increase this limit, "
|
||||||
|
"[upgrade your plan|target:self](%s)"
|
||||||
|
|
||||||
|
#, markdown
|
||||||
|
msgid "subscription.workspace.versions.warning.subtext-member"
|
||||||
|
msgstr ""
|
||||||
|
"If you'd like to increase this limit, contact with the team owner: "
|
||||||
|
"[%s](mailto)"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/versions.cljs:368
|
#: src/app/main/ui/workspace/sidebar/versions.cljs:368
|
||||||
msgid "workspace.versions.warning.text"
|
msgid "workspace.versions.warning.text"
|
||||||
msgstr "Autosaved versions will be kept for %s days."
|
msgstr "Autosaved versions will be kept for %s days."
|
||||||
|
|
|
@ -4307,29 +4307,10 @@ msgstr ""
|
||||||
"El plan Professional está diseñado para equipos de hasta 8 editores "
|
"El plan Professional está diseñado para equipos de hasta 8 editores "
|
||||||
"(propietario, administrador y editor)."
|
"(propietario, administrador y editor)."
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:157
|
|
||||||
msgid "subscription.dashboard.cta.trial-plan-designed"
|
|
||||||
msgstr ""
|
|
||||||
"El plan Unlimited (de prueba) está diseñado para equipos de más de 8 "
|
|
||||||
"editores (propietario, administrador y editor)."
|
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:160
|
#: src/app/main/ui/dashboard/subscription.cljs:160
|
||||||
msgid "subscription.dashboard.cta.unlimited-many-editors"
|
msgid "subscription.dashboard.cta.unlimited-many-editors"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"¡Parece que tu equipo ha crecido! Tu plan incluye %s asientos, pero ahora "
|
"¡Parece que tu equipo ha crecido! Tu plan incluye %s asientos, pero ahora estás usando %s"
|
||||||
"estás usando más que eso."
|
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:174
|
|
||||||
#, markdown
|
|
||||||
msgid "subscription.dashboard.cta.upgrade-to-full-access-member"
|
|
||||||
msgstr ""
|
|
||||||
"Desbloquea el acceso completo para siempre. Contacta con el propietario del "
|
|
||||||
"equipo: %s"
|
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:171
|
|
||||||
#, markdown
|
|
||||||
msgid "subscription.dashboard.cta.upgrade-to-full-access-owner"
|
|
||||||
msgstr "Desbloquea el acceso completo para siempre. [Suscríbete ahora.](%s)"
|
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:168
|
#: src/app/main/ui/dashboard/subscription.cljs:168
|
||||||
#, markdown
|
#, markdown
|
||||||
|
@ -4344,12 +4325,17 @@ msgstr ""
|
||||||
msgid "subscription.dashboard.cta.upgrade-to-unlimited-enterprise-owner"
|
msgid "subscription.dashboard.cta.upgrade-to-unlimited-enterprise-owner"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Consigue más editores, más almacenamiento y más versiones guardadas "
|
"Consigue más editores, más almacenamiento y más versiones guardadas "
|
||||||
"automáticamente con el plan Unlimited o Enterprise. [Suscríbete ahora.](%s)"
|
"automáticamente con el plan Unlimited o Enterprise. [Suscríbete ahora.|target:self](%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:176
|
#: src/app/main/ui/dashboard/subscription.cljs:176
|
||||||
#, markdown
|
#, markdown
|
||||||
msgid "subscription.dashboard.cta.upgrade-to-unlimited-enterprise-owner-more-seats"
|
msgid "subscription.dashboard.cta.upgrade-more-seats-owner"
|
||||||
msgstr "Por favor, mejóralo para adaptarlo a tu uso. [Suscríbete ahora.](%s)"
|
msgstr "Por favor, mejóralo para adaptarlo a tu uso. [Suscríbete ahora.|target:self](%s)"
|
||||||
|
|
||||||
|
#, markdown
|
||||||
|
msgid "subscription.dashboard.cta.upgrade-more-seats-member"
|
||||||
|
msgstr "Por favor, mejóralo para adaptarlo a tu uso. Contacta con el "
|
||||||
|
"propietario del equipo: %s"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:80
|
#: src/app/main/ui/dashboard/subscription.cljs:80
|
||||||
msgid "subscription.dashboard.power-up.enterprise-plan"
|
msgid "subscription.dashboard.power-up.enterprise-plan"
|
||||||
|
@ -4365,7 +4351,7 @@ msgstr "Seguridad avanzada, registros de actividad, asistencia dedicada y mucho
|
||||||
msgid "subscription.dashboard.power-up.professional.bottom-description"
|
msgid "subscription.dashboard.power-up.professional.bottom-description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Consigue editores y almacenamiento adicionales, copias de seguridad de "
|
"Consigue editores y almacenamiento adicionales, copias de seguridad de "
|
||||||
"archivos y mucho más con el Plan Unlimited[Mejóralo](%s)"
|
"archivos y mucho más con el Plan Unlimited[Mejóralo|target:self](%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:59
|
#: src/app/main/ui/dashboard/subscription.cljs:59
|
||||||
msgid "subscription.dashboard.power-up.professional.top-title"
|
msgid "subscription.dashboard.power-up.professional.top-title"
|
||||||
|
@ -4381,7 +4367,7 @@ msgstr "Suscríbete"
|
||||||
msgid "subscription.dashboard.power-up.trial.bottom-description"
|
msgid "subscription.dashboard.power-up.trial.bottom-description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"¿Disfrutas de la prueba? Desbloquea el acceso completo para "
|
"¿Disfrutas de la prueba? Desbloquea el acceso completo para "
|
||||||
"siempre.[Suscríbete](%s)"
|
"siempre.[Suscríbete|target:self](%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:62
|
#: src/app/main/ui/dashboard/subscription.cljs:62
|
||||||
#, unused
|
#, unused
|
||||||
|
@ -4394,16 +4380,19 @@ msgstr ""
|
||||||
msgid "subscription.dashboard.power-up.trial.top-title"
|
msgid "subscription.dashboard.power-up.trial.top-title"
|
||||||
msgstr "Plan Unlimited (Prueba)"
|
msgstr "Plan Unlimited (Prueba)"
|
||||||
|
|
||||||
|
msgid "subscription.dashboard.power-up.enterprise-trial.top-title"
|
||||||
|
msgstr "Plan Enterprise (Prueba)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:73
|
#: src/app/main/ui/dashboard/subscription.cljs:73
|
||||||
msgid "subscription.dashboard.power-up.unlimited-plan"
|
msgid "subscription.dashboard.power-up.unlimited-plan"
|
||||||
msgstr "Plan ilimitado"
|
msgstr "Plan Unlimited"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:74
|
#: src/app/main/ui/dashboard/subscription.cljs:74
|
||||||
#, markdown
|
#, markdown
|
||||||
msgid "subscription.dashboard.power-up.unlimited.bottom-description"
|
msgid "subscription.dashboard.power-up.unlimited.bottom-description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Obtenga seguridad avanzada, registros de actividad, asistencia dedicada y "
|
"Obtenga seguridad avanzada, registros de actividad, asistencia dedicada y "
|
||||||
"mucho más. Echa un ojo al[Plan Enterprise](%s)"
|
"mucho más. Echa un ojo al[Plan Enterprise|target:self](%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/subscription.cljs:70
|
#: src/app/main/ui/dashboard/subscription.cljs:70
|
||||||
#, unused
|
#, unused
|
||||||
|
@ -4453,10 +4442,6 @@ msgstr "Enterprise"
|
||||||
msgid "subscription.settings.enterprise-trial"
|
msgid "subscription.settings.enterprise-trial"
|
||||||
msgstr "Enterprise (prueba)"
|
msgstr "Enterprise (prueba)"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:228
|
|
||||||
msgid "subscription.settings.enterprise-trial-modal"
|
|
||||||
msgstr "Enterprise de prueba"
|
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:271, src/app/main/ui/settings/subscription.cljs:320
|
#: src/app/main/ui/settings/subscription.cljs:271, src/app/main/ui/settings/subscription.cljs:320
|
||||||
msgid "subscription.settings.enterprise.logs"
|
msgid "subscription.settings.enterprise.logs"
|
||||||
msgstr "Registros de actividad"
|
msgstr "Registros de actividad"
|
||||||
|
@ -4509,7 +4494,7 @@ msgstr "Aplica %s a tus equipos"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:282
|
#: src/app/main/ui/settings/subscription.cljs:282
|
||||||
msgid "subscription.settings.member-since"
|
msgid "subscription.settings.member-since"
|
||||||
msgstr "Miembro de penpot desde %s"
|
msgstr "Miembro de penpot desde: %s"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:285
|
#: src/app/main/ui/settings/subscription.cljs:285
|
||||||
msgid "subscription.settings.other-plans"
|
msgid "subscription.settings.other-plans"
|
||||||
|
@ -4543,6 +4528,9 @@ msgstr "Equipos ilimitados de hasta 8 redactores"
|
||||||
msgid "subscription.settings.section-plan"
|
msgid "subscription.settings.section-plan"
|
||||||
msgstr "Tu suscripción"
|
msgstr "Tu suscripción"
|
||||||
|
|
||||||
|
msgid "subscription.settings.editors"
|
||||||
|
msgstr "(x %s editores)"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:145
|
#: src/app/main/ui/settings/subscription.cljs:145
|
||||||
msgid "subscription.settings.start-trial"
|
msgid "subscription.settings.start-trial"
|
||||||
msgstr "Comenzar prueba gratuita"
|
msgstr "Comenzar prueba gratuita"
|
||||||
|
@ -4567,7 +4555,7 @@ msgstr "Eres %s!"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:278
|
#: src/app/main/ui/settings/subscription.cljs:278
|
||||||
msgid "subscription.settings.support-us-since"
|
msgid "subscription.settings.support-us-since"
|
||||||
msgstr "Nos has estado apoyando con este plan desde %s"
|
msgstr "Nos has estado apoyando con este plan desde: %s"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:307, src/app/main/ui/settings/subscription.cljs:321
|
#: src/app/main/ui/settings/subscription.cljs:307, src/app/main/ui/settings/subscription.cljs:321
|
||||||
msgid "subscription.settings.try-it-free"
|
msgid "subscription.settings.try-it-free"
|
||||||
|
@ -4586,10 +4574,6 @@ msgstr "Unlimited"
|
||||||
msgid "subscription.settings.unlimited-trial"
|
msgid "subscription.settings.unlimited-trial"
|
||||||
msgstr "Unlimited (prueba)"
|
msgstr "Unlimited (prueba)"
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:227
|
|
||||||
msgid "subscription.settings.unlimited-trial-modal"
|
|
||||||
msgstr "Unlimited de prueba"
|
|
||||||
|
|
||||||
#: src/app/main/ui/settings/subscription.cljs:249, src/app/main/ui/settings/subscription.cljs:260, src/app/main/ui/settings/subscription.cljs:305
|
#: src/app/main/ui/settings/subscription.cljs:249, src/app/main/ui/settings/subscription.cljs:260, src/app/main/ui/settings/subscription.cljs:305
|
||||||
msgid "subscription.settings.unlimited.bill"
|
msgid "subscription.settings.unlimited.bill"
|
||||||
msgstr "Factura mensual limitada"
|
msgstr "Factura mensual limitada"
|
||||||
|
@ -7829,6 +7813,18 @@ msgstr "Abrir menu de versiones"
|
||||||
msgid "workspace.versions.warning.subtext"
|
msgid "workspace.versions.warning.subtext"
|
||||||
msgstr "Si quieres aumentar este límite, contáctanos en [support@penpot.app](%s)"
|
msgstr "Si quieres aumentar este límite, contáctanos en [support@penpot.app](%s)"
|
||||||
|
|
||||||
|
#, markdown
|
||||||
|
msgid "subscription.workspace.versions.warning.subtext-owner"
|
||||||
|
msgstr ""
|
||||||
|
"Si quieres aumentar este límite, "
|
||||||
|
"[mejora tu plan|target:self](%s)"
|
||||||
|
|
||||||
|
#, markdown
|
||||||
|
msgid "subscription.workspace.versions.warning.subtext-member"
|
||||||
|
msgstr ""
|
||||||
|
"Si quieres aumentar este límite, contacta con el propietario del equipo: "
|
||||||
|
"[%s](mailto)"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/sidebar/versions.cljs:368
|
#: src/app/main/ui/workspace/sidebar/versions.cljs:368
|
||||||
msgid "workspace.versions.warning.text"
|
msgid "workspace.versions.warning.text"
|
||||||
msgstr "Los autoguardados duran %s días."
|
msgstr "Los autoguardados duran %s días."
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue