mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-08-06 17:02:54 +02:00
#530 - Front Matter AI
This commit is contained in:
@@ -6,11 +6,13 @@
|
||||
|
||||
- External UI script support for dashboards
|
||||
- Visual Studio Code Theming support for the dashboards
|
||||
- Front matter AI 🤖
|
||||
|
||||
> **Info**: To enable the experimental features you need to set the `frontMatter.experimental` setting to `true`.
|
||||
|
||||
### ✨ New features
|
||||
|
||||
- [#530](https://github.com/estruyf/vscode-front-matter/issues/530): Implementation of the Front Matter AI 🤖 powered by [mendable.ai](https://mendable.ai)
|
||||
- [#513](https://github.com/estruyf/vscode-front-matter/issues/513): Added support for external UI scripts to add custom HTML on the dashboard elements
|
||||
|
||||
### 🎨 Enhancements
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#C5C5C5" d="M16 19a6.99 6.99 0 0 1-5.833-3.129l1.666-1.107a5 5 0 0 0 8.334 0l1.666 1.107A6.99 6.99 0 0 1 16 19zm4-11a2 2 0 1 0 2 2a1.98 1.98 0 0 0-2-2zm-8 0a2 2 0 1 0 2 2a1.98 1.98 0 0 0-2-2z"/>
|
||||
<path fill="#C5C5C5" d="M17.736 30L16 29l4-7h6a1.997 1.997 0 0 0 2-2V6a1.997 1.997 0 0 0-2-2H6a1.997 1.997 0 0 0-2 2v14a1.997 1.997 0 0 0 2 2h9v2H6a4 4 0 0 1-4-4V6a3.999 3.999 0 0 1 4-4h20a3.999 3.999 0 0 1 4 4v14a4 4 0 0 1-4 4h-4.835Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 540 B |
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
|
||||
<path fill="#424242" d="M16 19a6.99 6.99 0 0 1-5.833-3.129l1.666-1.107a5 5 0 0 0 8.334 0l1.666 1.107A6.99 6.99 0 0 1 16 19zm4-11a2 2 0 1 0 2 2a1.98 1.98 0 0 0-2-2zm-8 0a2 2 0 1 0 2 2a1.98 1.98 0 0 0-2-2z"/>
|
||||
<path fill="#424242" d="M17.736 30L16 29l4-7h6a1.997 1.997 0 0 0 2-2V6a1.997 1.997 0 0 0-2-2H6a1.997 1.997 0 0 0-2 2v14a1.997 1.997 0 0 0 2 2h9v2H6a4 4 0 0 1-4-4V6a3.999 3.999 0 0 1 4-4h20a3.999 3.999 0 0 1 4 4v14a4 4 0 0 1-4 4h-4.835Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 540 B |
+141
-158
@@ -10,8 +10,7 @@
|
||||
"color": "#0e131f",
|
||||
"theme": "dark"
|
||||
},
|
||||
"badges": [
|
||||
{
|
||||
"badges": [{
|
||||
"description": "version",
|
||||
"url": "https://img.shields.io/github/package-json/v/estruyf/vscode-front-matter?color=green&label=vscode-front-matter&style=flat-square",
|
||||
"href": "https://github.com/estruyf/vscode-front-matter"
|
||||
@@ -55,8 +54,7 @@
|
||||
],
|
||||
"main": "./dist/extension.js",
|
||||
"contributes": {
|
||||
"keybindings": [
|
||||
{
|
||||
"keybindings": [{
|
||||
"command": "frontMatter.dashboard",
|
||||
"key": "alt+d"
|
||||
},
|
||||
@@ -74,24 +72,20 @@
|
||||
}
|
||||
],
|
||||
"viewsContainers": {
|
||||
"activitybar": [
|
||||
{
|
||||
"id": "frontmatter-explorer",
|
||||
"title": "Front Matter",
|
||||
"icon": "assets/frontmatter-short-min.svg"
|
||||
}
|
||||
]
|
||||
"activitybar": [{
|
||||
"id": "frontmatter-explorer",
|
||||
"title": "Front Matter",
|
||||
"icon": "assets/frontmatter-short-min.svg"
|
||||
}]
|
||||
},
|
||||
"views": {
|
||||
"frontmatter-explorer": [
|
||||
{
|
||||
"id": "frontMatter.explorer",
|
||||
"name": "Front Matter",
|
||||
"icon": "assets/frontmatter-short-min.svg",
|
||||
"contextualTitle": "Front Matter",
|
||||
"type": "webview"
|
||||
}
|
||||
]
|
||||
"frontmatter-explorer": [{
|
||||
"id": "frontMatter.explorer",
|
||||
"name": "Front Matter",
|
||||
"icon": "assets/frontmatter-short-min.svg",
|
||||
"contextualTitle": "Front Matter",
|
||||
"type": "webview"
|
||||
}]
|
||||
},
|
||||
"configuration": {
|
||||
"title": "Front Matter: use frontmatter.json for shared team settings",
|
||||
@@ -126,8 +120,7 @@
|
||||
"frontMatter.content.defaultFileType": {
|
||||
"type": "string",
|
||||
"default": "md",
|
||||
"oneOf": [
|
||||
{
|
||||
"oneOf": [{
|
||||
"enum": [
|
||||
"md",
|
||||
"mdx"
|
||||
@@ -143,8 +136,7 @@
|
||||
"frontMatter.content.defaultSorting": {
|
||||
"type": "string",
|
||||
"default": "",
|
||||
"oneOf": [
|
||||
{
|
||||
"oneOf": [{
|
||||
"enum": [
|
||||
"LastModifiedAsc",
|
||||
"LastModifiedDesc",
|
||||
@@ -471,8 +463,7 @@
|
||||
"command": {
|
||||
"$id": "#scriptCommand",
|
||||
"type": "string",
|
||||
"oneOf": [
|
||||
{
|
||||
"oneOf": [{
|
||||
"enum": [
|
||||
"node",
|
||||
"bash",
|
||||
@@ -646,8 +637,7 @@
|
||||
"title",
|
||||
"file"
|
||||
],
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [{
|
||||
"required": [
|
||||
"schema"
|
||||
]
|
||||
@@ -701,8 +691,7 @@
|
||||
"id",
|
||||
"path"
|
||||
],
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [{
|
||||
"required": [
|
||||
"schema"
|
||||
]
|
||||
@@ -1048,8 +1037,7 @@
|
||||
"default": "",
|
||||
"description": "The ID of your taxonomy field. It cannot contain the \"tags\" or \"categories\" value.",
|
||||
"not": {
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [{
|
||||
"const": ""
|
||||
},
|
||||
{
|
||||
@@ -1209,8 +1197,7 @@
|
||||
"type",
|
||||
"name"
|
||||
],
|
||||
"allOf": [
|
||||
{
|
||||
"allOf": [{
|
||||
"if": {
|
||||
"properties": {
|
||||
"type": {
|
||||
@@ -1368,51 +1355,48 @@
|
||||
"fields"
|
||||
]
|
||||
},
|
||||
"default": [
|
||||
{
|
||||
"name": "default",
|
||||
"pageBundle": false,
|
||||
"fields": [
|
||||
{
|
||||
"title": "Title",
|
||||
"name": "title",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Description",
|
||||
"name": "description",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Publishing date",
|
||||
"name": "date",
|
||||
"type": "datetime",
|
||||
"default": "{{now}}",
|
||||
"isPublishDate": true
|
||||
},
|
||||
{
|
||||
"title": "Content preview",
|
||||
"name": "preview",
|
||||
"type": "image"
|
||||
},
|
||||
{
|
||||
"title": "Is in draft",
|
||||
"name": "draft",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"title": "Tags",
|
||||
"name": "tags",
|
||||
"type": "tags"
|
||||
},
|
||||
{
|
||||
"title": "Categories",
|
||||
"name": "categories",
|
||||
"type": "categories"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"default": [{
|
||||
"name": "default",
|
||||
"pageBundle": false,
|
||||
"fields": [{
|
||||
"title": "Title",
|
||||
"name": "title",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Description",
|
||||
"name": "description",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"title": "Publishing date",
|
||||
"name": "date",
|
||||
"type": "datetime",
|
||||
"default": "{{now}}",
|
||||
"isPublishDate": true
|
||||
},
|
||||
{
|
||||
"title": "Content preview",
|
||||
"name": "preview",
|
||||
"type": "image"
|
||||
},
|
||||
{
|
||||
"title": "Is in draft",
|
||||
"name": "draft",
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"title": "Tags",
|
||||
"name": "tags",
|
||||
"type": "tags"
|
||||
},
|
||||
{
|
||||
"title": "Categories",
|
||||
"name": "categories",
|
||||
"type": "categories"
|
||||
}
|
||||
]
|
||||
}],
|
||||
"scope": "Taxonomy"
|
||||
},
|
||||
"frontMatter.taxonomy.customTaxonomy": {
|
||||
@@ -1425,8 +1409,7 @@
|
||||
"type": "string",
|
||||
"description": "ID for your taxonomy field. It cannot contain the \"tags\" or \"categories\" value.",
|
||||
"not": {
|
||||
"anyOf": [
|
||||
{
|
||||
"anyOf": [{
|
||||
"const": ""
|
||||
},
|
||||
{
|
||||
@@ -1608,8 +1591,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"commands": [{
|
||||
"command": "frontMatter.config.reload",
|
||||
"title": "Reload config",
|
||||
"category": "Front Matter"
|
||||
@@ -1870,8 +1852,12 @@
|
||||
},
|
||||
{
|
||||
"command": "frontMatter.chatbot",
|
||||
"title": "Ask a bot to help you configure Front Matter",
|
||||
"category": "Front Matter"
|
||||
"title": "Ask the Front Matter AI for help",
|
||||
"category": "Front Matter",
|
||||
"icon": {
|
||||
"light": "assets/icons/chatbot-light.svg",
|
||||
"dark": "assets/icons/chatbot-dark.svg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "frontMatter.promoteSettings",
|
||||
@@ -1928,15 +1914,12 @@
|
||||
"category": "Front Matter"
|
||||
}
|
||||
],
|
||||
"submenus": [
|
||||
{
|
||||
"id": "frontmatter.submenu",
|
||||
"label": "Front Matter"
|
||||
}
|
||||
],
|
||||
"submenus": [{
|
||||
"id": "frontmatter.submenu",
|
||||
"label": "Front Matter"
|
||||
}],
|
||||
"menus": {
|
||||
"editor/title": [
|
||||
{
|
||||
"editor/title": [{
|
||||
"command": "frontMatter.markup.heading",
|
||||
"group": "navigation@-133",
|
||||
"when": "frontMatter:file:isValid == true && frontMatter:markdown:wysiwyg"
|
||||
@@ -2010,16 +1993,18 @@
|
||||
"command": "frontMatter.dashboard.close",
|
||||
"group": "navigation@-98",
|
||||
"when": "frontMatter:enabled == true && frontMatter:dashboard:open == true"
|
||||
},
|
||||
{
|
||||
"command": "frontMatter.chatbot",
|
||||
"group": "navigation@-97",
|
||||
"when": "resourceFilename == 'frontmatter.json'"
|
||||
}
|
||||
],
|
||||
"explorer/context": [
|
||||
{
|
||||
"submenu": "frontmatter.submenu",
|
||||
"group": "frontmatter@1"
|
||||
}
|
||||
],
|
||||
"frontmatter.submenu": [
|
||||
{
|
||||
"explorer/context": [{
|
||||
"submenu": "frontmatter.submenu",
|
||||
"group": "frontmatter@1"
|
||||
}],
|
||||
"frontmatter.submenu": [{
|
||||
"command": "frontMatter.createFromTemplate",
|
||||
"when": "explorerResourceIsFolder",
|
||||
"group": "frontmatter@1"
|
||||
@@ -2035,8 +2020,7 @@
|
||||
"group": "frontmatter@3"
|
||||
}
|
||||
],
|
||||
"commandPalette": [
|
||||
{
|
||||
"commandPalette": [{
|
||||
"command": "frontMatter.init",
|
||||
"when": "frontMatterCanInit"
|
||||
},
|
||||
@@ -2177,75 +2161,74 @@
|
||||
"when": "frontMatter:file:isValid == true"
|
||||
}
|
||||
],
|
||||
"view/title": [
|
||||
{
|
||||
"command": "frontMatter.collapseSections",
|
||||
"view/title": [{
|
||||
"command": "frontMatter.chatbot",
|
||||
"group": "navigation@0",
|
||||
"when": "view == frontMatter.explorer"
|
||||
},
|
||||
{
|
||||
"command": "frontMatter.mode.switch",
|
||||
"command": "frontMatter.collapseSections",
|
||||
"group": "navigation@1",
|
||||
"when": "view == frontMatter.explorer"
|
||||
},
|
||||
{
|
||||
"command": "frontMatter.mode.switch",
|
||||
"group": "navigation@2",
|
||||
"when": "view == frontMatter.explorer && frontMatter:has:modes == true"
|
||||
},
|
||||
{
|
||||
"command": "frontMatter.dashboard",
|
||||
"group": "navigation@2",
|
||||
"group": "navigation@3",
|
||||
"when": "view == frontMatter.explorer || view == explorer"
|
||||
}
|
||||
]
|
||||
},
|
||||
"grammars": [
|
||||
{
|
||||
"path": "./syntaxes/hugo.tmLanguage.json",
|
||||
"scopeName": "frontmatter.markdown.hugo",
|
||||
"injectTo": [
|
||||
"text.html.markdown"
|
||||
]
|
||||
}
|
||||
],
|
||||
"walkthroughs": [
|
||||
{
|
||||
"id": "frontmatter.welcome",
|
||||
"title": "Get started with Front Matter",
|
||||
"description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
|
||||
"steps": [
|
||||
{
|
||||
"id": "frontmatter.welcome.init",
|
||||
"title": "Get started",
|
||||
"description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/get-started.md"
|
||||
},
|
||||
"completionEvents": [
|
||||
"onContext:frontMatterInitialized"
|
||||
]
|
||||
"grammars": [{
|
||||
"path": "./syntaxes/hugo.tmLanguage.json",
|
||||
"scopeName": "frontmatter.markdown.hugo",
|
||||
"injectTo": [
|
||||
"text.html.markdown"
|
||||
]
|
||||
}],
|
||||
"walkthroughs": [{
|
||||
"id": "frontmatter.welcome",
|
||||
"title": "Get started with Front Matter",
|
||||
"description": "Discover the features of Front Matter and learn how to use the CMS for your SSG or static site.",
|
||||
"steps": [{
|
||||
"id": "frontmatter.welcome.init",
|
||||
"title": "Get started",
|
||||
"description": "Initial steps to get started.\n[Open dashboard](command:frontMatter.dashboard)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/get-started.md"
|
||||
},
|
||||
{
|
||||
"id": "frontmatter.welcome.documentation",
|
||||
"title": "Documentation",
|
||||
"description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/documentation.md"
|
||||
},
|
||||
"completionEvents": [
|
||||
"onLink:https://frontmatter.codes/docs"
|
||||
]
|
||||
"completionEvents": [
|
||||
"onContext:frontMatterInitialized"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "frontmatter.welcome.documentation",
|
||||
"title": "Documentation",
|
||||
"description": "Check out the documentation for Front Matter.\n[View our documentation](https://frontmatter.codes/docs)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/documentation.md"
|
||||
},
|
||||
{
|
||||
"id": "frontmatter.welcome.supporter",
|
||||
"title": "Support the project",
|
||||
"description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/support-the-project.md"
|
||||
},
|
||||
"completionEvents": [
|
||||
"onLink:https://github.com/sponsors/estruyf"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
"completionEvents": [
|
||||
"onLink:https://frontmatter.codes/docs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "frontmatter.welcome.supporter",
|
||||
"title": "Support the project",
|
||||
"description": "Become a supporter.\n[Support the project](https://github.com/sponsors/estruyf)",
|
||||
"media": {
|
||||
"markdown": "assets/walkthrough/support-the-project.md"
|
||||
},
|
||||
"completionEvents": [
|
||||
"onLink:https://github.com/sponsors/estruyf"
|
||||
]
|
||||
}
|
||||
]
|
||||
}]
|
||||
},
|
||||
"scripts": {
|
||||
"dev:ext": "npm run clean && npm-run-all --parallel watch:*",
|
||||
@@ -2375,4 +2358,4 @@
|
||||
"vsce": {
|
||||
"dependencies": false
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-21
@@ -1,26 +1,9 @@
|
||||
import { processFmPlaceholders } from './../helpers/processFmPlaceholders';
|
||||
import { processPathPlaceholders } from './../helpers/processPathPlaceholders';
|
||||
import { Telemetry } from './../helpers/Telemetry';
|
||||
import {
|
||||
SETTING_PREVIEW_HOST,
|
||||
SETTING_PREVIEW_PATHNAME,
|
||||
CONTEXT,
|
||||
TelemetryEvent,
|
||||
PreviewCommands,
|
||||
SETTING_EXPERIMENTAL,
|
||||
SETTING_DATE_FORMAT
|
||||
} from './../constants';
|
||||
import { ArticleHelper } from './../helpers/ArticleHelper';
|
||||
import { TelemetryEvent, PreviewCommands, SETTING_EXPERIMENTAL } from './../constants';
|
||||
import { join } from 'path';
|
||||
import { commands, env, Uri, ViewColumn, window } from 'vscode';
|
||||
import { Extension, parseWinPath, processKnownPlaceholders, Settings } from '../helpers';
|
||||
import { ContentFolder, ContentType, PreviewSettings } from '../models';
|
||||
import { format } from 'date-fns';
|
||||
import { DateHelper } from '../helpers/DateHelper';
|
||||
import { Article } from '.';
|
||||
import { urlJoin } from 'url-join-ts';
|
||||
import { commands, Uri, ViewColumn, window } from 'vscode';
|
||||
import { Extension, Settings } from '../helpers';
|
||||
import { WebviewHelper } from '@estruyf/vscode';
|
||||
import { Folders } from './Folders';
|
||||
|
||||
export class Chatbot {
|
||||
/**
|
||||
@@ -30,7 +13,7 @@ export class Chatbot {
|
||||
// Create the preview webview
|
||||
const webView = window.createWebviewPanel(
|
||||
'frontMatterChatbot',
|
||||
'Front Matter - Ask me anything',
|
||||
'Front Matter AI - Ask me anything',
|
||||
{
|
||||
viewColumn: ViewColumn.Beside,
|
||||
preserveFocus: true
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface IChatIconProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const ChatIcon: React.FunctionComponent<IChatIconProps> = ({ className }: React.PropsWithChildren<IChatIconProps>) => {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className={className || 'h-4 w-4'} viewBox="0 0 32 32">
|
||||
<path fill="currentcolor" d="M16 19a6.99 6.99 0 0 1-5.833-3.129l1.666-1.107a5 5 0 0 0 8.334 0l1.666 1.107A6.99 6.99 0 0 1 16 19zm4-11a2 2 0 1 0 2 2a1.98 1.98 0 0 0-2-2zm-8 0a2 2 0 1 0 2 2a1.98 1.98 0 0 0-2-2z" />
|
||||
<path fill="currentcolor" d="M17.736 30L16 29l4-7h6a1.997 1.997 0 0 0 2-2V6a1.997 1.997 0 0 0-2-2H6a1.997 1.997 0 0 0-2 2v14a1.997 1.997 0 0 0 2 2h9v2H6a4 4 0 0 1-4-4V6a3.999 3.999 0 0 1 4-4h20a3.999 3.999 0 0 1 4 4v14a4 4 0 0 1-4 4h-4.835Z" />
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
import * as React from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import { Feedback } from './Feedback';
|
||||
|
||||
export interface IAnswerProps {
|
||||
answer: string;
|
||||
answerId: number;
|
||||
sources: string[];
|
||||
}
|
||||
|
||||
export const Answer: React.FunctionComponent<IAnswerProps> = ({
|
||||
answer,
|
||||
answerId,
|
||||
sources,
|
||||
}: React.PropsWithChildren<IAnswerProps>) => {
|
||||
if (!answer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<li className='answer'>
|
||||
<div className='text-lg flex justify-between'>
|
||||
<p>Answer</p>
|
||||
|
||||
<Feedback answerId={answerId} />
|
||||
</div>
|
||||
|
||||
<ReactMarkdown children={answer} remarkPlugins={[remarkGfm]} />
|
||||
|
||||
{
|
||||
sources && sources.length > 0 && (
|
||||
<div>
|
||||
<p className='text-lg'>Resources</p>
|
||||
<ul className={`space-y-2 list-disc pl-4`}>
|
||||
{sources.map((source, idx) => (
|
||||
<li key={`source-${idx}`} className={`text-sm`}>
|
||||
<a className={`text-[var(--vscode-textLink-foreground)] hover:text-[var(--vscode-textLink-activeForeground)]`} href={source} target="_blank" rel="noreferrer">{source}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
<div className={`-mx-4 -mb-4 py-2 px-4 bg-[var(--vscode-sideBar-background)] text-[var(--vscode-sideBarTitle-foreground)] text-xs rounded-b`} style={{
|
||||
fontFamily: "var(--vscode-editor-font-family)",
|
||||
}}>
|
||||
Warning: Anwers might be wrong. In case of doubt, please consult the docs.
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
@@ -2,36 +2,35 @@ import * as React from 'react';
|
||||
import { InitResponse } from './models/InitResponse';
|
||||
import { NewConversationResponse } from './models/NewConversationResponse';
|
||||
import { fetchEventSource } from '@microsoft/fetch-event-source';
|
||||
import { ChatIcon, PaperAirplaneIcon, ThumbDownIcon, ThumbUpIcon } from '@heroicons/react/outline';
|
||||
import { ThumbDownIcon as ThumbDownSolidIcon, ThumbUpIcon as ThumbUpSolidIcon } from '@heroicons/react/solid';
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { Header } from './Header';
|
||||
import { Chatbox } from './Chatbox';
|
||||
import { Loader } from './Loader';
|
||||
import { QuestionAnswer } from './QuestionAnswer';
|
||||
import { Placeholder } from './Placeholder';
|
||||
import { useSettingsContext } from '../../providers/SettingsProvider';
|
||||
|
||||
export interface IChatbotProps { }
|
||||
|
||||
export const Chatbot: React.FunctionComponent<IChatbotProps> = (props: React.PropsWithChildren<IChatbotProps>) => {
|
||||
export const Chatbot: React.FunctionComponent<IChatbotProps> = ({ }: React.PropsWithChildren<IChatbotProps>) => {
|
||||
const { aiKey, aiUrl } = useSettingsContext();
|
||||
const [company, setCompany] = React.useState<string | undefined>(undefined);
|
||||
const [chatId, setChatId] = React.useState<number | undefined>(undefined);
|
||||
const [message, setMessage] = React.useState<string>("");
|
||||
const [questions, setQuestions] = React.useState<string[]>([]);
|
||||
const [answers, setAnswers] = React.useState<string[]>([]);
|
||||
const [answerIds, setAnswerIds] = React.useState<number[]>([]);
|
||||
const [sources, setSources] = React.useState<string[][]>([]);
|
||||
const [loading, setLoading] = React.useState<boolean>(false);
|
||||
|
||||
const [upVote, setUpVotes] = React.useState<number[]>([]);
|
||||
const [downVote, setDownvotes] = React.useState<number[]>([]);
|
||||
|
||||
const init = async () => {
|
||||
setLoading(true);
|
||||
const initResponse = await fetch('https://aijsplayground-production.up.railway.app/initializeMendable', {
|
||||
const initResponse = await fetch(`${aiUrl}/initializeMendable`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
anon_key: "466f5321-12d9-4d64-9e5b-ea5db41ed2ba"
|
||||
anon_key: aiKey
|
||||
})
|
||||
});
|
||||
|
||||
@@ -41,13 +40,13 @@ export const Chatbot: React.FunctionComponent<IChatbotProps> = (props: React.Pro
|
||||
|
||||
const initJson: InitResponse = await initResponse.json();
|
||||
|
||||
const newChatResponse = await fetch('https://aijsplayground-production.up.railway.app/newConversation', {
|
||||
const newChatResponse = await fetch(`${aiUrl}/newConversation`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
anon_key: "466f5321-12d9-4d64-9e5b-ea5db41ed2ba",
|
||||
anon_key: aiKey,
|
||||
messages: []
|
||||
})
|
||||
})
|
||||
@@ -63,31 +62,7 @@ export const Chatbot: React.FunctionComponent<IChatbotProps> = (props: React.Pro
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const onUpVote = useCallback(async (index: number) => {
|
||||
setUpVotes(prev => [...prev, index])
|
||||
setDownvotes(prev => prev.filter(i => i !== index))
|
||||
callVote(index, true)
|
||||
}, []);
|
||||
|
||||
const onDownVote = useCallback(async (index: number) => {
|
||||
setDownvotes(prev => [...prev, index])
|
||||
setUpVotes(prev => prev.filter(i => i !== index))
|
||||
callVote(index, false)
|
||||
}, []);
|
||||
|
||||
const callVote = async (index: number, vote: boolean) => {
|
||||
await fetch(`https://aijsplayground-production.up.railway.app/updateMessageRating/${index}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
ratingValue: vote ? 1 : -1,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const callChatbot = useCallback(async () => {
|
||||
const callChatbot = useCallback(async (message) => {
|
||||
const nrOfQuestions = questions.length + 1;
|
||||
setLoading(true);
|
||||
|
||||
@@ -96,15 +71,11 @@ export const Chatbot: React.FunctionComponent<IChatbotProps> = (props: React.Pro
|
||||
setSources(prev => [...prev, []])
|
||||
setAnswerIds(prev => [...prev, 0])
|
||||
|
||||
setTimeout(() => {
|
||||
setMessage("")
|
||||
}, 0);
|
||||
|
||||
if (!company || !chatId) {
|
||||
return;
|
||||
}
|
||||
|
||||
await fetchEventSource('https://aijsplayground-production.up.railway.app/qaChat', {
|
||||
await fetchEventSource(`${aiUrl}/qaChat`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -159,7 +130,7 @@ export const Chatbot: React.FunctionComponent<IChatbotProps> = (props: React.Pro
|
||||
}
|
||||
}
|
||||
});
|
||||
}, [company, chatId, message, questions]);
|
||||
}, [company, chatId, questions]);
|
||||
|
||||
useEffect(() => {
|
||||
init();
|
||||
@@ -167,130 +138,32 @@ export const Chatbot: React.FunctionComponent<IChatbotProps> = (props: React.Pro
|
||||
|
||||
return (
|
||||
<div className={`flex flex-col overflow-x-hidden h-full w-full items-center overflow-hidden`}>
|
||||
<header className={`w-full max-w-xl m-4`}>
|
||||
<h1 className='text-2xl flex items-center space-x-4'>
|
||||
<ChatIcon className='h-6 w-6' />
|
||||
<span>Ask Font Matter AI</span>
|
||||
</h1>
|
||||
<h2
|
||||
className='mt-2 text-sm text-[var(--frontmatter-secondary-text)]'
|
||||
style={{
|
||||
fontFamily: "var(--vscode-editor-font-family)",
|
||||
}}
|
||||
>
|
||||
Our AI, powered by <a className={`text-[var(--vscode-textLink-foreground)] hover:text-[var(--vscode-textLink-activeForeground)]`} href={`https://www.mendable.ai/`} title={`mendable.ai`}>mendable.ai</a>, has processed the documentation and can assist you with any queries regarding Front Matter. Go ahead and ask away!
|
||||
</h2>
|
||||
</header>
|
||||
<Header />
|
||||
|
||||
<div className='w-full h-[1px] bg-[var(--frontmatter-border)] mb-4'></div>
|
||||
<div className='w-full h-[1px] bg-[var(--frontmatter-border)] -mx-4 mb-4'></div>
|
||||
|
||||
<main className={`qa__bot flex-grow w-full max-w-xl overflow-y-auto overflow-x-hidden`}>
|
||||
<div>
|
||||
{
|
||||
questions.map((question, idx) => (
|
||||
<ul key={`question-${idx}`} className={`space-y-4`}>
|
||||
<li className='question'>{question}</li>
|
||||
{answers.length > 0 && answers[idx] && (
|
||||
<li className='answer'>
|
||||
<div className='text-lg flex justify-between'>
|
||||
<p>Answer</p>
|
||||
|
||||
{
|
||||
answerIds[idx] && (
|
||||
<div className='text-lg flex gap-4'>
|
||||
<button
|
||||
className='hover:text-[var(--vscode-textLink-activeForeground)]'
|
||||
onClick={() => onUpVote(answerIds[idx])}>
|
||||
{
|
||||
upVote.includes(answerIds[idx]) ? (
|
||||
<ThumbUpSolidIcon className='h-4 w-4 text-[var(--vscode-textLink-foreground)]' />
|
||||
) : (
|
||||
<ThumbUpIcon className='h-4 w-4' />
|
||||
)
|
||||
}
|
||||
</button>
|
||||
<button
|
||||
className='hover:text-[var(--vscode-textLink-activeForeground)]'
|
||||
onClick={() => onDownVote(answerIds[idx])}>
|
||||
{
|
||||
downVote.includes(answerIds[idx]) ? (
|
||||
<ThumbDownSolidIcon className='h-4 w-4 text-[var(--vscode-textLink-foreground)]' />
|
||||
) : (
|
||||
<ThumbDownIcon className='h-4 w-4' />
|
||||
)
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
<ReactMarkdown children={answers[idx]} remarkPlugins={[remarkGfm]} />
|
||||
|
||||
{
|
||||
sources[idx].length > 0 && sources[idx] && (
|
||||
<div>
|
||||
<p className='text-lg'>Resources</p>
|
||||
<ul className={`space-y-2 list-disc pl-4`}>
|
||||
{sources[idx].map((source, idx) => (
|
||||
<li key={`source-${idx}`} className={`text-sm`}>
|
||||
<a className={`text-[var(--vscode-textLink-foreground)] hover:text-[var(--vscode-textLink-activeForeground)]`} href={source} target="_blank" rel="noreferrer">{source}</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
<div className={`-mx-4 -mb-4 py-2 px-4 bg-[var(--vscode-sideBar-background)] text-[var(--vscode-sideBarTitle-foreground)] rounded-b`} style={{
|
||||
fontFamily: "var(--vscode-editor-font-family)",
|
||||
}}>
|
||||
Warning: Anwers might be wrong. In case of doubt, please consult the docs.
|
||||
</div>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
{
|
||||
questions && questions.length > 0 ? questions.map((question, idx) => (
|
||||
<QuestionAnswer
|
||||
key={idx}
|
||||
question={question}
|
||||
answer={answers[idx]}
|
||||
answerId={answerIds[idx]}
|
||||
sources={sources[idx]} />
|
||||
)) : (
|
||||
<Placeholder />
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
loading && (
|
||||
<div>
|
||||
<div className="mt-4 flex items-center justify-center space-x-2 animate-pulse">
|
||||
<div className="w-4 h-4 bg-[var(--frontmatter-button-background)] rounded-full"></div>
|
||||
<div className="w-4 h-4 bg-[var(--frontmatter-button-background)] rounded-full"></div>
|
||||
<div className="w-4 h-4 bg-[var(--frontmatter-button-background)] rounded-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
loading && (questions && questions.length > 0) && <Loader />
|
||||
}
|
||||
</main>
|
||||
|
||||
<footer className={`w-full max-w-xl relative my-4`}>
|
||||
<textarea
|
||||
className={`resize-none w-full outline-none border-0`}
|
||||
placeholder='How should I configure Front Matter?'
|
||||
autoFocus={true}
|
||||
value={message}
|
||||
cols={30}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
callChatbot();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Chatbox isLoading={loading} onTrigger={callChatbot} />
|
||||
|
||||
<button
|
||||
className={`absolute right-3 top-3 text-[var(--frontmatter-button-background)] hover:text-[var(--frontmatter-button-hoverBackground)] disabled:opacity-50 disabled:text-[var(--vscode-disabledForeground)]`}
|
||||
type='button'
|
||||
disabled={message.trim().length === 0 || loading}
|
||||
onClick={callChatbot}
|
||||
>
|
||||
<PaperAirplaneIcon className='h-6 w-6 rotate-90' />
|
||||
</button>
|
||||
</footer>
|
||||
<img className='hidden' src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Ffrontmatter.codes%2Fmetrics%2Fdashboards&slug=chatbot" alt="Chatbot metrics" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
import { PaperAirplaneIcon } from '@heroicons/react/outline';
|
||||
import * as React from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import useThemeColors from '../../hooks/useThemeColors';
|
||||
|
||||
export interface IChatboxProps {
|
||||
isLoading: boolean;
|
||||
onTrigger: (message: string) => void;
|
||||
}
|
||||
|
||||
export const Chatbox: React.FunctionComponent<IChatboxProps> = ({ isLoading, onTrigger }: React.PropsWithChildren<IChatboxProps>) => {
|
||||
const [message, setMessage] = React.useState<string>("");
|
||||
const [isFocussed, setIsFocussed] = React.useState<boolean>(false);
|
||||
const { getColors } = useThemeColors();
|
||||
|
||||
const callAi = useCallback(() => {
|
||||
setTimeout(() => {
|
||||
setMessage("")
|
||||
}, 0);
|
||||
|
||||
onTrigger(message);
|
||||
}, [message]);
|
||||
|
||||
return (
|
||||
<footer className={`w-full mt-4 bg-[var(--vscode-input-background)] border-t ${isFocussed ? "border-[var(--vscode-focusBorder)]" : "border-[var(--frontmatter-border)]"}`}>
|
||||
<div className={`w-full max-w-xl relative pb-4 mx-auto`}>
|
||||
<div className='chatbox px-4'>
|
||||
<textarea
|
||||
className={`
|
||||
resize-none w-full outline-none border-0 pr-8
|
||||
${getColors(
|
||||
'focus:outline-none border-gray-300 text-vulcan-500',
|
||||
'border-transparent bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] placeholder-[var(--vscode-input-placeholderForeground)] focus:outline-none focus:border-transparent'
|
||||
)}`}
|
||||
placeholder='How can I configure Front Matter?'
|
||||
autoFocus={true}
|
||||
value={message}
|
||||
cols={30}
|
||||
onChange={(e) => setMessage(e.target.value)}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter') {
|
||||
callAi();
|
||||
}
|
||||
}}
|
||||
onFocus={() => setIsFocussed(true)}
|
||||
onBlur={() => setIsFocussed(false)}
|
||||
/>
|
||||
|
||||
<button
|
||||
className={`absolute right-6 top-3 text-[var(--frontmatter-button-background)] hover:text-[var(--frontmatter-button-hoverBackground)] disabled:opacity-50 disabled:text-[var(--vscode-disabledForeground)]`}
|
||||
type='button'
|
||||
disabled={message.trim().length === 0 || isLoading}
|
||||
onClick={callAi}
|
||||
>
|
||||
<PaperAirplaneIcon className='h-6 w-6 rotate-90' />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
import * as React from 'react';
|
||||
import { ThumbDownIcon, ThumbUpIcon } from '@heroicons/react/outline';
|
||||
import { ThumbDownIcon as ThumbDownSolidIcon, ThumbUpIcon as ThumbUpSolidIcon } from '@heroicons/react/solid';
|
||||
import { useCallback } from 'react';
|
||||
import { useSettingsContext } from '../../providers/SettingsProvider';
|
||||
|
||||
export interface IFeedbackProps {
|
||||
answerId: number;
|
||||
}
|
||||
|
||||
export const Feedback: React.FunctionComponent<IFeedbackProps> = ({
|
||||
answerId
|
||||
}: React.PropsWithChildren<IFeedbackProps>) => {
|
||||
const { aiUrl } = useSettingsContext();
|
||||
const [isUpVoted, setIsUpVoted] = React.useState<boolean>(false);
|
||||
const [isDownVoted, setIsDownVoted] = React.useState<boolean>(false);
|
||||
|
||||
const onUpVote = useCallback(() => {
|
||||
setIsUpVoted(true)
|
||||
setIsDownVoted(false)
|
||||
callVote(true)
|
||||
}, []);
|
||||
|
||||
const onDownVote = useCallback(() => {
|
||||
setIsDownVoted(true)
|
||||
setIsUpVoted(false)
|
||||
callVote(false)
|
||||
}, []);
|
||||
|
||||
const callVote = useCallback(async (vote: boolean) => {
|
||||
await fetch(`${aiUrl}/updateMessageRating/${answerId}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
ratingValue: vote ? 1 : -1,
|
||||
})
|
||||
})
|
||||
}, [answerId])
|
||||
|
||||
if (!answerId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='text-lg flex gap-4'>
|
||||
<button
|
||||
className='hover:text-[var(--vscode-textLink-activeForeground)]'
|
||||
onClick={onUpVote}>
|
||||
{
|
||||
isUpVoted ? (
|
||||
<ThumbUpSolidIcon className='h-4 w-4 text-[var(--vscode-textLink-foreground)]' />
|
||||
) : (
|
||||
<ThumbUpIcon className='h-4 w-4' />
|
||||
)
|
||||
}
|
||||
</button>
|
||||
<button
|
||||
className='hover:text-[var(--vscode-textLink-activeForeground)]'
|
||||
onClick={() => onDownVote()}>
|
||||
{
|
||||
isDownVoted ? (
|
||||
<ThumbDownSolidIcon className='h-4 w-4 text-[var(--vscode-textLink-foreground)]' />
|
||||
) : (
|
||||
<ThumbDownIcon className='h-4 w-4' />
|
||||
)
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import * as React from 'react';
|
||||
import { ChatIcon } from '../../../components/icons/ChatIcon';
|
||||
|
||||
export interface IHeaderProps { }
|
||||
|
||||
export const Header: React.FunctionComponent<IHeaderProps> = (props: React.PropsWithChildren<IHeaderProps>) => {
|
||||
return (
|
||||
<header className={`w-full max-w-xl m-4 px-4`}>
|
||||
<h1 className='text-2xl flex items-center space-x-4'>
|
||||
<ChatIcon className='h-6 w-6' />
|
||||
<span>Ask Front Matter AI</span>
|
||||
</h1>
|
||||
<h2
|
||||
className='mt-2 text-sm text-[var(--frontmatter-secondary-text)]'
|
||||
style={{
|
||||
fontFamily: "var(--vscode-editor-font-family)",
|
||||
}}
|
||||
>
|
||||
Our AI, powered by <a className={`text-[var(--vscode-textLink-foreground)] hover:text-[var(--vscode-textLink-activeForeground)]`} href={`https://www.mendable.ai/`} title={`mendable.ai`}>mendable.ai</a>, has processed the documentation and can assist you with any queries regarding Front Matter. Go ahead and ask away!
|
||||
</h2>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface ILoaderProps { }
|
||||
|
||||
export const Loader: React.FunctionComponent<ILoaderProps> = (props: React.PropsWithChildren<ILoaderProps>) => {
|
||||
return (
|
||||
<div>
|
||||
<div className="mt-4 flex items-center justify-center space-x-2 animate-pulse">
|
||||
<div className="w-4 h-4 bg-[var(--frontmatter-button-background)] rounded-full"></div>
|
||||
<div className="w-4 h-4 bg-[var(--frontmatter-button-background)] rounded-full"></div>
|
||||
<div className="w-4 h-4 bg-[var(--frontmatter-button-background)] rounded-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import * as React from 'react';
|
||||
import { ChatIcon } from '../../../components/icons/ChatIcon';
|
||||
|
||||
export interface IPlaceholderProps { }
|
||||
|
||||
export const Placeholder: React.FunctionComponent<IPlaceholderProps> = (props: React.PropsWithChildren<IPlaceholderProps>) => {
|
||||
return (
|
||||
<div className='w-full h-full flex flex-col gap-2 items-center justify-center text-[var(--frontmatter-secondary-text)] opacity-80'>
|
||||
<ChatIcon className='h-16 w-16 text-[var(--vscode-sideBarTitle-foreground)]' />
|
||||
|
||||
<div className='text-[var(--vscode-sideBarTitle-foreground)] text-2xl mt-4'>
|
||||
Start by asking a question
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import * as React from 'react';
|
||||
import { Answer } from './Answer';
|
||||
|
||||
export interface IQuestionAnswerProps {
|
||||
question: string;
|
||||
answer: string;
|
||||
answerId: number;
|
||||
sources: string[];
|
||||
}
|
||||
|
||||
export const QuestionAnswer: React.FunctionComponent<IQuestionAnswerProps> = ({ question, answer, answerId, sources }: React.PropsWithChildren<IQuestionAnswerProps>) => {
|
||||
return (
|
||||
<ul className={`space-y-4 px-4`}>
|
||||
<li className='question'>{question}</li>
|
||||
|
||||
<Answer
|
||||
answer={answer}
|
||||
answerId={answerId}
|
||||
sources={sources} />
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
@@ -43,6 +43,8 @@ export const Contents: React.FunctionComponent<IContentsProps> = ({
|
||||
version={settings?.versionInfo}
|
||||
isBacker={settings?.isBacker}
|
||||
/>
|
||||
|
||||
<img className='hidden' src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Ffrontmatter.codes%2Fmetrics%2Fdashboards&slug=content" alt="Content metrics" />
|
||||
</PageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -317,6 +317,8 @@ export const DataView: React.FunctionComponent<IDataViewProps> = (
|
||||
/>
|
||||
|
||||
<ToastContainer />
|
||||
|
||||
<img className='hidden' src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Ffrontmatter.codes%2Fmetrics%2Fdashboards&slug=dataview" alt="DataView metrics" />
|
||||
</div >
|
||||
);
|
||||
};
|
||||
|
||||
@@ -272,6 +272,8 @@ export const Media: React.FunctionComponent<IMediaProps> = (
|
||||
version={settings?.versionInfo}
|
||||
isBacker={settings?.isBacker}
|
||||
/>
|
||||
|
||||
<img className='hidden' src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Ffrontmatter.codes%2Fmetrics%2Fdashboards&slug=media" alt="Media metrics" />
|
||||
</PageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -84,6 +84,8 @@ export const Preview: React.FunctionComponent<IPreviewProps> = ({
|
||||
marginTop: '30px'
|
||||
}}
|
||||
></iframe>
|
||||
|
||||
<img className='hidden' src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Ffrontmatter.codes%2Fmetrics%2Fdashboards&slug=preview" alt="Preview metrics" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -169,6 +169,8 @@ export const Snippets: React.FunctionComponent<ISnippetsProps> = (
|
||||
version={settings?.versionInfo}
|
||||
isBacker={settings?.isBacker}
|
||||
/>
|
||||
|
||||
<img className='hidden' src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Ffrontmatter.codes%2Fmetrics%2Fdashboards&slug=snippets" alt="Snippets metrics" />
|
||||
</PageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -97,6 +97,8 @@ export const TaxonomyView: React.FunctionComponent<ITaxonomyViewProps> = ({
|
||||
version={settings?.versionInfo}
|
||||
isBacker={settings?.isBacker}
|
||||
/>
|
||||
|
||||
<img className='hidden' src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Ffrontmatter.codes%2Fmetrics%2Fdashboards&slug=taxonomy" alt="Taxonomy metrics" />
|
||||
</PageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -121,6 +121,8 @@ export const WelcomeScreen: React.FunctionComponent<IWelcomeScreenProps> = ({
|
||||
</h2>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<img className='hidden' src="https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Ffrontmatter.codes%2Fmetrics%2Fdashboards&slug=welcome" alt="Welcome metrics" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -132,7 +132,13 @@ if (elm) {
|
||||
</SettingsProvider>, elm);
|
||||
} else if (type === 'chatbot') {
|
||||
render(
|
||||
<Chatbot />, elm);
|
||||
<SettingsProvider
|
||||
aiKey='466f5321-12d9-4d64-9e5b-ea5db41ed2ba'
|
||||
aiUrl='https://aijsplayground-production.up.railway.app'
|
||||
experimental={experimental === 'true'}
|
||||
version={version || ""}>
|
||||
<Chatbot />
|
||||
</SettingsProvider>, elm);
|
||||
} else {
|
||||
render(
|
||||
<RecoilRoot>
|
||||
|
||||
@@ -3,27 +3,20 @@ import * as React from 'react'
|
||||
interface ISettingsProviderProps {
|
||||
version?: string;
|
||||
experimental?: boolean;
|
||||
aiUrl?: string;
|
||||
aiKey?: string;
|
||||
}
|
||||
|
||||
const SettingsContext = React.createContext<ISettingsProviderProps | undefined>(undefined);
|
||||
|
||||
const SettingsProvider: React.FunctionComponent<ISettingsProviderProps> = ({ version, experimental, children }: React.PropsWithChildren<ISettingsProviderProps>) => {
|
||||
const [ crntVersion, setCrntVersion ] = React.useState<string | undefined>(undefined);
|
||||
const [ crntExprimental, setCrntExprimental ] = React.useState<boolean>(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
setCrntVersion(version);
|
||||
}, [version]);
|
||||
|
||||
React.useEffect(() => {
|
||||
setCrntExprimental(typeof experimental === 'boolean' ? experimental : false);
|
||||
}, [experimental]);
|
||||
|
||||
const SettingsProvider: React.FunctionComponent<ISettingsProviderProps> = ({ version, experimental, aiKey, aiUrl, children }: React.PropsWithChildren<ISettingsProviderProps>) => {
|
||||
return (
|
||||
<SettingsContext.Provider
|
||||
<SettingsContext.Provider
|
||||
value={{
|
||||
version: crntVersion,
|
||||
experimental: crntExprimental
|
||||
version,
|
||||
experimental,
|
||||
aiUrl,
|
||||
aiKey
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -432,12 +432,25 @@
|
||||
circle at top right,
|
||||
rgba(0, 0, 0, 0) 0,
|
||||
rgba(0, 0, 0, 0) var(--size),
|
||||
rgb(0 154 163 / var(--tw-bg-opacity)) var(--size)
|
||||
#009aa3 var(--size)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.answer {
|
||||
@apply rounded border border-teal-100 border-opacity-20 p-4 pb-0;
|
||||
@apply break-all rounded border border-teal-100 border-opacity-20 p-4 pb-0;
|
||||
}
|
||||
}
|
||||
|
||||
.chatbox {
|
||||
textarea {
|
||||
border: 0;
|
||||
outline: 0;
|
||||
|
||||
&:focus {
|
||||
border: 0 !important;
|
||||
outline: 0 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user