Vokturz commited on
Commit
4a70176
·
1 Parent(s): 1b3b6e1

Update UI layout and improve interface responsiveness

Browse files
src/App.tsx CHANGED
@@ -13,6 +13,7 @@ import { PipelineLayout } from './components/PipelineLayout'
13
 
14
  function App() {
15
  const [isSidebarOpen, setIsSidebarOpen] = useState(false)
 
16
  const { pipeline, setModels, setModelInfo, modelInfo, setIsFetching } =
17
  useModel()
18
 
@@ -34,38 +35,28 @@ function App() {
34
  }, [setModels, setModelInfo, setIsFetching, pipeline])
35
 
36
  return (
37
- <div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
38
  <Header />
39
  <PipelineLayout>
40
- <div className="flex h-[calc(100vh-4rem)]">
41
  {/* Header is h-16 = 4rem */}
42
  {/* Main Content */}
43
  <main className="flex-1 overflow-auto">
44
- <div className="h-full px-4 sm:px-6 lg:px-8 py-8 lg:pr-4 max-w-none">
45
  {/* Mobile menu button */}
46
- <div className="flex flex-row space-x-4">
47
- <div className="lg:hidden mb-4">
48
- <button
49
- onClick={() => setIsSidebarOpen(true)}
50
- className="inline-flex items-center px-4 py-2 bg-white border border-gray-300 rounded-lg shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
51
- >
52
- <Settings className="w-4 h-4 mr-2" />
53
- Configuration
54
- </button>
55
- </div>
56
- {/* Model README Button */}
57
- <div className="mb-4">
58
- {modelInfo?.readme && (
59
- <ModelReadme
60
- readme={modelInfo.readme}
61
- modelName={modelInfo.name}
62
- pipeline={pipeline}
63
- />
64
- )}
65
- </div>
66
  </div>
67
  {/* Pipeline Component */}
68
  <div className="bg-white rounded-lg shadow-sm border overflow-hidden">
 
 
 
69
  {pipeline === 'zero-shot-classification' && (
70
  <ZeroShotClassification />
71
  )}
@@ -79,9 +70,18 @@ function App() {
79
  <Sidebar
80
  isOpen={isSidebarOpen}
81
  onClose={() => setIsSidebarOpen(false)}
 
82
  />
83
  </div>
84
  </PipelineLayout>
 
 
 
 
 
 
 
 
85
  </div>
86
  )
87
  }
 
13
 
14
  function App() {
15
  const [isSidebarOpen, setIsSidebarOpen] = useState(false)
16
+ const [isModalOpen, setIsModalOpen] = useState(false)
17
  const { pipeline, setModels, setModelInfo, modelInfo, setIsFetching } =
18
  useModel()
19
 
 
35
  }, [setModels, setModelInfo, setIsFetching, pipeline])
36
 
37
  return (
38
+ <div className="relative min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
39
  <Header />
40
  <PipelineLayout>
41
+ <div className=" flex h-[calc(100vh-4rem)]">
42
  {/* Header is h-16 = 4rem */}
43
  {/* Main Content */}
44
  <main className="flex-1 overflow-auto">
45
+ <div className="h-full px-4 sm:px-6 lg:px-8 py-2 lg:pr-4 max-w-none">
46
  {/* Mobile menu button */}
47
+ <div className="absolute right-0 top-16 lg:hidden mb-4">
48
+ <button
49
+ onClick={() => setIsSidebarOpen(true)}
50
+ className="items-center px-2 py-2 bg-white border border-gray-300 rounded-l-lg shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50"
51
+ >
52
+ <Settings className="w-5 h-5" />
53
+ </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  </div>
55
  {/* Pipeline Component */}
56
  <div className="bg-white rounded-lg shadow-sm border overflow-hidden">
57
+ <p className="text-xs text-gray-400 pl-4 pt-2 mb-[-20px]">
58
+ {modelInfo?.name}
59
+ </p>
60
  {pipeline === 'zero-shot-classification' && (
61
  <ZeroShotClassification />
62
  )}
 
70
  <Sidebar
71
  isOpen={isSidebarOpen}
72
  onClose={() => setIsSidebarOpen(false)}
73
+ setIsModalOpen={setIsModalOpen}
74
  />
75
  </div>
76
  </PipelineLayout>
77
+ {modelInfo?.readme && (
78
+ <ModelReadme
79
+ readme={modelInfo.readme}
80
+ modelName={modelInfo.name}
81
+ isModalOpen={isModalOpen}
82
+ setIsModalOpen={setIsModalOpen}
83
+ />
84
+ )}
85
  </div>
86
  )
87
  }
src/Header.tsx CHANGED
@@ -23,7 +23,7 @@ function Header() {
23
  </div>
24
  </div>
25
  </header>
26
- );
27
  }
28
 
29
- export default Header;
 
23
  </div>
24
  </div>
25
  </header>
26
+ )
27
  }
28
 
29
+ export default Header
src/components/ModelReadme.tsx CHANGED
@@ -1,17 +1,20 @@
1
- import { ExternalLink, FileText } from 'lucide-react'
2
- import { useState } from 'react'
3
  import Modal from './Modal'
4
  import MarkdownRenderer from './MarkdownRenderer'
5
 
6
  interface ModelReadmeProps {
7
  readme: string
8
- pipeline: string
9
  modelName: string
 
 
10
  }
11
 
12
- const ModelReadme = ({ readme, pipeline, modelName }: ModelReadmeProps) => {
13
- const [isModalOpen, setIsModalOpen] = useState(false)
14
-
 
 
 
15
  const title = (
16
  <div className="flex items-center space-x-2">
17
  <a
@@ -30,14 +33,6 @@ const ModelReadme = ({ readme, pipeline, modelName }: ModelReadmeProps) => {
30
 
31
  return (
32
  <>
33
- <button
34
- onClick={() => setIsModalOpen(true)}
35
- className="flex items-center w-full px-3 py-2 text-sm text-gray-600 bg-gray-50 rounded-lg border border-gray-200 hover:bg-gray-100 transition-colors"
36
- >
37
- <FileText className="w-4 h-4 mr-2 flex-shrink-0" />
38
- <span className="truncate">View README.md</span>
39
- </button>
40
-
41
  <Modal
42
  isOpen={isModalOpen}
43
  onClose={() => setIsModalOpen(false)}
 
1
+ import { ExternalLink } from 'lucide-react'
 
2
  import Modal from './Modal'
3
  import MarkdownRenderer from './MarkdownRenderer'
4
 
5
  interface ModelReadmeProps {
6
  readme: string
 
7
  modelName: string
8
+ isModalOpen: boolean
9
+ setIsModalOpen: (isOpen: boolean) => void
10
  }
11
 
12
+ const ModelReadme = ({
13
+ readme,
14
+ modelName,
15
+ isModalOpen,
16
+ setIsModalOpen
17
+ }: ModelReadmeProps) => {
18
  const title = (
19
  <div className="flex items-center space-x-2">
20
  <a
 
33
 
34
  return (
35
  <>
 
 
 
 
 
 
 
 
36
  <Modal
37
  isOpen={isModalOpen}
38
  onClose={() => setIsModalOpen(false)}
src/components/PipelineSelector.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import React from 'react';
2
  import {
3
  Listbox,
4
  ListboxOption,
@@ -6,43 +6,41 @@ import {
6
  ListboxOptions,
7
  Transition
8
  } from '@headlessui/react'
9
- import { ChevronDown, Check } from 'lucide-react';
10
 
11
  export const supportedPipelines = [
12
- 'text-classification',
13
- 'zero-shot-classification',
14
  'text-generation',
15
- 'summarization',
16
  'feature-extraction',
17
- 'sentiment-analysis',
18
  'image-classification',
19
- 'question-answering',
 
20
  'translation'
21
- ];
22
 
23
  interface PipelineSelectorProps {
24
- pipeline: string;
25
- setPipeline: (pipeline: string) => void;
26
  }
27
 
28
  const PipelineSelector: React.FC<PipelineSelectorProps> = ({
29
  pipeline,
30
  setPipeline
31
  }) => {
32
- const selectedPipeline = pipeline;
33
 
34
  const formatPipelineName = (pipelineId: string) => {
35
  return pipelineId
36
  .split('-')
37
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
38
- .join(' ');
39
- };
40
 
41
  return (
42
  <div className="relative">
43
  <Listbox value={selectedPipeline} onChange={setPipeline}>
44
  <div className="relative">
45
- <ListboxButton className="relative w-full cursor-default rounded-lg bg-white py-2 pl-3 pr-10 text-left focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm border border-gray-300">
46
  <span className="block truncate font-medium">
47
  {formatPipelineName(selectedPipeline)}
48
  </span>
@@ -53,7 +51,7 @@ const PipelineSelector: React.FC<PipelineSelectorProps> = ({
53
  />
54
  </span>
55
  </ListboxButton>
56
-
57
  <Transition
58
  enter="transition duration-100 ease-out"
59
  enterFrom="transform scale-95 opacity-0"
@@ -62,7 +60,7 @@ const PipelineSelector: React.FC<PipelineSelectorProps> = ({
62
  leaveFrom="transform scale-100 opacity-100"
63
  leaveTo="transform scale-95 opacity-0"
64
  >
65
- <ListboxOptions className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
66
  {supportedPipelines.map((p) => (
67
  <ListboxOption
68
  key={p}
@@ -96,7 +94,7 @@ const PipelineSelector: React.FC<PipelineSelectorProps> = ({
96
  </div>
97
  </Listbox>
98
  </div>
99
- );
100
- };
101
 
102
- export default PipelineSelector;
 
1
+ import React from 'react'
2
  import {
3
  Listbox,
4
  ListboxOption,
 
6
  ListboxOptions,
7
  Transition
8
  } from '@headlessui/react'
9
+ import { ChevronDown, Check } from 'lucide-react'
10
 
11
  export const supportedPipelines = [
 
 
12
  'text-generation',
 
13
  'feature-extraction',
14
+ 'zero-shot-classification',
15
  'image-classification',
16
+ 'text-classification',
17
+ 'summarization',
18
  'translation'
19
+ ]
20
 
21
  interface PipelineSelectorProps {
22
+ pipeline: string
23
+ setPipeline: (pipeline: string) => void
24
  }
25
 
26
  const PipelineSelector: React.FC<PipelineSelectorProps> = ({
27
  pipeline,
28
  setPipeline
29
  }) => {
30
+ const selectedPipeline = pipeline
31
 
32
  const formatPipelineName = (pipelineId: string) => {
33
  return pipelineId
34
  .split('-')
35
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
36
+ .join(' ')
37
+ }
38
 
39
  return (
40
  <div className="relative">
41
  <Listbox value={selectedPipeline} onChange={setPipeline}>
42
  <div className="relative">
43
+ <ListboxButton className="relative w-full cursor-default rounded-lg bg-white py-2 pl-3 pr-10 text-left focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 text-sm xl:text-base border border-gray-300">
44
  <span className="block truncate font-medium">
45
  {formatPipelineName(selectedPipeline)}
46
  </span>
 
51
  />
52
  </span>
53
  </ListboxButton>
54
+
55
  <Transition
56
  enter="transition duration-100 ease-out"
57
  enterFrom="transform scale-95 opacity-0"
 
60
  leaveFrom="transform scale-100 opacity-100"
61
  leaveTo="transform scale-95 opacity-0"
62
  >
63
+ <ListboxOptions className="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-sm xl:text-base ring-1 ring-black ring-opacity-5 focus:outline-none">
64
  {supportedPipelines.map((p) => (
65
  <ListboxOption
66
  key={p}
 
94
  </div>
95
  </Listbox>
96
  </div>
97
+ )
98
+ }
99
 
100
+ export default PipelineSelector
src/components/Sidebar.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { X } from 'lucide-react'
2
  import PipelineSelector from './PipelineSelector'
3
  import ModelSelector from './ModelSelector'
4
  import ModelInfo from './ModelInfo'
@@ -10,9 +10,10 @@ import ZeroShotClassificationConfig from './pipelines/ZeroShotClassificationConf
10
  interface SidebarProps {
11
  isOpen: boolean
12
  onClose: () => void
 
13
  }
14
 
15
- const Sidebar = ({ isOpen, onClose }: SidebarProps) => {
16
  const { pipeline, setPipeline } = useModel()
17
 
18
  return (
@@ -51,7 +52,7 @@ const Sidebar = ({ isOpen, onClose }: SidebarProps) => {
51
  <div className="flex-1 overflow-y-auto p-4 space-y-6">
52
  {/* Pipeline Selection */}
53
  <div className="space-y-3 flex flex-row items-center space-x-4 text-center">
54
- <h3 className="text-lg font-semibold text-gray-900 w-2/5 mt-2">
55
  Choose a Pipeline
56
  </h3>
57
  <div className="w-3/5">
@@ -71,8 +72,18 @@ const Sidebar = ({ isOpen, onClose }: SidebarProps) => {
71
  </div>
72
 
73
  {/* Model Info */}
74
- <div className="flex items-center justify-center">
75
  <ModelInfo />
 
 
 
 
 
 
 
 
 
 
76
  </div>
77
 
78
  <hr className="border-gray-200" />
 
1
+ import { FileText, X } from 'lucide-react'
2
  import PipelineSelector from './PipelineSelector'
3
  import ModelSelector from './ModelSelector'
4
  import ModelInfo from './ModelInfo'
 
10
  interface SidebarProps {
11
  isOpen: boolean
12
  onClose: () => void
13
+ setIsModalOpen: (isOpen: boolean) => void
14
  }
15
 
16
+ const Sidebar = ({ isOpen, onClose, setIsModalOpen }: SidebarProps) => {
17
  const { pipeline, setPipeline } = useModel()
18
 
19
  return (
 
52
  <div className="flex-1 overflow-y-auto p-4 space-y-6">
53
  {/* Pipeline Selection */}
54
  <div className="space-y-3 flex flex-row items-center space-x-4 text-center">
55
+ <h3 className="text-md xl:text-lg font-semibold text-gray-900 w-2/5 mt-2">
56
  Choose a Pipeline
57
  </h3>
58
  <div className="w-3/5">
 
72
  </div>
73
 
74
  {/* Model Info */}
75
+ <div className="flex flex-col items-center justify-center">
76
  <ModelInfo />
77
+ {/* Model README Button */}
78
+ <div className="mt-4 w-42">
79
+ <button
80
+ onClick={() => setIsModalOpen(true)}
81
+ className="flex items-center w-full px-3 py-2 text-sm text-gray-600 bg-gray-50 rounded-lg border border-gray-200 hover:bg-gray-100 transition-colors"
82
+ >
83
+ <FileText className="w-4 h-4 mr-2 flex-shrink-0" />
84
+ <span className="truncate">View README.md</span>
85
+ </button>
86
+ </div>
87
  </div>
88
 
89
  <hr className="border-gray-200" />
src/components/pipelines/FeatureExtraction.tsx CHANGED
@@ -224,7 +224,7 @@ function FeatureExtraction() {
224
  const busy = status !== 'ready' || isExtracting
225
 
226
  return (
227
- <div className="flex flex-col h-[70vh] max-h-[100vh] w-full p-4">
228
  <div className="flex items-center justify-between mb-4">
229
  <h1 className="text-2xl font-bold">Feature Extraction (Embeddings)</h1>
230
  <div className="flex gap-2">
 
224
  const busy = status !== 'ready' || isExtracting
225
 
226
  return (
227
+ <div className="flex flex-col h-full max-h-[92vh] w-full p-4">
228
  <div className="flex items-center justify-between mb-4">
229
  <h1 className="text-2xl font-bold">Feature Extraction (Embeddings)</h1>
230
  <div className="flex gap-2">
src/components/pipelines/TextClassification.tsx CHANGED
@@ -80,7 +80,7 @@ function TextClassification() {
80
  }
81
 
82
  return (
83
- <div className="flex flex-col h-[60vh] max-h-[100vh] w-full p-4">
84
  <h1 className="text-2xl font-bold mb-4 flex-shrink-0">
85
  Text Classification
86
  </h1>
 
80
  }
81
 
82
  return (
83
+ <div className="flex flex-col h-full max-h-[92vh] w-full p-4">
84
  <h1 className="text-2xl font-bold mb-4 flex-shrink-0">
85
  Text Classification
86
  </h1>
src/components/pipelines/TextGeneration.tsx CHANGED
@@ -153,10 +153,10 @@ function TextGeneration() {
153
  const hasChatTemplate = modelInfo?.hasChatTemplate
154
 
155
  return (
156
- <div className="flex flex-col h-[70vh] max-h-[100vh] w-full p-4">
157
  <div className="flex items-center justify-between mb-4">
158
  <h1 className="text-2xl font-bold">
159
- {hasChatTemplate ? 'Chat with AI' : 'Text Generation'}
160
  </h1>
161
  <div className="flex gap-2">
162
  <button
 
153
  const hasChatTemplate = modelInfo?.hasChatTemplate
154
 
155
  return (
156
+ <div className="flex flex-col min-h-[70vh] h-full max-h-[92vh] w-full p-4">
157
  <div className="flex items-center justify-between mb-4">
158
  <h1 className="text-2xl font-bold">
159
+ Text Generation {hasChatTemplate ? '(Chat)' : ''}
160
  </h1>
161
  <div className="flex gap-2">
162
  <button
src/components/pipelines/ZeroShotClassification.tsx CHANGED
@@ -81,7 +81,7 @@ function ZeroShotClassification() {
81
  const busy: boolean = status !== 'ready'
82
 
83
  return (
84
- <div className="flex flex-col h-full max-h-[100vh] w-full p-4">
85
  <div className="flex items-center justify-between mb-4">
86
  <h1 className="text-2xl font-bold">Zero-Shot Classification</h1>
87
  </div>
 
81
  const busy: boolean = status !== 'ready'
82
 
83
  return (
84
+ <div className="flex flex-col h-full max-h-[92vh] w-full p-4">
85
  <div className="flex items-center justify-between mb-4">
86
  <h1 className="text-2xl font-bold">Zero-Shot Classification</h1>
87
  </div>
src/contexts/ModelContext.tsx CHANGED
@@ -36,7 +36,7 @@ export function ModelProvider({ children }: { children: React.ReactNode }) {
36
  const [models, setModels] = useState<ModelInfoResponse[]>(
37
  [] as ModelInfoResponse[]
38
  )
39
- const [pipeline, setPipeline] = useState<string>('text-classification')
40
  const [selectedQuantization, setSelectedQuantization] =
41
  useState<QuantizationType>('int8')
42
  const [activeWorker, setActiveWorker] = useState<Worker | null>(null)
 
36
  const [models, setModels] = useState<ModelInfoResponse[]>(
37
  [] as ModelInfoResponse[]
38
  )
39
+ const [pipeline, setPipeline] = useState<string>('feature-extraction') //text-generation
40
  const [selectedQuantization, setSelectedQuantization] =
41
  useState<QuantizationType>('int8')
42
  const [activeWorker, setActiveWorker] = useState<Worker | null>(null)
tsconfig.json CHANGED
@@ -1,12 +1,7 @@
1
  {
2
  "compilerOptions": {
3
  "target": "es2020",
4
- "lib": [
5
- "dom",
6
- "dom.iterable",
7
- "esnext",
8
- "WebWorker"
9
- ],
10
  "allowJs": true,
11
  "skipLibCheck": true,
12
  "esModuleInterop": true,
@@ -22,4 +17,4 @@
22
  "jsx": "react-jsx"
23
  },
24
  "include": ["src", "public/workers"]
25
- }
 
1
  {
2
  "compilerOptions": {
3
  "target": "es2020",
4
+ "lib": ["dom", "dom.iterable", "esnext", "WebWorker"],
 
 
 
 
 
5
  "allowJs": true,
6
  "skipLibCheck": true,
7
  "esModuleInterop": true,
 
17
  "jsx": "react-jsx"
18
  },
19
  "include": ["src", "public/workers"]
20
+ }