diff --git a/web/packages/teleport/src/Sessions/SessionList/SessionJoinBtn.test.tsx b/web/packages/teleport/src/Sessions/SessionList/SessionJoinBtn.test.tsx index df7d86724b1f7..2c82b97afd806 100644 --- a/web/packages/teleport/src/Sessions/SessionList/SessionJoinBtn.test.tsx +++ b/web/packages/teleport/src/Sessions/SessionList/SessionJoinBtn.test.tsx @@ -25,6 +25,7 @@ test('all participant modes are properly listed and in the correct order', () => sid={'4b038eda-ddca-5533-9a49-3a34f133b5f4'} clusterId={'test-cluster'} participantModes={['moderator', 'peer', 'observer']} + showCTA={false} /> ); @@ -50,3 +51,28 @@ test('all participant modes are properly listed and in the correct order', () => expect(menuItems[1]).toHaveTextContent('As a Moderator'); expect(menuItems[2]).toHaveTextContent('As a Peer'); }); + +test('all possible participant modes are properly listed in the CTA without join links', () => { + render( + + ); + + const joinBtn = screen.queryByText(/Join/i); + expect(joinBtn).toBeInTheDocument(); + + fireEvent.click(joinBtn); + + // Make sure that no link to join session is available when showCTA = true. + const menuItems = screen.queryByRole('link'); + expect(menuItems).not.toBeInTheDocument(); + + const cta = screen.queryByText( + 'Join Active Sessions with Teleport Enterprise' + ); + expect(cta).toBeInTheDocument(); +}); diff --git a/web/packages/teleport/src/Sessions/SessionList/SessionJoinBtn.tsx b/web/packages/teleport/src/Sessions/SessionList/SessionJoinBtn.tsx index 9d687ae3722b3..e5f1172a2352a 100644 --- a/web/packages/teleport/src/Sessions/SessionList/SessionJoinBtn.tsx +++ b/web/packages/teleport/src/Sessions/SessionList/SessionJoinBtn.tsx @@ -21,18 +21,28 @@ import { CarrotDown, Warning } from 'design/Icon'; import cfg from 'teleport/config'; import { ParticipantMode } from 'teleport/services/session'; +import { ButtonLockedFeature } from 'teleport/components/ButtonLockedFeature'; export const SessionJoinBtn = ({ sid, clusterId, participantModes, + showCTA, }: { sid: string; clusterId: string; participantModes: ParticipantMode[]; + showCTA: boolean; }) => { return ( + {showCTA && ( + + + Join Active Sessions with Teleport Enterprise + + + )} ); @@ -64,7 +77,7 @@ export const SessionJoinBtn = ({ function JoinMenu({ children }: { children: React.ReactNode }) { const [anchorEl, setAnchorEl] = useState(null); - const handleClickListItem = event => { + const handleClickListItem = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; @@ -103,14 +116,16 @@ function JoinMenuItem({ hasAccess, participantMode, url, + showCTA, }: { title: string; description: string; hasAccess: boolean; participantMode: ParticipantMode; url: string; + showCTA: boolean; }) { - if (hasAccess) { + if (hasAccess && !showCTA) { return ( {title} {description} - - - - {modeWarningText[participantMode]} - - + {!showCTA && ( + + + + {modeWarningText[participantMode]} + + + )} ); diff --git a/web/packages/teleport/src/Sessions/SessionList/SessionList.tsx b/web/packages/teleport/src/Sessions/SessionList/SessionList.tsx index f4b481756e093..bebef8ab9ce9c 100644 --- a/web/packages/teleport/src/Sessions/SessionList/SessionList.tsx +++ b/web/packages/teleport/src/Sessions/SessionList/SessionList.tsx @@ -24,7 +24,7 @@ import { Participant, Session, SessionKind } from 'teleport/services/session'; import { SessionJoinBtn } from './SessionJoinBtn'; export default function SessionList(props: Props) { - const { sessions, pageSize = 100 } = props; + const { sessions, pageSize = 100, showActiveSessionsCTA } = props; return ( + renderJoinCell({ ...session, showActiveSessionsCTA }), }, ]} emptyText="No Active Sessions Found" @@ -102,12 +103,14 @@ const renderIconCell = (kind: SessionKind) => { ); }; +type renderJoinCellProps = Session & { showActiveSessionsCTA: boolean }; const renderJoinCell = ({ sid, clusterId, kind, participantModes, -}: Session) => { + showActiveSessionsCTA, +}: renderJoinCellProps) => { const { joinable } = kinds[kind]; if (!joinable || participantModes.length === 0) { return ; @@ -119,6 +122,7 @@ const renderJoinCell = ({ sid={sid} clusterId={clusterId} participantModes={participantModes} + showCTA={showActiveSessionsCTA} /> ); @@ -132,6 +136,7 @@ function renderUsersCell({ parties }: Session) { type Props = { sessions: Session[]; pageSize?: number; + showActiveSessionsCTA: boolean; }; function participantMatcher( diff --git a/web/packages/teleport/src/Sessions/Sessions.story.test.tsx b/web/packages/teleport/src/Sessions/Sessions.story.test.tsx index aa46d4f7f4096..8276c7c69ed26 100644 --- a/web/packages/teleport/src/Sessions/Sessions.story.test.tsx +++ b/web/packages/teleport/src/Sessions/Sessions.story.test.tsx @@ -18,9 +18,14 @@ import React from 'react'; import { render } from 'design/utils/testing'; -import { Loaded } from './Sessions.story'; +import { Loaded, LoadedWithCTA } from './Sessions.story'; test('loaded', () => { const { container } = render(); expect(container.firstChild).toMatchSnapshot(); }); + +test('loaded with CTA', () => { + const { container } = render(); + expect(container.firstChild).toMatchSnapshot(); +}); diff --git a/web/packages/teleport/src/Sessions/Sessions.story.tsx b/web/packages/teleport/src/Sessions/Sessions.story.tsx index aaa35376d7b22..f83d49722a0e6 100644 --- a/web/packages/teleport/src/Sessions/Sessions.story.tsx +++ b/web/packages/teleport/src/Sessions/Sessions.story.tsx @@ -32,6 +32,22 @@ export function Loaded() { isFailed: false, message: '', }, + showActiveSessionsCTA: false, + }; + + return ; +} + +export function LoadedWithCTA() { + const props = { + sessions, + attempt: { + isSuccess: true, + isProcessing: false, + isFailed: false, + message: '', + }, + showActiveSessionsCTA: true, }; return ; diff --git a/web/packages/teleport/src/Sessions/Sessions.tsx b/web/packages/teleport/src/Sessions/Sessions.tsx index 01cd8a13b79e3..ad45b8d304f94 100644 --- a/web/packages/teleport/src/Sessions/Sessions.tsx +++ b/web/packages/teleport/src/Sessions/Sessions.tsx @@ -27,6 +27,8 @@ import useTeleport from 'teleport/useTeleport'; import useStickerClusterId from 'teleport/useStickyClusterId'; +import { ButtonLockedFeature } from 'teleport/components/ButtonLockedFeature'; + import SessionList from './SessionList'; import useSessions from './useSessions'; @@ -38,11 +40,18 @@ export default function Container() { } export function Sessions(props: ReturnType) { - const { attempt, sessions } = props; + const { attempt, sessions, showActiveSessionsCTA } = props; return ( - + Active Sessions + {showActiveSessionsCTA && ( + + + Join Active Sessions With Teleport Enterprise + + + )} {attempt.isFailed && {attempt.message} } {attempt.isProcessing && ( @@ -50,7 +59,12 @@ export function Sessions(props: ReturnType) { )} - {attempt.isSuccess && } + {attempt.isSuccess && ( + + )} ); } diff --git a/web/packages/teleport/src/Sessions/__snapshots__/Sessions.story.test.tsx.snap b/web/packages/teleport/src/Sessions/__snapshots__/Sessions.story.test.tsx.snap index 656ac00d54b18..81f8c4fbfebe0 100644 --- a/web/packages/teleport/src/Sessions/__snapshots__/Sessions.story.test.tsx.snap +++ b/web/packages/teleport/src/Sessions/__snapshots__/Sessions.story.test.tsx.snap @@ -202,6 +202,7 @@ exports[`loaded 1`] = ` margin-bottom: 24px; display: flex; align-items: center; + justify-content: space-between; flex-shrink: 0; border-bottom: 1px solid rgba(255,255,255,0.07); height: 56px; @@ -771,3 +772,863 @@ exports[`loaded 1`] = ` `; + +exports[`loaded with CTA 1`] = ` +.c3 { + box-sizing: border-box; + width: 340px; +} + +.c28 { + box-sizing: border-box; + width: 80px; + text-align: center; +} + +.c4 { + line-height: 1.5; + margin: 0; + display: inline-flex; + justify-content: center; + align-items: center; + box-sizing: border-box; + border: none; + border-radius: 4px; + cursor: pointer; + font-family: inherit; + font-weight: 600; + outline: none; + position: relative; + text-align: center; + text-decoration: none; + text-transform: uppercase; + transition: all 0.3s; + -webkit-font-smoothing: antialiased; + color: #000000; + background: #9F85FF; + min-height: 32px; + font-size: 12px; + padding: 0px 24px; + height: 36px; +} + +.c4:hover, +.c4:focus { + background: #B29DFF; +} + +.c4:active { + background: #C5B6FF; +} + +.c4:disabled { + background: rgba(255,255,255,0.12); + color: rgba(255,255,255,0.3); + cursor: auto; +} + +.c29 { + line-height: 1.5; + margin: 0; + display: inline-flex; + justify-content: center; + align-items: center; + box-sizing: border-box; + border: none; + border-radius: 4px; + cursor: pointer; + font-family: inherit; + font-weight: 600; + outline: none; + position: relative; + text-align: center; + text-decoration: none; + text-transform: uppercase; + transition: all 0.3s; + -webkit-font-smoothing: antialiased; + color: #FFFFFF; + background: rgba(255,255,255,0); + border: 1px solid rgba(255,255,255,0.36); + font-size: 10px; + min-height: 24px; + padding: 0px 16px; +} + +.c29:hover, +.c29:focus { + background: rgba(255,255,255,0.07); +} + +.c29:active { + background: rgba(255,255,255,0.13); +} + +.c29:disabled { + background: rgba(255,255,255,0.12); + color: rgba(255,255,255,0.3); + cursor: auto; +} + +.c8 { + display: inline-block; + transition: color 0.3s; + color: #FFFFFF; +} + +.c23 { + display: inline-block; + transition: color 0.3s; + color: #FFFFFF; + font-size: 16px; +} + +.c27 { + display: inline-block; + transition: color 0.3s; + color: #FFFFFF; + margin-right: 16px; + padding: 4px; + font-size: 16px; +} + +.c30 { + display: inline-block; + transition: color 0.3s; + color: #FFFFFF; + margin-left: 4px; + color: rgba(255,255,255,0.72); + font-size: 14px; +} + +.c21 { + align-items: center; + border: none; + cursor: pointer; + display: flex; + outline: none; + border-radius: 50%; + overflow: visible; + justify-content: center; + text-align: center; + flex: 0 0 auto; + background: transparent; + color: inherit; + transition: all 0.3s; + -webkit-font-smoothing: antialiased; + font-size: 16px; + height: 32px; + width: 32px; + margin-left: 0px; + margin-right: 0px; +} + +.c21 .c7 { + color: inherit; +} + +.c21:disabled { + color: rgba(255,255,255,0.36); +} + +.c21:disabled { + color: rgba(255,255,255,0.36); + cursor: default; +} + +.c21:hover:enabled, +.c21:focus:enabled { + background: rgba(255,255,255,0.13); +} + +.c21:active:enabled { + background: rgba(255,255,255,0.18); +} + +.c24 { + align-items: center; + border: none; + cursor: pointer; + display: flex; + outline: none; + border-radius: 50%; + overflow: visible; + justify-content: center; + text-align: center; + flex: 0 0 auto; + background: transparent; + color: inherit; + transition: all 0.3s; + -webkit-font-smoothing: antialiased; + font-size: 16px; + height: 32px; + width: 32px; + margin-left: 0px; +} + +.c24 .c7 { + color: inherit; +} + +.c24:disabled { + color: rgba(255,255,255,0.36); +} + +.c24:disabled { + color: rgba(255,255,255,0.36); + cursor: default; +} + +.c24:hover:enabled, +.c24:focus:enabled { + background: rgba(255,255,255,0.13); +} + +.c24:active:enabled { + background: rgba(255,255,255,0.18); +} + +.c19 { + overflow: hidden; + text-overflow: ellipsis; + font-weight: 400; + font-size: 12px; + line-height: 16px; + margin: 0px; + margin-right: 4px; + color: #FFFFFF; +} + +.c6 { + box-sizing: border-box; + display: flex; + align-items: center; +} + +.c17 { + box-sizing: border-box; + width: 100%; + display: flex; + justify-content: flex-end; +} + +.c18 { + box-sizing: border-box; + margin-right: 8px; + display: flex; + align-items: center; +} + +.c20 { + box-sizing: border-box; + display: flex; +} + +.c1 { + box-sizing: border-box; + margin-bottom: 24px; + display: flex; + align-items: center; + justify-content: space-between; + flex-shrink: 0; + border-bottom: 1px solid rgba(255,255,255,0.07); + height: 56px; + margin-left: -40px; + margin-right: -40px; + padding-left: 40px; + padding-right: 40px; +} + +.c2 { + overflow: hidden; + text-overflow: ellipsis; + font-weight: 300; + font-size: 22px; + line-height: 32px; + margin: 0px; + white-space: nowrap; +} + +.c0 { + box-sizing: border-box; + padding-left: 40px; + padding-right: 40px; + display: flex; + width: 100%; + height: 100%; + flex-direction: column; +} + +.c0::after { + content: ' '; + padding-bottom: 24px; +} + +.c5 { + text-transform: none; + width: 100%; + padding-top: 12px; + padding-bottom: 12px; + font-size: 12px; +} + +.c9 { + color: inherit; + font-weight: 500; + font-size: 15px; + margin-right: 4px; +} + +.c25 { + background: #222C59; + border-collapse: collapse; + border-spacing: 0; + border-style: hidden; + font-size: 12px; + width: 100%; + border-top-left-radius: 0px; + border-top-right-radius: 0px; + border-bottom-right-radius: 8px; + border-bottom-left-radius: 8px; +} + +.c25 > thead > tr > th, +.c25 > tbody > tr > th, +.c25 > tfoot > tr > th, +.c25 > thead > tr > td, +.c25 > tbody > tr > td, +.c25 > tfoot > tr > td { + padding: 8px 8px; + vertical-align: middle; +} + +.c25 > thead > tr > th:first-child, +.c25 > tbody > tr > th:first-child, +.c25 > tfoot > tr > th:first-child, +.c25 > thead > tr > td:first-child, +.c25 > tbody > tr > td:first-child, +.c25 > tfoot > tr > td:first-child { + padding-left: 24px; +} + +.c25 > thead > tr > th:last-child, +.c25 > tbody > tr > th:last-child, +.c25 > tfoot > tr > th:last-child, +.c25 > thead > tr > td:last-child, +.c25 > tbody > tr > td:last-child, +.c25 > tfoot > tr > td:last-child { + padding-right: 24px; +} + +.c25 > tbody > tr > td { + vertical-align: middle; +} + +.c25 > thead > tr > th { + background: rgba(255,255,255,0.07); + color: #FFFFFF; + cursor: pointer; + font-size: 10px; + font-weight: 400; + padding-bottom: 0; + padding-top: 0; + text-align: left; + opacity: 0.75; + text-transform: uppercase; + white-space: nowrap; +} + +.c25 > thead > tr > th .c7 { + font-weight: bold; + font-size: 8px; + margin-left: 8px; +} + +.c25 > tbody > tr > td { + color: #FFFFFF; + line-height: 16px; +} + +.c25 tbody tr { + border-bottom: 1px solid rgb(49,58,100); +} + +.c25 tbody tr:hover { + background-color: rgba(255,255,255,0.07); +} + +.c11 { + padding: 16px 24px; + display: flex; + height: 24px; + flex-shrink: 0; + align-items: center; + justify-content: space-between; + background: #222C59; +} + +.c10 { + box-shadow: 0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px rgba(0,0,0,0.14),0px 1px 3px rgba(0,0,0,0.12); + overflow: hidden; + border-radius: 8px; +} + +.c22 .c7 { + font-size: 20px; +} + +.c22 .c7:before { + padding-left: 1px; +} + +.c16 { + position: relative; + height: 100%; + right: 0; + display: flex; + align-items: center; + justify-content: center; + background: rgba(255,255,255,0.07); + border-radius: 200px; +} + +.c15 { + position: absolute; + height: 100%; + right: 0; + display: flex; + align-items: center; + justify-content: center; + background: #222C59; + border-radius: 200px; +} + +.c13 { + position: relative; + display: flex; + overflow: hidden; + width: 100%; + border-radius: 200px; + height: 32px; + background: transparent; +} + +.c12 { + background: #0C143D; + border-radius: 200px; + width: 100%; + height: 32px; +} + +.c14 { + border: none; + outline: none; + box-sizing: border-box; + height: 100%; + font-size: 12px; + width: 100%; + transition: all 0.2s; + padding-left: 16px; + padding-right: 16px; + color: #FFFFFF; + background: #0C143D; + padding-right: 184px; +} + +.c14:hover, +.c14:focus, +.c14:active { + color: #FFFFFF; + background: rgba(255,255,255,0.07); +} + +.c14::placeholder { + color: rgba(255,255,255,0.54); + font-size: 12px; +} + +.c26 tbody > tr > td { + vertical-align: middle; +} + +
+
+
+ Active Sessions +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Type + + + + + Name + + + + Session ID + + Users + + + Duration + + + +
+ + + minikube + + 7174aded-340a-4863-b661-7ba52aeb22c8 + + lisa2 + + 59 minutes + +
+ + + im-a-nodename + + c7befbb4-3885-4d08-a466-de832a73c3d4 + + lisa2 + + 5 seconds + +
+ +
+
+ + + im-a-nodename-2 + + b204924e-6b74-5d92-89ea-d95043a969f1 + + lisa3 + + 5 seconds + +
+ +
+
+ + + im-a-nodename-3 + + 8830cfe5-369e-5485-9c3d-19cc50e6f548 + + lisa2 + + 5 seconds + +
+ +
+
+ + + desktop-2 + + acacfbb4-3885-4d08-a466-de832a73ffac + + lisa2 + + 5 seconds + +
+ + + databse-32 + + 2314fbb4-3885-4d08-a466-de832a731222 + + lisa2 + + 3 minutes + +
+ + + grafana + + cafefbb4-3885-4d08-a466-de832a7313131 + + lisa2 + + 13 minutes + +
+
+
+`; diff --git a/web/packages/teleport/src/Sessions/useSessions.ts b/web/packages/teleport/src/Sessions/useSessions.ts index 916b8a0c831c6..2118dbd7d3285 100644 --- a/web/packages/teleport/src/Sessions/useSessions.ts +++ b/web/packages/teleport/src/Sessions/useSessions.ts @@ -51,5 +51,6 @@ export default function useSessions(ctx: Ctx, clusterId: string) { return { attempt, sessions, + showActiveSessionsCTA: ctx.ctas.activeSessions, }; } diff --git a/web/packages/teleport/src/Support/Support.story.test.tsx b/web/packages/teleport/src/Support/Support.story.test.tsx index 29cd6e7bab883..d317549c96278 100644 --- a/web/packages/teleport/src/Support/Support.story.test.tsx +++ b/web/packages/teleport/src/Support/Support.story.test.tsx @@ -18,7 +18,12 @@ import React from 'react'; import { render } from 'design/utils/testing'; -import { SupportOSS, SupportCloud, SupportEnterprise } from './Support.story'; +import { + SupportOSS, + SupportCloud, + SupportEnterprise, + SupportWithCTA, +} from './Support.story'; test('support OSS', () => { const { container } = render(); @@ -34,3 +39,8 @@ test('support Enterprise', () => { const { container } = render(); expect(container.firstChild).toMatchSnapshot(); }); + +test('support Enterprise with CTA', () => { + const { container } = render(); + expect(container.firstChild).toMatchSnapshot(); +}); diff --git a/web/packages/teleport/src/Support/Support.story.tsx b/web/packages/teleport/src/Support/Support.story.tsx index 3e13725c558ef..aaf4c3436157d 100644 --- a/web/packages/teleport/src/Support/Support.story.tsx +++ b/web/packages/teleport/src/Support/Support.story.tsx @@ -30,6 +30,10 @@ export const SupportEnterprise = () => ( ); +export const SupportWithCTA = () => ( + +); + export const SupportWithTunnelAddress = () => ( ); @@ -41,4 +45,5 @@ const props: Props = { isEnterprise: false, isCloud: false, tunnelPublicAddress: null, + showPremiumSupportCTA: false, }; diff --git a/web/packages/teleport/src/Support/Support.tsx b/web/packages/teleport/src/Support/Support.tsx index 37965c1f398d5..57f62fbc1254b 100644 --- a/web/packages/teleport/src/Support/Support.tsx +++ b/web/packages/teleport/src/Support/Support.tsx @@ -23,6 +23,7 @@ import styled from 'styled-components'; import { FeatureBox } from 'teleport/components/Layout'; import useTeleport from 'teleport/useTeleport'; import cfg from 'teleport/config'; +import { ButtonLockedFeature } from 'teleport/components/ButtonLockedFeature'; export default function Container({ children, @@ -38,6 +39,7 @@ export default function Container({ isEnterprise={cfg.isEnterprise} tunnelPublicAddress={cfg.tunnelPublicAddress} isCloud={cfg.isCloud} + showPremiumSupportCTA={ctx.ctas.premiumSupport} children={children} /> ); @@ -51,6 +53,7 @@ export const Support = ({ tunnelPublicAddress, isCloud, children, + showPremiumSupportCTA, }: Props) => { const docs = getDocUrls(authVersion, isEnterprise); @@ -60,7 +63,7 @@ export const Support = ({
} /> - {isEnterprise && ( + {isEnterprise && !showPremiumSupportCTA && ( + {isEnterprise && showPremiumSupportCTA && ( + + Unlock Premium Support w/Enterprise + + )}
} /> @@ -236,4 +244,5 @@ export type Props = { isCloud: boolean; tunnelPublicAddress?: string; children?: React.ReactNode; + showPremiumSupportCTA: boolean; }; diff --git a/web/packages/teleport/src/Support/__snapshots__/Support.story.test.tsx.snap b/web/packages/teleport/src/Support/__snapshots__/Support.story.test.tsx.snap index 23d9527ec980e..7e3a07d6f4986 100644 --- a/web/packages/teleport/src/Support/__snapshots__/Support.story.test.tsx.snap +++ b/web/packages/teleport/src/Support/__snapshots__/Support.story.test.tsx.snap @@ -770,6 +770,462 @@ exports[`support Enterprise 1`] = ` `; +exports[`support Enterprise with CTA 1`] = ` +.c3 { + box-sizing: border-box; +} + +.c9 { + line-height: 1.5; + margin: 0; + display: inline-flex; + justify-content: center; + align-items: center; + box-sizing: border-box; + border: none; + border-radius: 4px; + cursor: pointer; + font-family: inherit; + font-weight: 600; + outline: none; + position: relative; + text-align: center; + text-decoration: none; + text-transform: uppercase; + transition: all 0.3s; + -webkit-font-smoothing: antialiased; + color: #000000; + background: #9F85FF; + min-height: 32px; + font-size: 12px; + padding: 0px 24px; +} + +.c9:hover, +.c9:focus { + background: #B29DFF; +} + +.c9:active { + background: #C5B6FF; +} + +.c9:disabled { + background: rgba(255,255,255,0.12); + color: rgba(255,255,255,0.3); + cursor: auto; +} + +.c6 { + display: inline-block; + transition: color 0.3s; + color: #FFFFFF; +} + +.c1 { + box-sizing: border-box; + padding-bottom: 40px; + padding-top: 4px; + padding-left: 32px; + padding-right: 32px; + background-color: #222C59; + box-shadow: 0px 3px 5px -1px rgba(0,0,0,0.2),0px 6px 10px rgba(0,0,0,0.14),0px 1px 18px rgba(0,0,0,0.12); + border-radius: 8px; +} + +.c5 { + overflow: hidden; + text-overflow: ellipsis; + font-size: 18px; + margin: 0px; + padding-right: 8px; +} + +.c7 { + overflow: hidden; + text-overflow: ellipsis; + text-transform: uppercase; + margin: 0px; +} + +.c14 { + overflow: hidden; + text-overflow: ellipsis; + text-transform: uppercase; + margin: 0px; + margin-bottom: 24px; + font-weight: 600; +} + +.c16 { + overflow: hidden; + text-overflow: ellipsis; + font-weight: 600; + font-size: 12px; + line-height: 16px; + margin: 0px; +} + +.c17 { + overflow: hidden; + text-overflow: ellipsis; + font-weight: 400; + font-size: 12px; + line-height: 16px; + margin: 0px; +} + +.c2 { + box-sizing: border-box; + display: flex; + justify-content: space-between; + flex-wrap: wrap; +} + +.c11 { + box-sizing: border-box; + display: flex; + align-items: center; +} + +.c15 { + box-sizing: border-box; + margin-bottom: 16px; + display: flex; +} + +.c0 { + box-sizing: border-box; + padding-top: 24px; + padding-left: 40px; + padding-right: 40px; + display: flex; + width: 100%; + height: 100%; + flex-direction: column; +} + +.c0::after { + content: ' '; + padding-bottom: 24px; +} + +.c10 { + text-transform: none; + width: 100%; + padding-top: 12px; + padding-bottom: 12px; + font-size: 12px; +} + +.c12 { + color: inherit; + font-weight: 500; + font-size: 15px; + margin-right: 4px; +} + +.c13 { + box-sizing: border-box; + margin-top: 24px; + padding-left: 32px; + padding-right: 32px; + padding-top: 24px; + padding-bottom: 24px; + border-radius: 8px; + border: 1px solid rgba(255,255,255,0.13); +} + +.c8 { + display: block; + color: #FFFFFF; + border-radius: 4px; + text-decoration: none; + margin-bottom: 8px; + padding: 4px 8px; + transition: all 0.3s; + font-weight: 400; + font-size: 12px; + line-height: 16px; +} + +.c8:hover, +.c8:focus { + background: rgba(255,255,255,0.07); +} + +.c4 { + box-sizing: border-box; + margin-bottom: 16px; + margin-top: 24px; + padding-bottom: 8px; + width: 210px; + display: flex; + align-items: center; + border-bottom: 1px solid rgba(255,255,255,0.18); +} + +
+
+
+
+
+
+ +
+
+ Support +
+
+ + Ask the Community Questions + + + Request a New Feature + + + Send Product Feedback + + +
+ +
+
+
+ +
+
+ Troubleshooting +
+
+ + Monitoring & Debugging + +
+
+
+
+ +
+
+ Updates +
+
+ + Product Changelog + + + Teleport Blog + +
+
+
+
+
+ Cluster Information +
+
+
+ Cluster Name + : +
+
+ test +
+
+
+
+ Teleport Version + : +
+
+ 4.4.0-dev +
+
+
+
+ Public Address + : +
+
+ localhost:3080 +
+
+
+
+`; + exports[`support OSS 1`] = ` .c3 { box-sizing: border-box; diff --git a/web/packages/teleport/src/components/ButtonLockedFeature/ButtonLockedFeature.tsx b/web/packages/teleport/src/components/ButtonLockedFeature/ButtonLockedFeature.tsx new file mode 100644 index 0000000000000..b70e81875cf9e --- /dev/null +++ b/web/packages/teleport/src/components/ButtonLockedFeature/ButtonLockedFeature.tsx @@ -0,0 +1,55 @@ +/* +Copyright 2023 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import styled from 'styled-components'; +import { ButtonPrimary } from 'design/Button'; +import { Unlock } from 'design/Icon'; +import Flex from 'design/Flex'; + +export type Props = { + children: React.ReactNode; + noIcon?: boolean; + [index: string]: any; +}; + +const salesUrl = 'https://goteleport.com/signup/enterprise/'; + +export function ButtonLockedFeature({ children, noIcon = false, ...rest }) { + return ( + window.open(salesUrl, 'blank')} {...rest}> + + {!noIcon && } + {children} + + + ); +} + +const StyledButton = styled(ButtonPrimary)` + text-transform: none; + width: 100%; + padding-top: 12px; + padding-bottom: 12px; + font-size: 12px; +`; + +const UnlockIcon = styled(Unlock)` + color: inherit; + font-weight: 500; + font-size: 15px; + margin-right: 4px; +`; diff --git a/web/packages/teleport/src/components/ButtonLockedFeature/index.ts b/web/packages/teleport/src/components/ButtonLockedFeature/index.ts new file mode 100644 index 0000000000000..fa3c8efca2842 --- /dev/null +++ b/web/packages/teleport/src/components/ButtonLockedFeature/index.ts @@ -0,0 +1,17 @@ +/* +Copyright 2023 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export { ButtonLockedFeature } from './ButtonLockedFeature'; diff --git a/web/packages/teleport/src/teleportContext.tsx b/web/packages/teleport/src/teleportContext.tsx index 23f7aa0c4c1a3..3dbd84e5dbda7 100644 --- a/web/packages/teleport/src/teleportContext.tsx +++ b/web/packages/teleport/src/teleportContext.tsx @@ -57,13 +57,21 @@ class TeleportContext implements types.Context { desktopService = desktopService; userGroupService = userGroupService; mfaService = new MfaService(); + isEnterprise = cfg.isEnterprise; isCloud = cfg.isCloud; - automaticUpgradesEnabled = false; - agentService = agentService; + // No CTA is currently shown + ctas = { + authConnectors: false, + activeSessions: false, + accessRequests: false, + premiumSupport: false, + trustedDevices: false, + }; + // init fetches data required for initial rendering of components. // The caller of this function provides the try/catch // block.