Просмотр исходного кода

web: Add style CI workflow to enforce eslint checks on web module (#1910)

Bowen Liang 1 год назад
Родитель
Сommit
a798dcfae9
29 измененных файлов с 141 добавлено и 102 удалено
  1. 34 0
      .github/workflows/style.yml
  2. 3 2
      web/.eslintrc.json
  3. 1 1
      web/app/(commonLayout)/datasets/DatasetFooter.tsx
  4. 1 1
      web/app/(shareLayout)/completion/[token]/page.tsx
  5. 4 3
      web/app/components/app/chat/loading-anim/index.tsx
  6. 0 1
      web/app/components/app/chat/mermaid/index.tsx
  7. 4 3
      web/app/components/app/configuration/base/group-name/index.tsx
  8. 3 2
      web/app/components/app/configuration/base/icons/more-like-this-icon.tsx
  9. 5 4
      web/app/components/app/configuration/base/operation-btn/index.tsx
  10. 3 4
      web/app/components/app/configuration/base/var-highlight/index.tsx
  11. 4 3
      web/app/components/app/configuration/base/warning-mask/has-not-set-api.tsx
  12. 3 2
      web/app/components/app/configuration/base/warning-mask/index.tsx
  13. 4 3
      web/app/components/app/configuration/config-var/modal-foot.tsx
  14. 4 3
      web/app/components/app/configuration/config/feature/feature-group/index.tsx
  15. 6 6
      web/app/components/app/configuration/dataset-config/type-icon/index.tsx
  16. 3 2
      web/app/components/app/configuration/features/experience-enchance-group/index.tsx
  17. 4 3
      web/app/components/app/configuration/features/experience-enchance-group/more-like-this/index.tsx
  18. 2 2
      web/app/components/app/text-generate/index.tsx
  19. 3 2
      web/app/components/base/app-unavailable.tsx
  20. 7 9
      web/app/components/base/panel/index.tsx
  21. 5 7
      web/app/components/datasets/create/empty-dataset-creation-modal/index.tsx
  22. 6 7
      web/app/components/datasets/create/stop-embedding-modal/index.tsx
  23. 1 1
      web/app/components/develop/code.tsx
  24. 9 8
      web/app/components/develop/doc.tsx
  25. 9 9
      web/app/components/develop/md.tsx
  26. 2 2
      web/app/components/header/account-setting/Integrations-page/index.tsx
  27. 1 1
      web/app/components/header/account-setting/members-page/operation/index.tsx
  28. 0 1
      web/app/components/header/app-back/index.tsx
  29. 10 10
      web/app/components/share/chat/value-panel/index.tsx

+ 34 - 0
.github/workflows/style.yml

@@ -0,0 +1,34 @@
+name: Style check
+
+on:
+  pull_request:
+    branches:
+      - main
+  push:
+    branches:
+      - deploy/dev
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+
+    steps:
+    - name: Checkout code
+      uses: actions/checkout@v4
+
+    - name: Setup NodeJS
+      uses: actions/setup-node@v4
+      with:
+        node-version: 18
+        cache: yarn
+        cache-dependency-path: ./web/package.json
+
+    - name: Web dependencies
+      run: |
+        cd ./web
+        yarn install --frozen-lockfile
+
+    - name: Web style check
+      run: |
+        cd ./web
+        yarn run lint

+ 3 - 2
web/.eslintrc.json

@@ -23,6 +23,7 @@
         ]
       }
     ],
-    "react-hooks/exhaustive-deps": "warn"
+    "react-hooks/exhaustive-deps": "warn",
+    "react/display-name": "warn"
   }
-}
+}

+ 1 - 1
web/app/(commonLayout)/datasets/DatasetFooter.tsx

@@ -1,6 +1,6 @@
 'use client'
 
-import { useTranslation } from "react-i18next"
+import { useTranslation } from 'react-i18next'
 
 const DatasetFooter = () => {
   const { t } = useTranslation()

+ 1 - 1
web/app/(shareLayout)/completion/[token]/page.tsx

@@ -10,4 +10,4 @@ const TextGeneration: FC<IMainProps> = () => {
   )
 }
 
-export default React.memo(TextGeneration)
+export default React.memo(TextGeneration)

+ 4 - 3
web/app/components/app/chat/loading-anim/index.tsx

@@ -1,13 +1,14 @@
 'use client'
-import React, { FC } from 'react'
+import type { FC } from 'react'
+import React from 'react'
 import s from './style.module.css'
 
-export interface ILoaidingAnimProps {
+export type ILoaidingAnimProps = {
   type: 'text' | 'avatar'
 }
 
 const LoaidingAnim: FC<ILoaidingAnimProps> = ({
-  type
+  type,
 }) => {
   return (
     <div className={`${s['dot-flashing']} ${s[type]}`}></div>

+ 0 - 1
web/app/components/app/chat/mermaid/index.tsx

@@ -23,7 +23,6 @@ const style = {
   overflow: 'auto',
 }
 
-// eslint-disable-next-line react/display-name
 const Flowchart = React.forwardRef((props: {
   PrimitiveCode: string
 }, ref) => {

+ 4 - 3
web/app/components/app/configuration/base/group-name/index.tsx

@@ -1,12 +1,13 @@
 'use client'
-import React, { FC } from 'react'
+import type { FC } from 'react'
+import React from 'react'
 
-export interface IGroupNameProps {
+export type IGroupNameProps = {
   name: string
 }
 
 const GroupName: FC<IGroupNameProps> = ({
-  name
+  name,
 }) => {
   return (
     <div className='flex items-center mb-1'>

Разница между файлами не показана из-за своего большого размера
+ 3 - 2
web/app/components/app/configuration/base/icons/more-like-this-icon.tsx


Разница между файлами не показана из-за своего большого размера
+ 5 - 4
web/app/components/app/configuration/base/operation-btn/index.tsx


+ 3 - 4
web/app/components/app/configuration/base/var-highlight/index.tsx

@@ -1,9 +1,10 @@
 'use client'
-import React, { FC } from 'react'
+import type { FC } from 'react'
+import React from 'react'
 
 import s from './style.module.css'
 
-export interface IVarHighlightProps {
+export type IVarHighlightProps = {
   name: string
 }
 
@@ -31,6 +32,4 @@ export const varHighlightHTML = ({ name }: IVarHighlightProps) => {
   return html
 }
 
-
-
 export default React.memo(VarHighlight)

+ 4 - 3
web/app/components/app/configuration/base/warning-mask/has-not-set-api.tsx

@@ -1,10 +1,11 @@
 'use client'
-import React, { FC } from 'react'
+import type { FC } from 'react'
+import React from 'react'
 import { useTranslation } from 'react-i18next'
 import WarningMask from '.'
 import Button from '@/app/components/base/button'
 
-export interface IHasNotSetAPIProps {
+export type IHasNotSetAPIProps = {
   isTrailFinished: boolean
   onSetting: () => void
 }
@@ -18,7 +19,7 @@ const icon = (
 
 const HasNotSetAPI: FC<IHasNotSetAPIProps> = ({
   isTrailFinished,
-  onSetting
+  onSetting,
 }) => {
   const { t } = useTranslation()
 

+ 3 - 2
web/app/components/app/configuration/base/warning-mask/index.tsx

@@ -1,9 +1,10 @@
 'use client'
-import React, { FC } from 'react'
+import type { FC } from 'react'
+import React from 'react'
 
 import s from './style.module.css'
 
-export interface IWarningMaskProps {
+export type IWarningMaskProps = {
   title: string
   description: string
   footer: React.ReactNode

+ 4 - 3
web/app/components/app/configuration/config-var/modal-foot.tsx

@@ -1,16 +1,17 @@
 'use client'
-import React, { FC } from 'react'
+import type { FC } from 'react'
+import React from 'react'
 import { useTranslation } from 'react-i18next'
 import Button from '@/app/components/base/button'
 
-export interface IModalFootProps {
+export type IModalFootProps = {
   onConfirm: () => void
   onCancel: () => void
 }
 
 const ModalFoot: FC<IModalFootProps> = ({
   onConfirm,
-  onCancel
+  onCancel,
 }) => {
   const { t } = useTranslation()
   return (

+ 4 - 3
web/app/components/app/configuration/config/feature/feature-group/index.tsx

@@ -1,8 +1,9 @@
 'use client'
-import React, { FC } from 'react'
+import type { FC } from 'react'
+import React from 'react'
 import GroupName from '@/app/components/app/configuration/base/group-name'
 
-export interface IFeatureGroupProps {
+export type IFeatureGroupProps = {
   title: string
   description?: string
   children: React.ReactNode
@@ -11,7 +12,7 @@ export interface IFeatureGroupProps {
 const FeatureGroup: FC<IFeatureGroupProps> = ({
   title,
   description,
-  children
+  children,
 }) => {
   return (
     <div className='mb-6'>

Разница между файлами не показана из-за своего большого размера
+ 6 - 6
web/app/components/app/configuration/dataset-config/type-icon/index.tsx


+ 3 - 2
web/app/components/app/configuration/features/experience-enchance-group/index.tsx

@@ -1,11 +1,12 @@
 'use client'
-import React, { FC } from 'react'
+import type { FC } from 'react'
+import React from 'react'
 import { useTranslation } from 'react-i18next'
 import GroupName from '../../base/group-name'
 import MoreLikeThis from './more-like-this'
 
 /*
-* Include 
+* Include
 * 1. More like this
 */
 const ExperienceEnchanceGroup: FC = () => {

+ 4 - 3
web/app/components/app/configuration/features/experience-enchance-group/more-like-this/index.tsx

@@ -1,10 +1,11 @@
 'use client'
-import React, { FC } from 'react'
-import Panel from '@/app/components/app/configuration/base/feature-panel'
+import type { FC } from 'react'
+import React from 'react'
 import { useTranslation } from 'react-i18next'
-import MoreLikeThisIcon from '../../../base/icons/more-like-this-icon'
 import { XMarkIcon } from '@heroicons/react/24/outline'
 import { useLocalStorageState } from 'ahooks'
+import MoreLikeThisIcon from '../../../base/icons/more-like-this-icon'
+import Panel from '@/app/components/app/configuration/base/feature-panel'
 
 const GENERATE_NUM = 1
 

+ 2 - 2
web/app/components/app/text-generate/index.tsx

@@ -1,7 +1,7 @@
 'use client'
 import type { FC } from 'react'
-import { format } from '@/service/base'
 import React from 'react'
+import { format } from '@/service/base'
 
 export type ITextGenerationProps = {
   value: string
@@ -16,7 +16,7 @@ const TextGeneration: FC<ITextGenerationProps> = ({
     <div
       className={className}
       dangerouslySetInnerHTML={{
-        __html: format(value)
+        __html: format(value),
       }}
     >
     </div>

+ 3 - 2
web/app/components/base/app-unavailable.tsx

@@ -1,8 +1,9 @@
 'use client'
-import React, { FC } from 'react'
+import type { FC } from 'react'
+import React from 'react'
 import { useTranslation } from 'react-i18next'
 
-interface IAppUnavailableProps {
+type IAppUnavailableProps = {
   code?: number
   isUnknwonReason?: boolean
   unknownReason?: string

+ 7 - 9
web/app/components/base/panel/index.tsx

@@ -1,11 +1,11 @@
 'use client'
-import React, { FC, useEffect } from 'react'
+import type { FC } from 'react'
+import React, { useEffect } from 'react'
 import cn from 'classnames'
 import { useBoolean } from 'ahooks'
 import { ChevronRightIcon } from '@heroicons/react/24/outline'
 
-
-export interface IPanelProps {
+export type IPanelProps = {
   className?: string
   headerIcon: React.ReactNode
   title: React.ReactNode
@@ -30,23 +30,21 @@ const Panel: FC<IPanelProps> = ({
   foldDisabled = false,
   onFoldChange,
   controlUnFold,
-  controlFold
+  controlFold,
 }) => {
-  const [fold, { setTrue: setFold, setFalse: setUnFold, toggle: toggleFold }] = useBoolean(keepUnFold ? false : true)
+  const [fold, { setTrue: setFold, setFalse: setUnFold, toggle: toggleFold }] = useBoolean(!keepUnFold)
   useEffect(() => {
     onFoldChange?.(fold)
   }, [fold])
 
   useEffect(() => {
-    if (controlUnFold) {
+    if (controlUnFold)
       setUnFold()
-    }
   }, [controlUnFold])
 
   useEffect(() => {
-    if (controlFold) {
+    if (controlFold)
       setFold()
-    }
   }, [controlFold])
 
   // overflow-hidden

+ 5 - 7
web/app/components/datasets/create/empty-dataset-creation-modal/index.tsx

@@ -3,6 +3,8 @@ import React, { useState } from 'react'
 import { useRouter } from 'next/navigation'
 import { useTranslation } from 'react-i18next'
 import { useContext } from 'use-context-selector'
+import cn from 'classnames'
+import s from './index.module.css'
 import Modal from '@/app/components/base/modal'
 import Input from '@/app/components/base/input'
 import Button from '@/app/components/base/button'
@@ -10,12 +12,9 @@ import Button from '@/app/components/base/button'
 import { ToastContext } from '@/app/components/base/toast'
 import { createEmptyDataset } from '@/service/datasets'
 
-import cn from 'classnames'
-import s from './index.module.css'
-
 type IProps = {
-  show: boolean,
-  onHide: () => void,
+  show: boolean
+  onHide: () => void
 }
 
 const EmptyDatasetCreationModal = ({
@@ -27,7 +26,7 @@ const EmptyDatasetCreationModal = ({
   const { notify } = useContext(ToastContext)
   const router = useRouter()
 
-  const submit =  async () => {
+  const submit = async () => {
     if (!inputValue) {
       notify({ type: 'error', message: t('datasetCreation.stepOne.modal.nameNotEmpty') })
       return
@@ -43,7 +42,6 @@ const EmptyDatasetCreationModal = ({
     }
     catch (err) {
       notify({ type: 'error', message: t('datasetCreation.stepOne.modal.failed') })
-      return
     }
   }
 

+ 6 - 7
web/app/components/datasets/create/stop-embedding-modal/index.tsx

@@ -1,16 +1,15 @@
 'use client'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import Modal from '@/app/components/base/modal'
-import Button from '@/app/components/base/button'
-
 import cn from 'classnames'
 import s from './index.module.css'
+import Modal from '@/app/components/base/modal'
+import Button from '@/app/components/base/button'
 
 type IProps = {
-  show: boolean,
-  onConfirm: () => void,
-  onHide: () => void,
+  show: boolean
+  onConfirm: () => void
+  onHide: () => void
 }
 
 const StopEmbeddingModal = ({
@@ -34,7 +33,7 @@ const StopEmbeddingModal = ({
       <div className={s.icon}/>
       <span className={s.close} onClick={onHide}/>
       <div className={s.title}>{t('datasetCreation.stepThree.modelTitle')}</div>
-      <div className={s.content}>{t('datasetCreation.stepThree.modelContent')}</div>      
+      <div className={s.content}>{t('datasetCreation.stepThree.modelContent')}</div>
       <div className='flex flex-row-reverse'>
         <Button className='w-24 ml-2' type='primary' onClick={submit}>{t('datasetCreation.stepThree.modelButtonConfirm')}</Button>
         <Button className='w-24' onClick={onHide}>{t('datasetCreation.stepThree.modelButtonCancel')}</Button>

+ 1 - 1
web/app/components/develop/code.tsx

@@ -257,7 +257,7 @@ const CodeGroupContext = createContext(false)
 
 export function CodeGroup({ children, title, inputs, targetCode, ...props }: IChildrenProps) {
   const languages = Children.map(children, child =>
-    getPanelTitle(child.props.children.props)
+    getPanelTitle(child.props.children.props),
   )
   const tabGroupProps = useTabGroupProps(languages)
   const hasTabs = Children.count(children) > 1

+ 9 - 8
web/app/components/develop/doc.tsx

@@ -1,9 +1,9 @@
 'use client'
+import { useContext } from 'use-context-selector'
 import TemplateEn from './template/template.en.mdx'
 import TemplateZh from './template/template.zh.mdx'
 import TemplateChatEn from './template/template_chat.en.mdx'
 import TemplateChatZh from './template/template_chat.zh.mdx'
-import { useContext } from 'use-context-selector'
 import I18n from '@/context/i18n'
 
 type IDocProps = {
@@ -14,20 +14,21 @@ const Doc = ({ appDetail }: IDocProps) => {
   const { locale } = useContext(I18n)
   const variables = appDetail?.model_config?.configs?.prompt_variables || []
   const inputs = variables.reduce((res: any, variable: any) => {
-    res[variable.key] = variable.name || '';
+    res[variable.key] = variable.name || ''
     return res
   }, {})
 
   return (
     <article className="prose prose-xl" >
-      {appDetail?.mode === 'completion' ? (
-        locale === 'en' ? <TemplateEn appDetail={appDetail} variables={variables} inputs={inputs} /> : <TemplateZh appDetail={appDetail} variables={variables} inputs={inputs} />
-      ) : (
-        locale === 'en' ? <TemplateChatEn appDetail={appDetail} variables={variables} inputs={inputs} /> : <TemplateChatZh appDetail={appDetail} variables={variables} inputs={inputs} />
-      )}
+      {appDetail?.mode === 'completion'
+        ? (
+          locale === 'en' ? <TemplateEn appDetail={appDetail} variables={variables} inputs={inputs} /> : <TemplateZh appDetail={appDetail} variables={variables} inputs={inputs} />
+        )
+        : (
+          locale === 'en' ? <TemplateChatEn appDetail={appDetail} variables={variables} inputs={inputs} /> : <TemplateChatZh appDetail={appDetail} variables={variables} inputs={inputs} />
+        )}
     </article>
   )
-
 }
 
 export default Doc

+ 9 - 9
web/app/components/develop/md.tsx

@@ -22,20 +22,20 @@ export const Heading = function H2({
   title,
   name,
 }: IHeaderingProps) {
-  let style = '';
+  let style = ''
   switch (method) {
     case 'PUT':
-      style = 'ring-amber-300 bg-amber-400/10 text-amber-500 dark:ring-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400';
-      break;
+      style = 'ring-amber-300 bg-amber-400/10 text-amber-500 dark:ring-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400'
+      break
     case 'DELETE':
-      style = 'ring-rose-200 bg-rose-50 text-red-500 dark:ring-rose-500/20 dark:bg-rose-400/10 dark:text-rose-400';
-      break;
+      style = 'ring-rose-200 bg-rose-50 text-red-500 dark:ring-rose-500/20 dark:bg-rose-400/10 dark:text-rose-400'
+      break
     case 'POST':
-      style = 'ring-sky-300 bg-sky-400/10 text-sky-500 dark:ring-sky-400/30 dark:bg-sky-400/10 dark:text-sky-400';
-      break;
+      style = 'ring-sky-300 bg-sky-400/10 text-sky-500 dark:ring-sky-400/30 dark:bg-sky-400/10 dark:text-sky-400'
+      break
     default:
-      style = 'ring-emerald-300 dark:ring-emerald-400/30 bg-emerald-400/10 text-emerald-500 dark:text-emerald-400';
-      break;
+      style = 'ring-emerald-300 dark:ring-emerald-400/30 bg-emerald-400/10 text-emerald-500 dark:text-emerald-400'
+      break
   }
   return (
     <>

+ 2 - 2
web/app/components/header/account-setting/Integrations-page/index.tsx

@@ -2,9 +2,9 @@
 
 import { useTranslation } from 'react-i18next'
 import classNames from 'classnames'
-import s from './index.module.css'
 import useSWR from 'swr'
 import Link from 'next/link'
+import s from './index.module.css'
 import { fetchAccountIntegrates } from '@/service/common'
 
 const titleClassName = `
@@ -42,7 +42,7 @@ export default function IntegrationsPage() {
               </div>
               {
                 !integrate.is_bound && (
-                  <Link 
+                  <Link
                     className='flex items-center h-8 px-[7px] bg-white rounded-lg border border-gray-200 text-xs font-medium text-gray-700 cursor-pointer'
                     href={integrate.link}
                     target={'_blank'}>

+ 1 - 1
web/app/components/header/account-setting/members-page/operation/index.tsx

@@ -99,7 +99,7 @@ const Operation = ({
                 <div className="px-1 py-1">
                   {
                     ['admin', 'normal'].map(role => (
-                      <Menu.Item>
+                      <Menu.Item key={role}>
                         <div className={itemClassName} onClick={() => handleUpdateMemberRole(role)}>
                           {
                             role === member.role

+ 0 - 1
web/app/components/header/app-back/index.tsx

@@ -6,7 +6,6 @@ import { useTranslation } from 'react-i18next'
 import { ArrowLeftIcon, Squares2X2Icon } from '@heroicons/react/24/solid'
 import type { AppDetailResponse } from '@/models/app'
 
-
 type IAppBackProps = {
   curApp: AppDetailResponse
 }

+ 10 - 10
web/app/components/share/chat/value-panel/index.tsx

@@ -1,13 +1,13 @@
 'use client'
-import React, { FC, ReactNode } from 'react'
+import type { FC, ReactNode } from 'react'
+import React from 'react'
 import cn from 'classnames'
-import { StarIcon } from '@/app/components/share/chat/welcome/massive-component'
-import Button from '@/app/components/base/button'
 import { useTranslation } from 'react-i18next'
-
 import s from './style.module.css'
+import { StarIcon } from '@/app/components/share/chat/welcome/massive-component'
+import Button from '@/app/components/base/button'
 
-export interface ITemplateVarPanelProps {
+export type ITemplateVarPanelProps = {
   className?: string
   header: ReactNode
   children?: ReactNode | null
@@ -18,7 +18,7 @@ const TemplateVarPanel: FC<ITemplateVarPanelProps> = ({
   className,
   header,
   children,
-  isFold
+  isFold,
 }) => {
   return (
     <div className={cn(isFold ? 'border border-indigo-100' : s.boxShodow, className, 'rounded-xl ')}>
@@ -38,9 +38,9 @@ const TemplateVarPanel: FC<ITemplateVarPanelProps> = ({
   )
 }
 
-export const PanelTitle: FC<{ title: string, className?: string }> = ({
+export const PanelTitle: FC<{ title: string; className?: string }> = ({
   title,
-  className
+  className,
 }) => {
   return (
     <div className={cn(className, 'flex items-center space-x-1 text-indigo-600')}>
@@ -50,10 +50,10 @@ export const PanelTitle: FC<{ title: string, className?: string }> = ({
   )
 }
 
-export const VarOpBtnGroup: FC<{ className?: string, onConfirm: () => void, onCancel: () => void }> = ({
+export const VarOpBtnGroup: FC<{ className?: string; onConfirm: () => void; onCancel: () => void }> = ({
   className,
   onConfirm,
-  onCancel
+  onCancel,
 }) => {
   const { t } = useTranslation()