Skip to content

Commit

Permalink
Merge pull request #294 from lucafaggianelli/improve-in-app-help
Browse files Browse the repository at this point in the history
Improve in app help
  • Loading branch information
lucafaggianelli committed Nov 23, 2023
2 parents 1d3d6c1 + fec6aea commit 170607b
Show file tree
Hide file tree
Showing 13 changed files with 612 additions and 325 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]

### Added
- Link to REST API docs in settings menu
- Add download task data button in data view dialog (close #46)
- Add `python-socketio` dependency

Expand All @@ -16,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Changed
- Migrated plain websocket to SocketIO for improved communication stability
- (internal): pipeline HTTP run url is now `/pipelines/{pipeline_id}/run`

### Removed
- Removed python `websockets` dependency
Expand Down
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.17.0",
"react-syntax-highlighter": "^15.5.0",
"socket.io-client": "^4.7.2"
},
"devDependencies": {
"@types/json-schema": "^7.0.15",
"@types/node": "^20.8.10",
"@types/react": "^18.2.33",
"@types/react-dom": "^18.2.17",
"@types/react-syntax-highlighter": "^15.5.9",
"@vitejs/plugin-react": "^4.0.4",
"autoprefixer": "^10.4.13",
"postcss": "^8.4.21",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/PipelinesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const PipelinesList: React.FC = () => {
href="https://lucafaggianelli.github.io/plombery/pipelines/"
target="_blank"
className="inline-flex items-center gap-2 bg-indigo-50/30 hover:bg-indigo-50 dark:bg-indigo-950/50 dark:hover:bg-indigo-950 rounded-sm px-4 py-2 text-indigo-500 transition-colors duration-300 cursor-pointer no-underline"
rel="noopener noreferrer"
>
How to create pipelines
<Icon
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/Popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ export const PopoverContent = React.forwardRef<
top: context.y ?? 0,
left: context.x ?? 0,
width: 'max-content',
zIndex: 20,
...props.style,
...styles,
}}
Expand Down
57 changes: 50 additions & 7 deletions frontend/src/components/SettingsMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { useAuthState } from '@/contexts/AuthContext'
import { Card, Tab, TabGroup, TabList } from '@tremor/react'
import { Popover, PopoverContent, PopoverTrigger } from './Popover'
import { Card, Icon, List, Tab, TabGroup, TabList, Text } from '@tremor/react'
import {
Cog6ToothIcon,
MoonIcon,
SunIcon,
ComputerDesktopIcon,
CodeBracketSquareIcon,
ArrowTopRightOnSquareIcon,
ArchiveBoxIcon,
} from '@heroicons/react/24/outline'
import UserInfo from './UserInfo'
import { useState } from 'react'

import { useAuthState } from '@/contexts/AuthContext'
import { getApiUrl } from '@/repository'
import { Popover, PopoverContent, PopoverTrigger } from './Popover'
import UserInfo from './UserInfo'

interface Props {}

const THEME_MODE_LIGHT = 0
Expand Down Expand Up @@ -88,10 +93,48 @@ const SettingsMenu: React.FC<Props> = () => {
</div>
</PopoverTrigger>
<PopoverContent>
<Card className="shadow-xl z-20">
<ThemeSwitch />
<Card className="p-0 pt-4 shadow-xl z-20">
<List>
<a
className="flex items-center px-6 py-2 hover:bg-tremor-brand-faint hover:dark:bg-dark-tremor-brand-faint transition-colors no-underline"
href={getApiUrl().replace(/\/api$/, '/docs')}
target="_blank"
rel="noopener noreferrer"
>
<Icon
icon={CodeBracketSquareIcon}
color="slate"
className="mr-3"
/>
<Text className="flex-grow no-underline border-0">
REST API docs
</Text>
<Icon icon={ArrowTopRightOnSquareIcon} color="slate" />
</a>

<a
className="flex items-center px-6 py-2 hover:bg-tremor-brand-faint hover:dark:bg-dark-tremor-brand-faint transition-colors no-underline"
href="https://github.com/lucafaggianelli/plombery"
target="_blank"
rel="noopener noreferrer"
>
<Icon
icon={ArchiveBoxIcon}
color="slate"
className="mr-3"
/>
<Text className="flex-grow no-underline border-0">
GitHub
</Text>
<Icon icon={ArrowTopRightOnSquareIcon} color="slate" />
</a>
</List>

<div className="p-6">
<ThemeSwitch />

{isAuthenticationEnabled && <UserInfo />}
{isAuthenticationEnabled && <UserInfo />}
</div>
</Card>
</PopoverContent>
</Popover>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/TriggersList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const TriggersList: React.FC<Props> = ({ pipeline }) => {
href="https://lucafaggianelli.github.io/plombery/triggers/"
target="_blank"
className="inline-flex items-center gap-2 bg-indigo-50/30 hover:bg-indigo-50 dark:bg-indigo-950/50 dark:hover:bg-indigo-950 rounded-sm px-4 py-2 text-indigo-500 transition-colors duration-300 cursor-pointer no-underline"
rel="noopener noreferrer"
>
How to create triggers
<Icon icon={ArrowTopRightOnSquareIcon} size="sm" className='p-0' color='indigo' />
Expand Down
107 changes: 107 additions & 0 deletions frontend/src/components/help/PipelineHttpRun.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import {
Button,
Tab,
TabGroup,
TabList,
TabPanel,
TabPanels,
} from '@tremor/react'
import { QuestionMarkCircleIcon } from '@heroicons/react/24/outline'
import { useState } from 'react'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import {
okaidia,
oneLight,
} from 'react-syntax-highlighter/dist/esm/styles/prism'

import CopyButton from '@/components/CopyButton'
import Dialog from '@/components/Dialog'
import { getPipelineRunUrl } from '@/repository'

interface Props {
pipelineId: string
triggerId?: string
}

const PipelineHttpRun: React.FC<Props> = ({ pipelineId, triggerId }) => {
const [open, setOpen] = useState(false)
const isDark = document.documentElement.classList.contains('dark')

const SNIPPETS = [
{
language: 'python',
name: 'Python',
code: `import httpx
httpx.post('${getPipelineRunUrl(pipelineId)}', json={
"pipeline_id": "${pipelineId}",${triggerId ? `\n "trigger_id": "${triggerId}",` : ''}
"params": {
"name": "value",
}
})`,
},
{
language: 'js',
name: 'JavaScript',
code: `fetch('${getPipelineRunUrl(pipelineId)}', {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
pipeline_id: '${pipelineId}',${triggerId ? `\n trigger_id: '${triggerId}',` : ''}
params: {},
}),
})`,
},
]

return (
<>
<Button
color="indigo"
variant="secondary"
size="xs"
icon={QuestionMarkCircleIcon}
onClick={() => setOpen(true)}
></Button>

<Dialog
isOpen={open}
title="Run via HTTP request"
subtitle="You can run pipelines and triggers via HTTP requests"
onClose={() => setOpen(false)}
>
<TabGroup>
<TabList className="mt-8">
{SNIPPETS.map((snippet) => (
<Tab key={snippet.name}>{snippet.name}</Tab>
))}
</TabList>
<TabPanels>
{SNIPPETS.map((snippet) => (
<TabPanel key={snippet.name}>
<div className="mt-6 relative group">
<SyntaxHighlighter
language={snippet.language}
style={isDark ? okaidia : oneLight}
customStyle={{ borderRadius: 8 }}
>
{snippet.code}
</SyntaxHighlighter>

<CopyButton
content={snippet.code}
className="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity bg-slate-200/80 dark:bg-slate-800/80 rounded p-2"
/>
</div>
</TabPanel>
))}
</TabPanels>
</TabGroup>
</Dialog>
</>
)
}

export default PipelineHttpRun
52 changes: 11 additions & 41 deletions frontend/src/pages/pipelines/[pipelineId]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,20 @@ import {
List,
Bold,
Grid,
TextInput,
} from '@tremor/react'
import { useParams } from 'react-router-dom'
import React from 'react'
import {
ArrowTopRightOnSquareIcon,
QuestionMarkCircleIcon,
} from '@heroicons/react/24/outline'
import { ArrowTopRightOnSquareIcon } from '@heroicons/react/24/outline'

import CopyButton from '@/components/CopyButton'
import Breadcrumbs from '@/components/Breadcrumbs'
import RunsDurationChart from '@/components/RunsDurationChart'
import RunsList from '@/components/RunsList'
import RunsStatusChart from '@/components/RunsStatusChart'
import { getPipeline, getPipelineRunUrl, listRuns } from '@/repository'
import { getPipeline, listRuns } from '@/repository'
import ManualRunDialog from '@/components/ManualRunDialog'
import TriggersList from '@/components/TriggersList'
import PageLayout from '@/components/PageLayout'
import PipelineHttpRun from '@/components/help/PipelineHttpRun'

const PipelineView: React.FC = () => {
const urlParams = useParams()
Expand All @@ -36,15 +32,9 @@ const PipelineView: React.FC = () => {
const pipelineQuery = useQuery(getPipeline(pipelineId))
const runsQuery = useQuery(listRuns(pipelineId))

const CopyUrlButton = () => (
<CopyButton content={getPipelineRunUrl(pipelineId)} className="ml-2.5" />
)

if (pipelineQuery.isLoading)
return <div>Loading...</div>
if (pipelineQuery.isLoading) return <div>Loading...</div>

if (pipelineQuery.isError)
return <div>An error has occurred</div>
if (pipelineQuery.isError) return <div>An error has occurred</div>

const pipeline = pipelineQuery.data

Expand Down Expand Up @@ -101,6 +91,7 @@ const PipelineView: React.FC = () => {
href="https://lucafaggianelli.github.io/plombery/tasks/"
target="_blank"
className="inline-flex items-center gap-2 bg-indigo-50/30 hover:bg-indigo-50 dark:bg-indigo-950/50 dark:hover:bg-indigo-950 rounded-sm px-4 py-2 text-indigo-500 transition-colors duration-300 cursor-pointer no-underline"
rel="noopener noreferrer"
>
How to create tasks
<Icon
Expand All @@ -117,32 +108,14 @@ const PipelineView: React.FC = () => {

<div style={{ flexGrow: 1 }} />

<Flex className="gap-8">
<Flex className="justify-start w-auto flex-shrink-0">
<Text>Run URL</Text>

<Icon
size="sm"
color="slate"
icon={QuestionMarkCircleIcon}
tooltip="URL to run the pipeline programmatically via an HTTP POST request"
/>
</Flex>
<Flex className="justify-between gap-8">
<Text>Run URL</Text>

<TextInput
title={getPipelineRunUrl(pipelineId)}
value={getPipelineRunUrl(pipelineId)}
readOnly
icon={CopyUrlButton}
className="flex-grow"
/>
<PipelineHttpRun pipelineId={pipelineId} />
</Flex>
</Card>

<RunsStatusChart
subject="Pipeline"
query={runsQuery}
/>
<RunsStatusChart subject="Pipeline" query={runsQuery} />

<RunsDurationChart query={runsQuery} />
</Grid>
Expand All @@ -159,10 +132,7 @@ const PipelineView: React.FC = () => {
</Col>

<Col>
<RunsList
query={runsQuery}
pipelineId={pipelineId}
/>
<RunsList query={runsQuery} pipelineId={pipelineId} />
</Col>
</Grid>
</PageLayout>
Expand Down
Loading

0 comments on commit 170607b

Please sign in to comment.