docs: create docs workspace (#5174)
* docs: migrate ui docs to docs universe * created yarn workspace * added eslint and tsconfig configurations * fix eslint configurations * fixed eslint configurations * shared tailwind configurations * added shared ui package * added more shared components * migrating more components * made details components shared * move InlineCode component * moved InputText * moved Loading component * Moved Modal component * moved Select components * Moved Tooltip component * moved Search components * moved ColorMode provider * Moved Notification components and providers * used icons package * use UI colors in api-reference * moved Navbar component * used Navbar and Search in UI docs * added Feedback to UI docs * general enhancements * fix color mode * added copy colors file from ui-preset * added features and enhancements to UI docs * move Sidebar component and provider * general fixes and preparations for deployment * update docusaurus version * adjusted versions * fix output directory * remove rootDirectory property * fix yarn.lock * moved code component * added vale for all docs MD and MDX * fix tests * fix vale error * fix deployment errors * change ignore commands * add output directory * fix docs test * general fixes * content fixes * fix announcement script * added changeset * fix vale checks * added nofilter option * fix vale error
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
"use client"
|
||||
|
||||
import React, { useEffect, useState } from "react"
|
||||
import { request } from "@octokit/request"
|
||||
import { Link } from "@/components/Link"
|
||||
|
||||
export type SolutionsProps = {
|
||||
feedback: boolean
|
||||
message?: string
|
||||
}
|
||||
|
||||
export type GitHubSearchItem = {
|
||||
url: string
|
||||
html_url: string
|
||||
title: string
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export const Solutions = ({ feedback, message }: SolutionsProps) => {
|
||||
const [possibleSolutionsQuery, setPossibleSolutionsQuery] =
|
||||
useState<string>("")
|
||||
const [possibleSolutions, setPossibleSolutions] = useState<
|
||||
GitHubSearchItem[]
|
||||
>([])
|
||||
|
||||
function constructQuery(searchQuery: string) {
|
||||
return `${searchQuery} repo:medusajs/medusa is:closed is:issue`
|
||||
}
|
||||
|
||||
async function searchGitHub(query: string) {
|
||||
return request(`GET /search/issues`, {
|
||||
q: query,
|
||||
sort: "updated",
|
||||
per_page: 3,
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!feedback) {
|
||||
let query = constructQuery(
|
||||
// Github does not allow queries longer than 256 characters
|
||||
message ? message.substring(0, 256) : document.title
|
||||
)
|
||||
searchGitHub(query)
|
||||
.then(async (result) => {
|
||||
if (!result.data.items.length && message) {
|
||||
query = constructQuery(document.title)
|
||||
result = await searchGitHub(query)
|
||||
}
|
||||
|
||||
setPossibleSolutionsQuery(query)
|
||||
setPossibleSolutions(result.data.items)
|
||||
})
|
||||
.catch((err) => console.error(err))
|
||||
} else {
|
||||
setPossibleSolutionsQuery("")
|
||||
setPossibleSolutions([])
|
||||
}
|
||||
}, [feedback, message])
|
||||
|
||||
return (
|
||||
<>
|
||||
{possibleSolutions.length > 0 && (
|
||||
<div className="text-compact-large-plus font-normal">
|
||||
<span className="my-docs_1 mx-0 inline-block">
|
||||
If you faced a problem, here are some possible solutions from
|
||||
GitHub:
|
||||
</span>
|
||||
<ul>
|
||||
{possibleSolutions.map((solution) => (
|
||||
<li key={solution.url} className="mb-docs_0.5 last:mb-0">
|
||||
<Link href={solution.html_url} target="_blank" rel="noreferrer">
|
||||
{solution.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<span>
|
||||
Explore more issues in{" "}
|
||||
<a
|
||||
href={`https://github.com/medusajs/medusa/issues?q=${possibleSolutionsQuery}`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
the GitHub repository
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
"use client"
|
||||
|
||||
import React, { useRef, useState } from "react"
|
||||
import { CSSTransition, SwitchTransition } from "react-transition-group"
|
||||
import { Solutions } from "./Solutions"
|
||||
import { ExtraData, useAnalytics } from "@/providers/Analytics"
|
||||
import clsx from "clsx"
|
||||
import { TextArea } from "@/components/TextArea"
|
||||
import { Label } from "@/components/Label"
|
||||
import { Button } from "docs-ui"
|
||||
import { Details } from "@/components/Details"
|
||||
import { InputText } from "@/components/Input/Text"
|
||||
|
||||
export type FeedbackProps = {
|
||||
event: string
|
||||
pathName: string
|
||||
reportLink?: string
|
||||
question?: string
|
||||
positiveBtn?: string
|
||||
negativeBtn?: string
|
||||
positiveQuestion?: string
|
||||
negativeQuestion?: string
|
||||
submitBtn?: string
|
||||
submitMessage?: string
|
||||
showPossibleSolutions?: boolean
|
||||
className?: string
|
||||
extraData?: ExtraData
|
||||
vertical?: boolean
|
||||
showLongForm?: boolean
|
||||
} & React.HTMLAttributes<HTMLDivElement>
|
||||
|
||||
export const Feedback = ({
|
||||
event,
|
||||
pathName,
|
||||
reportLink,
|
||||
question = "Was this section helpful?",
|
||||
positiveBtn = "Yes",
|
||||
negativeBtn = "No",
|
||||
positiveQuestion = "What was most helpful?",
|
||||
negativeQuestion = "What can we improve?",
|
||||
submitBtn = "Submit",
|
||||
submitMessage = "Thank you for helping improve our documentation!",
|
||||
showPossibleSolutions = true,
|
||||
className = "",
|
||||
extraData = {},
|
||||
vertical = false,
|
||||
showLongForm = false,
|
||||
}: FeedbackProps) => {
|
||||
const [showForm, setShowForm] = useState(false)
|
||||
const [submittedFeedback, setSubmittedFeedback] = useState(false)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const inlineFeedbackRef = useRef<HTMLDivElement>(null)
|
||||
const inlineQuestionRef = useRef<HTMLDivElement>(null)
|
||||
const inlineMessageRef = useRef<HTMLDivElement>(null)
|
||||
const [positiveFeedback, setPositiveFeedback] = useState(false)
|
||||
const [message, setMessage] = useState("")
|
||||
const [steps, setSteps] = useState("")
|
||||
const [medusaVersion, setMedusaVersion] = useState("")
|
||||
const [errorFix, setErrorFix] = useState("")
|
||||
const [contactInfo, setContactInfo] = useState("")
|
||||
const nodeRef: React.RefObject<HTMLDivElement> = submittedFeedback
|
||||
? inlineMessageRef
|
||||
: showForm
|
||||
? inlineQuestionRef
|
||||
: inlineFeedbackRef
|
||||
const { loaded, track } = useAnalytics()
|
||||
|
||||
function handleFeedback(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
|
||||
if (!loaded) {
|
||||
return
|
||||
}
|
||||
const feedback = (e.target as Element).classList.contains("positive")
|
||||
setPositiveFeedback(feedback)
|
||||
setShowForm(true)
|
||||
submitFeedback(e, feedback)
|
||||
}
|
||||
|
||||
function submitFeedback(
|
||||
e: React.MouseEvent<HTMLButtonElement, MouseEvent>,
|
||||
feedback = false
|
||||
) {
|
||||
if (showForm) {
|
||||
setLoading(true)
|
||||
}
|
||||
track(
|
||||
event,
|
||||
{
|
||||
url: pathName,
|
||||
label: document.title,
|
||||
feedback:
|
||||
(feedback !== null && feedback) ||
|
||||
(feedback === null && positiveFeedback)
|
||||
? "yes"
|
||||
: "no",
|
||||
message: message?.length ? message : null,
|
||||
os: window.navigator.userAgent,
|
||||
...extraData,
|
||||
},
|
||||
function () {
|
||||
if (showForm) {
|
||||
setLoading(false)
|
||||
resetForm()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
setShowForm(false)
|
||||
setSubmittedFeedback(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={clsx("mt-docs_3", className)}>
|
||||
<SwitchTransition mode="out-in">
|
||||
<CSSTransition
|
||||
key={
|
||||
showForm
|
||||
? "show_form"
|
||||
: !submittedFeedback
|
||||
? "feedback"
|
||||
: "submitted_feedback"
|
||||
}
|
||||
nodeRef={nodeRef}
|
||||
timeout={300}
|
||||
addEndListener={(done) => {
|
||||
nodeRef.current?.addEventListener("transitionend", done, false)
|
||||
}}
|
||||
classNames={{
|
||||
enter: "animate-fadeIn animation-fill-forwards animate-fast",
|
||||
exit: "animate-fadeOut animation-fill-forwards animate-fast",
|
||||
}}
|
||||
>
|
||||
<>
|
||||
{!showForm && !submittedFeedback && (
|
||||
<div
|
||||
className={clsx(
|
||||
"flex",
|
||||
!vertical && "flex-row items-center",
|
||||
vertical && "flex-col justify-center gap-docs_1"
|
||||
)}
|
||||
ref={inlineFeedbackRef}
|
||||
>
|
||||
<Label className="mr-docs_1.5">{question}</Label>
|
||||
<div
|
||||
className={clsx("flex flex-row items-center gap-docs_0.5")}
|
||||
>
|
||||
<Button
|
||||
onClick={handleFeedback}
|
||||
className="positive w-fit"
|
||||
variant="secondary"
|
||||
>
|
||||
{positiveBtn}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleFeedback}
|
||||
className="w-fit"
|
||||
variant="secondary"
|
||||
>
|
||||
{negativeBtn}
|
||||
</Button>
|
||||
{reportLink && (
|
||||
<Button variant="secondary">
|
||||
<a href={reportLink}>Report Issue</a>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{showForm && !submittedFeedback && (
|
||||
<div className="flex flex-col gap-docs_1" ref={inlineQuestionRef}>
|
||||
<Label>
|
||||
{positiveFeedback ? positiveQuestion : negativeQuestion}
|
||||
</Label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
value={message}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
/>
|
||||
{showLongForm && !positiveFeedback && (
|
||||
<Details summaryContent="More Details" className="mt-docs_1">
|
||||
<div className="flex flex-col gap-docs_0.5">
|
||||
<div className="flex flex-col gap-docs_0.5">
|
||||
<Label>
|
||||
Can you provide the exact steps you took before
|
||||
receiving the error? For example, the commands you
|
||||
ran.
|
||||
</Label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
value={steps}
|
||||
onChange={(e) => setSteps(e.target.value)}
|
||||
placeholder="1. I ran npm dev..."
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-docs_0.5">
|
||||
<Label>
|
||||
If applicable, what version of Medusa are you using?
|
||||
If a plugin is related to the error, please provide a
|
||||
version of that as well.
|
||||
</Label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
value={medusaVersion}
|
||||
onChange={(e) => setMedusaVersion(e.target.value)}
|
||||
placeholder="@medusajs/medusa: vX"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-docs_0.5">
|
||||
<Label>
|
||||
Were you able to fix the error? If so, what steps did
|
||||
you follow?
|
||||
</Label>
|
||||
<TextArea
|
||||
rows={4}
|
||||
value={errorFix}
|
||||
onChange={(e) => setErrorFix(e.target.value)}
|
||||
placeholder="@medusajs/medusa: vX"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-docs_0.5">
|
||||
<Label>
|
||||
Can you provide your email or discord username? This
|
||||
would allow us to contact you for further info or
|
||||
assist you with your issue.
|
||||
</Label>
|
||||
<InputText
|
||||
value={contactInfo}
|
||||
onChange={(e) => setContactInfo(e.target.value)}
|
||||
placeholder="user@example.com"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Details>
|
||||
)}
|
||||
<Button
|
||||
onClick={submitFeedback}
|
||||
disabled={loading}
|
||||
className="w-fit"
|
||||
variant="secondary"
|
||||
>
|
||||
{submitBtn}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{submittedFeedback && (
|
||||
<div>
|
||||
<div
|
||||
className="text-compact-large-plus flex flex-col"
|
||||
ref={inlineMessageRef}
|
||||
>
|
||||
<span>{submitMessage}</span>
|
||||
{showPossibleSolutions && (
|
||||
<Solutions message={message} feedback={positiveFeedback} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
</CSSTransition>
|
||||
</SwitchTransition>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user