mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-23 03:51:36 +03:00
Added Algolia Search (#5524)
-Added Algolia Search Box : <img width="707" alt="Screenshot 2024-05-22 at 10 05 13" src="https://github.com/twentyhq/twenty/assets/102751374/d26f9748-2a80-4690-88ca-16b078c52915"> -Added Algolia Search Bar: <img width="294" alt="Screenshot 2024-05-22 at 10 05 56" src="https://github.com/twentyhq/twenty/assets/102751374/ad503894-4ae1-41e4-bd4b-6241f7679142"> --------- Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
parent
2e79bcc70b
commit
40bd42efc4
@ -116,7 +116,7 @@ const config = {
|
||||
algolia: {
|
||||
appId: 'J2OX2P2QAO',
|
||||
apiKey: 'e0a7a59c7862598a0cf87307c8ea97f2',
|
||||
indexName: 'twenty',
|
||||
indexName: 'twenty-developer-docs',
|
||||
|
||||
// Optional: see doc section below
|
||||
contextualSearch: true,
|
||||
|
@ -1,2 +1,4 @@
|
||||
GITHUB_TOKEN=your_github_token
|
||||
DATABASE_PG_URL=postgres://website:website@localhost:5432/website # only if using postgres
|
||||
NEXT_PUBLIC_ALGOLIA_APP_ID=twenty_appId
|
||||
NEXT_PUBLIC_ALGOLIA_API_KEY=twenty_apiKey
|
||||
|
@ -12,7 +12,7 @@ const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
h1 {
|
||||
h2 {
|
||||
margin: 0px;
|
||||
font-size: ${Theme.font.size.lg};
|
||||
}
|
||||
@ -75,10 +75,10 @@ export default function ArticleEditContent({
|
||||
return (
|
||||
<StyledContainer>
|
||||
<div>
|
||||
<h1>Noticed something to modify?</h1>
|
||||
<h2>Noticed something to change?</h2>
|
||||
<p>
|
||||
As an open-source company, we welcome contributions to our GitHub user
|
||||
guide. Help us keep it up-to-date, accurate, and easy to understand by
|
||||
As an open-source company, we welcome contributions through Github.
|
||||
Help us keep it up-to-date, accurate, and easy to understand by
|
||||
getting involved and sharing your ideas!
|
||||
</p>
|
||||
<StyledButtonContainer>
|
||||
|
@ -0,0 +1,48 @@
|
||||
import { DocSearch } from '@docsearch/react';
|
||||
import { StoredDocSearchHit } from '@docsearch/react/dist/esm/types';
|
||||
|
||||
interface AlgoliaHit extends StoredDocSearchHit {
|
||||
_snippetResult?: {
|
||||
content: { value: string };
|
||||
};
|
||||
}
|
||||
|
||||
export const AlgoliaDocSearch = () => {
|
||||
return (
|
||||
<DocSearch
|
||||
hitComponent={({ hit }: { hit: AlgoliaHit }) => (
|
||||
<section className="DocSearch-Hits">
|
||||
<a href={hit.url}>
|
||||
<div className="DocSearch-Hit-Container">
|
||||
<div className="DocSearch-Hit-icon">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20">
|
||||
<path
|
||||
d="M13 13h4-4V8H7v5h6v4-4H7V8H3h4V3v5h6V3v5h4-4v5zm-6 0v4-4H3h4z"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
fillRule="evenodd"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="DocSearch-Hit-action">
|
||||
<h2>
|
||||
{hit.hierarchy.lvl1 ? hit.hierarchy.lvl1 : hit.hierarchy.lvl0}
|
||||
</h2>
|
||||
<p
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: hit?._snippetResult?.content?.value || '',
|
||||
}}
|
||||
></p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</section>
|
||||
)}
|
||||
appId={process.env.NEXT_PUBLIC_ALGOLIA_APP_ID as string}
|
||||
apiKey={process.env.NEXT_PUBLIC_ALGOLIA_API_KEY as string}
|
||||
indexName="twenty-user-guide"
|
||||
/>
|
||||
);
|
||||
};
|
@ -6,9 +6,13 @@ import { useRouter } from 'next/navigation';
|
||||
import { IconBook } from '@/app/_components/ui/icons';
|
||||
import mq from '@/app/_components/ui/theme/mq';
|
||||
import { Theme } from '@/app/_components/ui/theme/theme';
|
||||
import { AlgoliaDocSearch } from '@/app/_components/user-guide/AlgoliaDocSearch';
|
||||
import UserGuideSidebarSection from '@/app/_components/user-guide/UserGuideSidebarSection';
|
||||
import { UserGuideArticlesProps } from '@/content/user-guide/constants/getUserGuideArticles';
|
||||
|
||||
import '@docsearch/css';
|
||||
import '../../user-guide/algolia.css';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
${mq({
|
||||
display: ['none', 'flex', 'flex'],
|
||||
@ -66,6 +70,7 @@ const UserGuideSidebar = ({
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<AlgoliaDocSearch />
|
||||
<StyledHeading>
|
||||
<StyledIconContainer>
|
||||
<IconBook size={Theme.icon.size.md} />
|
||||
|
122
packages/twenty-website/src/app/user-guide/algolia.css
Normal file
122
packages/twenty-website/src/app/user-guide/algolia.css
Normal file
@ -0,0 +1,122 @@
|
||||
.DocSearch-Hit-source{
|
||||
color: #1c1e21;
|
||||
}
|
||||
|
||||
.DocSearch-Search-Icon {
|
||||
color: #1c1e21;
|
||||
}
|
||||
|
||||
.DocSearch-Logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.DocSearch-Footer{
|
||||
flex-direction: row;
|
||||
box-shadow: none;
|
||||
border: 1px solid #14141414;
|
||||
}
|
||||
|
||||
.DocSearch-Form {
|
||||
box-shadow: none;
|
||||
border: 1px solid #141414;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.DocSearch-Modal {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.DocSearch-Hits {
|
||||
width: 100%;
|
||||
margin-bottom: 2px !important;
|
||||
}
|
||||
|
||||
.DocSearch-Hit[aria-selected=true] mark {
|
||||
color: #1961ED !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.DocSearch-Hit a {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.DocSearch-Hits mark {
|
||||
background-color: #E8EFFD;
|
||||
color: #1961ED;
|
||||
}
|
||||
|
||||
.DocSearch-Hit-action {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
.DocSearch-Hit-action h2{
|
||||
font-size: .9em;
|
||||
margin: 0 0 4px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.DocSearch-Hit-action p{
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
width: 90%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
font-family: var(--font-inter);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.DocSearch-Button {
|
||||
margin: 0px;
|
||||
min-height: 36px;
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #14141414;
|
||||
}
|
||||
|
||||
.DocSearch-Button:hover {
|
||||
color: #B3B3B3;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.DocSearch-Button-Placeholder{
|
||||
color: #B3B3B3;
|
||||
}
|
||||
|
||||
.DocSearch-Search-Icon {
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
color: #B3B3B3 !important;
|
||||
}
|
||||
|
||||
.DocSearch-Hit-source {
|
||||
background: none;
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
font-family: var(--font-inter);
|
||||
}
|
||||
|
||||
.DocSearch-Button-Placeholder {
|
||||
font-weight: 500;
|
||||
font-family: var(--font-gabarito);
|
||||
}
|
||||
|
||||
.DocSearch-Button-Keys {
|
||||
display: none
|
||||
}
|
||||
|
||||
:root {
|
||||
--docsearch-primary-color: #1c1e21;
|
||||
--docsearch-highlight-color: #1414140F;
|
||||
--docsearch-hit-active-color: var(--docsearch-muted-color);
|
||||
}
|
||||
|
||||
.anchor {
|
||||
scroll-margin-top: calc(80px);
|
||||
}
|
@ -26,7 +26,7 @@ Since your API key gives access to sensitive information, you shouldn't share it
|
||||
<div style={{padding:'70.59% 0 0 0', position:'relative', margin: '32px 0px 0px' }}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/928786722?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
@ -62,7 +62,7 @@ For instance, a webhook can alert your system in real-time when someone creates
|
||||
<div style={{padding:'70.59% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/928786708?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -14,7 +14,7 @@ image: /images/user-guide/create-workspace/workspace-cover.png
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927066829?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -41,7 +41,7 @@ Your newly created field is now available within the application's fields. To di
|
||||
<div style={{padding:'71.15% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927628219?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -26,7 +26,7 @@ To export data from an object:
|
||||
<div style={{padding:'71.24% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/926226303?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -24,7 +24,7 @@ Sync Twenty with 3000+ apps using <ArticleLink href="https://zapier.com/apps/twe
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927913866?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -16,7 +16,7 @@ Kanban views visually map out process flows, where each column stands for a dist
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927888627?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
@ -43,7 +43,7 @@ To add a stage, access the Select Field Settings by navigating to Settings > Dat
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927890428?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -32,7 +32,7 @@ You can also change the background color and text color of each block to highlig
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927896302?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -40,7 +40,7 @@ To create a new custom object:
|
||||
<div style={{padding:'71.24% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/926288174?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
@ -61,7 +61,7 @@ To create a new custom object:
|
||||
<div style={{padding:'71.24% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/926293493?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -18,7 +18,7 @@ Enter the record name then press `Enter` to save. To edit a record name, click o
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927071691?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
@ -45,7 +45,7 @@ Enter the record name then press `Enter` to save. To edit a record name, click o
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927073570?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -17,7 +17,7 @@ Creating tasks in Twenty is seamless. You can either:
|
||||
<div style={{padding:'70.59% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/928786754?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
@ -49,7 +49,7 @@ You can also see tasks for a given Record on its `Record page`.
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927908280?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
@ -86,7 +86,7 @@ This procedure will help keep an updated record of your accomplishments.
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927910083?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -16,7 +16,7 @@ Workspace admins can edit its name and logo in settings.
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927915481?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
@ -43,7 +43,7 @@ Select **Dark**. The system will automatically save your changes.
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927916570?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -36,7 +36,7 @@ The newly created view opens automatically.
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927639721?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
@ -59,7 +59,7 @@ When you change the `Sorting` and `Filtering` of an existing view, a `Save as ne
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927643495?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
@ -88,7 +88,7 @@ You will then be able to modify the view. To delete it, press the `Delete` butto
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927645774?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
@ -124,7 +124,7 @@ To filter a view:
|
||||
<div style={{padding:'71.24% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/926282262?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
@ -148,7 +148,7 @@ Order your fields data in ascending or descending order:
|
||||
<div style={{padding:'69.01% 0 0 0', position:'relative', margin: '32px 0px 0px'}}>
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/927885588?autoplay=1&loop=1&autopause=0&background=1&app_id=58479"
|
||||
frameborder="0"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write"
|
||||
style={{
|
||||
position:'absolute',
|
||||
|
@ -25,6 +25,7 @@ export const wrapHeadingsWithAnchor = (children: ReactNode): ReactNode => {
|
||||
.toLowerCase();
|
||||
return cloneElement(child as ReactElement<any>, {
|
||||
id: id,
|
||||
className: 'anchor',
|
||||
children: <a href={`#${id}`}>{child.props.children}</a>,
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user