forked from extern/bruno
feat: golden edition modal
This commit is contained in:
parent
2608ec035e
commit
0db6103b69
@ -0,0 +1,20 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const StyledWrapper = styled.div`
|
||||
color: ${(props) => props.theme.text};
|
||||
.collection-options {
|
||||
svg {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.label {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledWrapper;
|
177
packages/bruno-app/src/components/Sidebar/GoldenEdition/index.js
Normal file
177
packages/bruno-app/src/components/Sidebar/GoldenEdition/index.js
Normal file
@ -0,0 +1,177 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Modal from 'components/Modal/index';
|
||||
import { PostHog } from 'posthog-node';
|
||||
import { uuid } from 'utils/common';
|
||||
import { IconHeart, IconUser, IconUsers } from '@tabler/icons';
|
||||
import platformLib from 'platform';
|
||||
import StyledWrapper from './StyledWrapper';
|
||||
|
||||
let posthogClient = null;
|
||||
const posthogApiKey = 'phc_7gtqSrrdZRohiozPMLIacjzgHbUlhalW1Bu16uYijMR';
|
||||
const getPosthogClient = () => {
|
||||
if (posthogClient) {
|
||||
return posthogClient;
|
||||
}
|
||||
|
||||
posthogClient = new PostHog(posthogApiKey);
|
||||
return posthogClient;
|
||||
};
|
||||
const getAnonymousTrackingId = () => {
|
||||
let id = localStorage.getItem('bruno.anonymousTrackingId');
|
||||
|
||||
if (!id || !id.length || id.length !== 21) {
|
||||
id = uuid();
|
||||
localStorage.setItem('bruno.anonymousTrackingId', id);
|
||||
}
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
const HeartIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="currentColor"
|
||||
className="flex-shrink-0 w-5 h-4 text-yellow-600"
|
||||
viewBox="0 0 16 16"
|
||||
>
|
||||
<path fillRule="evenodd" d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314z" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const CheckIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
className="flex-shrink-0 w-5 h-5 text-green-500"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
|
||||
clipRule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
const GoldenEdition = ({ onClose }) => {
|
||||
useEffect(() => {
|
||||
const anonymousId = getAnonymousTrackingId();
|
||||
const client = getPosthogClient();
|
||||
client.capture({
|
||||
distinctId: anonymousId,
|
||||
event: 'golden-edition-modal-opened',
|
||||
properties: {
|
||||
os: platformLib.os.family
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
const goldenEditionBuyClick = () => {
|
||||
const anonymousId = getAnonymousTrackingId();
|
||||
const client = getPosthogClient();
|
||||
client.capture({
|
||||
distinctId: anonymousId,
|
||||
event: 'golden-edition-buy-clicked',
|
||||
properties: {
|
||||
os: platformLib.os.family
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const goldenEditon = [
|
||||
'Inbuilt Bru File Explorer',
|
||||
'Visual Git (Like Gitlens for Vscode)',
|
||||
'GRPC, Websocket, SocketIO, MQTT',
|
||||
'Intergration with Secret Managers',
|
||||
'Load Data from File for Collection Run',
|
||||
'Developer Tools',
|
||||
'OpenAPI Designer',
|
||||
'Performance/Load Testing',
|
||||
'Inbuilt Terminal',
|
||||
'Custom Themes'
|
||||
];
|
||||
|
||||
const [pricingOption, setPricingOption] = useState('individuals');
|
||||
|
||||
const handlePricingOptionChange = (option) => {
|
||||
setPricingOption(option);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<Modal size="sm" title={'Golden Edition'} handleCancel={onClose} hideFooter={true}>
|
||||
<div className="flex flex-col text-gray-900 bg-white w-full">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-lg font-semibold">Golden Edition</h3>
|
||||
<a
|
||||
onClick={() => {
|
||||
goldenEditionBuyClick();
|
||||
window.open('https://www.usebruno.com/pricing', '_blank');
|
||||
}}
|
||||
target="_blank"
|
||||
className="flex text-white bg-yellow-600 hover:bg-yellow-700 font-medium rounded-lg text-sm px-4 py-2 text-center cursor-pointer"
|
||||
>
|
||||
<IconHeart size={18} strokeWidth={1.5} />{' '}
|
||||
<span className="ml-2">{pricingOption === 'individuals' ? 'Buy' : 'Subscribe'}</span>
|
||||
</a>
|
||||
</div>
|
||||
{pricingOption === 'individuals' ? (
|
||||
<div>
|
||||
<div className="my-4">
|
||||
<span className="text-3xl font-extrabold">$19</span>
|
||||
</div>
|
||||
<p className="bg-yellow-200 rounded-md px-2 py-1 mb-2 inline-flex text-sm">One Time Payment</p>
|
||||
<p className="text-sm">perpetual license for 2 devices, with 2 years of updates</p>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<div className="my-4">
|
||||
<span className="text-3xl font-extrabold">$2</span>
|
||||
</div>
|
||||
<p>/user/month</p>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className="flex items-center justify-between my-8 w-40 bg-gray-200 rounded-full p-1"
|
||||
style={{ width: '24rem' }}
|
||||
>
|
||||
<div
|
||||
className={`cursor-pointer w-1/2 h-8 flex items-center justify-center rounded-full ${
|
||||
pricingOption === 'individuals' ? 'bg-white text-gray-900 font-medium' : 'text-gray-500'
|
||||
}`}
|
||||
onClick={() => handlePricingOptionChange('individuals')}
|
||||
>
|
||||
<IconUser className="text-gray-500 mr-2 icon" size={16} strokeWidth={1.5} /> Individuals
|
||||
</div>
|
||||
<div
|
||||
className={`cursor-pointer w-1/2 h-8 flex items-center justify-center rounded-full ${
|
||||
pricingOption === 'organizations' ? 'bg-white text-gray-900 font-medium' : 'text-gray-500'
|
||||
}`}
|
||||
onClick={() => handlePricingOptionChange('organizations')}
|
||||
>
|
||||
<IconUsers className="text-gray-500 mr-2 icon" size={16} strokeWidth={1.5} /> Organizations
|
||||
</div>
|
||||
</div>
|
||||
<ul role="list" className="space-y-3 text-left">
|
||||
<li className="flex items-center space-x-3">
|
||||
<HeartIcon />
|
||||
<span>Support Bruno's Development</span>
|
||||
</li>
|
||||
{goldenEditon.map((item, index) => (
|
||||
<li className="flex items-center space-x-3" key={index}>
|
||||
<CheckIcon />
|
||||
<span>{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</Modal>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default GoldenEdition;
|
@ -4,19 +4,21 @@ import StyledWrapper from './StyledWrapper';
|
||||
import GitHubButton from 'react-github-btn';
|
||||
import Preferences from 'components/Preferences';
|
||||
import Cookies from 'components/Cookies';
|
||||
import GoldenEdition from './GoldenEdition';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { IconSettings, IconCookie } from '@tabler/icons';
|
||||
import { IconSettings, IconCookie, IconHeart } from '@tabler/icons';
|
||||
import { updateLeftSidebarWidth, updateIsDragging, showPreferences } from 'providers/ReduxStore/slices/app';
|
||||
import { useTheme } from 'providers/Theme';
|
||||
|
||||
const MIN_LEFT_SIDEBAR_WIDTH = 222;
|
||||
const MIN_LEFT_SIDEBAR_WIDTH = 221;
|
||||
const MAX_LEFT_SIDEBAR_WIDTH = 600;
|
||||
|
||||
const Sidebar = () => {
|
||||
const leftSidebarWidth = useSelector((state) => state.app.leftSidebarWidth);
|
||||
const preferencesOpen = useSelector((state) => state.app.showPreferences);
|
||||
const [goldenEditonOpen, setGoldenEditonOpen] = useState(false);
|
||||
|
||||
const [asideWidth, setAsideWidth] = useState(leftSidebarWidth);
|
||||
const [cookiesOpen, setCookiesOpen] = useState(false);
|
||||
@ -79,6 +81,7 @@ const Sidebar = () => {
|
||||
return (
|
||||
<StyledWrapper className="flex relative h-screen">
|
||||
<aside>
|
||||
{goldenEditonOpen && <GoldenEdition onClose={() => setGoldenEditonOpen(false)} />}
|
||||
<div className="flex flex-row h-screen w-full">
|
||||
{preferencesOpen && <Preferences onClose={() => dispatch(showPreferences(false))} />}
|
||||
{cookiesOpen && <Cookies onClose={() => setCookiesOpen(false)} />}
|
||||
@ -103,6 +106,12 @@ const Sidebar = () => {
|
||||
className="mr-2 hover:text-gray-700"
|
||||
onClick={() => setCookiesOpen(true)}
|
||||
/>
|
||||
<IconHeart
|
||||
size={18}
|
||||
strokeWidth={1.5}
|
||||
className="mr-2 hover:text-gray-700"
|
||||
onClick={() => setGoldenEditonOpen(true)}
|
||||
/>
|
||||
</div>
|
||||
<div className="pl-1" style={{ position: 'relative', top: '3px' }}>
|
||||
{/* This will get moved to home page */}
|
||||
|
@ -107,7 +107,7 @@ app.on('ready', async () => {
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler((details) => {
|
||||
require('electron').shell.openExternal(details.url);
|
||||
return { action: 'allow' };
|
||||
return { action: 'deny' };
|
||||
});
|
||||
|
||||
// register all ipc handlers
|
||||
|
Loading…
Reference in New Issue
Block a user