Skip to content

Commit

Permalink
Merge pull request #3160 from Blargian/kb_tagged_search_mixed
Browse files Browse the repository at this point in the history
KB: Improve KB search - search by title, description (tags)
  • Loading branch information
gingerwizard authored Feb 5, 2025
2 parents 49cb829 + 9a4f7d2 commit 4c51dec
Show file tree
Hide file tree
Showing 27 changed files with 2,134 additions and 49 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ clickhouse-docs.code-workspace
yarn.lock
yarn.error-log
.comments
yarn-error.log

# Output files used by scripts to verify links
sidebar_links.txt
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
"build-api-doc": "node clickhouseapi.js",
"build-swagger": "npx @redocly/cli build-docs https://api.clickhouse.cloud/v1 --output build/en/cloud/manage/api/swagger.html",
"auto-generate-settings": "bash ./scripts/settings/autogenerate-settings.sh",
"new-build": "yarn copy-clickhouse-repo-docs && yarn auto-generate-settings && yarn build-api-doc && yarn build && yarn build-swagger",
"auto-generate-table-of-contents": "bash ./scripts/autogenerate-table-of-contents.sh",
"new-build": "yarn copy-clickhouse-repo-docs && yarn auto-generate-settings && yarn auto-generate-table-of-contents && yarn build-api-doc && yarn build && yarn build-swagger",
"start": "docusaurus start",
"swizzle": "docusaurus swizzle",
"write-heading-ids": "docusaurus write-heading-ids",
Expand All @@ -31,12 +32,14 @@
"@docusaurus/theme-mermaid": "3.7.0",
"@docusaurus/theme-search-algolia": "^3.7.0",
"@mdx-js/react": "^3.1.0",
"@yaireo/tagify": "^4.33.2",
"@radix-ui/react-navigation-menu": "^1.2.4",
"axios": "^1.7.9",
"clsx": "^2.1.0",
"docusaurus-plugin-sass": "^0.2.6",
"esbuild": "^0.20.1",
"esbuild-loader": "^4.0.3",
"flexsearch": "^0.7.43",
"gray-matter": "^4.0.3",
"hast-util-is-element": "1.1.0",
"http-proxy-middleware": "3.0.3",
Expand Down
22 changes: 22 additions & 0 deletions scripts/autogenerate-table-of-contents.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash

# This script is used for automatically generating any .json table of contents files
# used for various things on the docs site, such as:
# - landing pages
# - indexing of the knowledgebase

# check if virtual environment exists
if [ ! -d "venv" ]; then
echo "Creating virtual environment..."
python3 -m venv venv
fi

source venv/bin/activate
pip install -r scripts/table-of-contents-generator/requirements.txt

# Add runs of the script below for any table of contents files that need to be generated
# You can run toc_gen.py --help for descriptions of the parameters
python3 scripts/table-of-contents-generator/toc_gen.py --dir="knowledgebase" --single-toc --out="static" --ignore images

deactivate
rm -r venv
1 change: 1 addition & 0 deletions scripts/settings/autogenerate-settings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,4 @@ if [ -f ./clickhouse ]; then
fi

echo "[$SCRIPT_NAME] Autogenerating settings completed"

2 changes: 1 addition & 1 deletion scripts/table-of-contents-generator/toc_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def write_to_file(json_items, directory, output=None):
except OSError as e:
if e.errno == 21:
print(f"Directory already exists: {e}")
else:
elif e.errno != 17:
print(f"An error occurred creating directory: {e}")
def write_file(json_items, args, directory):
print(args)
Expand Down
81 changes: 81 additions & 0 deletions src/components/BlogBreadcrumbs/BlogBreadcrumbs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, {useEffect} from 'react';
import {useLocation} from '@docusaurus/router';
import Link from '@docusaurus/Link';
import styles from './styles.module.css'
import HomeBreadcrumbItem from "@theme/DocBreadcrumbs/Items/Home";

function capitalizeFirstLetter(str) {

if (str === 'knowledgebase')
return 'Knowledge Base'
if (str.length === 0) {
return str; // Handle empty string case
}
return str.charAt(0).toUpperCase() + str.slice(1);
}

function pretty(str) {

if (str === 'knowledgebase')
return 'Knowledge Base'

let spacedStr = str.replace(/[-_]/g, ' ');
let words = spacedStr.split(' ');

let capitalizedWords = words.map(word => {
// Handle already capitalized words e.g. TTL
if (word === word.toUpperCase()) {
return word; // Leave as is
} else {
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); // convert other letters to lowercase
}
});

return capitalizedWords.join(' ');
}


const BlogBreadcrumbs = () => {

const location = useLocation();
const location_paths = location.pathname.split("/")
let cleaned_location_paths = location_paths.filter((path)=>{
return !(path === '' || path === 'docs');
})
let accumulatedPath = '/docs/';

return(
<div className={styles.BlogBreadcrumbsContainer}>
<HomeBreadcrumbItem />
<div className={styles.BlogBreadcrumbs}>
{
cleaned_location_paths.map((path, index)=>{
accumulatedPath += path;
const toPath = accumulatedPath;

if (index < cleaned_location_paths.length - 1) { // Check if it's not the last element
accumulatedPath += '/'; // Add a slash if it's not the last element
return (
<div className={styles.breadCrumbLinkItem}>
<Link className={styles.BreadcrumbLink} key={path} to={toPath}>
{capitalizeFirstLetter(path)}
</Link>
<span className={styles.forwardSlash}>{"/"}</span>
</div>
);
} else { // Last element
return (
<Link className={styles.BreadcrumbLinkBold} key={path} to={toPath}>
{pretty(path)}
</Link>
);
}
})
}
</div>
</div>
)
}

export default BlogBreadcrumbs

86 changes: 86 additions & 0 deletions src/components/BlogBreadcrumbs/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
.BlogBreadcrumbsContainer {
display: flex;
margin-top: 32px;
}

.BlogBreadcrumbs {
font-size: 14px;
margin-bottom: 16px;
display: flex;
}

.BreadcrumbLink {
font-weight: 400;
text-decoration: none;
}

[data-theme='light'] .BreadcrumbLink {
color: #8e8c8d !important;
}

.BreadcrumbLink:hover {
text-decoration: none;
}

/* the link + "/" (which is in a span element) */
.breadCrumbLinkItem {
display: flex;
}

.forwardSlash {
margin-left: 10px;
margin-right: 10px;
}

[data-theme='dark'] .forwardSlash {
color: #3c3c3c;
}

[data-theme='light'] .forwardSlash {
color: #8d8d8e;
}

[data-theme='dark'] .BreadcrumbLink:hover {
color: yellow !important;
}

[data-theme='light'] .BreadcrumbLink:hover {
color: #135BE6 !important;
}

.BreadcrumbLinkBold {
font-weight: 600;
cursor: default;
}

[data-theme='dark'] .BreadcrumbLinkBold {

color: white;

}

[data-theme='light'] .BreadcrumbLinkBold {
color: black;
}

.BreadcrumbLinkBold:hover {
text-decoration: none;
cursor: text;
font-weight: 600;
}

[data-theme='dark'] .BreadcrumbLinkBold:hover {
color: white;
}

[data-theme='light'] .BreadcrumbLinkBold:hover {
color: black;
}

[data-theme='dark'] .BlogBreadcrumbs .BreadcrumbLink {
color: white;
}

[data-theme='light'] .BlogBreadcrumbs .BreadcrumbLink {
color: black;
}
68 changes: 68 additions & 0 deletions src/components/ButtonGroup/ButtonGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import { HTMLAttributes, ReactNode } from "react";
import styles from './styles.module.css'

type ButtonGroupType = "default" | "borderless";

export interface ButtonGroupElementProps
extends Omit<HTMLAttributes<HTMLButtonElement>, "children"> {
value: string;
label?: ReactNode;
}

export interface ButtonGroupProps
extends Omit<HTMLAttributes<HTMLDivElement>, "onClick"> {
options: Array<ButtonGroupElementProps>;
selected?: string;
onClick?: (value: string) => void;
fillWidth?: boolean;
type?: ButtonGroupType;
}

export const ButtonGroup = ({
options,
selected,
fillWidth,
onClick,
type,
...props
}: ButtonGroupProps) => {
const lastIndex = options.length - 1;
const btns = options.map(({ value, label, ...rest }, index) => {
const position: ButtonPosition =
index === 0 ? "left" : index === lastIndex ? "right" : "center";
const isActive = value === selected;

return (
<button
key={value}
className={`${styles.button} ${isActive ? styles.active : ""} ${
styles[position]
} ${fillWidth ? styles.fillWidth : ""} ${
type === "borderless" ? styles.borderless : ""
}`}
onClick={() => onClick?.(value)}
role="button"
aria-pressed={isActive}
{...rest}
>
{label}
</button>
);
});
return (
<div
className={`${styles.buttonGroupWrapper} ${
fillWidth ? styles.fillWidth : ""
} ${type === "borderless" ? styles.borderless : ""}`}
{...props}
>
{btns}
</div>
);
};

type ButtonPosition = "left" | "center" | "right";

export default ButtonGroup;

Loading

0 comments on commit 4c51dec

Please sign in to comment.