diff --git a/src/components/Feedback/index.jsx b/src/components/Feedback/index.jsx new file mode 100644 index 00000000000..df6eeb4797f --- /dev/null +++ b/src/components/Feedback/index.jsx @@ -0,0 +1,217 @@ +import React, { useState, useRef, useEffect } from 'react'; +import { IconButton, Popover, Title, RadioGroup, TextAreaField, Button, IconButton, Panel, Text} from '@clickhouse/click-ui/bundled' +import { getGoogleAnalyticsUserIdFromBrowserCookie } from '../../lib/google/google' +import { useColorMode } from '@docusaurus/theme-common' +import styles from './styles.module.scss' +import clsx from 'clsx' + +export default function Feedback() { + const [open, setOpen] = useState(false); + const [negResponse, setNegResponse] = useState(''); + const [comment, setComment] = useState(''); + const [selected, setSelected] = useState(''); + + const handleClick = (response) => { + //send row with google id, up or down + setSelected(response ? 'pos': 'neg') + if (!response) { + setOpen(true); + } + }; + + const handleSubmit = async (response) => { + setOpen(false); + + let gaId = getGoogleAnalyticsUserIdFromBrowserCookie('_ga') + const data = { + page_url: window.location.href, + date: new Date().toISOString().replace('T', ' ').slice(0, 19), + sentiment: response ? 'Positive' : 'Negative', + reason: response ? '' : negResponse, + google_id: gaId || 'anonymous', + comment, + }; + + const insertQuery = ` + INSERT INTO docs_feedback.feedback (page_url, date, sentiment, reason, google_id, comment) + VALUES + ('${data.page_url}', '${data.date}', '${data.sentiment}', '${data.reason}', '${data.google_id}', '${data.comment.replace(/'/g, "''")}') + `; + try { + const response = await fetch('https://sql-clickhouse.clickhouse.com', { + method: 'POST', + headers: { + 'Content-Type': 'text/plain', + }, + body: insertQuery, + headers: { + 'x-clickhouse-user': 'docs_feedback', + 'x-clickhouse-key': '', + 'Content-Type': 'text/plain', + } + }); + + if (!response.ok) { + console.error('Failed to insert feedback:', await response.text()); + } else { + console.log('Feedback submitted successfully'); + } + } catch (err) { + console.error('Error submitting feedback:', err); + } + } + + const popoverRef = useRef(); + + useEffect(() => { + function handleClickOutside(event) { + if (popoverRef.current && !popoverRef.current.contains(event.target)) { + if (open) { + handleSubmit(false); + } + } + } + + if (open) { + document.addEventListener('mousedown', handleClickOutside); + } + + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [open]); + + + + const negative_feedback = ( + +
+
+ Why was is not helpful? + handleSubmit(false) } type='ghost'/> +
+ + +
+ + + + + +
+ setComment(value)}/> +
+
+
+
+
+ ) + + const { colorMode } = useColorMode(); + + const getStroke = (highlighted, colorMode) => { + if (colorMode === 'light') { + return highlighted ? '#000' : '#696E79'; + } else { + return highlighted ? '#FAFF69' : '#B3B6BD'; + } + }; + + const ThumbsUp = ({ highlighted, colorMode }) => ( + + + + + + + + + + + + ); + + + const ThumbsDown = ({ highlighted, colorMode }) => ( + + + + + + + + + + + + ); + + + return ( + + + +
+ Was this page helpful? +
+
+
{ handleClick(true); handleSubmit(true)}}> + +
+ +
handleClick(false)}> + +
+
+ +
+ { + selected === 'neg' && negative_feedback + } +
+
+ ); +} diff --git a/src/components/Feedback/styles.module.scss b/src/components/Feedback/styles.module.scss new file mode 100644 index 00000000000..2f545f66595 --- /dev/null +++ b/src/components/Feedback/styles.module.scss @@ -0,0 +1,30 @@ +.Button { + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + cursor: pointer; + margin-right: 8px; + border: 1px solid; + background-color: transparent; + + &.dark { + border-color: #323232; + background-color: transparent; + + &.selected { + background-color: #282828; + } + } + + &.light { + border-color: #E6E7E9; + background-color: #fff; + + &.selected { + background-color: #F6F7FA; + } + } +} diff --git a/src/theme/DocItem/TOC/Desktop/index.js b/src/theme/DocItem/TOC/Desktop/index.js index 783b74e5c01..460e17fd1c5 100644 --- a/src/theme/DocItem/TOC/Desktop/index.js +++ b/src/theme/DocItem/TOC/Desktop/index.js @@ -4,20 +4,10 @@ import {useDoc} from '@docusaurus/plugin-content-docs/client'; import TOC from '@theme/TOC'; import clsx from "clsx"; import styles from './styles.module.css' -import IconClose from '@theme/Icon/Close'; +import Feedback from '../../../../components/Feedback'; export default function DocItemTOCDesktop() { const {toc, frontMatter} = useDoc(); - const [isClosed, setClosed] = useState(true) - - useEffect(() => { - const closed = - window.localStorage.getItem('doc-cloud-card-banner') === 'closed' - if (!isClosed || closed !== isClosed) { - setClosed(closed) - } - }, []) - return (
- {!isClosed && (
+
+ +
+ +
Try ClickHouse Cloud for FREE

Separation of storage and compute, automatic scaling, built-in SQL console, and lots more. $300 in free credits when signing up.

Try it for Free -
)} +
); }