@prisma/client#notionSites TypeScript Examples
The following examples show how to use
@prisma/client#notionSites.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SiteCard.tsx From pagely with MIT License | 6 votes |
SiteCard: React.FC<{ siteData: notionSites }> = ({ siteData }) => {
const { siteName, siteDesc, id, ogImageUrl } = siteData;
return (
<div className='max-w-[400px] mx-auto'>
<Link href={`/notion-site/${id}`}>
<a>
<div className='mb-8 transition-all duration-500 border border-gray-300 rounded hover:shadow-xl'>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={ogImageUrl || '/no-og-image.png'}
alt={siteName}
className='object-cover w-full h-32 mx-auto rounded-t'
/>
<div className='px-3 pt-4 pb-5'>
<h2 className='text-2xl font-bold'>{siteName}</h2>
<p className='mt-1 text-base text-gray-600'>
{truncate(siteDesc, { length: 50 }) ||
'No description ¯\\_(ツ)_/¯'}
</p>
</div>
</div>
</a>
</Link>
</div>
);
}
Example #2
Source File: index.tsx From pagely with MIT License | 5 votes |
Page = () => {
const router = useRouter();
const { data } = useClerkSWR<notionSites>(
`/api/getSiteData/notion/?siteId=${router.query.notionId}`
);
return (
<div>
<SidebarLayout activeTab='setup'>
<h1 className='text-4xl font-extrabold capitalize'>
{data?.siteName || 'Just a second...'}
</h1>
<p className='mt-4 text-gray-800 font-base'>
{data?.siteDesc ||
'Crunching the data for you. Please give a second.'}
</p>
<div className='flex flex-wrap mt-8'>
<a
href={data?.notionPageUrl}
target='_blank'
rel='noopener noreferrer'>
<div className='inline-block px-3 py-4 my-2 mr-3 transition-all bg-yellow-100 border rounded-md hover:shadow hover:border-yellow-500'>
<SiNotion className='relative inline-block mx-2 bottom-[2px]' />
Open in Notion
</div>
</a>
<a
href={
'https://developers.google.com/speed/pagespeed/insights/?url=https://' +
data?.subdomain +
'.pagely.site'
}
target='_blank'
rel='noopener noreferrer'>
<div className='inline-block px-3 py-4 my-2 mr-3 transition-all bg-blue-100 border rounded-md hover:shadow hover:border-blue-500'>
<SiLighthouse className='relative inline-block mx-2 bottom-[2px]' />
Open Lighthouse score
</div>
</a>
<a
href={'https://' + data?.subdomain + '.pagely.site'}
target='_blank'
rel='noopener noreferrer'>
<div className='inline-block px-3 py-4 my-2 mr-3 transition-all bg-green-100 border rounded-md hover:shadow hover:border-green-500'>
<VscGlobe className='relative inline-block mx-2 bottom-[2px]' />
Open website
</div>
</a>
</div>
</SidebarLayout>
</div>
);
}
Example #3
Source File: TwitterPreview.tsx From pagely with MIT License | 4 votes |
TwitterPreview: React.FC<{ data: notionSites }> = ({ data }) => {
const [isImageLoading, setIsImageLoading] = useState<boolean>(true);
const { firstName, primaryEmailAddress } = useUser();
return (
<div>
<div className='w-full max-w-xl px-5 py-3 border border-gray-300 rounded-2xl'>
<div className='flex'>
<div className='mr-2 w-14'>
<Image
src={Elon}
alt='Elon'
className='object-cover rounded-full'
/>
</div>
<div>
<div className='flex space-x-1'>
<span className='font-bold'>Elon Musk</span>
<span className='text-twitter-blue' title='Verified account'>
<svg
className='w-6 h-6'
fill='currentColor'
viewBox='0 0 24 24'
aria-label='Verified account'>
<g>
<path d='M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z' />
</g>
</svg>
</span>
</div>
<div className='leading-4 text-gray-500'>@elonmusk</div>
</div>
<div className='ml-auto text-twitter-blue'>
<svg viewBox='0 0 24 24' fill='currentColor' className='w-6 h-6'>
<g>
<path d='M23.643 4.937c-.835.37-1.732.62-2.675.733.962-.576 1.7-1.49 2.048-2.578-.9.534-1.897.922-2.958 1.13-.85-.904-2.06-1.47-3.4-1.47-2.572 0-4.658 2.086-4.658 4.66 0 .364.042.718.12 1.06-3.873-.195-7.304-2.05-9.602-4.868-.4.69-.63 1.49-.63 2.342 0 1.616.823 3.043 2.072 3.878-.764-.025-1.482-.234-2.11-.583v.06c0 2.257 1.605 4.14 3.737 4.568-.392.106-.803.162-1.227.162-.3 0-.593-.028-.877-.082.593 1.85 2.313 3.198 4.352 3.234-1.595 1.25-3.604 1.995-5.786 1.995-.376 0-.747-.022-1.112-.065 2.062 1.323 4.51 2.093 7.14 2.093 8.57 0 13.255-7.098 13.255-13.254 0-.2-.005-.402-.014-.602.91-.658 1.7-1.477 2.323-2.41z' />
</g>
</svg>
</div>
</div>
<div className='py-3'>
<p className='text-lg'>
Check this website out. Made by{' '}
{firstName || primaryEmailAddress.emailAddress.split('@')[0]}
</p>
<p className='text-lg text-twitter-blue'>
https://{data?.subdomain}.pagely.site
</p>
<div className='my-2 w-[90%] hover:bg-gray-100 cursor-pointer'>
<div>
{data?.ogImageUrl !== 'https://no-og.image' && (
<>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={
data?.ogImageUrl ||
'https://ogimage.glitch.me/i/' +
encodeURIComponent(data?.siteName)
}
alt={data?.siteName}
className='rounded-t-xl'
onLoad={() => setIsImageLoading(false)}
/>
{isImageLoading && (
<Skeleton
height='240px'
className='!rounded-t-xl w-[90%]'
/>
)}
</>
)}
<div
className={`px-2 py-3 border border-gray-400 bg-gray-50/10 ${
data?.ogImageUrl == 'https://no-og.image'
? 'rounded-md'
: 'rounded-b-xl'
}`}>
<h3 className='font-bold text-gray-600'>
{data?.siteName || 'OG title loading'}
</h3>
<div className='text-base text-gray-400'>
{data?.siteDesc || 'OG description loading'}
</div>
</div>
</div>
</div>
<div className='flex'>
<p className='pt-1 text-gray-500'>1:57 PM · Feb 4, 2021</p>
<svg
className='w-6 h-6 ml-auto text-gray-500'
fill='currentColor'
viewBox='0 0 24 24'>
<g>
<path d='M12 18.042c-.553 0-1-.447-1-1v-5.5c0-.553.447-1 1-1s1 .447 1 1v5.5c0 .553-.447 1-1 1z' />
<circle cx={12} cy='8.042' r='1.25' />
<path d='M12 22.75C6.072 22.75 1.25 17.928 1.25 12S6.072 1.25 12 1.25 22.75 6.072 22.75 12 17.928 22.75 12 22.75zm0-20C6.9 2.75 2.75 6.9 2.75 12S6.9 21.25 12 21.25s9.25-4.15 9.25-9.25S17.1 2.75 12 2.75z' />
</g>
</svg>
</div>
</div>
<div className='flex pt-3 space-x-5 text-gray-500 border-t border-gray-300'>
<div className='flex space-x-2'>
<svg
viewBox='0 0 24 24'
fill='currentColor'
className='w-6 h-6'
style={{}}>
<g>
<path d='M12 21.638h-.014C9.403 21.59 1.95 14.856 1.95 8.478c0-3.064 2.525-5.754 5.403-5.754 2.29 0 3.83 1.58 4.646 2.73.814-1.148 2.354-2.73 4.645-2.73 2.88 0 5.404 2.69 5.404 5.755 0 6.376-7.454 13.11-10.037 13.157H12zM7.354 4.225c-2.08 0-3.903 1.988-3.903 4.255 0 5.74 7.034 11.596 8.55 11.658 1.518-.062 8.55-5.917 8.55-11.658 0-2.267-1.823-4.255-3.903-4.255-2.528 0-3.94 2.936-3.952 2.965-.23.562-1.156.562-1.387 0-.014-.03-1.425-2.965-3.954-2.965z' />
</g>
</svg>
<span>783.9k</span>
</div>
<div className='flex space-x-2'>
<svg viewBox='0 0 24 24' fill='currentColor' className='w-6 h-6'>
<g>
<path d='M14.046 2.242l-4.148-.01h-.002c-4.374 0-7.8 3.427-7.8 7.802 0 4.098 3.186 7.206 7.465 7.37v3.828c0 .108.044.286.12.403.142.225.384.347.632.347.138 0 .277-.038.402-.118.264-.168 6.473-4.14 8.088-5.506 1.902-1.61 3.04-3.97 3.043-6.312v-.017c-.006-4.367-3.43-7.787-7.8-7.788zm3.787 12.972c-1.134.96-4.862 3.405-6.772 4.643V16.67c0-.414-.335-.75-.75-.75h-.396c-3.66 0-6.318-2.476-6.318-5.886 0-3.534 2.768-6.302 6.3-6.302l4.147.01h.002c3.532 0 6.3 2.766 6.302 6.296-.003 1.91-.942 3.844-2.514 5.176z' />
</g>
</svg>
<span>139.7k</span>
</div>
<div className='hidden space-x-2 sm:flex'>
<svg
viewBox='0 0 24 24'
fill='currentColor'
className='w-6 h-6'
style={{}}>
<g>
<path d='M11.96 14.945c-.067 0-.136-.01-.203-.027-1.13-.318-2.097-.986-2.795-1.932-.832-1.125-1.176-2.508-.968-3.893s.942-2.605 2.068-3.438l3.53-2.608c2.322-1.716 5.61-1.224 7.33 1.1.83 1.127 1.175 2.51.967 3.895s-.943 2.605-2.07 3.438l-1.48 1.094c-.333.246-.804.175-1.05-.158-.246-.334-.176-.804.158-1.05l1.48-1.095c.803-.592 1.327-1.463 1.476-2.45.148-.988-.098-1.975-.69-2.778-1.225-1.656-3.572-2.01-5.23-.784l-3.53 2.608c-.802.593-1.326 1.464-1.475 2.45-.15.99.097 1.975.69 2.778.498.675 1.187 1.15 1.992 1.377.4.114.633.528.52.928-.092.33-.394.547-.722.547z' />
<path d='M7.27 22.054c-1.61 0-3.197-.735-4.225-2.125-.832-1.127-1.176-2.51-.968-3.894s.943-2.605 2.07-3.438l1.478-1.094c.334-.245.805-.175 1.05.158s.177.804-.157 1.05l-1.48 1.095c-.803.593-1.326 1.464-1.475 2.45-.148.99.097 1.975.69 2.778 1.225 1.657 3.57 2.01 5.23.785l3.528-2.608c1.658-1.225 2.01-3.57.785-5.23-.498-.674-1.187-1.15-1.992-1.376-.4-.113-.633-.527-.52-.927.112-.4.528-.63.926-.522 1.13.318 2.096.986 2.794 1.932 1.717 2.324 1.224 5.612-1.1 7.33l-3.53 2.608c-.933.693-2.023 1.026-3.105 1.026z' />
</g>
</svg>
<span>Copy link to tweet</span>
</div>
</div>
</div>
</div>
);
}
Example #4
Source File: SidebarLayout.tsx From pagely with MIT License | 4 votes |
SidebarLayout: React.FC<{
activeTab: 'code' | 'setup' | 'pages' | 'settings' | 'seo';
title?: string;
}> = ({ activeTab, title, ...props }) => {
const { emailAddresses, profileImageUrl, fullName, firstName } = useUser();
const { signOut } = useClerk();
const router = useRouter();
const { data } = useClerkSWR<notionSites>(
`/api/getSiteData/notion/?siteId=${router.query.notionId}`
);
return (
<div>
<div className='block lg:hidden'>
<DashboardNav />
<Head>
<title>
{title ||
data?.siteName +
' - ' +
activeTab.charAt(0).toUpperCase() +
activeTab.slice(1) +
' | ' +
'Pagely'}
</title>
</Head>
</div>
<div className='lg:flex'>
{/* <div className='sticky top-0 overflow-y-hidden'> */}
<div
style={{ position: 'sticky' }}
className='absolute top-0 h-screen left-0 px-10 py-5 bg-gray-50 w-[20vw] border-r hidden flex-col justify-between lg:flex'>
<div>
<Link href='/dashboard'>
<a>
<small className='text-gray-700 hover:text-gray-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-700'>
{' '}
{'<'}- Go back
</small>
</a>
</Link>
<ul className='mt-10'>
<li
className={`my-2 rounded ${
activeTab === 'setup' ? ' bg-gray-200' : ' hover:bg-gray-300'
}`}>
<Link href={'/notion-site/' + data?.id}>
<a className='block px-3 py-2 my-2 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-700'>
{' '}
<GoInbox className='relative inline-block bottom-[2px]' />{' '}
Setup
</a>
</Link>
</li>
<li
className={`my-2 rounded ${
activeTab === 'seo' ? ' bg-gray-200' : ' hover:bg-gray-300'
}`}>
<Link href={`/notion-site/${data?.id}/seo`}>
<a className='block px-3 py-2 my-2 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-700'>
{' '}
<BiSearchAlt className='relative inline-block bottom-[2px]' />{' '}
SEO
</a>
</Link>
</li>
<li
className={`my-2 rounded ${
activeTab === 'code' ? ' bg-gray-200' : ' hover:bg-gray-300'
}`}>
<Link href={`/notion-site/${data?.id}/code`}>
<a className='block px-3 py-2 my-2 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-700'>
{' '}
<BiCode className='relative inline-block bottom-[2px]' />{' '}
Code injection
</a>
</Link>
</li>
<li
className={`my-2 rounded ${
activeTab === 'pages' ? ' bg-gray-200' : ' hover:bg-gray-300'
}`}>
<Link href={`/notion-site/${data?.id}/pages`}>
<a className='block px-3 py-2 my-2 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-700'>
{' '}
<HiOutlineNewspaper className='relative inline-block bottom-[2px]' />{' '}
Pages
</a>
</Link>
</li>
<li
className={`my-2 rounded ${
activeTab === 'settings'
? ' bg-gray-200'
: ' hover:bg-gray-300'
}`}>
<Link href={`/notion-site/${data?.id}/settings`}>
<a className='block px-3 py-2 my-2 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-700'>
{' '}
<FiSettings className='relative inline-block bottom-[2px]' />{' '}
Settings
</a>
</Link>
</li>
</ul>
</div>
<ProfileDropdown
emailAddresses={emailAddresses}
profileImageUrl={profileImageUrl}
fullName={fullName}
firstName={firstName}
signOut={signOut}
/>
</div>
<div className='mx-10 mt-20'>{props.children}</div>
</div>
<Toaster />
</div>
);
}
Example #5
Source File: dashboard.tsx From pagely with MIT License | 4 votes |
Dashboard = () => {
const { data: notionSites, error } = useClerkSWR<notionSites[]>(
'/api/getAllSites/notion'
);
const { data: githubSites, error: errorFetchingGithubSites } = useClerkSWR<
ghSites[]
>('/api/getAllSites/github');
const { data: showcaseWebsites } = useClerkSWR<ShowcaseWebsites[]>(
'/api/getShowcaseWebsites'
);
return (
<MainLayout>
<div>
<div className='max-w-5xl mx-auto'>
<h1 className='text-4xl font-bold text-center lg:text-left md:relative lg:left-14'>
Your websites
</h1>
<div className='flex'>
<div
className='flex-1 mr-2 mt-10 h-[70vh] overflow-y-scroll pb-5'
id='websites'>
<div>
<h3 className='mb-5 text-lg font-medium lg:text-left md:relative lg:left-14'>
Notion websites
</h3>
{notionSites?.map((site) => (
// @ts-ignore
<SiteCard key={site.id} siteData={site} />
))}
{error && (
<h1>
Your Notion sites could not be fetched. Please reload and
try again
</h1>
)}
{!error && !notionSites && (
<Skeleton
width='384px'
height='200px'
count={3}
className='!block mb-8 mx-auto'
/>
)}
</div>
<hr className='w-[80%] my-5 text-gray-300 mx-auto' />
<div className='mb-5'>
<h3 className='mb-5 text-lg font-medium lg:text-left md:relative lg:left-14'>
GitHub websites
</h3>
{githubSites?.map((site) => (
// @ts-ignore
<GitHubSiteCard key={site.id} siteData={site} />
// <p key={site.id}>{JSON.stringify(site, null, 2)}</p>
))}
{errorFetchingGithubSites && (
<h1>
Your GitHub sites could not be fetched. Please reload and
try again
</h1>
)}
{!errorFetchingGithubSites && !githubSites && (
<Skeleton
width='384px'
height='200px'
count={3}
className='!block mb-8 mx-auto'
/>
)}
</div>
</div>
<div className='sticky top-0 flex-1 hidden mt-10 lg:block'>
<div className='text-center transition-all bg-blue-100 border border-blue-300 rounded shadow-sm hover:bg-blue-200'>
<Link href='/new'>
<a className='block px-4 py-3 text-lg -mt-[50px]'>
<HiOutlinePlusCircle className='relative inline-block w-8 h-8 mr-1 text-gray-600 bottom-[2px]' />
Create new website
</a>
</Link>
</div>
<hr className='my-5 w-[80%] mx-auto text-gray-300' />
<div className='mt-4 text-center'>
<h3 className='text-2xl font-medium'>
Some awesome websites made with Pagely
</h3>
<div
className='flex flex-wrap px-2 mt-3 overflow-y-auto h-[50vh] pb-5'
id='showcase-websites'>
{showcaseWebsites?.map((site) => {
return (
<div
key={site.siteName}
style={{ zoom: '0.6' }}
className='mr-1'>
<a
href={'https://' + site.subdomain + '.pagely.site'}
target='_blank'
rel='noopener noreferrer'>
<div className='max-w-sm px-3 mx-auto text-center transition-all duration-500 rounded-lg py-7 hover:border border-bluegray-200 hover:shadow-lg group'>
{(
// eslint-disable-next-line @next/next/no-img-element
<img
src={site.ogImageUrl || '/no-og-image.png'}
alt={site.siteName}
className='w-[80%] mx-auto mb-4 rounded-lg group-hover:scale-105 object-cover transform transition-all duration-500 border border-gray-300'
/>
) || (
<Skeleton className='w-[80%] mx-auto mb-4 rounded-lg group-hover:scale-105 object-cover transform transition-all duration-500 border border-gray-300' />
)}
<h3 className='text-2xl font-medium'>
{truncate(site.siteName, { length: 30 })}
</h3>
</div>
</a>
</div>
);
})}
</div>
</div>
</div>
</div>
</div>
</div>
<style jsx>{`
#showcase-websites::-webkit-scrollbar {
display: none;
}
#showcase-websites {
-ms-overflow-style: none;
}
#websites::-webkit-scrollbar {
display: none;
}
#websites {
-ms-overflow-style: none;
}
`}</style>
</MainLayout>
);
}
Example #6
Source File: code.tsx From pagely with MIT License | 4 votes |
Page = () => {
const router = useRouter();
const { data } = useClerkSWR<notionSites>(
`/api/getSiteData/notion/?siteId=${router.query.notionId}`
);
const [css, setCss] = useState<string>(data?.customCss);
const [head, setHead] = useState<string>(data?.customHead);
let [isOpen, setIsOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const urlWithSession = useUserWithSession('/api/updateSiteData/notion/code');
function closeModal() {
setIsOpen(false);
}
function openModal() {
setIsOpen(true);
}
useEffect(() => {
window.addEventListener('keydown', (e) => {
if (e.metaKey && e.key === 's') {
e.preventDefault();
document.getElementById('update-custom-code-btn').click();
}
});
}, []);
return (
<div>
<div>
<SidebarLayout activeTab='code'>
<h1 className='text-4xl font-extrabold'>Code Injection</h1>
<p className='mt-4 text-gray-800 font-base'>
{data?.siteName || 'Just a second...'}
</p>
<div className='my-3'>
<button
onClick={openModal}
className='px-2 py-1 text-green-600 border border-green-500 rounded shadow bg-green-50 hover:bg-green-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-green-200'>
Open styling tools
</button>
<p className='my-1 text-sm text-gray-500'>
PROTIP: Use the{' '}
<a
target='_blank'
rel='noopener noreferrer'
className='underline'
href='https://chrome.google.com/webstore/detail/stylebot/oiaejidbmkiecgbjeifoejpgmdaleoha'>
`Stylebot`
</a>{' '}
extension to style your website without code. View demo at{' '}
<a
className='underline'
target='_blank'
rel='noopener noreferrer'
href={process.env.NEXT_PUBLIC_LOOM_VIDEO_URL}>
here
</a>
.
</p>
</div>
<div className='mt-8'>
<p className='my-3 font-mono text-xl font-bold text-gray-500'>{`<style>`}</p>
<TextareaAutosize
spellCheck={false}
value={css}
onChange={(e) => setCss(e.target.value)}
className='w-[70vw] py-5 font-mono border text-sm min-h-[100px] border-gray-600 rounded-md shadow-sm block text-gray-500 focus:outline-none focus:border-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-500'
onKeyDown={(e) => handleHotkeys(e)}
/>
<p className='my-3 font-mono text-xl font-bold text-gray-500'>{`</style>`}</p>
</div>
<hr className='my-10 text-gray-300' />
<div className='mt-8'>
<p className='my-3 font-mono text-xl font-bold text-gray-500'>{`<head>`}</p>
<TextareaAutosize
spellCheck={false}
value={head}
onChange={(e) => setHead(e.target.value)}
className='w-[70vw] py-5 font-mono border text-sm min-h-[100px] border-gray-600 rounded-md shadow-sm block text-gray-500 focus:outline-none focus:border-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-500'
/>
<p className='my-3 font-mono text-xl font-bold text-gray-500'>{`</head>`}</p>
<div className='my-10'>
<button
id='update-custom-code-btn'
onClick={() => {
setIsLoading(true);
axios
.post(urlWithSession, {
customCss: css,
customHead: head,
siteId: data.id,
})
.then((res) => {
console.log(res);
toast.success('Successfully updated site code.', {
duration: 5000,
});
setIsLoading(false);
});
}}
className={`h-10 px-3 mb-10 bg-gray-800 rounded shadow-md text-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-800 hover:bg-gray-700 ${
isLoading && 'opacity-50 cursor-wait'
}`}>
{/* className={`h-10 px-3 shadow-md bg-gray-800 rounded text-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-800 hover:bg-gray-700 ${
isLoading && 'opacity-60 cursor-pointer pointer-events-none'
}`}> */}
Update Custom Code
</button>
<p className='mt-3 text-base text-gray-600'>
You can press <b>Cmd + S</b> to save the code too ✌️
</p>
</div>
</div>
</SidebarLayout>
<Transition appear show={isOpen} as={Fragment}>
<Dialog
as='div'
className='fixed inset-0 z-10 overflow-y-auto'
onClose={closeModal}>
<div className='min-h-screen px-4 text-center'>
<Transition.Child
as={Fragment}
enter='ease-out duration-300'
enterFrom='opacity-0'
enterTo='opacity-100'
leave='ease-in duration-200'
leaveFrom='opacity-100'
leaveTo='opacity-0'>
<Dialog.Overlay className='fixed inset-0 backdrop-filter backdrop-blur-sm bg-white/40' />
</Transition.Child>
{/* This element is to trick the browser into centering the modal contents. */}
<span
className='inline-block h-screen align-middle'
aria-hidden='true'>
​
</span>
<Transition.Child
as={Fragment}
enter='ease-out duration-300'
enterFrom='opacity-0 scale-95'
enterTo='opacity-100 scale-100'
leave='ease-in duration-200'
leaveFrom='opacity-100 scale-100'
leaveTo='opacity-0 scale-95'>
<div className='inline-block w-full max-w-3xl p-6 my-8 overflow-hidden text-left align-middle transition-all transform bg-white border rounded-md shadow-xl border-gray-500/40'>
<Dialog.Title
as='h3'
className='text-lg font-medium leading-6 text-gray-900'>
CSS Utilities ?
</Dialog.Title>
<div className='mt-2 mb-10'>
<p className='text-sm text-gray-500'>
A tiny set of utilities to help you style your app and
make it look great. Many more utilities are coming soon.
</p>
<hr className='w-full mx-auto my-5 text-gray-200' />
<Utility />
</div>
<div className='mt-4'>
<button
type='button'
className='inline-flex justify-center px-4 py-1 text-sm font-medium text-blue-900 bg-blue-100 border border-blue-500 rounded-md hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-blue-500'
onClick={openModal}>
Thanks!
</button>
</div>
</div>
</Transition.Child>
</div>
</Dialog>
</Transition>
</div>
</div>
);
}
Example #7
Source File: seo.tsx From pagely with MIT License | 4 votes |
Page = () => {
const router = useRouter();
const { data, mutate } = useClerkSWR<notionSites>(
`/api/getSiteData/notion/?siteId=${router.query.notionId}`
);
const [isImageLoading, setIsImageLoading] = useState<boolean>(true);
const [isLoading, setIsLoading] = useState<boolean>(false);
const updateUrlWithSession = useUrlWithSession(
'/api/updateSiteData/notion/seo'
);
const {
handleSubmit,
register,
setValue,
formState: { errors },
control,
} = useForm<NotionSeoSettings>({
resolver: zodResolver(notionPageSeoSchema),
defaultValues: {
ogImageUrl: data?.ogImageUrl,
siteName: data?.siteName,
siteDesc: data?.siteDesc,
},
});
const updateSeoData = (formData) => {
setIsLoading(true);
console.log('updating SEO');
const { ogImageUrl, siteName, siteDesc } = formData;
console.log('values obtained' + JSON.stringify(formData));
console.log('about to post');
axios
.post(updateUrlWithSession, {
siteId: data?.id,
ogImageUrl: ogImageUrl,
siteName: siteName,
siteDesc: siteDesc,
})
.then(() => {
console.log('done updating');
setIsLoading(false);
toast.success('SEO settings updated.');
mutate(
{
...data,
ogImageUrl: ogImageUrl,
siteName: siteName,
siteDesc: siteDesc,
},
false
);
console.log('done');
})
.catch((err) => {
console.log('caught error');
setIsLoading(false);
toast.error('Failed to update SEO settings\n' + err.message, {
duration: 5000,
});
});
console.log('done posting');
};
return (
<div>
{process.env.NODE_ENV !== 'production' && (
<DevTool control={control} placement='top-right' />
)}
<SidebarLayout activeTab='seo'>
<h1 className='text-4xl font-extrabold'>SEO Settings</h1>
<p className='mt-4 text-gray-800 font-base'>
{data?.siteName || 'Just a second...'}
</p>
<div className='my-5 mt-10'>
<h2 className='mb-5 text-2xl font-bold'>Twitter Preview</h2>
<TwitterPreview data={data} />
</div>
<form
id='notion-seo-form'
className='mt-8'
onSubmit={(e) => {
e.preventDefault();
handleSubmit(updateSeoData)();
}}>
<hr className='my-10 text-gray-400' />
<h2 className='mb-5 text-2xl font-bold'>OG Image</h2>
<div className='max-w-[600px] max-h-[315px]'>
{data?.ogImageUrl === 'https://no-og.image' ? (
<Image
alt='No OG Image'
src={NoOgImage}
onLoad={() => setIsImageLoading(false)}
className='border border-gray-400 rounded'
/>
) : (
// eslint-disable-next-line @next/next/no-img-element
<img
src={
data?.ogImageUrl ||
'https://ogimage.glitch.me/i/' +
encodeURIComponent(data?.siteName)
}
alt={data?.siteName}
className='object-cover rounded-md'
onLoad={() => setIsImageLoading(false)}
/>
)}
{isImageLoading && <Skeleton width='600px' height='315px' />}
</div>
<div>
<label className='block mt-3'>
<span className='mt-1 text-sm text-gray-600'>
If left blank, the OG Image will be automatically generated from
site name and Notion page's title!!
</span>
<InfoPopover content='This is the image that will appear in the OG cards and Twitter cards. 1200x630 is the recommended dimension for the OG image. This can boost your conversion rate by upto 2 times!!'>
<Image
placeholder='blur'
src={OgImage}
alt=''
className='inline-block w-full rounded'
/>
</InfoPopover>
<div className='flex items-center'>
<input
type='text'
className='inline-block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200'
placeholder='https://picsum.photos/1200/630'
{...register('ogImageUrl')}
/>
</div>
<p className='mt-2 text-sm text-red-500'>
{errors.ogImageUrl && errors.ogImageUrl.message}
</p>
<div>
<div>
<div className='inline-block px-2 py-px mt-2 text-sm text-gray-700 border border-gray-200 rounded cursor-pointer bg-gray-50 hover:bg-gray-100'>
<Dropzone
onDrop={(files) => {
uploadImage(files, setValue);
}}>
{({ getRootProps, getInputProps }) => (
<div {...getRootProps()}>
<input type='file' {...getInputProps()} />
<BiCloudUpload className='relative inline-block w-5 h-5 bottom-px' />{' '}
Upload image
</div>
)}
</Dropzone>
</div>
<p className='mt-1 text-sm text-gray-500'>
Or just drag 'n' drop an image over the button !
</p>
</div>
</div>
</label>
</div>
<hr className='my-10 text-gray-200' />
<div>
<h2 className='mb-5 text-2xl font-bold'>OG Title</h2>
<p className='text-gray-800'>{data?.siteName}</p>
<div>
<label className='block mt-3'>
<span className='mt-1 text-sm text-gray-600'>
This name will be used for generating OG title
</span>
<InfoPopover content='This is the name of your website. It is also the title in Twitter cards and OG cards.'>
<Image
placeholder='blur'
src={TweetTitleImage}
alt=''
className='inline-block w-full rounded'
/>
</InfoPopover>
<div className='flex items-center'>
<input
type='text'
className='inline-block w-full mt-1 mr-1 border-gray-300 rounded-md shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200'
placeholder='Blog - Elon'
{...register('siteName')}
/>
</div>
<p className='mt-2 text-sm text-red-500'>
{errors.siteName && errors.siteName.message}
</p>
</label>
</div>
</div>
<hr className='my-10 text-gray-200' />
<div className='mb-5'>
<h2 className='mb-5 text-2xl font-bold'>OG Description</h2>
<p className='text-gray-800'>{data?.siteDesc}</p>
<div>
<label className='block mt-3'>
<span className='mt-1 text-sm text-gray-600'>
This name will be used for generating OG and Twitter
descriptions
</span>
<InfoPopover content='This is the description of your website. It is also the description in Twitter cards and OG cards.'>
<Image
placeholder='blur'
src={TweetDescImage}
alt=''
className='inline-block w-full rounded'
/>
</InfoPopover>
<textarea
className='block w-full mt-1 text-base border-gray-300 rounded-md shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50'
rows={4}
placeholder='Read my blog to...'
{...register('siteDesc')}
/>
<p className='mt-2 text-sm text-red-500'>
{errors.siteDesc && errors.siteDesc.message}
</p>
</label>
</div>
</div>
<div>
<button
type='submit'
form='notion-seo-form'
className={`h-10 px-3 mb-10 bg-gray-800 rounded shadow-md text-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-800 hover:bg-gray-700 ${
isLoading && 'opacity-50 cursor-wait'
}`}>
{isLoading ? 'Saving changes...' : 'Save changes'}
</button>
</div>
</form>
</SidebarLayout>
</div>
);
}
Example #8
Source File: settings.tsx From pagely with MIT License | 4 votes |
Page = () => {
const router = useRouter();
const { data } = useClerkSWR<notionSites>(
`/api/getSiteData/notion/?siteId=${router.query.notionId}`
);
const urlWithSession = useUserWithSession(
'/api/updateSiteData/notion/showcase'
);
const deleteUrlWithSession = useUserWithSession('/api/deleteSite/notion');
const [enabled, setEnabled] = useState(data?.inShowcase);
const [isLoading, setIsLoading] = useState(false);
const [isOpen, setIsOpen] = useState(false);
function closeModal() {
setIsOpen(false);
}
function openModal() {
setIsOpen(true);
}
return (
<div>
<div>
<SidebarLayout activeTab='settings'>
<h1 className='text-4xl font-extrabold'>Settings</h1>
<p className='mt-4 text-gray-800 font-base'>
{data?.siteName || 'Just a second...'}
</p>
<div className='mt-8'>
<h2 className='text-2xl font-bold'>Showcase Settings</h2>
<div className='flex items-center my-5'>
<span className='inline-block mr-2'>
I prefer not to display{' '}
<strong title={data?.siteName}>
{truncate(data?.siteName, {
length: 15,
})}
</strong>{' '}
in showcase
</span>
<Switch
checked={enabled}
onChange={setEnabled}
style={{ zoom: 0.5 }}
className={`${enabled ? 'bg-gray-900' : 'bg-gray-700'}
relative inline-flex flex-shrink-0 h-[38px] w-[74px] border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75`}>
<span className='sr-only'>Use setting</span>
<span
aria-hidden='true'
className={`${enabled ? 'translate-x-9' : 'translate-x-0'}
pointer-events-none inline-block h-[34px] w-[34px] rounded-full bg-white shadow-lg transform ring-0 transition ease-in-out duration-200`}
/>
</Switch>
<span className='inline-block ml-2'>
Display{' '}
<strong title={data?.siteName}>
{truncate(data?.siteName, {
length: 15,
})}
</strong>{' '}
in{' '}
<Link href='/showcase'>
<a className='text-blue-500 hover:underline'>Showcase</a>
</Link>
</span>
</div>
<button
onClick={() => {
setIsLoading(true);
axios
.post(urlWithSession, {
inShowcase: enabled,
siteId: data.id,
})
.then((res) => {
console.log(res);
toast.success(
enabled
? `Yay ?, ${data?.siteName} will be displayed in showcase soon.`
: `${data?.siteName} will be removed showcase soon.`,
{
duration: 5000,
}
);
setIsLoading(false);
});
}}
className={`h-10 px-3 mb-10 bg-gray-800 rounded shadow-md text-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-800 hover:bg-gray-700 ${
isLoading && 'opacity-50 cursor-wait'
}`}>
Update Showcase Settings
</button>
</div>
<hr className='w-[70vw] my-3 text-gray-200' />
<div className='mt-8'>
<h2 className='text-2xl font-bold'>Password protection</h2>
{data?.isPasswordProtected ? (
<div>
<div className='flex items-center my-5'>
<span className='inline-block'>
<strong>{data?.siteName}</strong> has already been password
protected
</span>
</div>
<button className='h-10 px-3 mb-10 bg-gray-800 rounded shadow-md text-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-800 hover:bg-gray-700'>
<a
href='https://staticshield.vercel.app/dashboard'
target='_blank'
rel='noopener noreferrer'>
View details
</a>
</button>
</div>
) : (
<div>
<div className='flex items-center my-5'>
<span className='inline-block'>
Password protect <strong>{data?.siteName}</strong>
</span>
</div>
<button
onClick={() => {
window.open(
`https://staticshield.vercel.app/new/?name=${data?.siteName}&desc=${data?.siteDesc}&url=${data?.subdomain}.pagely.site&id=${data?.id}`,
'_blank'
);
}}
className={`mb-10 h-10 inline-flex items-center px-3 bg-gray-800 rounded shadow-md text-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-800 hover:bg-gray-700`}>
Password protect{' '}
<strong className='mx-1'>{data?.siteName}</strong> with{' '}
<span className='inline-flex !items-center justify-center p-1 mx-1 bg-white rounded'>
<Image
src='/staticshield.png'
alt=''
width='20'
height='20'
// className='block mt-2'
/>
</span>
StaticShield
</button>
</div>
)}
</div>
<hr className='w-[70vw] my-3 text-gray-200' />
<div className='mt-8'>
<h2 className='text-2xl font-bold text-red-500'>Danger Zone</h2>
<div className='mt-5'>
<button
onClick={openModal}
className='h-10 px-3 mb-10 bg-red-600 rounded shadow-md text-red-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-800 hover:bg-red-400'>
{/* <button className='px-2 py-1 text-red-600 border border-red-500 rounded shadow bg-red-50 hover:bg-red-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-red-200'> */}
Delete <strong>{data?.siteName}</strong>
</button>
</div>
</div>
</SidebarLayout>
<Transition appear show={isOpen} as={Fragment}>
<Dialog
as='div'
className='fixed inset-0 z-10 overflow-y-auto'
onClose={closeModal}>
<div className='min-h-screen px-4 text-center'>
<Transition.Child
as={Fragment}
enter='ease-out duration-300'
enterFrom='opacity-0'
enterTo='opacity-100'
leave='ease-in duration-200'
leaveFrom='opacity-100'
leaveTo='opacity-0'>
<Dialog.Overlay className='fixed inset-0 backdrop-filter backdrop-blur-sm bg-white/40' />
</Transition.Child>
{/* This element is to trick the browser into centering the modal contents. */}
<span
className='inline-block h-screen align-middle'
aria-hidden='true'>
​
</span>
<Transition.Child
as={Fragment}
enter='ease-out duration-300'
enterFrom='opacity-0 scale-95'
enterTo='opacity-100 scale-100'
leave='ease-in duration-200'
leaveFrom='opacity-100 scale-100'
leaveTo='opacity-0 scale-95'>
<div className='inline-block w-full max-w-lg p-6 my-8 overflow-hidden text-left align-middle transition-all transform bg-white border rounded-md shadow-xl border-gray-500/40'>
<Dialog.Title
as='h3'
className='text-lg font-medium leading-6 text-red-700'>
Are you sure that you want to delete{' '}
<strong>{data?.siteName}</strong>?
</Dialog.Title>
<div className='mt-2 mb-10'>
<p className='text-sm text-gray-500'>
Proceed with caution. This action cannot be reversed.
</p>
</div>
<div className='mt-4'>
<button
type='button'
className='inline-flex justify-center px-4 py-1 mr-2 text-sm font-medium text-blue-900 bg-blue-100 border border-blue-500 rounded-md hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-blue-500'
onClick={closeModal}>
Cancel
</button>
<button
type='button'
className='inline-flex justify-center px-4 py-1 text-sm font-medium text-red-900 bg-red-100 border border-red-500 rounded-md hover:bg-red-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-red-500'
onClick={() => {
axios
.post(deleteUrlWithSession, {
siteId: data?.id,
})
.then((res) => {
if (res.data.success) {
toast.success('Site deleted successfully', {
duration: 2000,
});
setTimeout(() => {
router.push('/dashboard');
}, 2000);
} else {
toast.error('Site deletion failed');
}
});
}}>
Delete
</button>
</div>
</div>
</Transition.Child>
</div>
</Dialog>
</Transition>
</div>
</div>
);
}