From 1b1be1231c39700c004e52116c255846444fb4a4 Mon Sep 17 00:00:00 2001 From: Anil Vishnoi Date: Tue, 10 Dec 2024 00:48:33 -0800 Subject: [PATCH 1/6] Commit made following changes *.* Refactor the code and move the experimental dashboard/knowledge/skill components of the native mode parallel to the github dashboard/knowledge/skill components. *.* Dev mode features (such as form auto fill) are now enabled using IL_ENABLE_DEV_MODE=true. *.* IL_UI_DEPLOYMENT flag is repurposed to define the deploment mode of the ui stack. It supports two values - github and native. *.* Based on the DEPLOYMENT type user set, UI will load the related dashboard, knowledge and skill forms. *.* Repository cloning page is removed. Native mode has it's own local taxonomy repository, where it maintains all the user contribution. UI will provide an option to publish these contribution to any other taxonomy if they want to test these contributions. This allows UI stack to have total control over it's own taxonomy instance and minimize the modification it needs to do the main taxonomy repo (for testing, merging contributions). *.* Updated the docs to provide details about native mode. Signed-off-by: Anil Vishnoi --- .gitignore | 2 + docs/development.md | 98 ++++++++------- src/app/api/envConfig/route.ts | 1 + src/app/api/local/clone-repo/route.ts | 45 ------- src/app/api/native/clone-repo/route.ts | 42 +++++++ .../{local => native}/git/branches/route.ts | 8 +- .../{local => native}/pr/knowledge/route.ts | 6 +- .../api/{local => native}/pr/skill/route.ts | 6 +- src/app/contribute/knowledge/page.tsx | 9 +- src/app/contribute/skill/page.tsx | 9 +- src/app/dashboard/page.tsx | 21 ++-- .../edit-submission/knowledge/[id]/page.tsx | 2 +- src/app/edit-submission/skill/[id]/page.tsx | 2 +- .../configuration-local/page.tsx | 14 --- .../contribute-local/knowledge/page.tsx | 14 --- .../contribute-local/skill/page.tsx | 14 --- src/app/experimental/dashboard-local/page.tsx | 17 --- src/app/login/page.tsx | 2 +- src/app/page.tsx | 4 +- src/components/AppLayout.tsx | 8 +- .../Contribute/AuthorInformation.tsx | 4 +- .../EditKnowledge/EditKnowledge.tsx | 9 +- .../{ => Github}/EditSkill/EditSkill.tsx | 4 +- .../AttributionInformation.tsx | 0 .../{ => Github}/Knowledge/AutoFill.ts | 0 .../DocumentInformation.tsx | 2 +- .../DownloadAttribution.tsx | 0 .../DownloadDropdown/DownloadDropdown.tsx | 0 .../Knowledge/DownloadYaml/DownloadYaml.tsx | 0 .../FilePathInformation.tsx | 0 .../KnowledgeDescriptionContent.tsx | 0 .../KnowledgeInformation.tsx | 0 .../KnowledgeQuestionAnswerPairs.tsx | 0 .../KnowledgeSeedExample.tsx | 0 .../{ => Github}/Knowledge/Submit/Submit.tsx | 0 .../{ => Github}/Knowledge/Update/Update.tsx | 0 .../{ => Github}/Knowledge/UploadFile.tsx | 0 .../Knowledge/ViewDropdown/ViewDropdown.tsx | 0 .../{ => Github}/Knowledge/index.tsx | 18 +-- .../{ => Github}/Knowledge/knowledge.css | 0 .../{ => Github}/Knowledge/validation.tsx | 0 .../AttributionInformation.tsx | 0 .../Contribute/{ => Github}/Skill/AutoFill.ts | 0 .../DownloadAttribution.tsx | 0 .../DownloadDropdown/DownloadDropdown.tsx | 0 .../Skill/DownloadYaml/DownloadYaml.tsx | 0 .../FilePathInformation.tsx | 0 .../SkillsDescriptionContent.tsx | 0 .../SkillsInformation/SkillsInformation.tsx | 0 .../SkillsSeedExample/SkillsSeedExample.tsx | 0 .../{ => Github}/Skill/Submit/Submit.tsx | 0 .../{ => Github}/Skill/Update/Update.tsx | 0 .../Skill/ViewDropdown/ViewDropdown.tsx | 0 .../Contribute/{ => Github}/Skill/index.tsx | 18 +-- .../Contribute/{ => Github}/Skill/skills.css | 0 .../{ => Github}/Skill/validation.tsx | 0 .../Knowledge}/ReviewSubmission/index.tsx | 2 +- .../Native/Knowledge/Submit}/Submit.tsx | 8 +- .../Native}/Knowledge/index.tsx | 36 +++--- .../Native}/Knowledge/knowledge.css | 0 .../Native/Skill/Submit/SubmitNative.tsx} | 6 +- .../Native}/Skill/index.tsx | 34 +++--- .../Native}/Skill/skills.css | 0 .../{index.tsx => Github/dashboard.tsx} | 9 +- .../Native/dashboard.tsx} | 79 +++++++----- .../CloneRepoLocal/CloneRepoLocal.module.css | 9 -- .../CloneRepoLocal/CloneRepoLocal.tsx | 115 ------------------ src/components/GithubAccessPopup/index.tsx | 2 +- 68 files changed, 267 insertions(+), 412 deletions(-) delete mode 100644 src/app/api/local/clone-repo/route.ts create mode 100644 src/app/api/native/clone-repo/route.ts rename src/app/api/{local => native}/git/branches/route.ts (92%) rename src/app/api/{local => native}/pr/knowledge/route.ts (93%) rename src/app/api/{local => native}/pr/skill/route.ts (92%) delete mode 100644 src/app/experimental/contribute-local/configuration-local/page.tsx delete mode 100644 src/app/experimental/contribute-local/knowledge/page.tsx delete mode 100644 src/app/experimental/contribute-local/skill/page.tsx delete mode 100644 src/app/experimental/dashboard-local/page.tsx rename src/components/Contribute/{ => Github}/EditKnowledge/EditKnowledge.tsx (97%) rename src/components/Contribute/{ => Github}/EditSkill/EditSkill.tsx (97%) rename src/components/Contribute/{ => Github}/Knowledge/AttributionInformation/AttributionInformation.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/AutoFill.ts (100%) rename src/components/Contribute/{ => Github}/Knowledge/DocumentInformation/DocumentInformation.tsx (99%) rename src/components/Contribute/{ => Github}/Knowledge/DownloadAttribution/DownloadAttribution.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/DownloadDropdown/DownloadDropdown.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/DownloadYaml/DownloadYaml.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/FilePathInformation/FilePathInformation.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/Submit/Submit.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/Update/Update.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/UploadFile.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/ViewDropdown/ViewDropdown.tsx (100%) rename src/components/Contribute/{ => Github}/Knowledge/index.tsx (97%) rename src/components/Contribute/{ => Github}/Knowledge/knowledge.css (100%) rename src/components/Contribute/{ => Github}/Knowledge/validation.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/AttributionInformation/AttributionInformation.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/AutoFill.ts (100%) rename src/components/Contribute/{ => Github}/Skill/DownloadAttribution/DownloadAttribution.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/DownloadDropdown/DownloadDropdown.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/DownloadYaml/DownloadYaml.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/FilePathInformation/FilePathInformation.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/SkillsDescription/SkillsDescriptionContent.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/SkillsInformation/SkillsInformation.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/SkillsSeedExample/SkillsSeedExample.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/Submit/Submit.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/Update/Update.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/ViewDropdown/ViewDropdown.tsx (100%) rename src/components/Contribute/{ => Github}/Skill/index.tsx (97%) rename src/components/Contribute/{ => Github}/Skill/skills.css (100%) rename src/components/Contribute/{ => Github}/Skill/validation.tsx (100%) rename src/components/{Experimental => Contribute/Native/Knowledge}/ReviewSubmission/index.tsx (96%) rename src/components/{Experimental/ContributeLocal/Knowledge/SubmitLocal => Contribute/Native/Knowledge/Submit}/Submit.tsx (93%) rename src/components/{Experimental/ContributeLocal => Contribute/Native}/Knowledge/index.tsx (94%) rename src/components/{Experimental/ContributeLocal => Contribute/Native}/Knowledge/knowledge.css (100%) rename src/components/{Experimental/ContributeLocal/Skill/SubmitLocal/SubmitLocal.tsx => Contribute/Native/Skill/Submit/SubmitNative.tsx} (95%) rename src/components/{Experimental/ContributeLocal => Contribute/Native}/Skill/index.tsx (91%) rename src/components/{Experimental/ContributeLocal => Contribute/Native}/Skill/skills.css (100%) rename src/components/Dashboard/{index.tsx => Github/dashboard.tsx} (97%) rename src/components/{Experimental/DashboardLocal/index.tsx => Dashboard/Native/dashboard.tsx} (82%) delete mode 100644 src/components/Experimental/CloneRepoLocal/CloneRepoLocal.module.css delete mode 100644 src/components/Experimental/CloneRepoLocal/CloneRepoLocal.tsx diff --git a/.gitignore b/.gitignore index e00add2b..782698c0 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,9 @@ pathservice.pid /blob-report/ /playwright/.cache/ playwright/.auth +.instructlab-ui # dont track secrets in git deploy/k8s/overlays/kind/umami/umami-secret.yaml deploy/k8s/overlays/openshift/umami/qa/umami-secret.yaml deploy/k8s/overlays/openshift/umami/prod/umami-secret.yaml + diff --git a/docs/development.md b/docs/development.md index b18c55ee..39a85af4 100644 --- a/docs/development.md +++ b/docs/development.md @@ -2,6 +2,45 @@ This is a [NextJS](https://nextjs.org) framework with [Patternfly](https://www.patternfly.org/get-started/develop/) UI library components. +## Deploying the UI stack on your local machine + +Podman is a requirement. Install and init instructions [here](https://podman.io/docs/installation). + +Set the .env in the ui directory and make sure you uncomment the `IL_ENABLE_DEV_MODE=true`. `IL_ENABLE_DEV_MODE` flag enables assistive features that help you automate the time consuming and repetitive tasks, such as filling skill and knowledge forms for testing. Once .env file is setup, run the following: + +```bash +make start-dev-local +``` + +This will start the UI and the dependent pathservice locally on the machine. + +> [!NOTE] +> It might ask for permission to allow to listen on port 4000. + +To stop the the local dev environment run the following: + +```bash +make stop-dev-local +``` + +## Deploying the UI stack in KIND cluster + +Set the .env in the ui directory and run the following: + +```bash +make start-dev-kind +``` + +This will start the Kind cluster and deploy the UI stack related manifest files in the cluster. + +To stop the Kind cluster and delete the UI stack related resources, run the following: + +```bash +make stop-dev-kind +``` + +Use `make help` to see all the available commands. + ## Manually Running the React UI Set the .env in the ui directory and run the following: @@ -15,7 +54,7 @@ npm run build npm run start ``` -## Other helpful NPM Commands +### Other helpful NPM Commands ```bash # Run a production build (outputs to ".next" dir) @@ -38,53 +77,20 @@ npm run type-check ``` -## Make scripts - -Podman is a requirement. Install and init instructions [here](https://podman.io/docs/installation). +UI stack supports two mode of deployments: -```bash -# Run markdown linter -make md-lint -``` +- github - This is the default mode and it allows users to push their knowledge and skill contribution to the github taxonomy repository. +- native - This mode allow users to keep the skill and knowledge contribution in their local machine. -## Deploying the UI stack on your local machine +## Running the UI in Native Deployment Mode -Set the .env in the ui directory and make sure you uncomment the `IL_UI_DEPLOYMENT=dev`. Once .env file is setup, run the following: +To enable the native mode, set the `IL_UI_DEPLOYMENT=native` in the .env file. Once the flag is set, the UI will not push the knowledge and skill contribution to the github repository. Instead, it will keep the contribution in the local machine. In the `native` mode, the UI login page will show username and password input box to authenticate the user. You can setup the username and password in the .env file through the `IL_UI_ADMIN_USERNAME` and `IL_UI_ADMIN_USERNAME` flags. -```bash -make start-dev-local -``` +## Running the UI in Github Deployment Mode -This will start the UI and the dependent pathservice locally on the machine. - -> [!NOTE] -> It might ask for permission to allow to listen on port 4000. - -To stop the the local dev environment run the following: - -```bash -make stop-dev-local -``` - -## Deploying the UI stack in KIND cluster - -Set the .env in the ui directory and run the following: - -```bash -make start-dev-kind -``` - -This will start the Kind cluster and deploy the UI stack related manifest files in the cluster. - -To stop the Kind cluster and delete the UI stack related resources, run the following: - -```bash -make stop-dev-kind -``` - -Use `make help` to see all the available commands. +To enable the github mode, set the `IL_UI_DEPLOYMENT=github` in the .env file. Once the flag is set, the UI will push the knowledge and skill contribution to the github taxonomy repository. In the `github` mode, the UI login page will show the github login button to authenticate the user. -## OAuth Configuration +### OAuth Configuration for Github Deployment Mode You can either set up the Oauth app in your [GitHub](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) @@ -140,7 +146,7 @@ The chat interface should now use the server. ![enter image description here](../public/dev-local-chat-server/successful-chat.png) -### How to Cherry-Pick a Merged PR to `release-1.0` +## How to Cherry-Pick a Merged PR to `release-1.0` Until we finish automating releases, you may be asked to cherry-pick your PR after it is merged. Here are instructions for cherry-picking a merged Pull Request to the `release-1.0` branch. @@ -223,7 +229,7 @@ If there are multiple commits associated with the PR, repeat this command for ea - Navigate to your GitHub repository and create a new Pull Request from your cherry-pick branch (`cherry-pick-pr--release-1.0`) into the `release-1.0` branch. -### How to Run Playwright tests locally +## How to Run Playwright tests locally As a developer, you can add more integration (end to end tests) after you develop your feature. We use [playwright](https://playwright.dev/) as the automation test runner for executing integration tests on our app. To execute playwright tests locally run the following command: @@ -252,7 +258,7 @@ The configuration for playwright tests is defined in `playwright.config` file an If you'd like to run a specific single test, use the following command with the appropriate folder path to your test. Example: `npx playwright test tests/routing.spec.ts`. To get a detailed report of the completed tests, run `npx playwright show-report` and you'll get a detailed view. -### How to use the devcontainer +## How to use the devcontainer ** NOTE: requires the `devcontainer` binary @@ -285,6 +291,6 @@ This will generate the new encrypted sealed-secret manifest in the file you spec BE CERTAIN to delete the un-encrypted secret file, we do not want to leak these values in `git`. Finally you can move the `sealed-secret` to its correct location within this repo. -### Common issues +## Common issues - `error: cannot get sealed secret service: Unauthorized`: You must be signed in to the qa cluster to be able to communicate with the sealed secrets controller. diff --git a/src/app/api/envConfig/route.ts b/src/app/api/envConfig/route.ts index c58b2a65..5b30015e 100644 --- a/src/app/api/envConfig/route.ts +++ b/src/app/api/envConfig/route.ts @@ -15,6 +15,7 @@ export async function GET() { UPSTREAM_REPO_OWNER: process.env.NEXT_PUBLIC_TAXONOMY_REPO_OWNER || '', UPSTREAM_REPO_NAME: process.env.NEXT_PUBLIC_TAXONOMY_REPO || '', DEPLOYMENT_TYPE: process.env.IL_UI_DEPLOYMENT || '', + ENABLE_DEV_MODE: process.env.IL_ENABLE_DEV_MODE || '', EXPERIMENTAL_FEATURES: process.env.NEXT_PUBLIC_EXPERIMENTAL_FEATURES || '' }; diff --git a/src/app/api/local/clone-repo/route.ts b/src/app/api/local/clone-repo/route.ts deleted file mode 100644 index 309582c5..00000000 --- a/src/app/api/local/clone-repo/route.ts +++ /dev/null @@ -1,45 +0,0 @@ -// src/pages/api/clone-repo.ts -import { NextRequest, NextResponse } from 'next/server'; -import * as git from 'isomorphic-git'; -import http from 'isomorphic-git/http/node'; -import fs from 'fs'; -import path from 'path'; - -// Retrieve the base directory from the environment variable -const BASE_DIRECTORY = process.env.NEXT_PUBLIC_BASE_CLONE_DIRECTORY; - -export async function POST(req: NextRequest) { - const { repoUrl, directory } = await req.json(); - - if (!repoUrl || !directory) { - return NextResponse.json({ message: 'Repository URL and directory are required' }, { status: 400 }); - } - - if (!BASE_DIRECTORY) { - return NextResponse.json({ message: 'Base directory is not configured on the server' }, { status: 500 }); - } - - try { - const clonePath = path.resolve(BASE_DIRECTORY, directory); - - // Ensure clonePath is within BASE_DIRECTORY - if (!clonePath.startsWith(BASE_DIRECTORY)) { - return NextResponse.json({ message: 'Invalid directory path' }, { status: 403 }); - } - - await git.clone({ - fs, - http, - dir: clonePath, - url: repoUrl, - singleBranch: true, - depth: 1 - }); - - // Include the full path in the response for client display - return NextResponse.json({ message: `Repository cloned successfully.`, fullPath: clonePath }, { status: 200 }); - } catch (error: unknown) { - const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; - return NextResponse.json({ message: `Failed to clone repository: ${errorMessage}` }, { status: 500 }); - } -} diff --git a/src/app/api/native/clone-repo/route.ts b/src/app/api/native/clone-repo/route.ts new file mode 100644 index 00000000..81630c1f --- /dev/null +++ b/src/app/api/native/clone-repo/route.ts @@ -0,0 +1,42 @@ +// src/pages/api/clone-repo.ts +import { NextResponse } from 'next/server'; +import * as git from 'isomorphic-git'; +import http from 'isomorphic-git/http/node'; +import fs from 'fs'; +import path from 'path'; + +// Retrieve the base directory from the environment variable +const TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_TAXONOMY_ROOT_DIR || './.instructlab-ui'; +const TAXONOMY_REPO_URL = process.env.NEXT_PUBLIC_TAXONOMY_REPO_URL || 'https://github.com/instructlab/taxonomy.git'; + +export async function POST() { + const taxonomyDirectoryPath = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); + + if (fs.existsSync(taxonomyDirectoryPath)) { + const files = fs.readdirSync(taxonomyDirectoryPath); + if (files.length > 0) { + console.log(`Using existing native Taxonomy repository at ${taxonomyDirectoryPath}.`); + return NextResponse.json({ message: `Using existing native Taxonomy repository at ${taxonomyDirectoryPath}.` }, { status: 200 }); + } + fs.rmdirSync(taxonomyDirectoryPath, { recursive: true }); + } + + try { + await git.clone({ + fs, + http, + dir: taxonomyDirectoryPath, + url: TAXONOMY_REPO_URL, + singleBranch: true, + depth: 1 + }); + + // Include the full path in the response for client display + console.log(`Repository cloned successfully to ${TAXONOMY_ROOT_DIR}.`); + return NextResponse.json({ message: `Repository cloned successfully to ${TAXONOMY_ROOT_DIR}.` }, { status: 200 }); + } catch (error: unknown) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; + console.error(`Failed to clone taxonomy repository: ${errorMessage}`); + return NextResponse.json({ message: `Failed to clone taxonomy repository: ${errorMessage}` }, { status: 500 }); + } +} diff --git a/src/app/api/local/git/branches/route.ts b/src/app/api/native/git/branches/route.ts similarity index 92% rename from src/app/api/local/git/branches/route.ts rename to src/app/api/native/git/branches/route.ts index 2558f6f2..0fcd51d0 100644 --- a/src/app/api/local/git/branches/route.ts +++ b/src/app/api/native/git/branches/route.ts @@ -1,13 +1,14 @@ -// src/app/api/local/git/branches/route.ts +// src/app/api/native/git/branches/route.ts import { NextRequest, NextResponse } from 'next/server'; import * as git from 'isomorphic-git'; import fs from 'fs'; import path from 'path'; // Get the repository path from the environment variable -const REPO_DIR = process.env.NEXT_PUBLIC_LOCAL_REPO_PATH || '/path/to/local/repo'; +const TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_TAXONOMY_ROOT_DIR || './.instructlab-ui'; export async function GET() { + const REPO_DIR = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); try { // Ensure the repository path exists if (!fs.existsSync(REPO_DIR)) { @@ -30,6 +31,7 @@ export async function GET() { branchDetails.sort((a, b) => b.creationDate - a.creationDate); // Sort by creation date, newest first + console.log('Branches present in native taxonomy:', branchDetails); return NextResponse.json({ branches: branchDetails }, { status: 200 }); } catch (error) { console.error('Failed to list branches:', error); @@ -39,6 +41,7 @@ export async function GET() { // Handle POST requests for merge or branch comparison export async function POST(req: NextRequest) { + const REPO_DIR = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); const { branchName, action } = await req.json(); try { @@ -122,6 +125,7 @@ export async function POST(req: NextRequest) { // Helper function to recursively gather file paths and their oids from a tree async function getFilesFromTree(commitOid: string) { + const REPO_DIR = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); const fileMap: Record = {}; async function walkTree(dir: string) { diff --git a/src/app/api/local/pr/knowledge/route.ts b/src/app/api/native/pr/knowledge/route.ts similarity index 93% rename from src/app/api/local/pr/knowledge/route.ts rename to src/app/api/native/pr/knowledge/route.ts index 353a04c4..51549f81 100644 --- a/src/app/api/local/pr/knowledge/route.ts +++ b/src/app/api/native/pr/knowledge/route.ts @@ -1,4 +1,4 @@ -// src/app/api/local/pr/knowledge/route.ts +// src/app/api/native/pr/knowledge/route.ts import { NextResponse } from 'next/server'; import { NextRequest } from 'next/server'; @@ -10,10 +10,12 @@ import { KnowledgeYamlData } from '@/types'; import yaml from 'js-yaml'; // Define paths and configuration -const REPO_DIR = process.env.NEXT_PUBLIC_LOCAL_REPO_PATH || '/path/to/local/repo'; // Update with actual local path +const TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_TAXONOMY_ROOT_DIR || './.instructlab-ui'; + const KNOWLEDGE_DIR = 'knowledge'; export async function POST(req: NextRequest) { + const REPO_DIR = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); try { // Extract the data from the request body const { content, attribution, name, email, submissionSummary, filePath } = await req.json(); diff --git a/src/app/api/local/pr/skill/route.ts b/src/app/api/native/pr/skill/route.ts similarity index 92% rename from src/app/api/local/pr/skill/route.ts rename to src/app/api/native/pr/skill/route.ts index 873da074..72113bd3 100644 --- a/src/app/api/local/pr/skill/route.ts +++ b/src/app/api/native/pr/skill/route.ts @@ -1,4 +1,4 @@ -// src/app/api/local/pr/skill/route.ts +// src/app/api/native/pr/skill/route.ts import { NextResponse } from 'next/server'; import { NextRequest } from 'next/server'; import * as git from 'isomorphic-git'; @@ -7,10 +7,12 @@ import path from 'path'; import yaml from 'js-yaml'; // Define paths and configuration -const REPO_DIR = process.env.NEXT_PUBLIC_LOCAL_REPO_PATH || '/path/to/local/repo'; // Update with actual local path +const TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_TAXONOMY_ROOT_DIR || './.instructlab-ui'; + const SKILLS_DIR = 'compositional_skills'; export async function POST(req: NextRequest) { + const REPO_DIR = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); try { // Extract the QnA data from the request body TODO: what is documentOutline? const { content, attribution, name, email, submissionSummary, documentOutline, filePath } = await req.json(); // eslint-disable-line @typescript-eslint/no-unused-vars diff --git a/src/app/contribute/knowledge/page.tsx b/src/app/contribute/knowledge/page.tsx index cab86364..ff7f5e52 100644 --- a/src/app/contribute/knowledge/page.tsx +++ b/src/app/contribute/knowledge/page.tsx @@ -1,14 +1,11 @@ // src/app/contribute/knowledge/page.tsx +import KnowledgeFormNative from '@/components/Contribute/Native/Knowledge'; import * as React from 'react'; import { AppLayout } from '../../../components/AppLayout'; -import { KnowledgeForm } from '../../../components/Contribute/Knowledge'; +import { KnowledgeFormGithub } from '../../../components/Contribute/Github/Knowledge'; const KnowledgeFormPage: React.FC = () => { - return ( - - - - ); + return {process.env.IL_UI_DEPLOYMENT === 'native' ? : }; }; export default KnowledgeFormPage; diff --git a/src/app/contribute/skill/page.tsx b/src/app/contribute/skill/page.tsx index a2b5d3bc..63d00f74 100644 --- a/src/app/contribute/skill/page.tsx +++ b/src/app/contribute/skill/page.tsx @@ -1,14 +1,11 @@ // src/app/contribute/skill/page.tsx +import SkillFormNative from '@/components/Contribute/Native/Skill'; import * as React from 'react'; import { AppLayout } from '../../../components/AppLayout'; -import { SkillForm } from '../../../components/Contribute/Skill'; +import { SkillFormGithub } from '../../../components/Contribute/Github/Skill'; const SkillFormPage: React.FC = () => { - return ( - - - - ); + return {process.env.IL_UI_DEPLOYMENT === 'native' ? : }; }; export default SkillFormPage; diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index 646f1dfd..2d0fa212 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -4,14 +4,21 @@ import * as React from 'react'; import '@patternfly/react-core/dist/styles/base.css'; import { AppLayout } from '@/components/AppLayout'; -import { Index } from '@/components/Dashboard'; - +import { DashboardGithub } from '@/components/Dashboard/Github/dashboard'; +import { DashboardNative } from '@/components/Dashboard/Native/dashboard'; const Home: React.FunctionComponent = () => { - return ( - - - - ); + const [deploymentType, setDeploymentType] = React.useState(); + + React.useEffect(() => { + const getEnvVariables = async () => { + const res = await fetch('/api/envConfig'); + const envConfig = await res.json(); + setDeploymentType(envConfig.DEPLOYMENT_TYPE); + }; + getEnvVariables(); + }, []); + + return {deploymentType === 'native' ? : }; }; export default Home; diff --git a/src/app/edit-submission/knowledge/[id]/page.tsx b/src/app/edit-submission/knowledge/[id]/page.tsx index 55b25ce4..55495a72 100644 --- a/src/app/edit-submission/knowledge/[id]/page.tsx +++ b/src/app/edit-submission/knowledge/[id]/page.tsx @@ -1,7 +1,7 @@ // src/app/edit-submission/knowledge/[id]/page.tsx import * as React from 'react'; import { AppLayout } from '@/components/AppLayout'; -import EditKnowledge from '@/components/Contribute/EditKnowledge/EditKnowledge'; +import EditKnowledge from '@/components/Contribute/Github/EditKnowledge/EditKnowledge'; type PageProps = { params: Promise<{ id: string }>; diff --git a/src/app/edit-submission/skill/[id]/page.tsx b/src/app/edit-submission/skill/[id]/page.tsx index 735436fa..cb1131e0 100644 --- a/src/app/edit-submission/skill/[id]/page.tsx +++ b/src/app/edit-submission/skill/[id]/page.tsx @@ -1,7 +1,7 @@ // src/app/edit-submission/skill/[id]/page.tsx import * as React from 'react'; import { AppLayout } from '@/components/AppLayout'; -import EditSkill from '@/components/Contribute/EditSkill/EditSkill'; +import EditSkill from '@/components/Contribute/Github/EditSkill/EditSkill'; type PageProps = { params: Promise<{ id: string }>; diff --git a/src/app/experimental/contribute-local/configuration-local/page.tsx b/src/app/experimental/contribute-local/configuration-local/page.tsx deleted file mode 100644 index c7550df8..00000000 --- a/src/app/experimental/contribute-local/configuration-local/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/app/experimental/contribute-local/clone-repo/page.tsx -import * as React from 'react'; -import { AppLayout } from '@/components/AppLayout'; -import CloneRepoLocal from '@/components/Experimental/CloneRepoLocal/CloneRepoLocal'; - -const CloneRepoPage: React.FC = () => { - return ( - - - - ); -}; - -export default CloneRepoPage; diff --git a/src/app/experimental/contribute-local/knowledge/page.tsx b/src/app/experimental/contribute-local/knowledge/page.tsx deleted file mode 100644 index dc1a4cf2..00000000 --- a/src/app/experimental/contribute-local/knowledge/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/app/experimental/contribute-local/knowledge/page.tsx -import * as React from 'react'; -import { AppLayout } from '@/components/AppLayout'; -import { KnowledgeFormLocal } from '@/components/Experimental/ContributeLocal/Knowledge'; - -const KnowledgeFormLocalPage: React.FC = () => { - return ( - - - - ); -}; - -export default KnowledgeFormLocalPage; diff --git a/src/app/experimental/contribute-local/skill/page.tsx b/src/app/experimental/contribute-local/skill/page.tsx deleted file mode 100644 index 9bcdc347..00000000 --- a/src/app/experimental/contribute-local/skill/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/app/experimental/contribute-local/skill/page.tsx -import * as React from 'react'; -import { AppLayout } from '@/components/AppLayout'; -import SkillFormLocal from '@/components/Experimental/ContributeLocal/Skill'; - -const SkillFormPageLocal: React.FC = () => { - return ( - - - - ); -}; - -export default SkillFormPageLocal; diff --git a/src/app/experimental/dashboard-local/page.tsx b/src/app/experimental/dashboard-local/page.tsx deleted file mode 100644 index e1da680f..00000000 --- a/src/app/experimental/dashboard-local/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -// src/app/experimental/dashboard-local/page.tsx -'use client'; - -import * as React from 'react'; -import '@patternfly/react-core/dist/styles/base.css'; -import { AppLayout } from '@/components/AppLayout'; -import { DashboardLocal } from '@/components/Experimental/DashboardLocal'; - -const Home: React.FunctionComponent = () => { - return ( - - - - ); -}; - -export default Home; diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index cf5e59ce..949efc0a 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -14,7 +14,7 @@ const Login: React.FunctionComponent = () => { try { const res = await fetch('/api/envConfig'); const envConfig = await res.json(); - setIsProd(envConfig.DEPLOYMENT_TYPE !== 'dev'); + setIsProd(envConfig.DEPLOYMENT_TYPE === 'false'); } catch (error) { console.error('Error fetching environment config:', error); setIsProd(true); diff --git a/src/app/page.tsx b/src/app/page.tsx index 6853aa0b..75a82eda 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,11 +1,11 @@ // src/app/page.tsx 'use client'; +import { DashboardGithub } from '@/components/Dashboard/Github/dashboard'; import { GithubAccessPopup } from '@/components/GithubAccessPopup'; import * as React from 'react'; import { useState } from 'react'; import { AppLayout } from '../components/AppLayout'; -import { Index } from '../components/Dashboard'; const HomePage: React.FC = () => { const [isWarningConditionAccepted, setIsWarningConditionAccepted] = useState(false); @@ -19,7 +19,7 @@ const HomePage: React.FC = () => { return ( - {isWarningConditionAccepted && } + {isWarningConditionAccepted && } ); }; diff --git a/src/components/AppLayout.tsx b/src/components/AppLayout.tsx index 3023e6ce..f4a1f944 100644 --- a/src/components/AppLayout.tsx +++ b/src/components/AppLayout.tsx @@ -98,13 +98,7 @@ const AppLayout: React.FunctionComponent = ({ children }) => { }, isExperimentalEnabled && { path: '/experimental', - label: 'Experimental Features', - children: [ - { path: '/experimental/dashboard-local/', label: 'Local Dashboard' }, - { path: '/experimental/contribute-local/skill/', label: 'Local Skill' }, - { path: '/experimental/contribute-local/knowledge/', label: 'Local Knowledge' }, - { path: '/experimental/contribute-local/configuration-local/', label: 'Local Configuration' } - ] + label: 'Experimental Features' } ].filter(Boolean) as Route[]; diff --git a/src/components/Contribute/AuthorInformation.tsx b/src/components/Contribute/AuthorInformation.tsx index 1c384dd0..5e10135a 100644 --- a/src/components/Contribute/AuthorInformation.tsx +++ b/src/components/Contribute/AuthorInformation.tsx @@ -5,8 +5,8 @@ import { HelperText } from '@patternfly/react-core/dist/dynamic/components/Helpe import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { checkSkillFormCompletion } from './Skill/validation'; -import { checkKnowledgeFormCompletion } from './Knowledge/validation'; +import { checkSkillFormCompletion } from './Github/Skill/validation'; +import { checkKnowledgeFormCompletion } from './Github/Knowledge/validation'; export enum FormType { Knowledge, diff --git a/src/components/Contribute/EditKnowledge/EditKnowledge.tsx b/src/components/Contribute/Github/EditKnowledge/EditKnowledge.tsx similarity index 97% rename from src/components/Contribute/EditKnowledge/EditKnowledge.tsx rename to src/components/Contribute/Github/EditKnowledge/EditKnowledge.tsx index b37a35cf..b59693f3 100644 --- a/src/components/Contribute/EditKnowledge/EditKnowledge.tsx +++ b/src/components/Contribute/Github/EditKnowledge/EditKnowledge.tsx @@ -8,7 +8,12 @@ import { KnowledgeSchemaVersion } from '@/types/const'; import { fetchPullRequest, fetchFileContent, fetchPullRequestFiles } from '@/utils/github'; import yaml from 'js-yaml'; import axios from 'axios'; -import KnowledgeForm, { KnowledgeEditFormData, KnowledgeFormData, QuestionAndAnswerPair, SeedExample } from '@/components/Contribute/Knowledge'; +import KnowledgeFormGithub, { + KnowledgeEditFormData, + KnowledgeFormData, + QuestionAndAnswerPair, + SeedExample +} from '@/components/Contribute/Github/Knowledge'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; import { useEffect, useState } from 'react'; import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/deprecated/components/Modal/Modal'; @@ -175,7 +180,7 @@ const EditKnowledge: React.FC = ({ prNumber } return ( // - + // ); }; diff --git a/src/components/Contribute/EditSkill/EditSkill.tsx b/src/components/Contribute/Github/EditSkill/EditSkill.tsx similarity index 97% rename from src/components/Contribute/EditSkill/EditSkill.tsx rename to src/components/Contribute/Github/EditSkill/EditSkill.tsx index f98ae791..9cd7e19e 100644 --- a/src/components/Contribute/EditSkill/EditSkill.tsx +++ b/src/components/Contribute/Github/EditSkill/EditSkill.tsx @@ -7,7 +7,7 @@ import { useEffect, useState } from 'react'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/deprecated/components/Modal/Modal'; import { useRouter } from 'next/navigation'; -import SkillForm, { SkillEditFormData, SkillFormData, SeedExample } from '@/components/Contribute/Skill'; +import SkillFormGithub, { SkillEditFormData, SkillFormData, SeedExample } from '@/components/Contribute/Github/Skill'; import { fetchPullRequest, fetchFileContent, fetchPullRequestFiles } from '@/utils/github'; import yaml from 'js-yaml'; import axios from 'axios'; @@ -147,7 +147,7 @@ const EditSkill: React.FC = ({ prNumber }) => { ); } - return ; + return ; }; export default EditSkill; diff --git a/src/components/Contribute/Knowledge/AttributionInformation/AttributionInformation.tsx b/src/components/Contribute/Github/Knowledge/AttributionInformation/AttributionInformation.tsx similarity index 100% rename from src/components/Contribute/Knowledge/AttributionInformation/AttributionInformation.tsx rename to src/components/Contribute/Github/Knowledge/AttributionInformation/AttributionInformation.tsx diff --git a/src/components/Contribute/Knowledge/AutoFill.ts b/src/components/Contribute/Github/Knowledge/AutoFill.ts similarity index 100% rename from src/components/Contribute/Knowledge/AutoFill.ts rename to src/components/Contribute/Github/Knowledge/AutoFill.ts diff --git a/src/components/Contribute/Knowledge/DocumentInformation/DocumentInformation.tsx b/src/components/Contribute/Github/Knowledge/DocumentInformation/DocumentInformation.tsx similarity index 99% rename from src/components/Contribute/Knowledge/DocumentInformation/DocumentInformation.tsx rename to src/components/Contribute/Github/Knowledge/DocumentInformation/DocumentInformation.tsx index 53f249d3..285042a5 100644 --- a/src/components/Contribute/Knowledge/DocumentInformation/DocumentInformation.tsx +++ b/src/components/Contribute/Github/Knowledge/DocumentInformation/DocumentInformation.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'; import { FormFieldGroupHeader, FormGroup, FormHelperText } from '@patternfly/react-core/dist/dynamic/components/Form'; import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; import { TextInput } from '@patternfly/react-core/dist/dynamic/components/TextInput'; -import { UploadFile } from './../UploadFile'; +import { UploadFile } from '../UploadFile'; import { Alert, AlertActionLink, AlertActionCloseButton } from '@patternfly/react-core/dist/dynamic/components/Alert'; import { HelperText } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; diff --git a/src/components/Contribute/Knowledge/DownloadAttribution/DownloadAttribution.tsx b/src/components/Contribute/Github/Knowledge/DownloadAttribution/DownloadAttribution.tsx similarity index 100% rename from src/components/Contribute/Knowledge/DownloadAttribution/DownloadAttribution.tsx rename to src/components/Contribute/Github/Knowledge/DownloadAttribution/DownloadAttribution.tsx diff --git a/src/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown.tsx b/src/components/Contribute/Github/Knowledge/DownloadDropdown/DownloadDropdown.tsx similarity index 100% rename from src/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown.tsx rename to src/components/Contribute/Github/Knowledge/DownloadDropdown/DownloadDropdown.tsx diff --git a/src/components/Contribute/Knowledge/DownloadYaml/DownloadYaml.tsx b/src/components/Contribute/Github/Knowledge/DownloadYaml/DownloadYaml.tsx similarity index 100% rename from src/components/Contribute/Knowledge/DownloadYaml/DownloadYaml.tsx rename to src/components/Contribute/Github/Knowledge/DownloadYaml/DownloadYaml.tsx diff --git a/src/components/Contribute/Knowledge/FilePathInformation/FilePathInformation.tsx b/src/components/Contribute/Github/Knowledge/FilePathInformation/FilePathInformation.tsx similarity index 100% rename from src/components/Contribute/Knowledge/FilePathInformation/FilePathInformation.tsx rename to src/components/Contribute/Github/Knowledge/FilePathInformation/FilePathInformation.tsx diff --git a/src/components/Contribute/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent.tsx b/src/components/Contribute/Github/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent.tsx similarity index 100% rename from src/components/Contribute/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent.tsx rename to src/components/Contribute/Github/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent.tsx diff --git a/src/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx b/src/components/Contribute/Github/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx similarity index 100% rename from src/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx rename to src/components/Contribute/Github/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx diff --git a/src/components/Contribute/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx b/src/components/Contribute/Github/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx similarity index 100% rename from src/components/Contribute/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx rename to src/components/Contribute/Github/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx diff --git a/src/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx b/src/components/Contribute/Github/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx similarity index 100% rename from src/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx rename to src/components/Contribute/Github/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx diff --git a/src/components/Contribute/Knowledge/Submit/Submit.tsx b/src/components/Contribute/Github/Knowledge/Submit/Submit.tsx similarity index 100% rename from src/components/Contribute/Knowledge/Submit/Submit.tsx rename to src/components/Contribute/Github/Knowledge/Submit/Submit.tsx diff --git a/src/components/Contribute/Knowledge/Update/Update.tsx b/src/components/Contribute/Github/Knowledge/Update/Update.tsx similarity index 100% rename from src/components/Contribute/Knowledge/Update/Update.tsx rename to src/components/Contribute/Github/Knowledge/Update/Update.tsx diff --git a/src/components/Contribute/Knowledge/UploadFile.tsx b/src/components/Contribute/Github/Knowledge/UploadFile.tsx similarity index 100% rename from src/components/Contribute/Knowledge/UploadFile.tsx rename to src/components/Contribute/Github/Knowledge/UploadFile.tsx diff --git a/src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx b/src/components/Contribute/Github/Knowledge/ViewDropdown/ViewDropdown.tsx similarity index 100% rename from src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx rename to src/components/Contribute/Github/Knowledge/ViewDropdown/ViewDropdown.tsx diff --git a/src/components/Contribute/Knowledge/index.tsx b/src/components/Contribute/Github/Knowledge/index.tsx similarity index 97% rename from src/components/Contribute/Knowledge/index.tsx rename to src/components/Contribute/Github/Knowledge/index.tsx index fc472935..57f95ecc 100644 --- a/src/components/Contribute/Knowledge/index.tsx +++ b/src/components/Contribute/Github/Knowledge/index.tsx @@ -5,10 +5,10 @@ import './knowledge.css'; import { Alert, AlertActionCloseButton } from '@patternfly/react-core/dist/dynamic/components/Alert'; import { ActionGroup } from '@patternfly/react-core/dist/dynamic/components/Form'; import { Form } from '@patternfly/react-core/dist/dynamic/components/Form'; -import { getGitHubUsername } from '../../../utils/github'; +import { getGitHubUsername } from '../../../../utils/github'; import { useSession } from 'next-auth/react'; -import AuthorInformation from '../AuthorInformation'; -import { FormType } from '../AuthorInformation'; +import AuthorInformation from '../../AuthorInformation'; +import { FormType } from '../../AuthorInformation'; import KnowledgeInformation from './KnowledgeInformation/KnowledgeInformation'; import FilePathInformation from './FilePathInformation/FilePathInformation'; import DocumentInformation from './DocumentInformation/DocumentInformation'; @@ -34,7 +34,7 @@ import { Button } from '@patternfly/react-core/dist/esm/components/Button/Button import { useRouter } from 'next/navigation'; import { autoFillKnowledgeFields } from './AutoFill'; import { Spinner } from '@patternfly/react-core/dist/esm/components/Spinner'; -import { YamlFileUploadModal } from '../YamlFileUploadModal'; +import { YamlFileUploadModal } from '../../YamlFileUploadModal'; export interface QuestionAndAnswerPair { immutable: boolean; @@ -96,8 +96,8 @@ export interface KnowledgeFormProps { knowledgeEditFormData?: KnowledgeEditFormData; } -export const KnowledgeForm: React.FunctionComponent = ({ knowledgeEditFormData }) => { - const [deploymentType, setDeploymentType] = useState(); +export const KnowledgeFormGithub: React.FunctionComponent = ({ knowledgeEditFormData }) => { + const [devModeEnabled, setDevModeEnabled] = useState(); const { data: session } = useSession(); const [githubUsername, setGithubUsername] = useState(''); @@ -177,7 +177,7 @@ export const KnowledgeForm: React.FunctionComponent = ({ kno const getEnvVariables = async () => { const res = await fetch('/api/envConfig'); const envConfig = await res.json(); - setDeploymentType(envConfig.DEPLOYMENT_TYPE); + setDevModeEnabled(envConfig.ENABLE_DEV_MODE === 'true'); }; getEnvVariables(); }, []); @@ -514,7 +514,7 @@ export const KnowledgeForm: React.FunctionComponent = ({ kno - {deploymentType === 'dev' && ( + {devModeEnabled && ( @@ -655,4 +655,4 @@ export const KnowledgeForm: React.FunctionComponent = ({ kno ); }; -export default KnowledgeForm; +export default KnowledgeFormGithub; diff --git a/src/components/Contribute/Knowledge/knowledge.css b/src/components/Contribute/Github/Knowledge/knowledge.css similarity index 100% rename from src/components/Contribute/Knowledge/knowledge.css rename to src/components/Contribute/Github/Knowledge/knowledge.css diff --git a/src/components/Contribute/Knowledge/validation.tsx b/src/components/Contribute/Github/Knowledge/validation.tsx similarity index 100% rename from src/components/Contribute/Knowledge/validation.tsx rename to src/components/Contribute/Github/Knowledge/validation.tsx diff --git a/src/components/Contribute/Skill/AttributionInformation/AttributionInformation.tsx b/src/components/Contribute/Github/Skill/AttributionInformation/AttributionInformation.tsx similarity index 100% rename from src/components/Contribute/Skill/AttributionInformation/AttributionInformation.tsx rename to src/components/Contribute/Github/Skill/AttributionInformation/AttributionInformation.tsx diff --git a/src/components/Contribute/Skill/AutoFill.ts b/src/components/Contribute/Github/Skill/AutoFill.ts similarity index 100% rename from src/components/Contribute/Skill/AutoFill.ts rename to src/components/Contribute/Github/Skill/AutoFill.ts diff --git a/src/components/Contribute/Skill/DownloadAttribution/DownloadAttribution.tsx b/src/components/Contribute/Github/Skill/DownloadAttribution/DownloadAttribution.tsx similarity index 100% rename from src/components/Contribute/Skill/DownloadAttribution/DownloadAttribution.tsx rename to src/components/Contribute/Github/Skill/DownloadAttribution/DownloadAttribution.tsx diff --git a/src/components/Contribute/Skill/DownloadDropdown/DownloadDropdown.tsx b/src/components/Contribute/Github/Skill/DownloadDropdown/DownloadDropdown.tsx similarity index 100% rename from src/components/Contribute/Skill/DownloadDropdown/DownloadDropdown.tsx rename to src/components/Contribute/Github/Skill/DownloadDropdown/DownloadDropdown.tsx diff --git a/src/components/Contribute/Skill/DownloadYaml/DownloadYaml.tsx b/src/components/Contribute/Github/Skill/DownloadYaml/DownloadYaml.tsx similarity index 100% rename from src/components/Contribute/Skill/DownloadYaml/DownloadYaml.tsx rename to src/components/Contribute/Github/Skill/DownloadYaml/DownloadYaml.tsx diff --git a/src/components/Contribute/Skill/FilePathInformation/FilePathInformation.tsx b/src/components/Contribute/Github/Skill/FilePathInformation/FilePathInformation.tsx similarity index 100% rename from src/components/Contribute/Skill/FilePathInformation/FilePathInformation.tsx rename to src/components/Contribute/Github/Skill/FilePathInformation/FilePathInformation.tsx diff --git a/src/components/Contribute/Skill/SkillsDescription/SkillsDescriptionContent.tsx b/src/components/Contribute/Github/Skill/SkillsDescription/SkillsDescriptionContent.tsx similarity index 100% rename from src/components/Contribute/Skill/SkillsDescription/SkillsDescriptionContent.tsx rename to src/components/Contribute/Github/Skill/SkillsDescription/SkillsDescriptionContent.tsx diff --git a/src/components/Contribute/Skill/SkillsInformation/SkillsInformation.tsx b/src/components/Contribute/Github/Skill/SkillsInformation/SkillsInformation.tsx similarity index 100% rename from src/components/Contribute/Skill/SkillsInformation/SkillsInformation.tsx rename to src/components/Contribute/Github/Skill/SkillsInformation/SkillsInformation.tsx diff --git a/src/components/Contribute/Skill/SkillsSeedExample/SkillsSeedExample.tsx b/src/components/Contribute/Github/Skill/SkillsSeedExample/SkillsSeedExample.tsx similarity index 100% rename from src/components/Contribute/Skill/SkillsSeedExample/SkillsSeedExample.tsx rename to src/components/Contribute/Github/Skill/SkillsSeedExample/SkillsSeedExample.tsx diff --git a/src/components/Contribute/Skill/Submit/Submit.tsx b/src/components/Contribute/Github/Skill/Submit/Submit.tsx similarity index 100% rename from src/components/Contribute/Skill/Submit/Submit.tsx rename to src/components/Contribute/Github/Skill/Submit/Submit.tsx diff --git a/src/components/Contribute/Skill/Update/Update.tsx b/src/components/Contribute/Github/Skill/Update/Update.tsx similarity index 100% rename from src/components/Contribute/Skill/Update/Update.tsx rename to src/components/Contribute/Github/Skill/Update/Update.tsx diff --git a/src/components/Contribute/Skill/ViewDropdown/ViewDropdown.tsx b/src/components/Contribute/Github/Skill/ViewDropdown/ViewDropdown.tsx similarity index 100% rename from src/components/Contribute/Skill/ViewDropdown/ViewDropdown.tsx rename to src/components/Contribute/Github/Skill/ViewDropdown/ViewDropdown.tsx diff --git a/src/components/Contribute/Skill/index.tsx b/src/components/Contribute/Github/Skill/index.tsx similarity index 97% rename from src/components/Contribute/Skill/index.tsx rename to src/components/Contribute/Github/Skill/index.tsx index a11783d4..1c623b74 100644 --- a/src/components/Contribute/Skill/index.tsx +++ b/src/components/Contribute/Github/Skill/index.tsx @@ -5,10 +5,10 @@ import './skills.css'; import { Alert, AlertActionCloseButton } from '@patternfly/react-core/dist/dynamic/components/Alert'; import { ActionGroup } from '@patternfly/react-core/dist/dynamic/components/Form'; import { Form } from '@patternfly/react-core/dist/dynamic/components/Form'; -import { getGitHubUsername } from '../../../utils/github'; +import { getGitHubUsername } from '../../../../utils/github'; import { useSession } from 'next-auth/react'; -import AuthorInformation from '../AuthorInformation'; -import { FormType } from '../AuthorInformation'; +import AuthorInformation from '../../AuthorInformation'; +import { FormType } from '../../AuthorInformation'; import FilePathInformation from './FilePathInformation/FilePathInformation'; import AttributionInformation from './AttributionInformation/AttributionInformation'; import Submit from './Submit/Submit'; @@ -33,7 +33,7 @@ import SkillsInformation from './SkillsInformation/SkillsInformation'; import SkillsDescriptionContent from './SkillsDescription/SkillsDescriptionContent'; import { autoFillSkillsFields } from './AutoFill'; import { Spinner } from '@patternfly/react-core/dist/dynamic/components/Spinner'; -import { YamlFileUploadModal } from '../YamlFileUploadModal'; +import { YamlFileUploadModal } from '../../YamlFileUploadModal'; export interface SeedExample { immutable: boolean; @@ -84,8 +84,8 @@ export interface SkillFormProps { skillEditFormData?: SkillEditFormData; } -export const SkillForm: React.FunctionComponent = ({ skillEditFormData }) => { - const [deploymentType, setDeploymentType] = useState(); +export const SkillFormGithub: React.FunctionComponent = ({ skillEditFormData }) => { + const [devModeEnabled, setDevModeEnabled] = useState(); const { data: session } = useSession(); const [githubUsername, setGithubUsername] = useState(''); @@ -138,7 +138,7 @@ export const SkillForm: React.FunctionComponent = ({ skillEditFo const getEnvVariables = async () => { const res = await fetch('/api/envConfig'); const envConfig = await res.json(); - setDeploymentType(envConfig.DEPLOYMENT_TYPE); + setDevModeEnabled(envConfig.ENABLE_DEV_MODE === 'true'); }; getEnvVariables(); }, []); @@ -396,7 +396,7 @@ export const SkillForm: React.FunctionComponent = ({ skillEditFo - {deploymentType === 'dev' && ( + {devModeEnabled && ( @@ -520,4 +520,4 @@ export const SkillForm: React.FunctionComponent = ({ skillEditFo ); }; -export default SkillForm; +export default SkillFormGithub; diff --git a/src/components/Contribute/Skill/skills.css b/src/components/Contribute/Github/Skill/skills.css similarity index 100% rename from src/components/Contribute/Skill/skills.css rename to src/components/Contribute/Github/Skill/skills.css diff --git a/src/components/Contribute/Skill/validation.tsx b/src/components/Contribute/Github/Skill/validation.tsx similarity index 100% rename from src/components/Contribute/Skill/validation.tsx rename to src/components/Contribute/Github/Skill/validation.tsx diff --git a/src/components/Experimental/ReviewSubmission/index.tsx b/src/components/Contribute/Native/Knowledge/ReviewSubmission/index.tsx similarity index 96% rename from src/components/Experimental/ReviewSubmission/index.tsx rename to src/components/Contribute/Native/Knowledge/ReviewSubmission/index.tsx index 92ea05f5..8ff25114 100644 --- a/src/components/Experimental/ReviewSubmission/index.tsx +++ b/src/components/Contribute/Native/Knowledge/ReviewSubmission/index.tsx @@ -1,6 +1,6 @@ // src/components/Contribute/Knowledge/ReviewSubmission/ReviewSubmission.tsx import React from 'react'; -import { KnowledgeFormData } from '@/components/Experimental/ContributeLocal/Knowledge'; +import { KnowledgeFormData } from '@/components/Contribute/Native/Knowledge'; interface ReviewSubmissionProps { knowledgeFormData: KnowledgeFormData; diff --git a/src/components/Experimental/ContributeLocal/Knowledge/SubmitLocal/Submit.tsx b/src/components/Contribute/Native/Knowledge/Submit/Submit.tsx similarity index 93% rename from src/components/Experimental/ContributeLocal/Knowledge/SubmitLocal/Submit.tsx rename to src/components/Contribute/Native/Knowledge/Submit/Submit.tsx index 442e9ad4..3e3fdd72 100644 --- a/src/components/Experimental/ContributeLocal/Knowledge/SubmitLocal/Submit.tsx +++ b/src/components/Contribute/Native/Knowledge/Submit/Submit.tsx @@ -1,11 +1,11 @@ -// src/components/Experimental/ContributeLocal/Knowledge/SubmitLocal/Submit.tsx +// src/components/contribute/native/Knowledge/Submit/Submit.tsx import React from 'react'; import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; import { ActionGroupAlertContent, KnowledgeFormData } from '..'; import { AttributionData, KnowledgeYamlData } from '@/types'; import { KnowledgeSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; -import { validateFields } from '@/components/Contribute/Knowledge/validation'; +import { validateFields } from '@/components/Contribute/Github/Knowledge/validation'; interface Props { disableAction: boolean; @@ -65,7 +65,7 @@ const Submit: React.FC = ({ disableAction, knowledgeFormData, setActionGr const name = knowledgeFormData.name; const submissionSummary = knowledgeFormData.submissionSummary; const documentOutline = knowledgeFormData.documentOutline; - const response = await fetch('/api/local/pr/knowledge', { + const response = await fetch('/api/native/pr/knowledge', { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -95,7 +95,7 @@ const Submit: React.FC = ({ disableAction, knowledgeFormData, setActionGr const actionGroupAlertContent: ActionGroupAlertContent = { title: 'Knowledge contribution submitted successfully!', message: `Thank you for your contribution!`, - url: '/experimental/dashboard-local/', + url: '/dashboard/', success: true }; setActionGroupAlertContent(actionGroupAlertContent); diff --git a/src/components/Experimental/ContributeLocal/Knowledge/index.tsx b/src/components/Contribute/Native/Knowledge/index.tsx similarity index 94% rename from src/components/Experimental/ContributeLocal/Knowledge/index.tsx rename to src/components/Contribute/Native/Knowledge/index.tsx index 7a7d03db..e68cb266 100644 --- a/src/components/Experimental/ContributeLocal/Knowledge/index.tsx +++ b/src/components/Contribute/Native/Knowledge/index.tsx @@ -8,32 +8,32 @@ import { getGitHubUsername } from '@/utils/github'; import { useSession } from 'next-auth/react'; import AuthorInformation from '@/components/Contribute/AuthorInformation'; import { FormType } from '@/components/Contribute/AuthorInformation'; -import KnowledgeInformation from '@/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation'; -import FilePathInformation from '@/components/Contribute/Knowledge/FilePathInformation/FilePathInformation'; -import DocumentInformation from '@/components/Contribute/Knowledge/DocumentInformation/DocumentInformation'; -import AttributionInformation from '@/components/Contribute/Knowledge/AttributionInformation/AttributionInformation'; -import Submit from './SubmitLocal/Submit'; +import KnowledgeInformation from '@/components/Contribute/Github/Knowledge/KnowledgeInformation/KnowledgeInformation'; +import FilePathInformation from '@/components/Contribute/Github/Knowledge/FilePathInformation/FilePathInformation'; +import DocumentInformation from '@/components/Contribute/Github/Knowledge/DocumentInformation/DocumentInformation'; +import AttributionInformation from '@/components/Contribute/Github/Knowledge/AttributionInformation/AttributionInformation'; +import Submit from './Submit/Submit'; import { Breadcrumb } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; import { BreadcrumbItem } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; import { PageBreadcrumb } from '@patternfly/react-core/dist/dynamic/components/Page'; import { PageGroup } from '@patternfly/react-core/dist/dynamic/components/Page'; import { PageSection } from '@patternfly/react-core/dist/dynamic/components/Page'; import { Title } from '@patternfly/react-core/dist/dynamic/components/Title'; -import KnowledgeDescriptionContent from '@/components/Contribute/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent'; -import KnowledgeSeedExample from '@/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample'; -import { checkKnowledgeFormCompletion } from '@/components/Contribute/Knowledge/validation'; +import KnowledgeDescriptionContent from '@/components/Contribute/Github/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent'; +import KnowledgeSeedExample from '@/components/Contribute/Github/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample'; +import { checkKnowledgeFormCompletion } from '@/components/Contribute/Github/Knowledge/validation'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { DownloadDropdown } from '@/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown'; -import { ViewDropdown } from '@/components/Contribute/Knowledge/ViewDropdown/ViewDropdown'; -import Update from '@/components/Contribute/Knowledge/Update/Update'; +import { DownloadDropdown } from '@/components/Contribute/Github/Knowledge/DownloadDropdown/DownloadDropdown'; +import { ViewDropdown } from '@/components/Contribute/Github/Knowledge/ViewDropdown/ViewDropdown'; +import Update from '@/components/Contribute/Github/Knowledge/Update/Update'; import { PullRequestFile } from '@/types'; import { Button } from '@patternfly/react-core/dist/esm/components/Button/Button'; import { useRouter } from 'next/navigation'; -import { autoFillKnowledgeFields } from '@/components/Contribute/Knowledge/AutoFill'; +import { autoFillKnowledgeFields } from '@/components/Contribute/Github/Knowledge/AutoFill'; import { Spinner } from '@patternfly/react-core/dist/esm/components/Spinner'; import { Wizard, WizardStep } from '@patternfly/react-core/dist/esm/components/Wizard'; import { Content } from '@patternfly/react-core/dist/dynamic/components/Content'; -import ReviewSubmission from '@/components/Experimental/ReviewSubmission'; +import ReviewSubmission from '@/components/Contribute/Native/Knowledge/ReviewSubmission'; export interface QuestionAndAnswerPair { immutable: boolean; @@ -95,8 +95,8 @@ export interface KnowledgeFormProps { knowledgeEditFormData?: KnowledgeEditFormData; } -export const KnowledgeFormLocal: React.FunctionComponent = ({ knowledgeEditFormData }) => { - const [deploymentType, setDeploymentType] = useState(); +export const KnowledgeFormNative: React.FunctionComponent = ({ knowledgeEditFormData }) => { + const [devModeEnabled, setDevModeEnabled] = useState(); const { data: session } = useSession(); const [githubUsername, setGithubUsername] = useState(''); @@ -176,7 +176,7 @@ export const KnowledgeFormLocal: React.FunctionComponent = ( const getEnvVariables = async () => { const res = await fetch('/api/envConfig'); const envConfig = await res.json(); - setDeploymentType(envConfig.DEPLOYMENT_TYPE); + setDevModeEnabled(envConfig.ENABLE_DEV_MODE === 'true'); }; getEnvVariables(); }, []); @@ -597,7 +597,7 @@ export const KnowledgeFormLocal: React.FunctionComponent = ( - {deploymentType === 'dev' && ( + {devModeEnabled && ( @@ -667,4 +667,4 @@ export const KnowledgeFormLocal: React.FunctionComponent = ( ); }; -export default KnowledgeFormLocal; +export default KnowledgeFormNative; diff --git a/src/components/Experimental/ContributeLocal/Knowledge/knowledge.css b/src/components/Contribute/Native/Knowledge/knowledge.css similarity index 100% rename from src/components/Experimental/ContributeLocal/Knowledge/knowledge.css rename to src/components/Contribute/Native/Knowledge/knowledge.css diff --git a/src/components/Experimental/ContributeLocal/Skill/SubmitLocal/SubmitLocal.tsx b/src/components/Contribute/Native/Skill/Submit/SubmitNative.tsx similarity index 95% rename from src/components/Experimental/ContributeLocal/Skill/SubmitLocal/SubmitLocal.tsx rename to src/components/Contribute/Native/Skill/Submit/SubmitNative.tsx index 7cf9967a..c93323ab 100644 --- a/src/components/Experimental/ContributeLocal/Skill/SubmitLocal/SubmitLocal.tsx +++ b/src/components/Contribute/Native/Skill/Submit/SubmitNative.tsx @@ -4,7 +4,7 @@ import { ActionGroupAlertContent, SkillFormData } from '..'; import { AttributionData, SkillYamlData } from '@/types'; import { SkillSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; -import { validateFields } from '@/components/Contribute/Skill/validation'; +import { validateFields } from '@/components/Contribute/Github/Skill/validation'; interface Props { disableAction: boolean; @@ -57,7 +57,7 @@ const Submit: React.FC = ({ disableAction, skillFormData, setActionGroupA const name = skillFormData.name; const submissionSummary = skillFormData.submissionSummary; const documentOutline = skillFormData.documentOutline; - const response = await fetch('/api/local/pr/skill/', { + const response = await fetch('/api/native/pr/skill/', { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -87,7 +87,7 @@ const Submit: React.FC = ({ disableAction, skillFormData, setActionGroupA const actionGroupAlertContent: ActionGroupAlertContent = { title: 'Skill contribution submitted successfully!', message: `Thank you for your contribution!`, - url: '/experimental/dashboard-local/', + url: '/dashboard', success: true }; setActionGroupAlertContent(actionGroupAlertContent); diff --git a/src/components/Experimental/ContributeLocal/Skill/index.tsx b/src/components/Contribute/Native/Skill/index.tsx similarity index 91% rename from src/components/Experimental/ContributeLocal/Skill/index.tsx rename to src/components/Contribute/Native/Skill/index.tsx index 4ff6a35e..ff4508ad 100644 --- a/src/components/Experimental/ContributeLocal/Skill/index.tsx +++ b/src/components/Contribute/Native/Skill/index.tsx @@ -1,4 +1,4 @@ -// src/components/Experimental/ContributeLocal/Skill/index.tsx +// src/components/contribute/Skill/index.tsx 'use client'; import React, { useEffect, useState } from 'react'; import './skills.css'; @@ -8,9 +8,9 @@ import { Form } from '@patternfly/react-core/dist/dynamic/components/Form'; import { useSession } from 'next-auth/react'; import AuthorInformation from '@/components/Contribute/AuthorInformation'; import { FormType } from '@/components/Contribute/AuthorInformation'; -import FilePathInformation from '@/components/Contribute/Skill/FilePathInformation/FilePathInformation'; -import AttributionInformation from '@/components/Contribute/Skill/AttributionInformation/AttributionInformation'; -import Submit from '@/components/Experimental/ContributeLocal/Skill/SubmitLocal/SubmitLocal'; +import FilePathInformation from '@/components/Contribute/Github/Skill/FilePathInformation/FilePathInformation'; +import AttributionInformation from '@/components/Contribute/Github/Skill/AttributionInformation/AttributionInformation'; +import Submit from '@/components/Contribute/Native/Skill/Submit/SubmitNative'; import { Breadcrumb } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; import { BreadcrumbItem } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; import { PageBreadcrumb } from '@patternfly/react-core/dist/dynamic/components/Page'; @@ -18,18 +18,18 @@ import { PageGroup } from '@patternfly/react-core/dist/dynamic/components/Page'; import { PageSection } from '@patternfly/react-core/dist/dynamic/components/Page'; import { Content } from '@patternfly/react-core/dist/dynamic/components/Content'; import { Title } from '@patternfly/react-core/dist/dynamic/components/Title'; -import { checkSkillFormCompletion } from '@/components/Contribute/Skill/validation'; +import { checkSkillFormCompletion } from '@/components/Contribute/Github/Skill/validation'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { DownloadDropdown } from '@/components/Contribute/Skill/DownloadDropdown/DownloadDropdown'; -import { ViewDropdown } from '@/components/Contribute/Skill/ViewDropdown/ViewDropdown'; -import Update from '@/components/Contribute/Skill/Update/Update'; +import { DownloadDropdown } from '@/components/Contribute/Github/Skill/DownloadDropdown/DownloadDropdown'; +import { ViewDropdown } from '@/components/Contribute/Github/Skill/ViewDropdown/ViewDropdown'; +import Update from '@/components/Contribute/Github/Skill/Update/Update'; import { PullRequestFile } from '@/types'; import { Button } from '@patternfly/react-core/dist/esm/components/Button/Button'; import { useRouter } from 'next/navigation'; -import SkillsSeedExample from '@/components/Contribute/Skill/SkillsSeedExample/SkillsSeedExample'; -import SkillsInformation from '@/components/Contribute/Skill/SkillsInformation/SkillsInformation'; -import SkillsDescriptionContent from '@/components/Contribute/Skill/SkillsDescription/SkillsDescriptionContent'; -import { autoFillSkillsFields } from '@/components/Contribute/Skill/AutoFill'; +import SkillsSeedExample from '@/components/Contribute/Github/Skill/SkillsSeedExample/SkillsSeedExample'; +import SkillsInformation from '@/components/Contribute/Github/Skill/SkillsInformation/SkillsInformation'; +import SkillsDescriptionContent from '@/components/Contribute/Github/Skill/SkillsDescription/SkillsDescriptionContent'; +import { autoFillSkillsFields } from '@/components/Contribute/Github/Skill/AutoFill'; import { Spinner } from '@patternfly/react-core/dist/dynamic/components/Spinner'; export interface SeedExample { @@ -81,8 +81,8 @@ export interface SkillFormProps { skillEditFormData?: SkillEditFormData; } -export const SkillFormLocal: React.FunctionComponent = ({ skillEditFormData }) => { - const [deploymentType, setDeploymentType] = useState(); +export const SkillFormNative: React.FunctionComponent = ({ skillEditFormData }) => { + const [devModeEnabled, setDevModeEnabled] = useState(); const { data: session } = useSession(); const [githubUsername] = useState(''); @@ -133,7 +133,7 @@ export const SkillFormLocal: React.FunctionComponent = ({ skillE const getEnvVariables = async () => { const res = await fetch('/api/envConfig'); const envConfig = await res.json(); - setDeploymentType(envConfig.DEPLOYMENT_TYPE); + setDevModeEnabled(envConfig.ENABLE_DEV_MODE === 'true'); }; getEnvVariables(); }, []); @@ -343,7 +343,7 @@ export const SkillFormLocal: React.FunctionComponent = ({ skillE - {deploymentType === 'dev' && ( + {devModeEnabled && ( @@ -459,4 +459,4 @@ export const SkillFormLocal: React.FunctionComponent = ({ skillE ); }; -export default SkillFormLocal; +export default SkillFormNative; diff --git a/src/components/Experimental/ContributeLocal/Skill/skills.css b/src/components/Contribute/Native/Skill/skills.css similarity index 100% rename from src/components/Experimental/ContributeLocal/Skill/skills.css rename to src/components/Contribute/Native/Skill/skills.css diff --git a/src/components/Dashboard/index.tsx b/src/components/Dashboard/Github/dashboard.tsx similarity index 97% rename from src/components/Dashboard/index.tsx rename to src/components/Dashboard/Github/dashboard.tsx index c31b8d73..03a83ac0 100644 --- a/src/components/Dashboard/index.tsx +++ b/src/components/Dashboard/Github/dashboard.tsx @@ -1,3 +1,4 @@ +// src/components/dashboard/github/dashboard.tsx import * as React from 'react'; import { useSession } from 'next-auth/react'; import { Label } from '@patternfly/react-core/dist/dynamic/components/Label'; @@ -19,8 +20,8 @@ import GithubIcon from '@patternfly/react-icons/dist/esm/icons/github-icon'; import Image from 'next/image'; import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; import { useRouter } from 'next/navigation'; -import { fetchPullRequests, getGitHubUsername } from '../../utils/github'; -import { PullRequest } from '../../types'; +import { fetchPullRequests, getGitHubUsername } from '../../../utils/github'; +import { PullRequest } from '../../../types'; import { Breadcrumb, BreadcrumbItem } from '@patternfly/react-core/dist/esm/components/Breadcrumb'; import { Content } from '@patternfly/react-core/dist/esm/components/Content'; import OutlinedQuestionCircleIcon from '@patternfly/react-icons/dist/esm/icons/outlined-question-circle-icon'; @@ -32,7 +33,7 @@ import { Spinner } from '@patternfly/react-core/dist/esm/components/Spinner'; const InstructLabLogo: React.FC = () => InstructLab Logo; -const Index: React.FunctionComponent = () => { +const DashboardGithub: React.FunctionComponent = () => { const { data: session } = useSession(); const [pullRequests, setPullRequests] = React.useState([]); const [isFirstPullDone, setIsFirstPullDone] = React.useState(false); @@ -210,4 +211,4 @@ const Index: React.FunctionComponent = () => { ); }; -export { Index }; +export { DashboardGithub }; diff --git a/src/components/Experimental/DashboardLocal/index.tsx b/src/components/Dashboard/Native/dashboard.tsx similarity index 82% rename from src/components/Experimental/DashboardLocal/index.tsx rename to src/components/Dashboard/Native/dashboard.tsx index 3db4208d..3a66a965 100644 --- a/src/components/Experimental/DashboardLocal/index.tsx +++ b/src/components/Dashboard/Native/dashboard.tsx @@ -1,4 +1,4 @@ -// src/components/Experimental/DashboardLocal/index.tsx +// src/components/Dashboard/Native/dashboard.tsx import * as React from 'react'; import { Card, CardBody } from '@patternfly/react-core/dist/dynamic/components/Card'; import { Stack, StackItem } from '@patternfly/react-core/dist/dynamic/layouts/Stack'; @@ -17,7 +17,7 @@ import { useRouter } from 'next/navigation'; const InstructLabLogo: React.FC = () => InstructLab Logo; -const DashboardLocal: React.FunctionComponent = () => { +const DashboardNative: React.FunctionComponent = () => { const [branches, setBranches] = React.useState<{ name: string; creationDate: number }[]>([]); const [isLoading, setIsLoading] = React.useState(true); const [mergeStatus] = React.useState<{ branch: string; message: string; success: boolean } | null>(null); @@ -27,27 +27,53 @@ const DashboardLocal: React.FunctionComponent = () => { // Fetch branches from the API route React.useEffect(() => { - const fetchBranches = async () => { - try { - const response = await fetch('/api/local/git/branches'); - const result = await response.json(); - if (response.ok) { - // Filter out 'main' branch - const filteredBranches = result.branches.filter((branch: { name: string }) => branch.name !== 'main'); - setBranches(filteredBranches); - } else { - console.error('Failed to fetch branches:', result.error); - } - } catch (error) { - console.error('Error fetching branches:', error); - } finally { - setIsLoading(false); + cloneNativeTaxonomyRepo().then((success) => { + if (success) { + fetchBranches(); } - }; - - fetchBranches(); + }); }, []); + const fetchBranches = async () => { + try { + const response = await fetch('/api/native/git/branches'); + const result = await response.json(); + if (response.ok) { + // Filter out 'main' branch + const filteredBranches = result.branches.filter((branch: { name: string }) => branch.name !== 'main'); + setBranches(filteredBranches); + } else { + console.error('Failed to fetch branches:', result.error); + } + } catch (error) { + console.error('Error fetching branches:', error); + } finally { + setIsLoading(false); + } + }; + + async function cloneNativeTaxonomyRepo(): Promise { + try { + const response = await fetch('/api/native/clone-repo', { + method: 'POST', + headers: { 'Content-Type': 'application/json' } + }); + + const result = await response.json(); + if (response.ok) { + console.log(result.message); + return true; + } else { + console.error(result.message); + return false; + } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error'; + console.error('Error cloning repo:', errorMessage); + return false; + } + } + const formatDateTime = (timestamp: number) => { const date = new Date(timestamp); return `${date.toLocaleDateString()} ${date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`; @@ -57,7 +83,7 @@ const DashboardLocal: React.FunctionComponent = () => { // const handleMerge = async (branchName: string) => { // setMergeStatus(null); // Clear previous status // try { - // const response = await fetch('/api/local/git/branches', { + // const response = await fetch('/api/native/git/branches', { // method: 'POST', // headers: { 'Content-Type': 'application/json' }, // body: JSON.stringify({ branchName, action: 'merge' }) @@ -77,7 +103,7 @@ const DashboardLocal: React.FunctionComponent = () => { const handleShowChanges = async (branchName: string) => { try { - const response = await fetch('/api/local/git/branches', { + const response = await fetch('/api/native/git/branches', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ branchName, action: 'diff' }) @@ -123,13 +149,10 @@ const DashboardLocal: React.FunctionComponent = () => { - - - - - - {message && ( - - - {message} - - - )} - - {fullPath && ( - - - Cloned to: {fullPath} - - - )} - - ); -}; - -export default CloneRepoLocal; diff --git a/src/components/GithubAccessPopup/index.tsx b/src/components/GithubAccessPopup/index.tsx index bfa634ac..66044980 100644 --- a/src/components/GithubAccessPopup/index.tsx +++ b/src/components/GithubAccessPopup/index.tsx @@ -17,7 +17,7 @@ const GithubAccessPopup: React.FunctionComponent = ({ onAccept }) => { const showPopupWarning = async () => { const res = await fetch('/api/envConfig'); const envConfig = await res.json(); - if (envConfig.DEPLOYMENT_TYPE === 'dev') { + if (envConfig.DEPLOYMENT_TYPE === 'native' || envConfig.ENABLE_DEV_MODE === 'true') { setIsOpen(false); onAccept(); } else { From d71c73391529be768d3610d7c610b501319933a6 Mon Sep 17 00:00:00 2001 From: Anil Vishnoi Date: Wed, 11 Dec 2024 03:37:37 -0800 Subject: [PATCH 2/6] Add feature to delete, and publish the contribution Signed-off-by: Anil Vishnoi --- src/app/api/envConfig/route.ts | 3 +- src/app/api/native/clone-repo/route.ts | 8 +- src/app/api/native/git/branches/route.ts | 255 ++++++++++++++---- src/app/api/native/pr/knowledge/route.ts | 4 +- src/app/api/native/pr/skill/route.ts | 4 +- src/components/Dashboard/Native/dashboard.tsx | 222 ++++++++++++++- 6 files changed, 425 insertions(+), 71 deletions(-) diff --git a/src/app/api/envConfig/route.ts b/src/app/api/envConfig/route.ts index 5b30015e..330fb372 100644 --- a/src/app/api/envConfig/route.ts +++ b/src/app/api/envConfig/route.ts @@ -16,7 +16,8 @@ export async function GET() { UPSTREAM_REPO_NAME: process.env.NEXT_PUBLIC_TAXONOMY_REPO || '', DEPLOYMENT_TYPE: process.env.IL_UI_DEPLOYMENT || '', ENABLE_DEV_MODE: process.env.IL_ENABLE_DEV_MODE || '', - EXPERIMENTAL_FEATURES: process.env.NEXT_PUBLIC_EXPERIMENTAL_FEATURES || '' + EXPERIMENTAL_FEATURES: process.env.NEXT_PUBLIC_EXPERIMENTAL_FEATURES || '', + TAXONOMY_REPO_DIR: process.env.NEXT_PUBLIC_TAXONOMY_REPO_DIR || '' }; return NextResponse.json(envConfig); diff --git a/src/app/api/native/clone-repo/route.ts b/src/app/api/native/clone-repo/route.ts index 81630c1f..eb5fc362 100644 --- a/src/app/api/native/clone-repo/route.ts +++ b/src/app/api/native/clone-repo/route.ts @@ -6,11 +6,11 @@ import fs from 'fs'; import path from 'path'; // Retrieve the base directory from the environment variable -const TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_TAXONOMY_ROOT_DIR || './.instructlab-ui'; +const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || './.instructlab-ui'; const TAXONOMY_REPO_URL = process.env.NEXT_PUBLIC_TAXONOMY_REPO_URL || 'https://github.com/instructlab/taxonomy.git'; export async function POST() { - const taxonomyDirectoryPath = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); + const taxonomyDirectoryPath = path.join(LOCAL_TAXONOMY_ROOT_DIR, '/taxonomy'); if (fs.existsSync(taxonomyDirectoryPath)) { const files = fs.readdirSync(taxonomyDirectoryPath); @@ -32,8 +32,8 @@ export async function POST() { }); // Include the full path in the response for client display - console.log(`Repository cloned successfully to ${TAXONOMY_ROOT_DIR}.`); - return NextResponse.json({ message: `Repository cloned successfully to ${TAXONOMY_ROOT_DIR}.` }, { status: 200 }); + console.log(`Repository cloned successfully to ${LOCAL_TAXONOMY_ROOT_DIR}.`); + return NextResponse.json({ message: `Repository cloned successfully to ${LOCAL_TAXONOMY_ROOT_DIR}.` }, { status: 200 }); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; console.error(`Failed to clone taxonomy repository: ${errorMessage}`); diff --git a/src/app/api/native/git/branches/route.ts b/src/app/api/native/git/branches/route.ts index 0fcd51d0..092c5865 100644 --- a/src/app/api/native/git/branches/route.ts +++ b/src/app/api/native/git/branches/route.ts @@ -5,10 +5,14 @@ import fs from 'fs'; import path from 'path'; // Get the repository path from the environment variable -const TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_TAXONOMY_ROOT_DIR || './.instructlab-ui'; +const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || './.instructlab-ui'; +interface Diffs { + file: string; + status: string; +} export async function GET() { - const REPO_DIR = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); + const REPO_DIR = path.join(LOCAL_TAXONOMY_ROOT_DIR, '/taxonomy'); try { // Ensure the repository path exists if (!fs.existsSync(REPO_DIR)) { @@ -41,91 +45,234 @@ export async function GET() { // Handle POST requests for merge or branch comparison export async function POST(req: NextRequest) { - const REPO_DIR = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); - const { branchName, action } = await req.json(); + const LOCAL_TAXONOMY_DIR = path.join(LOCAL_TAXONOMY_ROOT_DIR, '/taxonomy'); + const { branchName, action, remoteTaxonomyRepoDir } = await req.json(); + console.log('Received POST request:', { branchName, action, remoteTaxonomyRepoDir }); + + if (action === 'delete') { + return handleDelete(branchName, LOCAL_TAXONOMY_DIR); + } + + if (action === 'diff') { + return handleDiff(branchName, LOCAL_TAXONOMY_DIR); + } + if (action === 'publish') { + return handlePublish(branchName, LOCAL_TAXONOMY_DIR, remoteTaxonomyRepoDir); + } + return NextResponse.json({ error: 'Invalid action specified' }, { status: 400 }); +} + +async function handleDelete(branchName: string, localTaxonomyDir: string) { try { - if (action === 'merge') { - // Ensure valid branch name - if (!branchName || branchName === 'main') { - return NextResponse.json({ error: 'Invalid branch name for merge' }, { status: 400 }); - } + if (!branchName || branchName === 'main') { + return NextResponse.json({ error: 'Invalid branch name for deletion' }, { status: 400 }); + } - // Initialize the repository and checkout main branch - await git.init({ fs, dir: REPO_DIR }); - await git.checkout({ fs, dir: REPO_DIR, ref: 'main' }); + // Delete the target branch + await git.deleteBranch({ fs, dir: localTaxonomyDir, ref: branchName }); - // Perform the merge - await git.merge({ - fs, - dir: REPO_DIR, - ours: 'main', - theirs: branchName, - author: { - name: 'Instruct Lab Local', - email: 'local@instructlab.ai' - } - }); + return NextResponse.json({ message: `Successfully deleted branch ${branchName}.` }, { status: 200 }); + } catch (error) { + console.error(`Failed to delete contribution ${branchName}:`, error); + return NextResponse.json( + { + error: `Failed to delete contribution ${branchName}` + }, + { status: 500 } + ); + } finally { + // Ensure switching back to 'main' branch after any operation + try { + await git.checkout({ fs, dir: localTaxonomyDir, ref: 'main' }); + } catch (checkoutError) { + console.error('Failed to switch back to main branch:', checkoutError); + } + } +} + +async function handleDiff(branchName: string, localTaxonomyDir: string) { + try { + // Ensure valid branch name + if (!branchName || branchName === 'main') { + return NextResponse.json({ error: 'Invalid branch name for comparison' }, { status: 400 }); + } + + const changes = await findDiff(branchName, localTaxonomyDir); + return NextResponse.json({ changes }, { status: 200 }); + } catch (error) { + console.error(`Failed to show contribution changes ${branchName}:`, error); + return NextResponse.json( + { + error: `Failed to show contribution changes for ${branchName}` + }, + { status: 500 } + ); + } finally { + // Ensure switching back to 'main' branch after any operation + try { + await git.checkout({ fs, dir: localTaxonomyDir, ref: 'main' }); + } catch (checkoutError) { + console.error('Failed to switch back to main branch:', checkoutError); + } + } +} + +async function findDiff(branchName: string, localTaxonomyDir: string): Promise { + // Fetch the commit SHA for `main` and the target branch + const mainCommit = await git.resolveRef({ fs, dir: localTaxonomyDir, ref: 'main' }); + const branchCommit = await git.resolveRef({ fs, dir: localTaxonomyDir, ref: branchName }); - return NextResponse.json({ message: `Successfully merged ${branchName} into main.` }, { status: 200 }); - } else if (action === 'diff') { - // Ensure valid branch name - if (!branchName || branchName === 'main') { - return NextResponse.json({ error: 'Invalid branch name for comparison' }, { status: 400 }); + const mainFiles = await getFilesFromTree(mainCommit); + const branchFiles = await getFilesFromTree(branchCommit); + + // Create an array of Diffs to store changes + const changes: Diffs[] = []; + // Identify modified and deleted files + for (const file in mainFiles) { + if (branchFiles[file]) { + if (mainFiles[file] !== branchFiles[file]) { + changes.push({ file, status: 'modified' }); } + } else { + changes.push({ file, status: 'deleted' }); + } + } + + // Identify added files + for (const file in branchFiles) { + if (!mainFiles[file]) { + changes.push({ file, status: 'added' }); + } + } + return changes; +} - // Fetch the commit SHA for `main` and the target branch - const mainCommit = await git.resolveRef({ fs, dir: REPO_DIR, ref: 'main' }); - const branchCommit = await git.resolveRef({ fs, dir: REPO_DIR, ref: branchName }); +async function getTopCommitDetails(dir: string, ref: string = 'HEAD') { + try { + // Fetch the top commit (latest commit on the branch) + const [topCommit] = await git.log({ + fs, + dir, + ref, + depth: 1 // Only fetch the latest commit + }); - const mainFiles = await getFilesFromTree(mainCommit); - const branchFiles = await getFilesFromTree(branchCommit); + if (!topCommit) { + throw new Error('No commits found in the repository.'); + } - const changes = []; + // Extract commit message + const commitMessage = topCommit.commit.message; - // Identify modified and deleted files - for (const file in mainFiles) { - if (branchFiles[file]) { - if (mainFiles[file] !== branchFiles[file]) { - changes.push({ file, status: 'modified' }); - } - } else { - changes.push({ file, status: 'deleted' }); - } + // Check for Signed-off-by line + const signoffMatch = commitMessage.match(/^Signed-off-by: (.+)$/m); + const signoff = signoffMatch ? signoffMatch[1] : null; + + return { + message: commitMessage, + signoff + }; + } catch (error) { + console.error('Error reading top commit details:', error); + throw error; + } +} +async function handlePublish(branchName: string, localTaxonomyDir: string, remoteTaxonomyDir: string) { + try { + if (!branchName || branchName === 'main') { + return NextResponse.json({ error: 'Invalid branch name for publish' }, { status: 400 }); + } + + console.log(`Publishing contribution from ${branchName} to remote taxonomy repo at ${remoteTaxonomyDir}`); + const changes = await findDiff(branchName, localTaxonomyDir); + + // Check if there are any changes to publish, create a new branch at remoteTaxonomyDir and copy all the files listed in the changes array to the new branch and create a commit + if (changes.length > 0) { + const remoteBranchName = branchName; + await git.checkout({ fs, dir: localTaxonomyDir, ref: branchName }); + // Read the commit message of the top commit from the branch + const details = await getTopCommitDetails(localTaxonomyDir); + + // Check if the remote branch exists, if not create it + const remoteBranchExists = await git.listBranches({ fs, dir: remoteTaxonomyDir }); + if (remoteBranchExists.includes(remoteBranchName)) { + console.log(`Branch ${remoteBranchName} exist in remote taxonomy, deleting it.`); + // Delete the remote branch if it exists, we will recreate it + await git.deleteBranch({ fs, dir: remoteTaxonomyDir, ref: remoteBranchName }); + } else { + console.log(`Branch ${remoteBranchName} does not exist in remote taxonomy, creating a new branch.`); } - // Identify added files - for (const file in branchFiles) { - if (!mainFiles[file]) { - changes.push({ file, status: 'added' }); + await git.checkout({ fs, dir: remoteTaxonomyDir, ref: 'main' }); + await git.branch({ fs, dir: remoteTaxonomyDir, ref: remoteBranchName }); + await git.checkout({ fs, dir: remoteTaxonomyDir, ref: remoteBranchName }); + + // Copy the files listed in the changes array to the remote branch and if the directories do not exist, create them + for (const change of changes) { + console.log(`Copying ${change.file} to remote branch`); + const filePath = path.join(localTaxonomyDir, change.file); + const remoteFilePath = path.join(remoteTaxonomyDir, change.file); + const remoteFileDir = path.dirname(remoteFilePath); + if (!fs.existsSync(remoteFileDir)) { + fs.mkdirSync(remoteFileDir, { recursive: true }); } + fs.copyFileSync(filePath, remoteFilePath); } - return NextResponse.json({ changes }, { status: 200 }); + await git.add({ fs, dir: remoteTaxonomyDir, filepath: '.' }); + + const authorInfo = details.signoff!.match(/(.*?) <(.*?)>/); + let authorName = ''; + let authorEmail = ''; + if (authorInfo) { + console.log(`Author information found in signoff: ${authorInfo}`); + authorName = authorInfo[1]; + authorEmail = authorInfo[2]; + } else { + return NextResponse.json({ message: `Author information is not present in the contribution ${branchName}.` }, { status: 500 }); + } + // Create a commit with the same message and signoff as the top commit from the local branch + await git.commit({ + fs, + dir: remoteTaxonomyDir, + message: details.message, + author: { + name: authorName, + email: authorEmail + } + }); + console.log(`Successfully published contribution from ${branchName} to remote taxonomy repo at ${remoteTaxonomyDir}`); + return NextResponse.json({ message: `Successfully published contribution to ${remoteTaxonomyDir}.` }, { status: 200 }); } else { - return NextResponse.json({ error: 'Invalid action specified' }, { status: 400 }); + return NextResponse.json({ message: `No changes to publish from ${branchName}.` }, { status: 200 }); } } catch (error) { - console.error(`Failed to ${action === 'merge' ? 'merge branch' : 'compare branches'}:`, error); + console.error(`Failed to publish contribution from ${branchName}:`, error); return NextResponse.json( { - error: `Failed to ${action === 'merge' ? 'merge branch' : 'compare branches'}` + error: `Failed to publish contribution from ${branchName}` }, { status: 500 } ); } finally { // Ensure switching back to 'main' branch after any operation try { - await git.checkout({ fs, dir: REPO_DIR, ref: 'main' }); + await git.checkout({ fs, dir: localTaxonomyDir, ref: 'main' }); } catch (checkoutError) { - console.error('Failed to switch back to main branch:', checkoutError); + console.error('Failed to switch back to main branch in local taxonomy repo:', checkoutError); + } + try { + await git.checkout({ fs, dir: remoteTaxonomyDir, ref: 'main' }); + } catch (checkoutError) { + console.error('Failed to switch back to main branch in remote taxonomy repo:', checkoutError); } } } // Helper function to recursively gather file paths and their oids from a tree async function getFilesFromTree(commitOid: string) { - const REPO_DIR = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); + const REPO_DIR = path.join(LOCAL_TAXONOMY_ROOT_DIR, '/taxonomy'); const fileMap: Record = {}; async function walkTree(dir: string) { diff --git a/src/app/api/native/pr/knowledge/route.ts b/src/app/api/native/pr/knowledge/route.ts index 51549f81..a999d971 100644 --- a/src/app/api/native/pr/knowledge/route.ts +++ b/src/app/api/native/pr/knowledge/route.ts @@ -10,12 +10,12 @@ import { KnowledgeYamlData } from '@/types'; import yaml from 'js-yaml'; // Define paths and configuration -const TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_TAXONOMY_ROOT_DIR || './.instructlab-ui'; +const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || './.instructlab-ui'; const KNOWLEDGE_DIR = 'knowledge'; export async function POST(req: NextRequest) { - const REPO_DIR = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); + const REPO_DIR = path.join(LOCAL_TAXONOMY_ROOT_DIR, '/taxonomy'); try { // Extract the data from the request body const { content, attribution, name, email, submissionSummary, filePath } = await req.json(); diff --git a/src/app/api/native/pr/skill/route.ts b/src/app/api/native/pr/skill/route.ts index 72113bd3..c8d2864a 100644 --- a/src/app/api/native/pr/skill/route.ts +++ b/src/app/api/native/pr/skill/route.ts @@ -7,12 +7,12 @@ import path from 'path'; import yaml from 'js-yaml'; // Define paths and configuration -const TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_TAXONOMY_ROOT_DIR || './.instructlab-ui'; +const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || './.instructlab-ui'; const SKILLS_DIR = 'compositional_skills'; export async function POST(req: NextRequest) { - const REPO_DIR = path.join(TAXONOMY_ROOT_DIR, '/taxonomy'); + const REPO_DIR = path.join(LOCAL_TAXONOMY_ROOT_DIR, '/taxonomy'); try { // Extract the QnA data from the request body TODO: what is documentOutline? const { content, attribution, name, email, submissionSummary, documentOutline, filePath } = await req.json(); // eslint-disable-line @typescript-eslint/no-unused-vars diff --git a/src/components/Dashboard/Native/dashboard.tsx b/src/components/Dashboard/Native/dashboard.tsx index 3a66a965..f5ffdf07 100644 --- a/src/components/Dashboard/Native/dashboard.tsx +++ b/src/components/Dashboard/Native/dashboard.tsx @@ -14,19 +14,50 @@ import { EmptyState, EmptyStateBody, EmptyStateFooter, EmptyStateActions } from import GithubIcon from '@patternfly/react-icons/dist/esm/icons/github-icon'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; +import { TrashIcon } from '@patternfly/react-icons/dist/esm/icons/trash-icon'; +import { Tooltip } from '@patternfly/react-core/dist/esm/components/Tooltip/Tooltip'; +import { CatalogIcon } from '@patternfly/react-icons/dist/esm/icons/catalog-icon'; +import { AlertGroup } from '@patternfly/react-core/dist/esm/components/Alert/AlertGroup'; +import { Alert, AlertProps, AlertVariant } from '@patternfly/react-core/dist/esm/components/Alert/Alert'; +import { AlertActionCloseButton } from '@patternfly/react-core/dist/esm/components/Alert/AlertActionCloseButton'; +import { PencilAltIcon } from '@patternfly/react-icons/dist/esm/icons/pencil-alt-icon'; +import { UploadIcon } from '@patternfly/react-icons/dist/esm/icons/upload-icon'; +import { ModalHeader } from '@patternfly/react-core/dist/esm/components/Modal/ModalHeader'; +import { ModalBody } from '@patternfly/react-core/dist/esm/components/Modal/ModalBody'; +import { FormGroup } from '@patternfly/react-core/dist/esm/components/Form/FormGroup'; +import { Form } from '@patternfly/react-core/dist/esm/components/Form/Form'; +import { TextInput } from '@patternfly/react-core/dist/esm/components/TextInput/TextInput'; +import { ModalFooter } from '@patternfly/react-core/dist/esm/components/Modal/ModalFooter'; const InstructLabLogo: React.FC = () => InstructLab Logo; const DashboardNative: React.FunctionComponent = () => { const [branches, setBranches] = React.useState<{ name: string; creationDate: number }[]>([]); + const [selectedTaxonomyRepoDir, setSelectedTaxonomyRepoDir] = React.useState(''); + const [defaultTaxonomyRepoDir, setDefaultTaxonomyRepoDir] = React.useState(''); const [isLoading, setIsLoading] = React.useState(true); const [mergeStatus] = React.useState<{ branch: string; message: string; success: boolean } | null>(null); const [diffData, setDiffData] = React.useState<{ branch: string; changes: { file: string; status: string }[] } | null>(null); const [isModalOpen, setIsModalOpen] = React.useState(false); + const [alerts, setAlerts] = React.useState[]>([]); + const [isDeleteModalOpen, setIsDeleteModalOpen] = React.useState(false); + const [isPublishModalOpen, setIsPublishModalOpen] = React.useState(false); + const [selectedBranch, setSelectedBranch] = React.useState(null); + + const getUniqueId = () => new Date().getTime(); + const router = useRouter(); // Fetch branches from the API route React.useEffect(() => { + const getEnvVariables = async () => { + const res = await fetch('/api/envConfig'); + const envConfig = await res.json(); + setDefaultTaxonomyRepoDir(envConfig.TAXONOMY_REPO_DIR); + setSelectedTaxonomyRepoDir(envConfig.TAXONOMY_REPO_DIR); + }; + getEnvVariables(); + cloneNativeTaxonomyRepo().then((success) => { if (success) { fetchBranches(); @@ -34,6 +65,22 @@ const DashboardNative: React.FunctionComponent = () => { }); }, []); + const addAlert = (title: string, variant: AlertProps['variant'], key: React.Key) => { + setAlerts((prevAlerts) => [...prevAlerts, { title, variant, key }]); + }; + + const removeAlert = (key: React.Key) => { + setAlerts((prevAlerts) => [...prevAlerts.filter((alert) => alert.key !== key)]); + }; + + const addSuccessAlert = (message: string) => { + addAlert(message, 'success', getUniqueId()); + }; + + const addDangerAlert = (message: string) => { + addAlert(message, 'danger', getUniqueId()); + }; + const fetchBranches = async () => { try { const response = await fetch('/api/native/git/branches'); @@ -121,6 +168,93 @@ const DashboardNative: React.FunctionComponent = () => { } }; + const handleDeleteContribution = async (branchName: string) => { + setSelectedBranch(branchName); + setIsDeleteModalOpen(true); + }; + + const handleDeleteContributionConfirm = async () => { + if (selectedBranch) { + await deleteContribution(selectedBranch); + setIsDeleteModalOpen(false); + } + }; + + const handleDeleteContributionCancel = () => { + setSelectedBranch(null); + setIsDeleteModalOpen(false); + }; + + const deleteContribution = async (branchName: string) => { + try { + const response = await fetch('/api/native/git/branches', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ branchName, action: 'delete' }) + }); + + const result = await response.json(); + if (response.ok) { + // Remove the branch from the list + setBranches((prevBranches) => prevBranches.filter((branch) => branch.name !== branchName)); + addSuccessAlert(result.message); + } else { + console.error(result.error); + addDangerAlert(result.error); + } + } catch (error) { + if (error instanceof Error) { + const errorMessage = 'Error deleting branch ' + branchName + ':' + error.message; + console.error(errorMessage); + addDangerAlert(errorMessage); + } else { + console.error('Unknown error deleting the contribution ${branchName}'); + addDangerAlert('Unknown error deleting the contribution ${branchName}'); + } + } + }; + const handleEditContribution = async (branchName: string) => { + setSelectedBranch(branchName); + setIsDeleteModalOpen(true); + }; + + const handlePublishContribution = async (branchName: string) => { + setSelectedBranch(branchName); + setIsPublishModalOpen(true); + }; + + const handlePublishContributionConfirm = async () => { + if (selectedBranch) { + try { + const response = await fetch('/api/native/git/branches', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ branchName: selectedBranch, action: 'publish', remoteTaxonomyRepoDir: selectedTaxonomyRepoDir }) + }); + + const result = await response.json(); + if (response.ok) { + addSuccessAlert(result.message); + setSelectedTaxonomyRepoDir(defaultTaxonomyRepoDir); + setSelectedBranch(null); + setIsPublishModalOpen(false); + } else { + console.error('Failed to publish the contribution:', result.error); + } + } catch (error) { + console.error('Error while publishing the contribution:', error); + } + } else { + addDangerAlert('No branch selected to publish'); + } + }; + + const handlePublishContributionCancel = () => { + setSelectedTaxonomyRepoDir(defaultTaxonomyRepoDir); + setSelectedBranch(null); + setIsPublishModalOpen(false); + }; + return (
@@ -135,6 +269,17 @@ const DashboardNative: React.FunctionComponent = () => { + + {alerts.map(({ key, variant, title }) => ( + removeAlert(key!)} />} + key={key} + /> + ))} + {isLoading ? ( ) : branches.length === 0 ? ( @@ -149,10 +294,10 @@ const DashboardNative: React.FunctionComponent = () => { - - */} - + Show Changes
}> + , + + ]} + > +

are you sure you want to delete this contribution?

+ + + setIsPublishModalOpen(false)} + aria-labelledby="form-modal-title" + aria-describedby="modal-box-description-form" + > + + + + + + + + + ); From 1f29e5f697cd42e07e25551e76033b324e25f4d2 Mon Sep 17 00:00:00 2001 From: Anil Vishnoi Date: Thu, 12 Dec 2024 01:57:45 -0800 Subject: [PATCH 3/6] Enable document upload feature for native mode In Native mode, taxonomy-knowledge-docs repo is cloned in the $HOME/.instructlab-ui/ directory and the docs are committed to the main branch. Commit sha of that branch is used in the knowledge contribution. In knowledge yaml, document url points to the filepath location of the taxonomy-knowledge-docs. Signed-off-by: Anil Vishnoi --- .env.example | 9 +- src/app/api/native/clone-repo/route.ts | 2 +- src/app/api/native/upload/route.ts | 98 +++++ src/app/contribute/knowledge/page.tsx | 4 +- src/app/contribute/skill/page.tsx | 4 +- .../edit-submission/knowledge/[id]/page.tsx | 2 +- src/app/edit-submission/skill/[id]/page.tsx | 2 +- .../Contribute/AuthorInformation.tsx | 4 +- .../EditKnowledge/EditKnowledge.tsx | 2 +- .../{Github => }/EditSkill/EditSkill.tsx | 8 +- .../Contribute/Github/Knowledge/knowledge.css | 31 -- .../AttributionInformation.tsx | 2 +- .../{Github => }/Knowledge/AutoFill.ts | 14 +- .../DownloadAttribution.tsx | 2 +- .../DownloadDropdown/DownloadDropdown.tsx | 2 +- .../Knowledge/DownloadYaml/DownloadYaml.tsx | 2 +- .../FilePathInformation.tsx | 0 .../DocumentInformation.tsx | 8 +- .../Github}/Submit/Submit.tsx | 2 +- .../Github}/Update/Update.tsx | 2 +- .../Knowledge => Knowledge/Github}/index.tsx | 20 +- .../KnowledgeDescriptionContent.tsx | 0 .../KnowledgeInformation.tsx | 2 +- .../KnowledgeQuestionAnswerPairs.tsx | 2 +- .../KnowledgeSeedExample.tsx | 2 +- .../DocumentInformation.tsx | 370 ++++++++++++++++++ .../Native}/ReviewSubmission/index.tsx | 2 +- .../Native}/Submit/Submit.tsx | 2 +- .../Knowledge => Knowledge/Native}/index.tsx | 26 +- .../{Github => }/Knowledge/UploadFile.tsx | 0 .../Knowledge/ViewDropdown/ViewDropdown.tsx | 2 +- .../{Native => }/Knowledge/knowledge.css | 0 .../{Github => }/Knowledge/validation.tsx | 2 +- .../AttributionInformation.tsx | 2 +- .../Contribute/{Github => }/Skill/AutoFill.ts | 4 +- .../DownloadAttribution.tsx | 2 +- .../DownloadDropdown/DownloadDropdown.tsx | 2 +- .../Skill/DownloadYaml/DownloadYaml.tsx | 3 +- .../FilePathInformation.tsx | 0 .../Skill => Skill/Github}/Submit/Submit.tsx | 6 +- .../Skill => Skill/Github}/Update/Update.tsx | 6 +- .../{Github/Skill => Skill/Github}/index.tsx | 64 +-- .../{Github/Skill => Skill/Github}/skills.css | 0 .../Native/Submit/Submit.tsx} | 6 +- .../{Native/Skill => Skill/Native}/index.tsx | 66 +--- .../{Native/Skill => Skill/Native}/skills.css | 0 .../SkillsDescriptionContent.tsx | 0 .../SkillsInformation/SkillsInformation.tsx | 2 +- .../SkillsSeedExample/SkillsSeedExample.tsx | 6 +- .../Skill/ViewDropdown/ViewDropdown.tsx | 3 +- .../{Github => }/Skill/validation.tsx | 5 +- src/types/index.ts | 28 ++ 52 files changed, 625 insertions(+), 210 deletions(-) create mode 100644 src/app/api/native/upload/route.ts rename src/components/Contribute/{Github => }/EditKnowledge/EditKnowledge.tsx (99%) rename src/components/Contribute/{Github => }/EditSkill/EditSkill.tsx (95%) delete mode 100644 src/components/Contribute/Github/Knowledge/knowledge.css rename src/components/Contribute/{Github => }/Knowledge/AttributionInformation/AttributionInformation.tsx (99%) rename src/components/Contribute/{Github => }/Knowledge/AutoFill.ts (99%) rename src/components/Contribute/{Github => }/Knowledge/DownloadAttribution/DownloadAttribution.tsx (96%) rename src/components/Contribute/{Github => }/Knowledge/DownloadDropdown/DownloadDropdown.tsx (97%) rename src/components/Contribute/{Github => }/Knowledge/DownloadYaml/DownloadYaml.tsx (97%) rename src/components/Contribute/{Github => }/Knowledge/FilePathInformation/FilePathInformation.tsx (100%) rename src/components/Contribute/{Github/Knowledge => Knowledge/Github}/DocumentInformation/DocumentInformation.tsx (98%) rename src/components/Contribute/{Github/Knowledge => Knowledge/Github}/Submit/Submit.tsx (98%) rename src/components/Contribute/{Github/Knowledge => Knowledge/Github}/Update/Update.tsx (99%) rename src/components/Contribute/{Github/Knowledge => Knowledge/Github}/index.tsx (97%) rename src/components/Contribute/{Github => }/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent.tsx (100%) rename src/components/Contribute/{Github => }/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx (99%) rename src/components/Contribute/{Github => }/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx (98%) rename src/components/Contribute/{Github => }/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx (98%) create mode 100644 src/components/Contribute/Knowledge/Native/DocumentInformation/DocumentInformation.tsx rename src/components/Contribute/{Native/Knowledge => Knowledge/Native}/ReviewSubmission/index.tsx (97%) rename src/components/Contribute/{Native/Knowledge => Knowledge/Native}/Submit/Submit.tsx (97%) rename src/components/Contribute/{Native/Knowledge => Knowledge/Native}/index.tsx (95%) rename src/components/Contribute/{Github => }/Knowledge/UploadFile.tsx (100%) rename src/components/Contribute/{Github => }/Knowledge/ViewDropdown/ViewDropdown.tsx (98%) rename src/components/Contribute/{Native => }/Knowledge/knowledge.css (100%) rename src/components/Contribute/{Github => }/Knowledge/validation.tsx (99%) rename src/components/Contribute/{Github => }/Skill/AttributionInformation/AttributionInformation.tsx (99%) rename src/components/Contribute/{Github => }/Skill/AutoFill.ts (96%) rename src/components/Contribute/{Github => }/Skill/DownloadAttribution/DownloadAttribution.tsx (96%) rename src/components/Contribute/{Github => }/Skill/DownloadDropdown/DownloadDropdown.tsx (97%) rename src/components/Contribute/{Github => }/Skill/DownloadYaml/DownloadYaml.tsx (94%) rename src/components/Contribute/{Github => }/Skill/FilePathInformation/FilePathInformation.tsx (100%) rename src/components/Contribute/{Github/Skill => Skill/Github}/Submit/Submit.tsx (95%) rename src/components/Contribute/{Github/Skill => Skill/Github}/Update/Update.tsx (96%) rename src/components/Contribute/{Github/Skill => Skill/Github}/index.tsx (90%) rename src/components/Contribute/{Github/Skill => Skill/Github}/skills.css (100%) rename src/components/Contribute/{Native/Skill/Submit/SubmitNative.tsx => Skill/Native/Submit/Submit.tsx} (94%) rename src/components/Contribute/{Native/Skill => Skill/Native}/index.tsx (86%) rename src/components/Contribute/{Native/Skill => Skill/Native}/skills.css (100%) rename src/components/Contribute/{Github => }/Skill/SkillsDescription/SkillsDescriptionContent.tsx (100%) rename src/components/Contribute/{Github => }/Skill/SkillsInformation/SkillsInformation.tsx (99%) rename src/components/Contribute/{Github => }/Skill/SkillsSeedExample/SkillsSeedExample.tsx (97%) rename src/components/Contribute/{Github => }/Skill/ViewDropdown/ViewDropdown.tsx (97%) rename src/components/Contribute/{Github => }/Skill/validation.tsx (95%) diff --git a/.env.example b/.env.example index b52e8d0f..c26bfa9c 100644 --- a/.env.example +++ b/.env.example @@ -11,7 +11,9 @@ IL_GRANITE_API= IL_GRANITE_MODEL_NAME= IL_MERLINITE_API= IL_MERLINITE_MODEL_NAME= -IL_UI_DEPLOYMENT=dev ## Comment it out if it's not a dev deployment + +IL_UI_DEPLOYMENT=native # Two deployment modes are available: github and native +IL_ENABLE_DEV_MODE=true #Enable this option if you want to enable UI features that helps in development, such as form Auto-Fill feature. GITHUB_TOKEN= TAXONOMY_DOCUMENTS_REPO=github.com/instructlab-public/taxonomy-knowledge-docs @@ -19,7 +21,6 @@ NEXT_PUBLIC_AUTHENTICATION_ORG= NEXT_PUBLIC_TAXONOMY_REPO_OWNER= NEXT_PUBLIC_TAXONOMY_REPO= +NEXT_PUBLIC_TAXONOMY_REPO_DIR= + NEXT_PUBLIC_EXPERIMENTAL_FEATURES=false -# The following requires experimental and dev mode to be enabled -# NEXT_PUBLIC_BASE_CLONE_DIRECTORY=/base/path/ -# NEXT_PUBLIC_LOCAL_REPO_PATH=/base/path/cloned_dir_name diff --git a/src/app/api/native/clone-repo/route.ts b/src/app/api/native/clone-repo/route.ts index eb5fc362..cf6a3cd2 100644 --- a/src/app/api/native/clone-repo/route.ts +++ b/src/app/api/native/clone-repo/route.ts @@ -6,7 +6,7 @@ import fs from 'fs'; import path from 'path'; // Retrieve the base directory from the environment variable -const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || './.instructlab-ui'; +const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || `${process.env.HOME}/.instructlab-ui`; const TAXONOMY_REPO_URL = process.env.NEXT_PUBLIC_TAXONOMY_REPO_URL || 'https://github.com/instructlab/taxonomy.git'; export async function POST() { diff --git a/src/app/api/native/upload/route.ts b/src/app/api/native/upload/route.ts new file mode 100644 index 00000000..b67a452f --- /dev/null +++ b/src/app/api/native/upload/route.ts @@ -0,0 +1,98 @@ +// src/app/api/native/upload/route.ts +import { NextResponse } from 'next/server'; +import { NextRequest } from 'next/server'; +import * as git from 'isomorphic-git'; +import http from 'isomorphic-git/http/node'; +import path from 'path'; +import fs from 'fs'; + +const LOCAL_TAXONOMY_DOCS_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || `${process.env.HOME}/.instructlab-ui`; +const TAXONOMY_KNOWLEDGE_DOCS_REPO_URL = 'https://github.com/instructlab-public/taxonomy-knowledge-docs.git'; + +export async function POST(req: NextRequest) { + try { + const body = await req.json(); + const { files } = body; + const docsRepoUrl = await cloneTaxonomyDocsRepo(); + + // If the repository was not cloned, return an error + if (!docsRepoUrl) { + return NextResponse.json({ error: 'Failed to clone taxonomy knowledge docs repository' }, { status: 500 }); + } + + const timestamp = new Date().toISOString().replace(/[-:.]/g, '').replace('T', 'T').slice(0, -1); + const filesWithTimestamp = files.map((file: { fileName: string; fileContent: string }) => { + const [name, extension] = file.fileName.split(/\.(?=[^.]+$)/); + return { + fileName: `${name}-${timestamp}.${extension}`, + fileContent: file.fileContent + }; + }); + + // Write the files to the repository + for (const file of filesWithTimestamp) { + const filePath = path.join(docsRepoUrl, file.fileName); + fs.writeFileSync(filePath, file.fileContent); + } + + // Checkout the main branch + await git.checkout({ fs, dir: docsRepoUrl, ref: 'main' }); + + // Stage the files + await git.add({ fs, dir: docsRepoUrl, filepath: '.' }); + + // Commit the files + const commitSha = await git.commit({ + fs, + dir: docsRepoUrl, + author: { name: 'instructlab-ui', email: 'ui@instructlab.ai' }, + message: `Add files: ${files + .map((file: { fileName: string; fileContent: string }) => file.fileName) + .join(', ')}\n\nSigned-off-by: ui@instructlab.ai` + }); + + return NextResponse.json( + { + repoUrl: docsRepoUrl, + commitSha, + documentNames: filesWithTimestamp.map((file: { fileName: string }) => file.fileName), + prUrl: '' + }, + { status: 201 } + ); + } catch (error) { + console.error('Failed to upload documents:', error); + return NextResponse.json({ error: 'Failed to upload documents' }, { status: 500 }); + } +} + +async function cloneTaxonomyDocsRepo() { + const taxonomyDocsDirectoryPath = path.join(LOCAL_TAXONOMY_DOCS_ROOT_DIR, '/taxonomy-knowledge-docs'); + console.log(`Cloning taxonomy docs repository to ${taxonomyDocsDirectoryPath}...`); + + if (fs.existsSync(taxonomyDocsDirectoryPath)) { + console.log(`Using existing taxonomy knowledge docs repository at ${taxonomyDocsDirectoryPath}.`); + return taxonomyDocsDirectoryPath; + } else { + console.log(`Taxonomy knowledge docs repository not found at ${taxonomyDocsDirectoryPath}. Cloning...`); + } + + try { + await git.clone({ + fs, + http, + dir: taxonomyDocsDirectoryPath, + url: TAXONOMY_KNOWLEDGE_DOCS_REPO_URL, + singleBranch: true, + depth: 1 + }); + + // Include the full path in the response for client display + console.log(`Repository cloned successfully to ${taxonomyDocsDirectoryPath}.`); + return taxonomyDocsDirectoryPath; + } catch (error: unknown) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; + console.error(`Failed to clone taxonomy docs repository: ${errorMessage}`); + return null; + } +} diff --git a/src/app/contribute/knowledge/page.tsx b/src/app/contribute/knowledge/page.tsx index ff7f5e52..19836b45 100644 --- a/src/app/contribute/knowledge/page.tsx +++ b/src/app/contribute/knowledge/page.tsx @@ -1,8 +1,8 @@ // src/app/contribute/knowledge/page.tsx -import KnowledgeFormNative from '@/components/Contribute/Native/Knowledge'; +import KnowledgeFormNative from '@/components/Contribute/Knowledge/Native'; import * as React from 'react'; import { AppLayout } from '../../../components/AppLayout'; -import { KnowledgeFormGithub } from '../../../components/Contribute/Github/Knowledge'; +import { KnowledgeFormGithub } from '../../../components/Contribute/Knowledge/Github'; const KnowledgeFormPage: React.FC = () => { return {process.env.IL_UI_DEPLOYMENT === 'native' ? : }; diff --git a/src/app/contribute/skill/page.tsx b/src/app/contribute/skill/page.tsx index 63d00f74..01f1d1cb 100644 --- a/src/app/contribute/skill/page.tsx +++ b/src/app/contribute/skill/page.tsx @@ -1,8 +1,8 @@ // src/app/contribute/skill/page.tsx -import SkillFormNative from '@/components/Contribute/Native/Skill'; +import SkillFormNative from '@/components/Contribute/Skill/Native'; import * as React from 'react'; import { AppLayout } from '../../../components/AppLayout'; -import { SkillFormGithub } from '../../../components/Contribute/Github/Skill'; +import { SkillFormGithub } from '../../../components/Contribute/Skill/Github'; const SkillFormPage: React.FC = () => { return {process.env.IL_UI_DEPLOYMENT === 'native' ? : }; diff --git a/src/app/edit-submission/knowledge/[id]/page.tsx b/src/app/edit-submission/knowledge/[id]/page.tsx index 55495a72..55b25ce4 100644 --- a/src/app/edit-submission/knowledge/[id]/page.tsx +++ b/src/app/edit-submission/knowledge/[id]/page.tsx @@ -1,7 +1,7 @@ // src/app/edit-submission/knowledge/[id]/page.tsx import * as React from 'react'; import { AppLayout } from '@/components/AppLayout'; -import EditKnowledge from '@/components/Contribute/Github/EditKnowledge/EditKnowledge'; +import EditKnowledge from '@/components/Contribute/EditKnowledge/EditKnowledge'; type PageProps = { params: Promise<{ id: string }>; diff --git a/src/app/edit-submission/skill/[id]/page.tsx b/src/app/edit-submission/skill/[id]/page.tsx index cb1131e0..735436fa 100644 --- a/src/app/edit-submission/skill/[id]/page.tsx +++ b/src/app/edit-submission/skill/[id]/page.tsx @@ -1,7 +1,7 @@ // src/app/edit-submission/skill/[id]/page.tsx import * as React from 'react'; import { AppLayout } from '@/components/AppLayout'; -import EditSkill from '@/components/Contribute/Github/EditSkill/EditSkill'; +import EditSkill from '@/components/Contribute/EditSkill/EditSkill'; type PageProps = { params: Promise<{ id: string }>; diff --git a/src/components/Contribute/AuthorInformation.tsx b/src/components/Contribute/AuthorInformation.tsx index 5e10135a..1c384dd0 100644 --- a/src/components/Contribute/AuthorInformation.tsx +++ b/src/components/Contribute/AuthorInformation.tsx @@ -5,8 +5,8 @@ import { HelperText } from '@patternfly/react-core/dist/dynamic/components/Helpe import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { checkSkillFormCompletion } from './Github/Skill/validation'; -import { checkKnowledgeFormCompletion } from './Github/Knowledge/validation'; +import { checkSkillFormCompletion } from './Skill/validation'; +import { checkKnowledgeFormCompletion } from './Knowledge/validation'; export enum FormType { Knowledge, diff --git a/src/components/Contribute/Github/EditKnowledge/EditKnowledge.tsx b/src/components/Contribute/EditKnowledge/EditKnowledge.tsx similarity index 99% rename from src/components/Contribute/Github/EditKnowledge/EditKnowledge.tsx rename to src/components/Contribute/EditKnowledge/EditKnowledge.tsx index b59693f3..e9287a81 100644 --- a/src/components/Contribute/Github/EditKnowledge/EditKnowledge.tsx +++ b/src/components/Contribute/EditKnowledge/EditKnowledge.tsx @@ -13,7 +13,7 @@ import KnowledgeFormGithub, { KnowledgeFormData, QuestionAndAnswerPair, SeedExample -} from '@/components/Contribute/Github/Knowledge'; +} from '@/components/Contribute/Knowledge/Github'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; import { useEffect, useState } from 'react'; import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/deprecated/components/Modal/Modal'; diff --git a/src/components/Contribute/Github/EditSkill/EditSkill.tsx b/src/components/Contribute/EditSkill/EditSkill.tsx similarity index 95% rename from src/components/Contribute/Github/EditSkill/EditSkill.tsx rename to src/components/Contribute/EditSkill/EditSkill.tsx index 9cd7e19e..3212ae4f 100644 --- a/src/components/Contribute/Github/EditSkill/EditSkill.tsx +++ b/src/components/Contribute/EditSkill/EditSkill.tsx @@ -7,11 +7,11 @@ import { useEffect, useState } from 'react'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/deprecated/components/Modal/Modal'; import { useRouter } from 'next/navigation'; -import SkillFormGithub, { SkillEditFormData, SkillFormData, SeedExample } from '@/components/Contribute/Github/Skill'; +import SkillFormGithub, { SkillEditFormData } from '@/components/Contribute/Skill/Github'; import { fetchPullRequest, fetchFileContent, fetchPullRequestFiles } from '@/utils/github'; import yaml from 'js-yaml'; import axios from 'axios'; -import { SkillYamlData, AttributionData, PullRequestFile } from '@/types'; +import { SkillYamlData, AttributionData, PullRequestFile, SkillFormData, SkillSeedExample } from '@/types'; import { SkillSchemaVersion } from '@/types/const'; interface EditSkillClientComponentProps { @@ -72,9 +72,9 @@ const EditSkill: React.FC = ({ prNumber }) => { // Populate the form fields with YAML data skillExistingFormData.documentOutline = yamlData.task_description; - const seedExamples: SeedExample[] = []; + const seedExamples: SkillSeedExample[] = []; yamlData.seed_examples.forEach((seed, index) => { - const example: SeedExample = { + const example: SkillSeedExample = { immutable: index < 5 ? true : false, isExpanded: true, context: seed.context || '', diff --git a/src/components/Contribute/Github/Knowledge/knowledge.css b/src/components/Contribute/Github/Knowledge/knowledge.css deleted file mode 100644 index 9f65e32c..00000000 --- a/src/components/Contribute/Github/Knowledge/knowledge.css +++ /dev/null @@ -1,31 +0,0 @@ -/* Knowledge CSS */ - -.form-k { - width: 80%; - margin-bottom: 50px; - background-color: white; -} - -.submit-k:hover, -.download-k-yaml:hover, -.download-k-attribution:hover, -.button-active, -.button-active:hover { - background-color: #45a049; -} - -.heading-k { - text-align: left; - font-size: medium; -} - -.button-secondary:hover { - border-color: #45a049; -} - -.spinner-container { - display: flex; - justify-content: center; - align-items: center; - gap: 1rem; -} diff --git a/src/components/Contribute/Github/Knowledge/AttributionInformation/AttributionInformation.tsx b/src/components/Contribute/Knowledge/AttributionInformation/AttributionInformation.tsx similarity index 99% rename from src/components/Contribute/Github/Knowledge/AttributionInformation/AttributionInformation.tsx rename to src/components/Contribute/Knowledge/AttributionInformation/AttributionInformation.tsx index 87f97851..38c4e8fd 100644 --- a/src/components/Contribute/Github/Knowledge/AttributionInformation/AttributionInformation.tsx +++ b/src/components/Contribute/Knowledge/AttributionInformation/AttributionInformation.tsx @@ -5,7 +5,7 @@ import { HelperText } from '@patternfly/react-core/dist/dynamic/components/Helpe import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { KnowledgeFormData } from '..'; +import { KnowledgeFormData } from '../Github'; import { checkKnowledgeFormCompletion } from '../validation'; interface Props { diff --git a/src/components/Contribute/Github/Knowledge/AutoFill.ts b/src/components/Contribute/Knowledge/AutoFill.ts similarity index 99% rename from src/components/Contribute/Github/Knowledge/AutoFill.ts rename to src/components/Contribute/Knowledge/AutoFill.ts index 568db39b..d188144b 100644 --- a/src/components/Contribute/Github/Knowledge/AutoFill.ts +++ b/src/components/Contribute/Knowledge/AutoFill.ts @@ -1,4 +1,4 @@ -import { KnowledgeFormData, QuestionAndAnswerPair, SeedExample } from '.'; +import { KnowledgeFormData, QuestionAndAnswerPair, SeedExample } from './Github'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; const questionAndAnswerPairs1: QuestionAndAnswerPair[] = [ @@ -238,12 +238,12 @@ const seedExamples: SeedExample[] = [ { immutable: true, isExpanded: true, - context: `Phoenix is the radiant of two annual meteor showers. The Phoenicids, - also known as the December Phoenicids, were first observed on 3 December 1887. - The shower was particularly intense in December 1956, and is thought related - to the breakup of the short-period comet 289P/Blanpain. It peaks around 4–5 - December, though is not seen every year.[58] A very minor meteor shower peaks - around July 14 with around one meteor an hour, though meteors can be seen + context: `Phoenix is the radiant of two annual meteor showers. The Phoenicids, + also known as the December Phoenicids, were first observed on 3 December 1887. + The shower was particularly intense in December 1956, and is thought related + to the breakup of the short-period comet 289P/Blanpain. It peaks around 4–5 + December, though is not seen every year.[58] A very minor meteor shower peaks + around July 14 with around one meteor an hour, though meteors can be seen anytime from July 3 to 18; this shower is referred to as the July Phoenicids.[59]`, isContextValid: ValidatedOptions.success, questionAndAnswers: questionAndAnswerPairs5 diff --git a/src/components/Contribute/Github/Knowledge/DownloadAttribution/DownloadAttribution.tsx b/src/components/Contribute/Knowledge/DownloadAttribution/DownloadAttribution.tsx similarity index 96% rename from src/components/Contribute/Github/Knowledge/DownloadAttribution/DownloadAttribution.tsx rename to src/components/Contribute/Knowledge/DownloadAttribution/DownloadAttribution.tsx index 3f0fe267..92d6a512 100644 --- a/src/components/Contribute/Github/Knowledge/DownloadAttribution/DownloadAttribution.tsx +++ b/src/components/Contribute/Knowledge/DownloadAttribution/DownloadAttribution.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { KnowledgeFormData } from '..'; +import { KnowledgeFormData } from '../Github'; import { DropdownItem } from '@patternfly/react-core/dist/esm/components/Dropdown/DropdownItem'; import FileIcon from '@patternfly/react-icons/dist/esm/icons/file-icon'; diff --git a/src/components/Contribute/Github/Knowledge/DownloadDropdown/DownloadDropdown.tsx b/src/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown.tsx similarity index 97% rename from src/components/Contribute/Github/Knowledge/DownloadDropdown/DownloadDropdown.tsx rename to src/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown.tsx index c7aa0dca..e8f962d8 100644 --- a/src/components/Contribute/Github/Knowledge/DownloadDropdown/DownloadDropdown.tsx +++ b/src/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown.tsx @@ -4,7 +4,7 @@ import { DropdownList } from '@patternfly/react-core/dist/dynamic/components/Dro import { MenuToggle, MenuToggleElement } from '@patternfly/react-core/dist/dynamic/components/MenuToggle'; import DownloadYaml from '../DownloadYaml/DownloadYaml'; import DownloadAttribution from '../DownloadAttribution/DownloadAttribution'; -import { KnowledgeFormData } from '..'; +import { KnowledgeFormData } from '../Github'; import DownloadIcon from '@patternfly/react-icons/dist/esm/icons/download-icon'; interface Props { diff --git a/src/components/Contribute/Github/Knowledge/DownloadYaml/DownloadYaml.tsx b/src/components/Contribute/Knowledge/DownloadYaml/DownloadYaml.tsx similarity index 97% rename from src/components/Contribute/Github/Knowledge/DownloadYaml/DownloadYaml.tsx rename to src/components/Contribute/Knowledge/DownloadYaml/DownloadYaml.tsx index c5990b9e..a451f55f 100644 --- a/src/components/Contribute/Github/Knowledge/DownloadYaml/DownloadYaml.tsx +++ b/src/components/Contribute/Knowledge/DownloadYaml/DownloadYaml.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { KnowledgeFormData } from '..'; +import { KnowledgeFormData } from '../Github'; import { KnowledgeYamlData } from '@/types'; import { KnowledgeSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; diff --git a/src/components/Contribute/Github/Knowledge/FilePathInformation/FilePathInformation.tsx b/src/components/Contribute/Knowledge/FilePathInformation/FilePathInformation.tsx similarity index 100% rename from src/components/Contribute/Github/Knowledge/FilePathInformation/FilePathInformation.tsx rename to src/components/Contribute/Knowledge/FilePathInformation/FilePathInformation.tsx diff --git a/src/components/Contribute/Github/Knowledge/DocumentInformation/DocumentInformation.tsx b/src/components/Contribute/Knowledge/Github/DocumentInformation/DocumentInformation.tsx similarity index 98% rename from src/components/Contribute/Github/Knowledge/DocumentInformation/DocumentInformation.tsx rename to src/components/Contribute/Knowledge/Github/DocumentInformation/DocumentInformation.tsx index 285042a5..53cbf0fd 100644 --- a/src/components/Contribute/Github/Knowledge/DocumentInformation/DocumentInformation.tsx +++ b/src/components/Contribute/Knowledge/Github/DocumentInformation/DocumentInformation.tsx @@ -2,14 +2,14 @@ import React, { useEffect, useState } from 'react'; import { FormFieldGroupHeader, FormGroup, FormHelperText } from '@patternfly/react-core/dist/dynamic/components/Form'; import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; import { TextInput } from '@patternfly/react-core/dist/dynamic/components/TextInput'; -import { UploadFile } from '../UploadFile'; +import { UploadFile } from '../../UploadFile'; import { Alert, AlertActionLink, AlertActionCloseButton } from '@patternfly/react-core/dist/dynamic/components/Alert'; import { HelperText } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; import { KnowledgeFormData } from '..'; -import { checkKnowledgeFormCompletion } from '../validation'; +import { checkKnowledgeFormCompletion } from '../../validation'; import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/deprecated/components/Modal/Modal'; interface Props { @@ -158,7 +158,9 @@ const DocumentInformation: React.FC = ({ console.log('Files uploaded:', result.documentNames); setSuccessAlertTitle('Document uploaded successfully!'); setSuccessAlertMessage('Documents have been uploaded to your repo to be referenced in the knowledge submission.'); - setSuccessAlertLink(result.prUrl); + if (result.prUrl !== '') { + setSuccessAlertLink(result.prUrl); + } } } }; diff --git a/src/components/Contribute/Github/Knowledge/Submit/Submit.tsx b/src/components/Contribute/Knowledge/Github/Submit/Submit.tsx similarity index 98% rename from src/components/Contribute/Github/Knowledge/Submit/Submit.tsx rename to src/components/Contribute/Knowledge/Github/Submit/Submit.tsx index d0c24bac..d2ca4043 100644 --- a/src/components/Contribute/Github/Knowledge/Submit/Submit.tsx +++ b/src/components/Contribute/Knowledge/Github/Submit/Submit.tsx @@ -4,7 +4,7 @@ import { ActionGroupAlertContent, KnowledgeFormData } from '..'; import { AttributionData, KnowledgeYamlData } from '@/types'; import { KnowledgeSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; -import { validateFields } from '../validation'; +import { validateFields } from '../../validation'; interface Props { disableAction: boolean; diff --git a/src/components/Contribute/Github/Knowledge/Update/Update.tsx b/src/components/Contribute/Knowledge/Github/Update/Update.tsx similarity index 99% rename from src/components/Contribute/Github/Knowledge/Update/Update.tsx rename to src/components/Contribute/Knowledge/Github/Update/Update.tsx index 4824c068..a525bfaf 100644 --- a/src/components/Contribute/Github/Knowledge/Update/Update.tsx +++ b/src/components/Contribute/Knowledge/Github/Update/Update.tsx @@ -4,7 +4,7 @@ import { ActionGroupAlertContent, KnowledgeFormData } from '..'; import { AttributionData, KnowledgeYamlData, PullRequestFile } from '@/types'; import { KnowledgeSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; -import { validateFields } from '../validation'; +import { validateFields } from '../../validation'; import { amendCommit, getGitHubUsername, updatePullRequest } from '@/utils/github'; import { useSession } from 'next-auth/react'; import { useRouter } from 'next/navigation'; diff --git a/src/components/Contribute/Github/Knowledge/index.tsx b/src/components/Contribute/Knowledge/Github/index.tsx similarity index 97% rename from src/components/Contribute/Github/Knowledge/index.tsx rename to src/components/Contribute/Knowledge/Github/index.tsx index 57f95ecc..f15c4142 100644 --- a/src/components/Contribute/Github/Knowledge/index.tsx +++ b/src/components/Contribute/Knowledge/Github/index.tsx @@ -1,7 +1,7 @@ // src/components/Contribute/Knowledge/index.tsx 'use client'; import React, { useEffect, useState } from 'react'; -import './knowledge.css'; +import '../knowledge.css'; import { Alert, AlertActionCloseButton } from '@patternfly/react-core/dist/dynamic/components/Alert'; import { ActionGroup } from '@patternfly/react-core/dist/dynamic/components/Form'; import { Form } from '@patternfly/react-core/dist/dynamic/components/Form'; @@ -9,10 +9,10 @@ import { getGitHubUsername } from '../../../../utils/github'; import { useSession } from 'next-auth/react'; import AuthorInformation from '../../AuthorInformation'; import { FormType } from '../../AuthorInformation'; -import KnowledgeInformation from './KnowledgeInformation/KnowledgeInformation'; -import FilePathInformation from './FilePathInformation/FilePathInformation'; +import KnowledgeInformation from '../KnowledgeInformation/KnowledgeInformation'; +import FilePathInformation from '../FilePathInformation/FilePathInformation'; import DocumentInformation from './DocumentInformation/DocumentInformation'; -import AttributionInformation from './AttributionInformation/AttributionInformation'; +import AttributionInformation from '../AttributionInformation/AttributionInformation'; import Submit from './Submit/Submit'; import { Breadcrumb } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; import { BreadcrumbItem } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; @@ -22,17 +22,17 @@ import { PageSection } from '@patternfly/react-core/dist/dynamic/components/Page import { Content } from '@patternfly/react-core/dist/dynamic/components/Content'; import { Title } from '@patternfly/react-core/dist/dynamic/components/Title'; import { Flex, FlexItem } from '@patternfly/react-core/dist/dynamic/layouts/Flex'; -import KnowledgeDescriptionContent from './KnowledgeDescription/KnowledgeDescriptionContent'; -import KnowledgeSeedExample from './KnowledgeSeedExample/KnowledgeSeedExample'; -import { checkKnowledgeFormCompletion } from './validation'; +import KnowledgeDescriptionContent from '../KnowledgeDescription/KnowledgeDescriptionContent'; +import KnowledgeSeedExample from '../KnowledgeSeedExample/KnowledgeSeedExample'; +import { checkKnowledgeFormCompletion } from '../validation'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { DownloadDropdown } from './DownloadDropdown/DownloadDropdown'; -import { ViewDropdown } from './ViewDropdown/ViewDropdown'; +import { DownloadDropdown } from '../DownloadDropdown/DownloadDropdown'; +import { ViewDropdown } from '../ViewDropdown/ViewDropdown'; import Update from './Update/Update'; import { KnowledgeYamlData, PullRequestFile } from '@/types'; import { Button } from '@patternfly/react-core/dist/esm/components/Button/Button'; import { useRouter } from 'next/navigation'; -import { autoFillKnowledgeFields } from './AutoFill'; +import { autoFillKnowledgeFields } from '../AutoFill'; import { Spinner } from '@patternfly/react-core/dist/esm/components/Spinner'; import { YamlFileUploadModal } from '../../YamlFileUploadModal'; diff --git a/src/components/Contribute/Github/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent.tsx b/src/components/Contribute/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent.tsx similarity index 100% rename from src/components/Contribute/Github/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent.tsx rename to src/components/Contribute/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent.tsx diff --git a/src/components/Contribute/Github/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx b/src/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx similarity index 99% rename from src/components/Contribute/Github/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx rename to src/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx index 677d72df..29ce1026 100644 --- a/src/components/Contribute/Github/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx +++ b/src/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx @@ -6,7 +6,7 @@ import { HelperText } from '@patternfly/react-core/dist/dynamic/components/Helpe import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { KnowledgeFormData } from '..'; +import { KnowledgeFormData } from '../Github'; import { checkKnowledgeFormCompletion } from '../validation'; interface Props { diff --git a/src/components/Contribute/Github/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx b/src/components/Contribute/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx similarity index 98% rename from src/components/Contribute/Github/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx rename to src/components/Contribute/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx index e57cc599..314aa7e3 100644 --- a/src/components/Contribute/Github/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx +++ b/src/components/Contribute/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { FormFieldGroupHeader, FormGroup, FormHelperText } from '@patternfly/react-core/dist/dynamic/components/Form'; import { TextArea } from '@patternfly/react-core/dist/dynamic/components/TextArea'; import { ExclamationCircleIcon } from '@patternfly/react-icons/dist/dynamic/icons/'; -import { QuestionAndAnswerPair, SeedExample } from '..'; +import { QuestionAndAnswerPair, SeedExample } from '../Github'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; import { HelperText } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; diff --git a/src/components/Contribute/Github/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx b/src/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx similarity index 98% rename from src/components/Contribute/Github/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx rename to src/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx index 9649763f..e68bc503 100644 --- a/src/components/Contribute/Github/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx +++ b/src/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { Accordion, AccordionItem, AccordionContent, AccordionToggle } from '@patternfly/react-core/dist/dynamic/components/Accordion'; import { FormFieldGroupHeader } from '@patternfly/react-core/dist/dynamic/components/Form'; import KnowledgeQuestionAnswerPairs from '../KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs'; -import { SeedExample } from '..'; +import { SeedExample } from '../Github'; import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; interface Props { diff --git a/src/components/Contribute/Knowledge/Native/DocumentInformation/DocumentInformation.tsx b/src/components/Contribute/Knowledge/Native/DocumentInformation/DocumentInformation.tsx new file mode 100644 index 00000000..a0511345 --- /dev/null +++ b/src/components/Contribute/Knowledge/Native/DocumentInformation/DocumentInformation.tsx @@ -0,0 +1,370 @@ +import React, { useEffect, useState } from 'react'; +import { FormFieldGroupHeader, FormGroup, FormHelperText } from '@patternfly/react-core/dist/dynamic/components/Form'; +import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; +import { TextInput } from '@patternfly/react-core/dist/dynamic/components/TextInput'; +import { Alert, AlertActionLink, AlertActionCloseButton } from '@patternfly/react-core/dist/dynamic/components/Alert'; +import { HelperText } from '@patternfly/react-core/dist/dynamic/components/HelperText'; +import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; +import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; +import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; +import { KnowledgeFormData } from '..'; +import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/deprecated/components/Modal/Modal'; +import { UploadFile } from '@/components/Contribute/Knowledge/UploadFile'; +import { checkKnowledgeFormCompletion } from '@/components/Contribute/Knowledge/validation'; + +interface Props { + reset: boolean; + isEditForm?: boolean; + knowledgeFormData: KnowledgeFormData; + setDisableAction: React.Dispatch>; + knowledgeDocumentRepositoryUrl: string; + setKnowledgeDocumentRepositoryUrl: React.Dispatch>; + knowledgeDocumentCommit: string; + setKnowledgeDocumentCommit: React.Dispatch>; + documentName: string; + setDocumentName: React.Dispatch>; +} + +const DocumentInformation: React.FC = ({ + reset, + isEditForm, + knowledgeFormData, + setDisableAction, + knowledgeDocumentRepositoryUrl, + setKnowledgeDocumentRepositoryUrl, + knowledgeDocumentCommit, + setKnowledgeDocumentCommit, + documentName, + setDocumentName +}) => { + const [useFileUpload, setUseFileUpload] = useState(true); + const [uploadedFiles, setUploadedFiles] = useState([]); + const [isModalOpen, setIsModalOpen] = useState(false); + const [modalText, setModalText] = useState(); + + const [successAlertTitle, setSuccessAlertTitle] = useState(); + const [successAlertMessage, setSuccessAlertMessage] = useState(); + const [successAlertLink, setSuccessAlertLink] = useState(); + + const [failureAlertTitle, setFailureAlertTitle] = useState(); + const [failureAlertMessage, setFailureAlertMessage] = useState(); + + const [validRepo, setValidRepo] = useState(); + const [validCommit, setValidCommit] = useState(); + const [validDocumentName, setValidDocumentName] = useState(); + + useEffect(() => { + setValidRepo(ValidatedOptions.default); + setValidCommit(ValidatedOptions.default); + setValidDocumentName(ValidatedOptions.default); + }, [reset]); + + useEffect(() => { + if (isEditForm) { + setValidRepo(ValidatedOptions.success); + setValidCommit(ValidatedOptions.success); + setValidDocumentName(ValidatedOptions.success); + } + }, [isEditForm]); + + const validateRepo = (repoStr: string) => { + const repo = repoStr.trim(); + if (repo.length === 0) { + setDisableAction(true); + setValidRepo(ValidatedOptions.error); + return; + } + try { + new URL(repo); + setValidRepo(ValidatedOptions.success); + setDisableAction(!checkKnowledgeFormCompletion(knowledgeFormData)); + return; + } catch (e) { + setDisableAction(true); + setValidRepo(ValidatedOptions.warning); + return; + } + }; + + const validateCommit = (commitStr: string) => { + const commit = commitStr.trim(); + if (commit.length > 0) { + setValidCommit(ValidatedOptions.success); + setDisableAction(!checkKnowledgeFormCompletion(knowledgeFormData)); + return; + } + setDisableAction(true); + setValidCommit(ValidatedOptions.error); + return; + }; + + const validateDocumentName = (document: string) => { + const documentName = document.trim(); + if (documentName.length > 0) { + setValidDocumentName(ValidatedOptions.success); + setDisableAction(!checkKnowledgeFormCompletion(knowledgeFormData)); + return; + } + setDisableAction(true); + setValidDocumentName(ValidatedOptions.error); + return; + }; + + const handleFilesChange = (files: File[]) => { + setUploadedFiles(files); + }; + + const handleDocumentUpload = async () => { + if (uploadedFiles.length > 0) { + const fileContents: { fileName: string; fileContent: string }[] = []; + + await Promise.all( + uploadedFiles.map( + (file) => + new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = (e) => { + const fileContent = e.target!.result as string; + fileContents.push({ fileName: file.name, fileContent }); + resolve(); + }; + reader.onerror = reject; + reader.readAsText(file); + }) + ) + ); + + if (fileContents.length === uploadedFiles.length) { + const response = await fetch('/api/native/upload', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ files: fileContents }) + }); + + if (!response.ok) { + setFailureAlertTitle('Failed to upload document'); + setFailureAlertMessage(`This upload failed. ${response.statusText}`); + new Error(response.statusText || 'Failed to upload document'); + return; + } + + const result = await response.json(); + + setKnowledgeDocumentRepositoryUrl(result.repoUrl); + setKnowledgeDocumentCommit(result.commitSha); + setDocumentName(result.documentNames.join(', ')); // Populate the patterns field + console.log('Files uploaded:', result.documentNames); + setSuccessAlertTitle('Document uploaded successfully!'); + setSuccessAlertMessage('Documents have been uploaded to your repo to be referenced in the knowledge submission.'); + if (result.prUrl !== '') { + setSuccessAlertLink(result.prUrl); + } + } + } + }; + + const onCloseSuccessAlert = () => { + setSuccessAlertTitle(undefined); + setSuccessAlertMessage(undefined); + setSuccessAlertLink(undefined); + }; + + const onCloseFailureAlert = () => { + setFailureAlertTitle(undefined); + setFailureAlertMessage(undefined); + }; + + const handleAutomaticUpload = () => { + if (knowledgeDocumentRepositoryUrl.length > 0 || knowledgeDocumentCommit.length > 0 || documentName.length > 0) { + setModalText('Switching to automatic upload will clear the document information. Are you sure you want to continue?'); + setIsModalOpen(true); + } else { + setUseFileUpload(true); + } + }; + + const handleManualUpload = () => { + if (uploadedFiles.length > 0) { + setModalText('Switching to manual upload will clear the uploaded files. Are you sure you want to continue?'); + setIsModalOpen(true); + } else { + setUseFileUpload(false); + } + }; + + const handleModalContinue = () => { + if (useFileUpload) { + setUploadedFiles([]); + } else { + setKnowledgeDocumentRepositoryUrl(''); + setValidRepo(ValidatedOptions.default); + setKnowledgeDocumentCommit(''); + setValidCommit(ValidatedOptions.default); + setDocumentName(''); + setValidDocumentName(ValidatedOptions.default); + } + setUseFileUpload(!useFileUpload); + setIsModalOpen(false); + }; + + return ( +
+ + Document Information * +

+ ), + id: 'doc-info-id' + }} + titleDescription="Add the relevant document's information" + /> + +
+ + +
+
+ setIsModalOpen(false)} + actions={[ + , + + ]} + > +

{modalText}

+
+ {!useFileUpload ? ( + <> + + setKnowledgeDocumentRepositoryUrl(value)} + onBlur={() => validateRepo(knowledgeDocumentRepositoryUrl)} + /> + {validRepo === ValidatedOptions.error && ( + + + } variant={validRepo}> + Required field + + + + )} + {validRepo === ValidatedOptions.warning && ( + + + } variant="error"> + Please enter a valid URL. + + + + )} + + + setKnowledgeDocumentCommit(value)} + onBlur={() => validateCommit(knowledgeDocumentCommit)} + /> + {validCommit === ValidatedOptions.error && ( + + + } variant={validCommit}> + Valid commit SHA is required. + + + + )} + + + setDocumentName(value)} + onBlur={() => validateDocumentName(documentName)} + /> + {validDocumentName === ValidatedOptions.error && ( + + + } variant={validDocumentName}> + Required field + + + + )} + + + ) : ( + <> + + + + )} + + {successAlertTitle && successAlertMessage && successAlertLink && ( + } + actionLinks={ + <> + + View it here + + + } + > + {successAlertMessage} + + )} + + {failureAlertTitle && failureAlertMessage && ( + }> + {failureAlertMessage} + + )} +
+ ); +}; + +export default DocumentInformation; diff --git a/src/components/Contribute/Native/Knowledge/ReviewSubmission/index.tsx b/src/components/Contribute/Knowledge/Native/ReviewSubmission/index.tsx similarity index 97% rename from src/components/Contribute/Native/Knowledge/ReviewSubmission/index.tsx rename to src/components/Contribute/Knowledge/Native/ReviewSubmission/index.tsx index 8ff25114..e9f4d30c 100644 --- a/src/components/Contribute/Native/Knowledge/ReviewSubmission/index.tsx +++ b/src/components/Contribute/Knowledge/Native/ReviewSubmission/index.tsx @@ -1,6 +1,6 @@ // src/components/Contribute/Knowledge/ReviewSubmission/ReviewSubmission.tsx import React from 'react'; -import { KnowledgeFormData } from '@/components/Contribute/Native/Knowledge'; +import { KnowledgeFormData } from '@/components/Contribute/Knowledge/Native'; interface ReviewSubmissionProps { knowledgeFormData: KnowledgeFormData; diff --git a/src/components/Contribute/Native/Knowledge/Submit/Submit.tsx b/src/components/Contribute/Knowledge/Native/Submit/Submit.tsx similarity index 97% rename from src/components/Contribute/Native/Knowledge/Submit/Submit.tsx rename to src/components/Contribute/Knowledge/Native/Submit/Submit.tsx index 3e3fdd72..059053bb 100644 --- a/src/components/Contribute/Native/Knowledge/Submit/Submit.tsx +++ b/src/components/Contribute/Knowledge/Native/Submit/Submit.tsx @@ -5,7 +5,7 @@ import { ActionGroupAlertContent, KnowledgeFormData } from '..'; import { AttributionData, KnowledgeYamlData } from '@/types'; import { KnowledgeSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; -import { validateFields } from '@/components/Contribute/Github/Knowledge/validation'; +import { validateFields } from '@/components/Contribute/Knowledge/validation'; interface Props { disableAction: boolean; diff --git a/src/components/Contribute/Native/Knowledge/index.tsx b/src/components/Contribute/Knowledge/Native/index.tsx similarity index 95% rename from src/components/Contribute/Native/Knowledge/index.tsx rename to src/components/Contribute/Knowledge/Native/index.tsx index e68cb266..57668733 100644 --- a/src/components/Contribute/Native/Knowledge/index.tsx +++ b/src/components/Contribute/Knowledge/Native/index.tsx @@ -1,17 +1,17 @@ // src/components/Experimental/ContributeLocal/Knowledge/index.tsx 'use client'; import React, { useEffect, useMemo, useState } from 'react'; -import './knowledge.css'; +import '../knowledge.css'; import { Alert, AlertActionCloseButton } from '@patternfly/react-core/dist/dynamic/components/Alert'; import { ActionGroup } from '@patternfly/react-core/dist/dynamic/components/Form'; import { getGitHubUsername } from '@/utils/github'; import { useSession } from 'next-auth/react'; import AuthorInformation from '@/components/Contribute/AuthorInformation'; import { FormType } from '@/components/Contribute/AuthorInformation'; -import KnowledgeInformation from '@/components/Contribute/Github/Knowledge/KnowledgeInformation/KnowledgeInformation'; -import FilePathInformation from '@/components/Contribute/Github/Knowledge/FilePathInformation/FilePathInformation'; -import DocumentInformation from '@/components/Contribute/Github/Knowledge/DocumentInformation/DocumentInformation'; -import AttributionInformation from '@/components/Contribute/Github/Knowledge/AttributionInformation/AttributionInformation'; +import KnowledgeInformation from '@/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation'; +import FilePathInformation from '@/components/Contribute/Knowledge/FilePathInformation/FilePathInformation'; +import DocumentInformation from '@/components/Contribute/Knowledge/Native/DocumentInformation/DocumentInformation'; +import AttributionInformation from '@/components/Contribute/Knowledge/AttributionInformation/AttributionInformation'; import Submit from './Submit/Submit'; import { Breadcrumb } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; import { BreadcrumbItem } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; @@ -19,21 +19,21 @@ import { PageBreadcrumb } from '@patternfly/react-core/dist/dynamic/components/P import { PageGroup } from '@patternfly/react-core/dist/dynamic/components/Page'; import { PageSection } from '@patternfly/react-core/dist/dynamic/components/Page'; import { Title } from '@patternfly/react-core/dist/dynamic/components/Title'; -import KnowledgeDescriptionContent from '@/components/Contribute/Github/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent'; -import KnowledgeSeedExample from '@/components/Contribute/Github/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample'; -import { checkKnowledgeFormCompletion } from '@/components/Contribute/Github/Knowledge/validation'; +import KnowledgeDescriptionContent from '@/components/Contribute/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent'; +import KnowledgeSeedExample from '@/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample'; +import { checkKnowledgeFormCompletion } from '@/components/Contribute/Knowledge/validation'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { DownloadDropdown } from '@/components/Contribute/Github/Knowledge/DownloadDropdown/DownloadDropdown'; -import { ViewDropdown } from '@/components/Contribute/Github/Knowledge/ViewDropdown/ViewDropdown'; -import Update from '@/components/Contribute/Github/Knowledge/Update/Update'; +import { DownloadDropdown } from '@/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown'; +import { ViewDropdown } from '@/components/Contribute/Knowledge/ViewDropdown/ViewDropdown'; +import Update from '@/components/Contribute/Knowledge/Github/Update/Update'; import { PullRequestFile } from '@/types'; import { Button } from '@patternfly/react-core/dist/esm/components/Button/Button'; import { useRouter } from 'next/navigation'; -import { autoFillKnowledgeFields } from '@/components/Contribute/Github/Knowledge/AutoFill'; +import { autoFillKnowledgeFields } from '@/components/Contribute/Knowledge/AutoFill'; import { Spinner } from '@patternfly/react-core/dist/esm/components/Spinner'; import { Wizard, WizardStep } from '@patternfly/react-core/dist/esm/components/Wizard'; import { Content } from '@patternfly/react-core/dist/dynamic/components/Content'; -import ReviewSubmission from '@/components/Contribute/Native/Knowledge/ReviewSubmission'; +import ReviewSubmission from '@/components/Contribute/Knowledge/Native/ReviewSubmission'; export interface QuestionAndAnswerPair { immutable: boolean; diff --git a/src/components/Contribute/Github/Knowledge/UploadFile.tsx b/src/components/Contribute/Knowledge/UploadFile.tsx similarity index 100% rename from src/components/Contribute/Github/Knowledge/UploadFile.tsx rename to src/components/Contribute/Knowledge/UploadFile.tsx diff --git a/src/components/Contribute/Github/Knowledge/ViewDropdown/ViewDropdown.tsx b/src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx similarity index 98% rename from src/components/Contribute/Github/Knowledge/ViewDropdown/ViewDropdown.tsx rename to src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx index bd1280bc..b0ed46f2 100644 --- a/src/components/Contribute/Github/Knowledge/ViewDropdown/ViewDropdown.tsx +++ b/src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx @@ -3,7 +3,7 @@ import { Dropdown } from '@patternfly/react-core/dist/dynamic/components/Dropdow import { DropdownItem } from '@patternfly/react-core/dist/dynamic/components/Dropdown'; import { DropdownList } from '@patternfly/react-core/dist/dynamic/components/Dropdown'; import { MenuToggle, MenuToggleElement } from '@patternfly/react-core/dist/dynamic/components/MenuToggle'; -import { KnowledgeFormData } from '..'; +import { KnowledgeFormData } from '../Github'; import YamlCodeModal from '@/components/YamlCodeModal'; import CodeIcon from '@patternfly/react-icons/dist/esm/icons/code-icon'; import { AttributionData, KnowledgeYamlData } from '@/types'; diff --git a/src/components/Contribute/Native/Knowledge/knowledge.css b/src/components/Contribute/Knowledge/knowledge.css similarity index 100% rename from src/components/Contribute/Native/Knowledge/knowledge.css rename to src/components/Contribute/Knowledge/knowledge.css diff --git a/src/components/Contribute/Github/Knowledge/validation.tsx b/src/components/Contribute/Knowledge/validation.tsx similarity index 99% rename from src/components/Contribute/Github/Knowledge/validation.tsx rename to src/components/Contribute/Knowledge/validation.tsx index e4bc819e..2e40c9ad 100644 --- a/src/components/Contribute/Github/Knowledge/validation.tsx +++ b/src/components/Contribute/Knowledge/validation.tsx @@ -1,5 +1,5 @@ import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { ActionGroupAlertContent, KnowledgeFormData, SeedExample } from '.'; +import { ActionGroupAlertContent, KnowledgeFormData, SeedExample } from './Github'; const validateEmail = (email: string): boolean => { const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/; diff --git a/src/components/Contribute/Github/Skill/AttributionInformation/AttributionInformation.tsx b/src/components/Contribute/Skill/AttributionInformation/AttributionInformation.tsx similarity index 99% rename from src/components/Contribute/Github/Skill/AttributionInformation/AttributionInformation.tsx rename to src/components/Contribute/Skill/AttributionInformation/AttributionInformation.tsx index bbedfc4a..024b9a53 100644 --- a/src/components/Contribute/Github/Skill/AttributionInformation/AttributionInformation.tsx +++ b/src/components/Contribute/Skill/AttributionInformation/AttributionInformation.tsx @@ -5,8 +5,8 @@ import { HelperText } from '@patternfly/react-core/dist/dynamic/components/Helpe import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { SkillFormData } from '..'; import { checkSkillFormCompletion } from '../validation'; +import { SkillFormData } from '@/types'; interface Props { reset: boolean; diff --git a/src/components/Contribute/Github/Skill/AutoFill.ts b/src/components/Contribute/Skill/AutoFill.ts similarity index 96% rename from src/components/Contribute/Github/Skill/AutoFill.ts rename to src/components/Contribute/Skill/AutoFill.ts index be1cec2a..6470a338 100644 --- a/src/components/Contribute/Github/Skill/AutoFill.ts +++ b/src/components/Contribute/Skill/AutoFill.ts @@ -1,7 +1,7 @@ -import { SeedExample, SkillFormData } from '.'; +import { SkillFormData, SkillSeedExample } from '@/types'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -const seedExamples: SeedExample[] = [ +const seedExamples: SkillSeedExample[] = [ { immutable: false, isExpanded: false, diff --git a/src/components/Contribute/Github/Skill/DownloadAttribution/DownloadAttribution.tsx b/src/components/Contribute/Skill/DownloadAttribution/DownloadAttribution.tsx similarity index 96% rename from src/components/Contribute/Github/Skill/DownloadAttribution/DownloadAttribution.tsx rename to src/components/Contribute/Skill/DownloadAttribution/DownloadAttribution.tsx index 1cfb3d67..330c274c 100644 --- a/src/components/Contribute/Github/Skill/DownloadAttribution/DownloadAttribution.tsx +++ b/src/components/Contribute/Skill/DownloadAttribution/DownloadAttribution.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import { SkillFormData } from '..'; import { DropdownItem } from '@patternfly/react-core/dist/esm/components/Dropdown/DropdownItem'; import FileIcon from '@patternfly/react-icons/dist/esm/icons/file-icon'; +import { SkillFormData } from '@/types'; interface Props { skillFormData: SkillFormData; diff --git a/src/components/Contribute/Github/Skill/DownloadDropdown/DownloadDropdown.tsx b/src/components/Contribute/Skill/DownloadDropdown/DownloadDropdown.tsx similarity index 97% rename from src/components/Contribute/Github/Skill/DownloadDropdown/DownloadDropdown.tsx rename to src/components/Contribute/Skill/DownloadDropdown/DownloadDropdown.tsx index 41f39e55..6b5663a6 100644 --- a/src/components/Contribute/Github/Skill/DownloadDropdown/DownloadDropdown.tsx +++ b/src/components/Contribute/Skill/DownloadDropdown/DownloadDropdown.tsx @@ -4,8 +4,8 @@ import { DropdownList } from '@patternfly/react-core/dist/dynamic/components/Dro import { MenuToggle, MenuToggleElement } from '@patternfly/react-core/dist/dynamic/components/MenuToggle'; import DownloadYaml from '../DownloadYaml/DownloadYaml'; import DownloadAttribution from '../DownloadAttribution/DownloadAttribution'; -import { SkillFormData } from '..'; import DownloadIcon from '@patternfly/react-icons/dist/esm/icons/download-icon'; +import { SkillFormData } from '@/types'; interface Props { skillFormData: SkillFormData; diff --git a/src/components/Contribute/Github/Skill/DownloadYaml/DownloadYaml.tsx b/src/components/Contribute/Skill/DownloadYaml/DownloadYaml.tsx similarity index 94% rename from src/components/Contribute/Github/Skill/DownloadYaml/DownloadYaml.tsx rename to src/components/Contribute/Skill/DownloadYaml/DownloadYaml.tsx index 321fd207..798a45c8 100644 --- a/src/components/Contribute/Github/Skill/DownloadYaml/DownloadYaml.tsx +++ b/src/components/Contribute/Skill/DownloadYaml/DownloadYaml.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { SkillFormData } from '..'; -import { SkillYamlData } from '@/types'; +import { SkillFormData, SkillYamlData } from '@/types'; import { dumpYaml } from '@/utils/yamlConfig'; import { DropdownItem } from '@patternfly/react-core/dist/esm/components/Dropdown/DropdownItem'; import CodeIcon from '@patternfly/react-icons/dist/esm/icons/code-icon'; diff --git a/src/components/Contribute/Github/Skill/FilePathInformation/FilePathInformation.tsx b/src/components/Contribute/Skill/FilePathInformation/FilePathInformation.tsx similarity index 100% rename from src/components/Contribute/Github/Skill/FilePathInformation/FilePathInformation.tsx rename to src/components/Contribute/Skill/FilePathInformation/FilePathInformation.tsx diff --git a/src/components/Contribute/Github/Skill/Submit/Submit.tsx b/src/components/Contribute/Skill/Github/Submit/Submit.tsx similarity index 95% rename from src/components/Contribute/Github/Skill/Submit/Submit.tsx rename to src/components/Contribute/Skill/Github/Submit/Submit.tsx index 2c99c578..a623d9a5 100644 --- a/src/components/Contribute/Github/Skill/Submit/Submit.tsx +++ b/src/components/Contribute/Skill/Github/Submit/Submit.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; -import { ActionGroupAlertContent, SkillFormData } from '..'; -import { AttributionData, SkillYamlData } from '@/types'; +import { ActionGroupAlertContent } from '..'; +import { AttributionData, SkillFormData, SkillYamlData } from '@/types'; import { SkillSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; -import { validateFields } from '../validation'; +import { validateFields } from '../../validation'; interface Props { disableAction: boolean; diff --git a/src/components/Contribute/Github/Skill/Update/Update.tsx b/src/components/Contribute/Skill/Github/Update/Update.tsx similarity index 96% rename from src/components/Contribute/Github/Skill/Update/Update.tsx rename to src/components/Contribute/Skill/Github/Update/Update.tsx index a63b95a7..7e1ecdcb 100644 --- a/src/components/Contribute/Github/Skill/Update/Update.tsx +++ b/src/components/Contribute/Skill/Github/Update/Update.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; -import { ActionGroupAlertContent, SkillFormData } from '..'; -import { AttributionData, SkillYamlData, PullRequestFile } from '@/types'; +import { ActionGroupAlertContent } from '..'; +import { AttributionData, SkillYamlData, PullRequestFile, SkillFormData } from '@/types'; import { SkillSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; -import { validateFields } from '../validation'; +import { validateFields } from '../../validation'; import { amendCommit, getGitHubUsername, updatePullRequest } from '@/utils/github'; import { useSession } from 'next-auth/react'; import { useRouter } from 'next/navigation'; diff --git a/src/components/Contribute/Github/Skill/index.tsx b/src/components/Contribute/Skill/Github/index.tsx similarity index 90% rename from src/components/Contribute/Github/Skill/index.tsx rename to src/components/Contribute/Skill/Github/index.tsx index 1c623b74..f4924a66 100644 --- a/src/components/Contribute/Github/Skill/index.tsx +++ b/src/components/Contribute/Skill/Github/index.tsx @@ -9,8 +9,8 @@ import { getGitHubUsername } from '../../../../utils/github'; import { useSession } from 'next-auth/react'; import AuthorInformation from '../../AuthorInformation'; import { FormType } from '../../AuthorInformation'; -import FilePathInformation from './FilePathInformation/FilePathInformation'; -import AttributionInformation from './AttributionInformation/AttributionInformation'; +import FilePathInformation from '../FilePathInformation/FilePathInformation'; +import AttributionInformation from '../AttributionInformation/AttributionInformation'; import Submit from './Submit/Submit'; import { Breadcrumb } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; import { BreadcrumbItem } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; @@ -20,47 +20,21 @@ import { PageSection } from '@patternfly/react-core/dist/dynamic/components/Page import { Content } from '@patternfly/react-core/dist/dynamic/components/Content'; import { Title } from '@patternfly/react-core/dist/dynamic/components/Title'; import { Flex, FlexItem } from '@patternfly/react-core/dist/dynamic/layouts/Flex'; -import { checkSkillFormCompletion } from './validation'; +import { checkSkillFormCompletion } from '../validation'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { DownloadDropdown } from './DownloadDropdown/DownloadDropdown'; -import { ViewDropdown } from './ViewDropdown/ViewDropdown'; +import { DownloadDropdown } from '../DownloadDropdown/DownloadDropdown'; +import { ViewDropdown } from '../ViewDropdown/ViewDropdown'; import Update from './Update/Update'; -import { SkillYamlData, PullRequestFile } from '@/types'; +import { SkillYamlData, PullRequestFile, SkillFormData, SkillSeedExample } from '@/types'; import { Button } from '@patternfly/react-core/dist/esm/components/Button/Button'; import { useRouter } from 'next/navigation'; -import SkillsSeedExample from './SkillsSeedExample/SkillsSeedExample'; -import SkillsInformation from './SkillsInformation/SkillsInformation'; -import SkillsDescriptionContent from './SkillsDescription/SkillsDescriptionContent'; -import { autoFillSkillsFields } from './AutoFill'; +import SkillsSeedExample from '../SkillsSeedExample/SkillsSeedExample'; +import SkillsInformation from '../SkillsInformation/SkillsInformation'; +import SkillsDescriptionContent from '../SkillsDescription/SkillsDescriptionContent'; +import { autoFillSkillsFields } from '../AutoFill'; import { Spinner } from '@patternfly/react-core/dist/dynamic/components/Spinner'; import { YamlFileUploadModal } from '../../YamlFileUploadModal'; -export interface SeedExample { - immutable: boolean; - isExpanded: boolean; - context?: string; - isContextValid?: ValidatedOptions; - validationError?: string; - question: string; - isQuestionValid: ValidatedOptions; - questionValidationError?: string; - answer: string; - isAnswerValid: ValidatedOptions; - answerValidationError?: string; -} - -export interface SkillFormData { - email: string; - name: string; - submissionSummary: string; - documentOutline: string; - filePath: string; - seedExamples: SeedExample[]; - titleWork: string; - licenseWork: string; - creators: string; -} - export interface SkillEditFormData { isEditForm: boolean; skillVersion: number; @@ -115,7 +89,7 @@ export const SkillFormGithub: React.FunctionComponent = ({ skill const router = useRouter(); - const emptySeedExample: SeedExample = { + const emptySeedExample: SkillSeedExample = { immutable: true, isExpanded: false, context: '', @@ -126,7 +100,7 @@ export const SkillFormGithub: React.FunctionComponent = ({ skill isAnswerValid: ValidatedOptions.default }; - const [seedExamples, setSeedExamples] = useState([ + const [seedExamples, setSeedExamples] = useState([ emptySeedExample, emptySeedExample, emptySeedExample, @@ -213,7 +187,7 @@ export const SkillFormGithub: React.FunctionComponent = ({ skill const handleContextInputChange = (seedExampleIndex: number, contextValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -226,7 +200,7 @@ export const SkillFormGithub: React.FunctionComponent = ({ skill const handleContextBlur = (seedExampleIndex: number): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -239,7 +213,7 @@ export const SkillFormGithub: React.FunctionComponent = ({ skill const handleAnswerInputChange = (seedExampleIndex: number, answerValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -252,7 +226,7 @@ export const SkillFormGithub: React.FunctionComponent = ({ skill const handleAnswerBlur = (seedExampleIndex: number): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -265,7 +239,7 @@ export const SkillFormGithub: React.FunctionComponent = ({ skill const handleQuestionInputChange = (seedExampleIndex: number, questionValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -278,7 +252,7 @@ export const SkillFormGithub: React.FunctionComponent = ({ skill const handleQuestionBlur = (seedExampleIndex: number): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -342,7 +316,7 @@ export const SkillFormGithub: React.FunctionComponent = ({ skill isContextValid: ValidatedOptions.default, question: yamlSeedExample.question, answer: yamlSeedExample.answer - })) as SeedExample[]; + })) as SkillSeedExample[]; }; const onYamlUploadSkillsFillForm = (data: SkillYamlData): void => { diff --git a/src/components/Contribute/Github/Skill/skills.css b/src/components/Contribute/Skill/Github/skills.css similarity index 100% rename from src/components/Contribute/Github/Skill/skills.css rename to src/components/Contribute/Skill/Github/skills.css diff --git a/src/components/Contribute/Native/Skill/Submit/SubmitNative.tsx b/src/components/Contribute/Skill/Native/Submit/Submit.tsx similarity index 94% rename from src/components/Contribute/Native/Skill/Submit/SubmitNative.tsx rename to src/components/Contribute/Skill/Native/Submit/Submit.tsx index c93323ab..b05bbf85 100644 --- a/src/components/Contribute/Native/Skill/Submit/SubmitNative.tsx +++ b/src/components/Contribute/Skill/Native/Submit/Submit.tsx @@ -1,10 +1,10 @@ import React from 'react'; import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; -import { ActionGroupAlertContent, SkillFormData } from '..'; -import { AttributionData, SkillYamlData } from '@/types'; +import { ActionGroupAlertContent } from '..'; +import { AttributionData, SkillFormData, SkillYamlData } from '@/types'; import { SkillSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; -import { validateFields } from '@/components/Contribute/Github/Skill/validation'; +import { validateFields } from '@/components/Contribute/Skill/validation'; interface Props { disableAction: boolean; diff --git a/src/components/Contribute/Native/Skill/index.tsx b/src/components/Contribute/Skill/Native/index.tsx similarity index 86% rename from src/components/Contribute/Native/Skill/index.tsx rename to src/components/Contribute/Skill/Native/index.tsx index ff4508ad..4a263e49 100644 --- a/src/components/Contribute/Native/Skill/index.tsx +++ b/src/components/Contribute/Skill/Native/index.tsx @@ -8,9 +8,9 @@ import { Form } from '@patternfly/react-core/dist/dynamic/components/Form'; import { useSession } from 'next-auth/react'; import AuthorInformation from '@/components/Contribute/AuthorInformation'; import { FormType } from '@/components/Contribute/AuthorInformation'; -import FilePathInformation from '@/components/Contribute/Github/Skill/FilePathInformation/FilePathInformation'; -import AttributionInformation from '@/components/Contribute/Github/Skill/AttributionInformation/AttributionInformation'; -import Submit from '@/components/Contribute/Native/Skill/Submit/SubmitNative'; +import FilePathInformation from '@/components/Contribute/Skill/FilePathInformation/FilePathInformation'; +import AttributionInformation from '@/components/Contribute/Skill/AttributionInformation/AttributionInformation'; +import Submit from '@/components/Contribute/Skill/Native/Submit/Submit'; import { Breadcrumb } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; import { BreadcrumbItem } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; import { PageBreadcrumb } from '@patternfly/react-core/dist/dynamic/components/Page'; @@ -18,46 +18,20 @@ import { PageGroup } from '@patternfly/react-core/dist/dynamic/components/Page'; import { PageSection } from '@patternfly/react-core/dist/dynamic/components/Page'; import { Content } from '@patternfly/react-core/dist/dynamic/components/Content'; import { Title } from '@patternfly/react-core/dist/dynamic/components/Title'; -import { checkSkillFormCompletion } from '@/components/Contribute/Github/Skill/validation'; +import { checkSkillFormCompletion } from '@/components/Contribute/Skill/validation'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { DownloadDropdown } from '@/components/Contribute/Github/Skill/DownloadDropdown/DownloadDropdown'; -import { ViewDropdown } from '@/components/Contribute/Github/Skill/ViewDropdown/ViewDropdown'; -import Update from '@/components/Contribute/Github/Skill/Update/Update'; -import { PullRequestFile } from '@/types'; +import { DownloadDropdown } from '@/components/Contribute/Skill/DownloadDropdown/DownloadDropdown'; +import { ViewDropdown } from '@/components/Contribute/Skill/ViewDropdown/ViewDropdown'; +import Update from '@/components/Contribute/Skill/Github/Update/Update'; +import { PullRequestFile, SkillSeedExample, SkillFormData } from '@/types'; import { Button } from '@patternfly/react-core/dist/esm/components/Button/Button'; import { useRouter } from 'next/navigation'; -import SkillsSeedExample from '@/components/Contribute/Github/Skill/SkillsSeedExample/SkillsSeedExample'; -import SkillsInformation from '@/components/Contribute/Github/Skill/SkillsInformation/SkillsInformation'; -import SkillsDescriptionContent from '@/components/Contribute/Github/Skill/SkillsDescription/SkillsDescriptionContent'; -import { autoFillSkillsFields } from '@/components/Contribute/Github/Skill/AutoFill'; +import SkillsSeedExample from '@/components/Contribute/Skill/SkillsSeedExample/SkillsSeedExample'; +import SkillsInformation from '@/components/Contribute/Skill/SkillsInformation/SkillsInformation'; +import SkillsDescriptionContent from '@/components/Contribute/Skill/SkillsDescription/SkillsDescriptionContent'; +import { autoFillSkillsFields } from '@/components/Contribute/Skill/AutoFill'; import { Spinner } from '@patternfly/react-core/dist/dynamic/components/Spinner'; -export interface SeedExample { - immutable: boolean; - isExpanded: boolean; - context?: string; - isContextValid?: ValidatedOptions; - validationError?: string; - question: string; - isQuestionValid: ValidatedOptions; - questionValidationError?: string; - answer: string; - isAnswerValid: ValidatedOptions; - answerValidationError?: string; -} - -export interface SkillFormData { - email: string; - name: string; - submissionSummary: string; - documentOutline: string; - filePath: string; - seedExamples: SeedExample[]; - titleWork: string; - licenseWork: string; - creators: string; -} - export interface SkillEditFormData { isEditForm: boolean; skillVersion: number; @@ -110,7 +84,7 @@ export const SkillFormNative: React.FunctionComponent = ({ skill const router = useRouter(); - const emptySeedExample: SeedExample = { + const emptySeedExample: SkillSeedExample = { immutable: true, isExpanded: false, context: '', @@ -121,7 +95,7 @@ export const SkillFormNative: React.FunctionComponent = ({ skill isAnswerValid: ValidatedOptions.default }; - const [seedExamples, setSeedExamples] = useState([ + const [seedExamples, setSeedExamples] = useState([ emptySeedExample, emptySeedExample, emptySeedExample, @@ -186,7 +160,7 @@ export const SkillFormNative: React.FunctionComponent = ({ skill const handleContextInputChange = (seedExampleIndex: number, contextValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -199,7 +173,7 @@ export const SkillFormNative: React.FunctionComponent = ({ skill const handleContextBlur = (seedExampleIndex: number): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -212,7 +186,7 @@ export const SkillFormNative: React.FunctionComponent = ({ skill const handleAnswerInputChange = (seedExampleIndex: number, answerValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -225,7 +199,7 @@ export const SkillFormNative: React.FunctionComponent = ({ skill const handleAnswerBlur = (seedExampleIndex: number): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -238,7 +212,7 @@ export const SkillFormNative: React.FunctionComponent = ({ skill const handleQuestionInputChange = (seedExampleIndex: number, questionValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -251,7 +225,7 @@ export const SkillFormNative: React.FunctionComponent = ({ skill const handleQuestionBlur = (seedExampleIndex: number): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: SkillSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, diff --git a/src/components/Contribute/Native/Skill/skills.css b/src/components/Contribute/Skill/Native/skills.css similarity index 100% rename from src/components/Contribute/Native/Skill/skills.css rename to src/components/Contribute/Skill/Native/skills.css diff --git a/src/components/Contribute/Github/Skill/SkillsDescription/SkillsDescriptionContent.tsx b/src/components/Contribute/Skill/SkillsDescription/SkillsDescriptionContent.tsx similarity index 100% rename from src/components/Contribute/Github/Skill/SkillsDescription/SkillsDescriptionContent.tsx rename to src/components/Contribute/Skill/SkillsDescription/SkillsDescriptionContent.tsx diff --git a/src/components/Contribute/Github/Skill/SkillsInformation/SkillsInformation.tsx b/src/components/Contribute/Skill/SkillsInformation/SkillsInformation.tsx similarity index 99% rename from src/components/Contribute/Github/Skill/SkillsInformation/SkillsInformation.tsx rename to src/components/Contribute/Skill/SkillsInformation/SkillsInformation.tsx index 9d40692f..c2f5fe4e 100644 --- a/src/components/Contribute/Github/Skill/SkillsInformation/SkillsInformation.tsx +++ b/src/components/Contribute/Skill/SkillsInformation/SkillsInformation.tsx @@ -6,8 +6,8 @@ import { HelperText } from '@patternfly/react-core/dist/dynamic/components/Helpe import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { SkillFormData } from '..'; import { checkSkillFormCompletion } from '../validation'; +import { SkillFormData } from '@/types'; interface Props { reset: boolean; diff --git a/src/components/Contribute/Github/Skill/SkillsSeedExample/SkillsSeedExample.tsx b/src/components/Contribute/Skill/SkillsSeedExample/SkillsSeedExample.tsx similarity index 97% rename from src/components/Contribute/Github/Skill/SkillsSeedExample/SkillsSeedExample.tsx rename to src/components/Contribute/Skill/SkillsSeedExample/SkillsSeedExample.tsx index ceef056a..59a95c25 100644 --- a/src/components/Contribute/Github/Skill/SkillsSeedExample/SkillsSeedExample.tsx +++ b/src/components/Contribute/Skill/SkillsSeedExample/SkillsSeedExample.tsx @@ -2,13 +2,13 @@ import React from 'react'; import { FormFieldGroupExpandable, FormFieldGroupHeader, FormGroup, FormHelperText } from '@patternfly/react-core/dist/dynamic/components/Form'; import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; import { TrashIcon, PlusCircleIcon, ExclamationCircleIcon, ExternalLinkAltIcon } from '@patternfly/react-icons/dist/dynamic/icons/'; -import { SeedExample } from '..'; import { TextArea } from '@patternfly/react-core/dist/esm/components/TextArea'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; import { HelperText, HelperTextItem } from '@patternfly/react-core/dist/esm/components/HelperText'; +import { SkillSeedExample } from '@/types'; interface Props { - seedExamples: SeedExample[]; + seedExamples: SkillSeedExample[]; handleContextInputChange: (seedExampleIndex: number, contextValue: string) => void; handleContextBlur: (seedExampleIndex: number) => void; handleQuestionInputChange: (seedExampleIndex: number, questionValue: string) => void; @@ -58,7 +58,7 @@ const SkillsSeedExample: React.FC = ({ /> } > - {seedExamples.map((seedExample: SeedExample, seedExampleIndex: number) => ( + {seedExamples.map((seedExample: SkillSeedExample, seedExampleIndex: number) => ( { const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/; return emailRegex.test(email); }; -const hasDuplicateSeedExamples = (seedExamples: SeedExample[]): { duplicate: boolean; index: number } => { +const hasDuplicateSeedExamples = (seedExamples: SkillSeedExample[]): { duplicate: boolean; index: number } => { const question = new Set(); for (let index = 0; index < seedExamples.length; index++) { const seedExample = seedExamples[index]; diff --git a/src/types/index.ts b/src/types/index.ts index 736124bf..2f8de3ed 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,5 @@ +import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; + export interface Endpoint { id: string; url: string; @@ -79,3 +81,29 @@ export interface PullRequestUpdateData { title: string; body: string; } + +export interface SkillSeedExample { + immutable: boolean; + isExpanded: boolean; + context?: string; + isContextValid?: ValidatedOptions; + validationError?: string; + question: string; + isQuestionValid: ValidatedOptions; + questionValidationError?: string; + answer: string; + isAnswerValid: ValidatedOptions; + answerValidationError?: string; +} + +export interface SkillFormData { + email: string; + name: string; + submissionSummary: string; + documentOutline: string; + filePath: string; + seedExamples: SkillSeedExample[]; + titleWork: string; + licenseWork: string; + creators: string; +} From 101419c853e87a5afed2da130426b6afdd6027c2 Mon Sep 17 00:00:00 2001 From: Anil Vishnoi Date: Thu, 12 Dec 2024 11:21:56 -0800 Subject: [PATCH 4/6] Updated github knowledge form to wizard based form. Signed-off-by: Anil Vishnoi --- .../EditKnowledge/EditKnowledge.tsx | 12 +- .../AttributionInformation.tsx | 2 +- .../Contribute/Knowledge/AutoFill.ts | 4 +- .../DownloadAttribution.tsx | 2 +- .../DownloadDropdown/DownloadDropdown.tsx | 2 +- .../Knowledge/DownloadYaml/DownloadYaml.tsx | 3 +- .../DocumentInformation.tsx | 2 +- .../Knowledge/Github/Submit/Submit.tsx | 4 +- .../Knowledge/Github/Update/Update.tsx | 4 +- .../Contribute/Knowledge/Github/index.tsx | 467 ++++++++---------- .../KnowledgeInformation.tsx | 2 +- .../KnowledgeQuestionAnswerPairs.tsx | 4 +- .../KnowledgeSeedExample.tsx | 6 +- .../DocumentInformation.tsx | 2 +- .../Knowledge/Native/Submit/Submit.tsx | 4 +- .../Contribute/Knowledge/Native/index.tsx | 67 +-- .../{Native => }/ReviewSubmission/index.tsx | 2 +- .../Knowledge/ViewDropdown/ViewDropdown.tsx | 3 +- .../Contribute/Knowledge/validation.tsx | 9 +- src/types/index.ts | 47 ++ 20 files changed, 304 insertions(+), 344 deletions(-) rename src/components/Contribute/Knowledge/{Native => }/ReviewSubmission/index.tsx (97%) diff --git a/src/components/Contribute/EditKnowledge/EditKnowledge.tsx b/src/components/Contribute/EditKnowledge/EditKnowledge.tsx index e9287a81..3a8a2639 100644 --- a/src/components/Contribute/EditKnowledge/EditKnowledge.tsx +++ b/src/components/Contribute/EditKnowledge/EditKnowledge.tsx @@ -8,16 +8,12 @@ import { KnowledgeSchemaVersion } from '@/types/const'; import { fetchPullRequest, fetchFileContent, fetchPullRequestFiles } from '@/utils/github'; import yaml from 'js-yaml'; import axios from 'axios'; -import KnowledgeFormGithub, { - KnowledgeEditFormData, - KnowledgeFormData, - QuestionAndAnswerPair, - SeedExample -} from '@/components/Contribute/Knowledge/Github'; +import { KnowledgeEditFormData, KnowledgeFormData, QuestionAndAnswerPair, KnowledgeSeedExample } from '@/types'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; import { useEffect, useState } from 'react'; import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/deprecated/components/Modal/Modal'; import { useRouter } from 'next/navigation'; +import KnowledgeFormGithub from '../Knowledge/Github'; interface EditKnowledgeClientComponentProps { prNumber: number; @@ -88,10 +84,10 @@ const EditKnowledge: React.FC = ({ prNumber } knowledgeExistingFormData.knowledgeDocumentCommit = yamlData.document.commit; knowledgeExistingFormData.documentName = yamlData.document.patterns.join(', '); - const seedExamples: SeedExample[] = []; + const seedExamples: KnowledgeSeedExample[] = []; yamlData.seed_examples.forEach((seed, index) => { // iterate through questions_and_answers and create a new object for each - const example: SeedExample = { + const example: KnowledgeSeedExample = { immutable: index < 5 ? true : false, isExpanded: true, context: seed.context, diff --git a/src/components/Contribute/Knowledge/AttributionInformation/AttributionInformation.tsx b/src/components/Contribute/Knowledge/AttributionInformation/AttributionInformation.tsx index 38c4e8fd..b606a3ce 100644 --- a/src/components/Contribute/Knowledge/AttributionInformation/AttributionInformation.tsx +++ b/src/components/Contribute/Knowledge/AttributionInformation/AttributionInformation.tsx @@ -5,8 +5,8 @@ import { HelperText } from '@patternfly/react-core/dist/dynamic/components/Helpe import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { KnowledgeFormData } from '../Github'; import { checkKnowledgeFormCompletion } from '../validation'; +import { KnowledgeFormData } from '@/types'; interface Props { reset: boolean; diff --git a/src/components/Contribute/Knowledge/AutoFill.ts b/src/components/Contribute/Knowledge/AutoFill.ts index d188144b..7e05911b 100644 --- a/src/components/Contribute/Knowledge/AutoFill.ts +++ b/src/components/Contribute/Knowledge/AutoFill.ts @@ -1,4 +1,4 @@ -import { KnowledgeFormData, QuestionAndAnswerPair, SeedExample } from './Github'; +import { KnowledgeFormData, KnowledgeSeedExample, QuestionAndAnswerPair } from '@/types'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; const questionAndAnswerPairs1: QuestionAndAnswerPair[] = [ @@ -127,7 +127,7 @@ const questionAndAnswerPairs5: QuestionAndAnswerPair[] = [ } ]; -const seedExamples: SeedExample[] = [ +const seedExamples: KnowledgeSeedExample[] = [ { immutable: true, isExpanded: true, diff --git a/src/components/Contribute/Knowledge/DownloadAttribution/DownloadAttribution.tsx b/src/components/Contribute/Knowledge/DownloadAttribution/DownloadAttribution.tsx index 92d6a512..571682af 100644 --- a/src/components/Contribute/Knowledge/DownloadAttribution/DownloadAttribution.tsx +++ b/src/components/Contribute/Knowledge/DownloadAttribution/DownloadAttribution.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import { KnowledgeFormData } from '../Github'; import { DropdownItem } from '@patternfly/react-core/dist/esm/components/Dropdown/DropdownItem'; import FileIcon from '@patternfly/react-icons/dist/esm/icons/file-icon'; +import { KnowledgeFormData } from '@/types'; interface Props { knowledgeFormData: KnowledgeFormData; diff --git a/src/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown.tsx b/src/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown.tsx index e8f962d8..2e216ab1 100644 --- a/src/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown.tsx +++ b/src/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown.tsx @@ -4,8 +4,8 @@ import { DropdownList } from '@patternfly/react-core/dist/dynamic/components/Dro import { MenuToggle, MenuToggleElement } from '@patternfly/react-core/dist/dynamic/components/MenuToggle'; import DownloadYaml from '../DownloadYaml/DownloadYaml'; import DownloadAttribution from '../DownloadAttribution/DownloadAttribution'; -import { KnowledgeFormData } from '../Github'; import DownloadIcon from '@patternfly/react-icons/dist/esm/icons/download-icon'; +import { KnowledgeFormData } from '@/types'; interface Props { knowledgeFormData: KnowledgeFormData; diff --git a/src/components/Contribute/Knowledge/DownloadYaml/DownloadYaml.tsx b/src/components/Contribute/Knowledge/DownloadYaml/DownloadYaml.tsx index a451f55f..78649408 100644 --- a/src/components/Contribute/Knowledge/DownloadYaml/DownloadYaml.tsx +++ b/src/components/Contribute/Knowledge/DownloadYaml/DownloadYaml.tsx @@ -1,6 +1,5 @@ import React from 'react'; -import { KnowledgeFormData } from '../Github'; -import { KnowledgeYamlData } from '@/types'; +import { KnowledgeFormData, KnowledgeYamlData } from '@/types'; import { KnowledgeSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; import { DropdownItem } from '@patternfly/react-core/dist/esm/components/Dropdown/DropdownItem'; diff --git a/src/components/Contribute/Knowledge/Github/DocumentInformation/DocumentInformation.tsx b/src/components/Contribute/Knowledge/Github/DocumentInformation/DocumentInformation.tsx index 53cbf0fd..788063c4 100644 --- a/src/components/Contribute/Knowledge/Github/DocumentInformation/DocumentInformation.tsx +++ b/src/components/Contribute/Knowledge/Github/DocumentInformation/DocumentInformation.tsx @@ -8,9 +8,9 @@ import { HelperText } from '@patternfly/react-core/dist/dynamic/components/Helpe import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { KnowledgeFormData } from '..'; import { checkKnowledgeFormCompletion } from '../../validation'; import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/deprecated/components/Modal/Modal'; +import { KnowledgeFormData } from '@/types'; interface Props { reset: boolean; diff --git a/src/components/Contribute/Knowledge/Github/Submit/Submit.tsx b/src/components/Contribute/Knowledge/Github/Submit/Submit.tsx index d2ca4043..9d7416df 100644 --- a/src/components/Contribute/Knowledge/Github/Submit/Submit.tsx +++ b/src/components/Contribute/Knowledge/Github/Submit/Submit.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; -import { ActionGroupAlertContent, KnowledgeFormData } from '..'; -import { AttributionData, KnowledgeYamlData } from '@/types'; +import { ActionGroupAlertContent } from '..'; +import { AttributionData, KnowledgeFormData, KnowledgeYamlData } from '@/types'; import { KnowledgeSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; import { validateFields } from '../../validation'; diff --git a/src/components/Contribute/Knowledge/Github/Update/Update.tsx b/src/components/Contribute/Knowledge/Github/Update/Update.tsx index a525bfaf..8961e2b7 100644 --- a/src/components/Contribute/Knowledge/Github/Update/Update.tsx +++ b/src/components/Contribute/Knowledge/Github/Update/Update.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; -import { ActionGroupAlertContent, KnowledgeFormData } from '..'; -import { AttributionData, KnowledgeYamlData, PullRequestFile } from '@/types'; +import { ActionGroupAlertContent } from '..'; +import { AttributionData, KnowledgeFormData, KnowledgeYamlData, PullRequestFile } from '@/types'; import { KnowledgeSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; import { validateFields } from '../../validation'; diff --git a/src/components/Contribute/Knowledge/Github/index.tsx b/src/components/Contribute/Knowledge/Github/index.tsx index f15c4142..36cf3008 100644 --- a/src/components/Contribute/Knowledge/Github/index.tsx +++ b/src/components/Contribute/Knowledge/Github/index.tsx @@ -1,87 +1,39 @@ -// src/components/Contribute/Knowledge/index.tsx +// src/components/Experimental/ContributeLocal/Knowledge/index.tsx 'use client'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import '../knowledge.css'; import { Alert, AlertActionCloseButton } from '@patternfly/react-core/dist/dynamic/components/Alert'; import { ActionGroup } from '@patternfly/react-core/dist/dynamic/components/Form'; -import { Form } from '@patternfly/react-core/dist/dynamic/components/Form'; -import { getGitHubUsername } from '../../../../utils/github'; +import { getGitHubUsername } from '@/utils/github'; import { useSession } from 'next-auth/react'; -import AuthorInformation from '../../AuthorInformation'; -import { FormType } from '../../AuthorInformation'; -import KnowledgeInformation from '../KnowledgeInformation/KnowledgeInformation'; -import FilePathInformation from '../FilePathInformation/FilePathInformation'; -import DocumentInformation from './DocumentInformation/DocumentInformation'; -import AttributionInformation from '../AttributionInformation/AttributionInformation'; +import AuthorInformation from '@/components/Contribute/AuthorInformation'; +import { FormType } from '@/components/Contribute/AuthorInformation'; +import KnowledgeInformation from '@/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation'; +import FilePathInformation from '@/components/Contribute/Knowledge/FilePathInformation/FilePathInformation'; +import DocumentInformation from '@/components/Contribute/Knowledge/Github/DocumentInformation/DocumentInformation'; +import AttributionInformation from '@/components/Contribute/Knowledge/AttributionInformation/AttributionInformation'; import Submit from './Submit/Submit'; import { Breadcrumb } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; import { BreadcrumbItem } from '@patternfly/react-core/dist/dynamic/components/Breadcrumb'; import { PageBreadcrumb } from '@patternfly/react-core/dist/dynamic/components/Page'; import { PageGroup } from '@patternfly/react-core/dist/dynamic/components/Page'; import { PageSection } from '@patternfly/react-core/dist/dynamic/components/Page'; -import { Content } from '@patternfly/react-core/dist/dynamic/components/Content'; import { Title } from '@patternfly/react-core/dist/dynamic/components/Title'; -import { Flex, FlexItem } from '@patternfly/react-core/dist/dynamic/layouts/Flex'; -import KnowledgeDescriptionContent from '../KnowledgeDescription/KnowledgeDescriptionContent'; -import KnowledgeSeedExample from '../KnowledgeSeedExample/KnowledgeSeedExample'; -import { checkKnowledgeFormCompletion } from '../validation'; +import KnowledgeDescriptionContent from '@/components/Contribute/Knowledge/KnowledgeDescription/KnowledgeDescriptionContent'; +import KnowledgeSeedExample from '@/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample'; +import { checkKnowledgeFormCompletion } from '@/components/Contribute/Knowledge/validation'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { DownloadDropdown } from '../DownloadDropdown/DownloadDropdown'; -import { ViewDropdown } from '../ViewDropdown/ViewDropdown'; -import Update from './Update/Update'; -import { KnowledgeYamlData, PullRequestFile } from '@/types'; +import { DownloadDropdown } from '@/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown'; +import { ViewDropdown } from '@/components/Contribute/Knowledge/ViewDropdown/ViewDropdown'; +import Update from '@/components/Contribute/Knowledge/Github/Update/Update'; +import { KnowledgeEditFormData, KnowledgeFormData, QuestionAndAnswerPair } from '@/types'; import { Button } from '@patternfly/react-core/dist/esm/components/Button/Button'; import { useRouter } from 'next/navigation'; -import { autoFillKnowledgeFields } from '../AutoFill'; +import { autoFillKnowledgeFields } from '@/components/Contribute/Knowledge/AutoFill'; import { Spinner } from '@patternfly/react-core/dist/esm/components/Spinner'; -import { YamlFileUploadModal } from '../../YamlFileUploadModal'; - -export interface QuestionAndAnswerPair { - immutable: boolean; - question: string; - isQuestionValid: ValidatedOptions; - questionValidationError?: string; - answer: string; - isAnswerValid: ValidatedOptions; - answerValidationError?: string; -} - -export interface SeedExample { - immutable: boolean; - isExpanded: boolean; - context: string; - isContextValid: ValidatedOptions; - validationError?: string; - questionAndAnswers: QuestionAndAnswerPair[]; -} - -export interface KnowledgeFormData { - email: string; - name: string; - submissionSummary: string; - domain: string; - documentOutline: string; - filePath: string; - seedExamples: SeedExample[]; - knowledgeDocumentRepositoryUrl: string; - knowledgeDocumentCommit: string; - documentName: string; - titleWork: string; - linkWork: string; - revision: string; - licenseWork: string; - creators: string; -} - -export interface KnowledgeEditFormData { - isEditForm: boolean; - knowledgeVersion: number; - pullRequestNumber: number; - branchName: string; - yamlFile: PullRequestFile; - attributionFile: PullRequestFile; - knowledgeFormData: KnowledgeFormData; -} +import { Wizard, WizardStep } from '@patternfly/react-core/dist/esm/components/Wizard'; +import { Content } from '@patternfly/react-core/dist/dynamic/components/Content'; +import ReviewSubmission from '@/components/Contribute/Knowledge/ReviewSubmission'; export interface ActionGroupAlertContent { title: string; @@ -131,11 +83,11 @@ export const KnowledgeFormGithub: React.FunctionComponent = const [disableAction, setDisableAction] = useState(true); const [reset, setReset] = useState(false); - const [isModalOpen, setIsModalOpen] = React.useState(false); - const router = useRouter(); - const emptySeedExample: SeedExample = { + const [activeStepIndex] = useState(1); + + const emptySeedExample: KnowledgeSeedExample = { immutable: true, isExpanded: false, context: '', @@ -165,7 +117,7 @@ export const KnowledgeFormGithub: React.FunctionComponent = ] }; - const [seedExamples, setSeedExamples] = useState([ + const [seedExamples, setSeedExamples] = useState([ emptySeedExample, emptySeedExample, emptySeedExample, @@ -189,7 +141,7 @@ export const KnowledgeFormGithub: React.FunctionComponent = } }, [session?.user]); - useEffect(() => { + useMemo(() => { const fetchUsername = async () => { if (session?.accessToken) { try { @@ -237,7 +189,7 @@ export const KnowledgeFormGithub: React.FunctionComponent = const contextStr = context.trim(); if (contextStr.length == 0) { setDisableAction(true); - return { msg: 'Required field', status: ValidatedOptions.error }; + return { msg: 'Context is required', status: ValidatedOptions.error }; } const tokens = contextStr.split(/\s+/); if (tokens.length > 0 && tokens.length <= 500) { @@ -253,7 +205,7 @@ export const KnowledgeFormGithub: React.FunctionComponent = const questionStr = question.trim(); if (questionStr.length == 0) { setDisableAction(true); - return { msg: 'Required field', status: ValidatedOptions.error }; + return { msg: 'Question is required', status: ValidatedOptions.error }; } const tokens = questionStr.split(/\s+/); if (tokens.length > 0 && tokens.length < 250) { @@ -268,7 +220,7 @@ export const KnowledgeFormGithub: React.FunctionComponent = const answerStr = answer.trim(); if (answerStr.length == 0) { setDisableAction(true); - return { msg: 'Required field', status: ValidatedOptions.error }; + return { msg: 'Answer is required', status: ValidatedOptions.error }; } const tokens = answerStr.split(/\s+/); if (tokens.length > 0 && tokens.length < 250) { @@ -281,7 +233,7 @@ export const KnowledgeFormGithub: React.FunctionComponent = const handleContextInputChange = (seedExampleIndex: number, contextValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: KnowledgeSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -293,7 +245,7 @@ export const KnowledgeFormGithub: React.FunctionComponent = }; const handleContextBlur = (seedExampleIndex: number): void => { - const updatedSeedExamples = seedExamples.map((seedExample: SeedExample, index: number): SeedExample => { + const updatedSeedExamples = seedExamples.map((seedExample: KnowledgeSeedExample, index: number): KnowledgeSeedExample => { if (index === seedExampleIndex) { const { msg, status } = validateContext(seedExample.context); return { @@ -309,7 +261,7 @@ export const KnowledgeFormGithub: React.FunctionComponent = const handleQuestionInputChange = (seedExampleIndex: number, questionAndAnswerIndex: number, questionValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: KnowledgeSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -329,7 +281,7 @@ export const KnowledgeFormGithub: React.FunctionComponent = const handleQuestionBlur = (seedExampleIndex: number, questionAndAnswerIndex: number): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: KnowledgeSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -352,7 +304,7 @@ export const KnowledgeFormGithub: React.FunctionComponent = const handleAnswerInputChange = (seedExampleIndex: number, questionAndAnswerIndex: number, answerValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: KnowledgeSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -372,7 +324,7 @@ export const KnowledgeFormGithub: React.FunctionComponent = const handleAnswerBlur = (seedExampleIndex: number, questionAndAnswerIndex: number): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: KnowledgeSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -393,6 +345,14 @@ export const KnowledgeFormGithub: React.FunctionComponent = ); }; + // const toggleSeedExampleExpansion = (index: number): void => { + // setSeedExamples(seedExamples.map((seedExample, idx) => (idx === index ? { ...seedExample, isExpanded: !seedExample.isExpanded } : seedExample))); + // }; + + const toggleSeedExampleExpansion = (index: number): void => { + setSeedExamples(seedExamples.map((seedExample, idx) => (idx === index ? { ...seedExample, isExpanded: !seedExample.isExpanded } : seedExample))); + }; + const onCloseActionGroupAlert = () => { setActionGroupAlertContent(undefined); }; @@ -436,32 +396,6 @@ export const KnowledgeFormGithub: React.FunctionComponent = setSeedExamples(autoFillKnowledgeFields.seedExamples); }; - const yamlSeedExampleToFormSeedExample = ( - yamlSeedExamples: { context: string; questions_and_answers: { question: string; answer: string }[] }[] - ) => { - return yamlSeedExamples.map((yamlSeedExample) => ({ - immutable: true, - isExpanded: false, - context: yamlSeedExample.context ?? '', - isContextValid: ValidatedOptions.default, - questionAndAnswers: yamlSeedExample.questions_and_answers.map((questionAndAnswer) => ({ - question: questionAndAnswer.question ?? '', - answer: questionAndAnswer.answer ?? '' - })) - })) as SeedExample[]; - }; - - const onYamlUploadKnowledgeFillForm = (data: KnowledgeYamlData): void => { - setName(data.created_by ?? ''); - setDocumentOutline(data.document_outline ?? ''); - setSubmissionSummary(data.document_outline ?? ''); - setDomain(data.domain ?? ''); - setKnowledgeDocumentRepositoryUrl(data.document.repo ?? ''); - setKnowledgeDocumentCommit(data.document.commit ?? ''); - setDocumentName(data.document.patterns.join(', ') ?? ''); - setSeedExamples(yamlSeedExampleToFormSeedExample(data.seed_examples)); - }; - const knowledgeFormData: KnowledgeFormData = { email: email, name: name, @@ -488,29 +422,131 @@ export const KnowledgeFormGithub: React.FunctionComponent = router.push('/dashboard'); }; + const steps = [ + { + id: 'author-info', + name: 'Author Information', + component: ( + + ) + }, + { + id: 'knowledge-info', + name: 'Knowledge Information', + component: ( + + ) + }, + { + id: 'file-path-info', + name: 'File Path Information', + component: ( + + ) + }, + { + id: 'seed-examples', + name: 'Seed Examples', + component: ( + + ) + }, + { + id: 'document-info', + name: 'Document Information', + component: ( + + ) + }, + { + id: 'attribution-info', + name: 'Attribution Information', + component: ( + + ) + }, + { + id: 'review-submission', + name: 'Review Submission', + component: , + footer: { + isNextDisabled: true + } + } + ]; + return ( - + Dashboard Knowledge Contribution - - - - - Knowledge Contribution - - - - - - - + + + Knowledge Contribution + @@ -520,136 +556,65 @@ export const KnowledgeFormGithub: React.FunctionComponent = )} - + + {steps.map((step) => ( + + {step.component} + + ))} + + + {actionGroupAlertContent && ( + } + > +

+ {actionGroupAlertContent.waitAlert && } + {actionGroupAlertContent.message} +
+ {!actionGroupAlertContent.waitAlert && + actionGroupAlertContent.success && + actionGroupAlertContent.url && + actionGroupAlertContent.url.trim().length > 0 && ( + + View your new branch + + )} +

+
+ )} -
- - - - - - - - - - - - - {actionGroupAlertContent && ( - } - > -

- {actionGroupAlertContent.waitAlert && } - {actionGroupAlertContent.message} -
- {!actionGroupAlertContent.waitAlert && - actionGroupAlertContent.success && - actionGroupAlertContent.url && - actionGroupAlertContent.url.trim().length > 0 && ( - - View your pull request - - )} -

-
+ + {knowledgeEditFormData?.isEditForm && ( + )} - - - {knowledgeEditFormData?.isEditForm && ( - - )} - {!knowledgeEditFormData?.isEditForm && ( - - )} - - - - - + {!knowledgeEditFormData?.isEditForm && ( + + )} + + + +
); diff --git a/src/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx b/src/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx index 29ce1026..4dc0435c 100644 --- a/src/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx +++ b/src/components/Contribute/Knowledge/KnowledgeInformation/KnowledgeInformation.tsx @@ -6,8 +6,8 @@ import { HelperText } from '@patternfly/react-core/dist/dynamic/components/Helpe import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { KnowledgeFormData } from '../Github'; import { checkKnowledgeFormCompletion } from '../validation'; +import { KnowledgeFormData } from '@/types'; interface Props { reset: boolean; diff --git a/src/components/Contribute/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx b/src/components/Contribute/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx index 314aa7e3..e464529d 100644 --- a/src/components/Contribute/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx +++ b/src/components/Contribute/Knowledge/KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs.tsx @@ -2,13 +2,13 @@ import React from 'react'; import { FormFieldGroupHeader, FormGroup, FormHelperText } from '@patternfly/react-core/dist/dynamic/components/Form'; import { TextArea } from '@patternfly/react-core/dist/dynamic/components/TextArea'; import { ExclamationCircleIcon } from '@patternfly/react-icons/dist/dynamic/icons/'; -import { QuestionAndAnswerPair, SeedExample } from '../Github'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; import { HelperText } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; +import { KnowledgeSeedExample, QuestionAndAnswerPair } from '@/types'; interface Props { - seedExample: SeedExample; + seedExample: KnowledgeSeedExample; seedExampleIndex: number; handleContextInputChange: (seedExampleIndex: number, contextValue: string) => void; handleContextBlur: (seedExampleIndex: number) => void; diff --git a/src/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx b/src/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx index e68bc503..5e984b2b 100644 --- a/src/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx +++ b/src/components/Contribute/Knowledge/KnowledgeSeedExample/KnowledgeSeedExample.tsx @@ -3,11 +3,11 @@ import React from 'react'; import { Accordion, AccordionItem, AccordionContent, AccordionToggle } from '@patternfly/react-core/dist/dynamic/components/Accordion'; import { FormFieldGroupHeader } from '@patternfly/react-core/dist/dynamic/components/Form'; import KnowledgeQuestionAnswerPairs from '../KnowledgeQuestionAnswerPairs/KnowledgeQuestionAnswerPairs'; -import { SeedExample } from '../Github'; +import type { KnowledgeSeedExample } from '@/types'; import ExternalLinkAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-alt-icon'; interface Props { - seedExamples: SeedExample[]; + seedExamples: KnowledgeSeedExample[]; handleContextInputChange: (seedExampleIndex: number, contextValue: string) => void; handleContextBlur: (seedExampleIndex: number) => void; handleQuestionInputChange: (seedExampleIndex: number, questionAndAnswerIndex: number, questionValue: string) => void; @@ -51,7 +51,7 @@ const KnowledgeSeedExample: React.FC = ({ /> - {seedExamples.map((seedExample: SeedExample, seedExampleIndex: number) => ( + {seedExamples.map((seedExample: KnowledgeSeedExample, seedExampleIndex: number) => ( toggleSeedExampleExpansion(seedExampleIndex)} id={`seed-example-toggle-${seedExampleIndex}`}> Seed Example {seedExampleIndex + 1} {seedExample.immutable && *} diff --git a/src/components/Contribute/Knowledge/Native/DocumentInformation/DocumentInformation.tsx b/src/components/Contribute/Knowledge/Native/DocumentInformation/DocumentInformation.tsx index a0511345..63f043c6 100644 --- a/src/components/Contribute/Knowledge/Native/DocumentInformation/DocumentInformation.tsx +++ b/src/components/Contribute/Knowledge/Native/DocumentInformation/DocumentInformation.tsx @@ -7,10 +7,10 @@ import { HelperText } from '@patternfly/react-core/dist/dynamic/components/Helpe import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; import ExclamationCircleIcon from '@patternfly/react-icons/dist/dynamic/icons/exclamation-circle-icon'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { KnowledgeFormData } from '..'; import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/deprecated/components/Modal/Modal'; import { UploadFile } from '@/components/Contribute/Knowledge/UploadFile'; import { checkKnowledgeFormCompletion } from '@/components/Contribute/Knowledge/validation'; +import { KnowledgeFormData } from '@/types'; interface Props { reset: boolean; diff --git a/src/components/Contribute/Knowledge/Native/Submit/Submit.tsx b/src/components/Contribute/Knowledge/Native/Submit/Submit.tsx index 059053bb..13255701 100644 --- a/src/components/Contribute/Knowledge/Native/Submit/Submit.tsx +++ b/src/components/Contribute/Knowledge/Native/Submit/Submit.tsx @@ -1,8 +1,8 @@ // src/components/contribute/native/Knowledge/Submit/Submit.tsx import React from 'react'; import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; -import { ActionGroupAlertContent, KnowledgeFormData } from '..'; -import { AttributionData, KnowledgeYamlData } from '@/types'; +import { ActionGroupAlertContent } from '..'; +import { AttributionData, KnowledgeFormData, KnowledgeYamlData } from '@/types'; import { KnowledgeSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; import { validateFields } from '@/components/Contribute/Knowledge/validation'; diff --git a/src/components/Contribute/Knowledge/Native/index.tsx b/src/components/Contribute/Knowledge/Native/index.tsx index 57668733..5c8b7f0e 100644 --- a/src/components/Contribute/Knowledge/Native/index.tsx +++ b/src/components/Contribute/Knowledge/Native/index.tsx @@ -26,61 +26,14 @@ import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/consta import { DownloadDropdown } from '@/components/Contribute/Knowledge/DownloadDropdown/DownloadDropdown'; import { ViewDropdown } from '@/components/Contribute/Knowledge/ViewDropdown/ViewDropdown'; import Update from '@/components/Contribute/Knowledge/Github/Update/Update'; -import { PullRequestFile } from '@/types'; +import { KnowledgeEditFormData, KnowledgeFormData, QuestionAndAnswerPair } from '@/types'; import { Button } from '@patternfly/react-core/dist/esm/components/Button/Button'; import { useRouter } from 'next/navigation'; import { autoFillKnowledgeFields } from '@/components/Contribute/Knowledge/AutoFill'; import { Spinner } from '@patternfly/react-core/dist/esm/components/Spinner'; import { Wizard, WizardStep } from '@patternfly/react-core/dist/esm/components/Wizard'; import { Content } from '@patternfly/react-core/dist/dynamic/components/Content'; -import ReviewSubmission from '@/components/Contribute/Knowledge/Native/ReviewSubmission'; - -export interface QuestionAndAnswerPair { - immutable: boolean; - question: string; - isQuestionValid: ValidatedOptions; - questionValidationError?: string; - answer: string; - isAnswerValid: ValidatedOptions; - answerValidationError?: string; -} - -export interface SeedExample { - immutable: boolean; - isExpanded: boolean; - context: string; - isContextValid: ValidatedOptions; - validationError?: string; - questionAndAnswers: QuestionAndAnswerPair[]; -} - -export interface KnowledgeFormData { - email: string; - name: string; - submissionSummary: string; - domain: string; - documentOutline: string; - filePath: string; - seedExamples: SeedExample[]; - knowledgeDocumentRepositoryUrl: string; - knowledgeDocumentCommit: string; - documentName: string; - titleWork: string; - linkWork: string; - revision: string; - licenseWork: string; - creators: string; -} - -export interface KnowledgeEditFormData { - isEditForm: boolean; - knowledgeVersion: number; - pullRequestNumber: number; - branchName: string; - yamlFile: PullRequestFile; - attributionFile: PullRequestFile; - knowledgeFormData: KnowledgeFormData; -} +import ReviewSubmission from '../ReviewSubmission'; export interface ActionGroupAlertContent { title: string; @@ -134,7 +87,7 @@ export const KnowledgeFormNative: React.FunctionComponent = const [activeStepIndex] = useState(1); - const emptySeedExample: SeedExample = { + const emptySeedExample: KnowledgeSeedExample = { immutable: true, isExpanded: false, context: '', @@ -164,7 +117,7 @@ export const KnowledgeFormNative: React.FunctionComponent = ] }; - const [seedExamples, setSeedExamples] = useState([ + const [seedExamples, setSeedExamples] = useState([ emptySeedExample, emptySeedExample, emptySeedExample, @@ -280,7 +233,7 @@ export const KnowledgeFormNative: React.FunctionComponent = const handleContextInputChange = (seedExampleIndex: number, contextValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: KnowledgeSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -292,7 +245,7 @@ export const KnowledgeFormNative: React.FunctionComponent = }; const handleContextBlur = (seedExampleIndex: number): void => { - const updatedSeedExamples = seedExamples.map((seedExample: SeedExample, index: number): SeedExample => { + const updatedSeedExamples = seedExamples.map((seedExample: KnowledgeSeedExample, index: number): KnowledgeSeedExample => { if (index === seedExampleIndex) { const { msg, status } = validateContext(seedExample.context); return { @@ -308,7 +261,7 @@ export const KnowledgeFormNative: React.FunctionComponent = const handleQuestionInputChange = (seedExampleIndex: number, questionAndAnswerIndex: number, questionValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: KnowledgeSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -328,7 +281,7 @@ export const KnowledgeFormNative: React.FunctionComponent = const handleQuestionBlur = (seedExampleIndex: number, questionAndAnswerIndex: number): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: KnowledgeSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -351,7 +304,7 @@ export const KnowledgeFormNative: React.FunctionComponent = const handleAnswerInputChange = (seedExampleIndex: number, questionAndAnswerIndex: number, answerValue: string): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: KnowledgeSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, @@ -371,7 +324,7 @@ export const KnowledgeFormNative: React.FunctionComponent = const handleAnswerBlur = (seedExampleIndex: number, questionAndAnswerIndex: number): void => { setSeedExamples( - seedExamples.map((seedExample: SeedExample, index: number) => + seedExamples.map((seedExample: KnowledgeSeedExample, index: number) => index === seedExampleIndex ? { ...seedExample, diff --git a/src/components/Contribute/Knowledge/Native/ReviewSubmission/index.tsx b/src/components/Contribute/Knowledge/ReviewSubmission/index.tsx similarity index 97% rename from src/components/Contribute/Knowledge/Native/ReviewSubmission/index.tsx rename to src/components/Contribute/Knowledge/ReviewSubmission/index.tsx index e9f4d30c..3e39715c 100644 --- a/src/components/Contribute/Knowledge/Native/ReviewSubmission/index.tsx +++ b/src/components/Contribute/Knowledge/ReviewSubmission/index.tsx @@ -1,6 +1,6 @@ // src/components/Contribute/Knowledge/ReviewSubmission/ReviewSubmission.tsx +import { KnowledgeFormData } from '@/types'; import React from 'react'; -import { KnowledgeFormData } from '@/components/Contribute/Knowledge/Native'; interface ReviewSubmissionProps { knowledgeFormData: KnowledgeFormData; diff --git a/src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx b/src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx index b0ed46f2..cd22f4a9 100644 --- a/src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx +++ b/src/components/Contribute/Knowledge/ViewDropdown/ViewDropdown.tsx @@ -3,10 +3,9 @@ import { Dropdown } from '@patternfly/react-core/dist/dynamic/components/Dropdow import { DropdownItem } from '@patternfly/react-core/dist/dynamic/components/Dropdown'; import { DropdownList } from '@patternfly/react-core/dist/dynamic/components/Dropdown'; import { MenuToggle, MenuToggleElement } from '@patternfly/react-core/dist/dynamic/components/MenuToggle'; -import { KnowledgeFormData } from '../Github'; import YamlCodeModal from '@/components/YamlCodeModal'; import CodeIcon from '@patternfly/react-icons/dist/esm/icons/code-icon'; -import { AttributionData, KnowledgeYamlData } from '@/types'; +import { AttributionData, KnowledgeFormData, KnowledgeYamlData } from '@/types'; import { KnowledgeSchemaVersion } from '@/types/const'; import { dumpYaml } from '@/utils/yamlConfig'; import FileIcon from '@patternfly/react-icons/dist/dynamic/icons/file-icon'; diff --git a/src/components/Contribute/Knowledge/validation.tsx b/src/components/Contribute/Knowledge/validation.tsx index 2e40c9ad..54d10d2c 100644 --- a/src/components/Contribute/Knowledge/validation.tsx +++ b/src/components/Contribute/Knowledge/validation.tsx @@ -1,12 +1,13 @@ +import { KnowledgeFormData, KnowledgeSeedExample } from '@/types'; import { ValidatedOptions } from '@patternfly/react-core/dist/esm/helpers/constants'; -import { ActionGroupAlertContent, KnowledgeFormData, SeedExample } from './Github'; +import { ActionGroupAlertContent } from './Github'; const validateEmail = (email: string): boolean => { const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/; return emailRegex.test(email); }; -const hasDuplicateSeedExamples = (seedExamples: SeedExample[]): { duplicate: boolean; index: number } => { +const hasDuplicateSeedExamples = (seedExamples: KnowledgeSeedExample[]): { duplicate: boolean; index: number } => { const contexts = new Set(); for (let index = 0; index < seedExamples.length; index++) { const seedExample = seedExamples[index]; @@ -20,7 +21,7 @@ const hasDuplicateSeedExamples = (seedExamples: SeedExample[]): { duplicate: boo }; // Check if the question in Q&A pairs in a each seed example are unique -const hasDuplicateQuestionAndAnswerPairs = (seedExample: SeedExample): { duplicate: boolean; index: number } => { +const hasDuplicateQuestionAndAnswerPairs = (seedExample: KnowledgeSeedExample): { duplicate: boolean; index: number } => { const questions = new Set(); for (let index = 0; index < seedExample.questionAndAnswers.length; index++) { const questionAndAnswerPair = seedExample.questionAndAnswers[index]; @@ -36,7 +37,7 @@ const hasDuplicateQuestionAndAnswerPairs = (seedExample: SeedExample): { duplica // Validate that the total length of all the question and answer pairs // and context in a seed example is not more than 750 characters. -const validateQuestionAndAnswerPairs = (seedExample: SeedExample): { success: boolean; currLength: number } => { +const validateQuestionAndAnswerPairs = (seedExample: KnowledgeSeedExample): { success: boolean; currLength: number } => { const totalQnAPairsTokenCount = seedExample.questionAndAnswers.reduce((acc, questionAndAnswerPair) => { const questionTokens = questionAndAnswerPair.question.trim().split(/\s+/); const answerTokens = questionAndAnswerPair.answer.trim().split(/\s+/); diff --git a/src/types/index.ts b/src/types/index.ts index 2f8de3ed..a1f0ead9 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -107,3 +107,50 @@ export interface SkillFormData { licenseWork: string; creators: string; } + +export interface QuestionAndAnswerPair { + immutable: boolean; + question: string; + isQuestionValid: ValidatedOptions; + questionValidationError?: string; + answer: string; + isAnswerValid: ValidatedOptions; + answerValidationError?: string; +} + +export interface KnowledgeSeedExample { + immutable: boolean; + isExpanded: boolean; + context: string; + isContextValid: ValidatedOptions; + validationError?: string; + questionAndAnswers: QuestionAndAnswerPair[]; +} + +export interface KnowledgeFormData { + email: string; + name: string; + submissionSummary: string; + domain: string; + documentOutline: string; + filePath: string; + seedExamples: KnowledgeSeedExample[]; + knowledgeDocumentRepositoryUrl: string; + knowledgeDocumentCommit: string; + documentName: string; + titleWork: string; + linkWork: string; + revision: string; + licenseWork: string; + creators: string; +} + +export interface KnowledgeEditFormData { + isEditForm: boolean; + knowledgeVersion: number; + pullRequestNumber: number; + branchName: string; + yamlFile: PullRequestFile; + attributionFile: PullRequestFile; + knowledgeFormData: KnowledgeFormData; +} From 75cc593f41b412bd6d6e20ed47220c3226a024b0 Mon Sep 17 00:00:00 2001 From: Anil Vishnoi Date: Thu, 12 Dec 2024 12:56:46 -0800 Subject: [PATCH 5/6] Update login page according to the supported mode If user deploy UI in github mode, login page shows on github login option If user deploy UI in native mode, login page shows only user/pass If user enable the dev mode, it shows both the options to login. Signed-off-by: Anil Vishnoi --- src/app/api/envConfig/route.ts | 2 +- src/app/api/native/git/branches/route.ts | 3 +- .../{locallogin.tsx => devmodelogin.tsx} | 10 +- src/app/login/nativelogin.tsx | 146 ++++++++++++++++++ src/app/login/page.tsx | 21 ++- 5 files changed, 167 insertions(+), 15 deletions(-) rename src/app/login/{locallogin.tsx => devmodelogin.tsx} (96%) create mode 100644 src/app/login/nativelogin.tsx diff --git a/src/app/api/envConfig/route.ts b/src/app/api/envConfig/route.ts index 330fb372..39515ea6 100644 --- a/src/app/api/envConfig/route.ts +++ b/src/app/api/envConfig/route.ts @@ -15,7 +15,7 @@ export async function GET() { UPSTREAM_REPO_OWNER: process.env.NEXT_PUBLIC_TAXONOMY_REPO_OWNER || '', UPSTREAM_REPO_NAME: process.env.NEXT_PUBLIC_TAXONOMY_REPO || '', DEPLOYMENT_TYPE: process.env.IL_UI_DEPLOYMENT || '', - ENABLE_DEV_MODE: process.env.IL_ENABLE_DEV_MODE || '', + ENABLE_DEV_MODE: process.env.IL_ENABLE_DEV_MODE || 'false', EXPERIMENTAL_FEATURES: process.env.NEXT_PUBLIC_EXPERIMENTAL_FEATURES || '', TAXONOMY_REPO_DIR: process.env.NEXT_PUBLIC_TAXONOMY_REPO_DIR || '' }; diff --git a/src/app/api/native/git/branches/route.ts b/src/app/api/native/git/branches/route.ts index 092c5865..d79fa18d 100644 --- a/src/app/api/native/git/branches/route.ts +++ b/src/app/api/native/git/branches/route.ts @@ -5,7 +5,8 @@ import fs from 'fs'; import path from 'path'; // Get the repository path from the environment variable -const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || './.instructlab-ui'; +const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || `${process.env.HOME}/.instructlab-ui`; + interface Diffs { file: string; status: string; diff --git a/src/app/login/locallogin.tsx b/src/app/login/devmodelogin.tsx similarity index 96% rename from src/app/login/locallogin.tsx rename to src/app/login/devmodelogin.tsx index f30e1136..21df3eb0 100644 --- a/src/app/login/locallogin.tsx +++ b/src/app/login/devmodelogin.tsx @@ -1,4 +1,4 @@ -// src/app/login/LocalLogin.tsx +// src/app/login/DevModeLogin.tsx import React, { useState } from 'react'; import { signIn } from 'next-auth/react'; import { Grid, GridItem } from '@patternfly/react-core/dist/dynamic/layouts/Grid'; @@ -12,7 +12,7 @@ import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/H import GithubIcon from '@patternfly/react-icons/dist/dynamic/icons/github-icon'; import './githublogin.css'; -const LocalLogin: React.FunctionComponent = () => { +const DevModeLogin: React.FunctionComponent = () => { const [, setShowHelperText] = useState(false); const [username, setUsername] = useState(''); const [isValidUsername, setIsValidUsername] = useState(true); @@ -27,7 +27,7 @@ const LocalLogin: React.FunctionComponent = () => { setIsValidUsername(false); setIsValidPassword(false); } else { - window.location.href = '/'; + window.location.href = '/dashboard'; } }; @@ -40,7 +40,7 @@ const LocalLogin: React.FunctionComponent = () => { }; const handleGitHubLogin = () => { - signIn('github', { callbackUrl: '/' }); + signIn('github', { callbackUrl: '/dashboard' }); }; return ( @@ -158,4 +158,4 @@ const LocalLogin: React.FunctionComponent = () => { ); }; -export default LocalLogin; +export default DevModeLogin; diff --git a/src/app/login/nativelogin.tsx b/src/app/login/nativelogin.tsx new file mode 100644 index 00000000..5f0c76e7 --- /dev/null +++ b/src/app/login/nativelogin.tsx @@ -0,0 +1,146 @@ +// src/app/login/NativeLogin.tsx +import React, { useState } from 'react'; +import { signIn } from 'next-auth/react'; +import { Grid, GridItem } from '@patternfly/react-core/dist/dynamic/layouts/Grid'; +import { Content } from '@patternfly/react-core/dist/dynamic/components/Content'; +import { Form } from '@patternfly/react-core/dist/dynamic/components/Form'; +import { FormGroup } from '@patternfly/react-core/dist/dynamic/components/Form'; +import { TextInput } from '@patternfly/react-core/dist/dynamic/components/TextInput'; +import { Button } from '@patternfly/react-core/dist/dynamic/components/Button'; +import { HelperText } from '@patternfly/react-core/dist/dynamic/components/HelperText'; +import { HelperTextItem } from '@patternfly/react-core/dist/dynamic/components/HelperText'; +import './githublogin.css'; + +const NativeLogin: React.FunctionComponent = () => { + const [, setShowHelperText] = useState(false); + const [username, setUsername] = useState(''); + const [isValidUsername, setIsValidUsername] = useState(true); + const [password, setPassword] = useState(''); + const [isValidPassword, setIsValidPassword] = useState(true); + + const handleLogin = async (e: React.FormEvent) => { + e.preventDefault(); + const result = await signIn('credentials', { redirect: false, username, password }); + if (result?.error) { + setShowHelperText(true); + setIsValidUsername(false); + setIsValidPassword(false); + } else { + window.location.href = '/dashboard'; + } + }; + + const handleUsernameChange = (_event: React.FormEvent, value: string) => { + setUsername(value); + }; + + const handlePasswordChange = (_event: React.FormEvent, value: string) => { + setPassword(value); + }; + + return ( +
+ + + + + Login locally with a username and password or via GitHub OAuth + + + + + Join the novel, community-based movement to create truly open-source LLMs + + +
+
+ + + {!isValidUsername && ( + + Invalid Username + + )} + + + + {!isValidPassword && ( + + Invalid password + + )} + + +
+
+ + + + GitHub + {' '} + |{' '} + + Collaborate + {' '} + |{' '} + + Code Of Conduct + + + + + Terms of use + {' '} + |{' '} + + Privacy Policy + + + +
+
+
+ ); +}; + +export default NativeLogin; diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 949efc0a..64a05ae4 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -3,32 +3,37 @@ import React, { useState, useEffect } from 'react'; import './githublogin.css'; -import LocalLogin from '@/app/login/locallogin'; +import NativeLogin from '@/app/login/nativelogin'; import GithubLogin from '@/app/login/githublogin'; +import DevModeLogin from './devmodelogin'; const Login: React.FunctionComponent = () => { - const [isProd, setIsProd] = useState(null); + const [deploymentType, setDeploymentType] = useState(); + const [isDevModeEnabled, setIsDevModeEnabled] = useState(false); useEffect(() => { const chooseLoginPage = async () => { try { const res = await fetch('/api/envConfig'); const envConfig = await res.json(); - setIsProd(envConfig.DEPLOYMENT_TYPE === 'false'); + setDeploymentType(envConfig.DEPLOYMENT_TYPE); + setIsDevModeEnabled(envConfig.ENABLE_DEV_MODE === 'true'); } catch (error) { console.error('Error fetching environment config:', error); - setIsProd(true); + setDeploymentType('github'); } }; chooseLoginPage(); }, []); - if (isProd === null) { + if (isDevModeEnabled) { + return ; + } + if (deploymentType === 'native') { // Render a loading indicator or null while determining the environment - return null; + return ; } - - return isProd ? : ; + return ; }; export default Login; From bb0cfd692b504d03db65fb49df868a3599ad7a18 Mon Sep 17 00:00:00 2001 From: Anil Vishnoi Date: Thu, 12 Dec 2024 13:10:29 -0800 Subject: [PATCH 6/6] Bug fixes encountered during testing of this patch Signed-off-by: Anil Vishnoi --- src/app/api/native/pr/knowledge/route.ts | 2 +- src/app/api/native/pr/skill/route.ts | 2 +- src/app/login/githublogin.tsx | 2 +- src/app/login/page.tsx | 8 ++++++-- src/components/Contribute/Knowledge/Native/index.tsx | 2 +- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/app/api/native/pr/knowledge/route.ts b/src/app/api/native/pr/knowledge/route.ts index a999d971..67cd6f8d 100644 --- a/src/app/api/native/pr/knowledge/route.ts +++ b/src/app/api/native/pr/knowledge/route.ts @@ -10,7 +10,7 @@ import { KnowledgeYamlData } from '@/types'; import yaml from 'js-yaml'; // Define paths and configuration -const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || './.instructlab-ui'; +const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || `${process.env.HOME}/.instructlab-ui`; const KNOWLEDGE_DIR = 'knowledge'; diff --git a/src/app/api/native/pr/skill/route.ts b/src/app/api/native/pr/skill/route.ts index c8d2864a..3d621899 100644 --- a/src/app/api/native/pr/skill/route.ts +++ b/src/app/api/native/pr/skill/route.ts @@ -7,7 +7,7 @@ import path from 'path'; import yaml from 'js-yaml'; // Define paths and configuration -const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || './.instructlab-ui'; +const LOCAL_TAXONOMY_ROOT_DIR = process.env.NEXT_PUBLIC_LOCAL_TAXONOMY_ROOT_DIR || `${process.env.HOME}/.instructlab-ui`; const SKILLS_DIR = 'compositional_skills'; diff --git a/src/app/login/githublogin.tsx b/src/app/login/githublogin.tsx index 4b20c9b8..8281b487 100644 --- a/src/app/login/githublogin.tsx +++ b/src/app/login/githublogin.tsx @@ -11,8 +11,8 @@ import { useRouter, useSearchParams } from 'next/navigation'; import { Modal, ModalVariant } from '@patternfly/react-core/dist/esm/deprecated/components/Modal'; const GithubLogin: React.FC = () => { - const searchParams = useSearchParams(); const router = useRouter(); + const searchParams = useSearchParams(); const [showError, setShowError] = useState(false); const [errorMsg, setErrorMsg] = useState('Something went wrong.'); const [githubUsername, setGithubUsername] = useState(null); diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 64a05ae4..85feca05 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -1,7 +1,7 @@ // src/app/login/page.tsx 'use client'; -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, Suspense } from 'react'; import './githublogin.css'; import NativeLogin from '@/app/login/nativelogin'; import GithubLogin from '@/app/login/githublogin'; @@ -33,7 +33,11 @@ const Login: React.FunctionComponent = () => { // Render a loading indicator or null while determining the environment return ; } - return ; + return ( + + + + ); }; export default Login; diff --git a/src/components/Contribute/Knowledge/Native/index.tsx b/src/components/Contribute/Knowledge/Native/index.tsx index 5c8b7f0e..6e43fc5c 100644 --- a/src/components/Contribute/Knowledge/Native/index.tsx +++ b/src/components/Contribute/Knowledge/Native/index.tsx @@ -580,7 +580,7 @@ export const KnowledgeFormNative: React.FunctionComponent = actionGroupAlertContent.success && actionGroupAlertContent.url && actionGroupAlertContent.url.trim().length > 0 && ( - + View your new branch )}