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; +}