Skip to content

Commit 606437e

Browse files
committed
No fleets notification #373
1 parent b2be6a7 commit 606437e

5 files changed

Lines changed: 134 additions & 66 deletions

File tree

frontend/src/locale/en.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,11 @@
563563
},
564564

565565
"fleets": {
566+
"no_alert": {
567+
"title": "No fleets",
568+
"description": "Please, create a fleet",
569+
"button_title": "Create a fleet"
570+
},
566571
"fleet": "Fleet",
567572
"fleet_placeholder": "Filtering by fleet",
568573
"fleet_name": "Fleet name",

frontend/src/pages/Fleets/List/index.tsx

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import React from 'react';
22
import { useTranslation } from 'react-i18next';
3+
import { ButtonProps } from '@cloudscape-design/components/button';
34

4-
import { Button, Header, Loader, PropertyFilter, SpaceBetween, Table, Toggle } from 'components';
5+
import { Alert, Button, Header, Loader, PropertyFilter, SpaceBetween, Table, Toggle } from 'components';
56

67
import { DEFAULT_TABLE_PAGE_SIZE } from 'consts';
78
import { useBreadcrumbs, useCollection, useInfiniteScroll } from 'hooks';
9+
import { goToUrl } from 'libs';
810
import { ROUTES } from 'routes';
9-
import { useLazyGetFleetsQuery } from 'services/fleet';
11+
import { useGetFleetsQuery, useLazyGetFleetsQuery } from 'services/fleet';
1012

1113
import { useColumnsDefinitions, useEmptyMessages, useFilters } from './hooks';
1214
import { useDeleteFleet } from './useDeleteFleet';
@@ -35,6 +37,8 @@ export const FleetList: React.FC = () => {
3537
isDisabledClearFilter,
3638
} = useFilters();
3739

40+
const { data: fleetsData, isLoading: isLoadingFleets } = useGetFleetsQuery({ limit: 1 });
41+
3842
const { data, isLoading, refreshList, isLoadingMore } = useInfiniteScroll<IFleet, TFleetListRequestParams>({
3943
useLazyQuery: useLazyGetFleetsQuery,
4044
args: { ...filteringRequestParams, limit: DEFAULT_TABLE_PAGE_SIZE },
@@ -67,6 +71,13 @@ export const FleetList: React.FC = () => {
6771
deleteFleets([...selectedItems]).catch(console.log);
6872
};
6973

74+
const noFleets = !isLoadingFleets && !fleetsData?.length;
75+
76+
const onCreateAFleet: ButtonProps['onClick'] = (event) => {
77+
event.preventDefault();
78+
goToUrl('https://dstack.ai/docs/quickstart/#create-a-fleet', true);
79+
};
80+
7081
return (
7182
<Table
7283
{...collectionProps}
@@ -78,25 +89,43 @@ export const FleetList: React.FC = () => {
7889
stickyHeader={true}
7990
selectionType="multi"
8091
header={
81-
<Header
82-
variant="awsui-h1-sticky"
83-
actions={
84-
<SpaceBetween size="xs" direction="horizontal">
85-
<Button formAction="none" onClick={deleteClickHandle} disabled={isDisabledDeleteButton}>
86-
{t('common.delete')}
87-
</Button>
88-
89-
<Button
90-
iconName="refresh"
91-
disabled={isLoading}
92-
ariaLabel={t('common.refresh')}
93-
onClick={refreshList}
94-
/>
95-
</SpaceBetween>
96-
}
97-
>
98-
{t('navigation.fleets')}
99-
</Header>
92+
<>
93+
{noFleets && (
94+
<div className={styles.alertBox}>
95+
<Alert
96+
header={t('fleets.no_alert.title')}
97+
type="info"
98+
action={
99+
<Button iconName="external" formAction="none" onClick={onCreateAFleet}>
100+
{t('fleets.no_alert.button_title')}
101+
</Button>
102+
}
103+
>
104+
{t('fleets.no_alert.description')}
105+
</Alert>
106+
</div>
107+
)}
108+
109+
<Header
110+
variant="awsui-h1-sticky"
111+
actions={
112+
<SpaceBetween size="xs" direction="horizontal">
113+
<Button formAction="none" onClick={deleteClickHandle} disabled={isDisabledDeleteButton}>
114+
{t('common.delete')}
115+
</Button>
116+
117+
<Button
118+
iconName="refresh"
119+
disabled={isLoading}
120+
ariaLabel={t('common.refresh')}
121+
onClick={refreshList}
122+
/>
123+
</SpaceBetween>
124+
}
125+
>
126+
{t('navigation.fleets')}
127+
</Header>
128+
</>
100129
}
101130
filter={
102131
<div className={styles.filters}>

frontend/src/pages/Runs/List/index.tsx

Lines changed: 75 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ import React from 'react';
22
import { useTranslation } from 'react-i18next';
33
import { useNavigate } from 'react-router-dom';
44
import { ButtonDropdownProps } from '@cloudscape-design/components';
5+
import { ButtonProps } from '@cloudscape-design/components/button';
56

6-
import { Button, ButtonDropdown, Header, Loader, PropertyFilter, SpaceBetween, Table, Toggle } from 'components';
7+
import { Alert, Button, ButtonDropdown, Header, Loader, PropertyFilter, SpaceBetween, Table, Toggle } from 'components';
78

89
import { DEFAULT_TABLE_PAGE_SIZE } from 'consts';
910
import { useBreadcrumbs, useCollection, useInfiniteScroll } from 'hooks';
11+
import { goToUrl } from 'libs';
1012
import { ROUTES } from 'routes';
13+
import { useGetFleetsQuery } from 'services/fleet';
1114
import { useLazyGetRunsQuery } from 'services/run';
1215

1316
import { useRunListPreferences } from './Preferences/useRunListPreferences';
@@ -49,6 +52,8 @@ export const RunList: React.FC = () => {
4952
localStorePrefix: 'administration-run-list-page',
5053
});
5154

55+
const { data: fleetsData, isLoading: isLoadingFleets } = useGetFleetsQuery({ limit: 1 });
56+
5257
const { data, isLoading, refreshList, isLoadingMore } = useInfiniteScroll<IRun, TRunsRequestParams>({
5358
useLazyQuery: useLazyGetRunsQuery,
5459
args: { ...filteringRequestParams, limit: DEFAULT_TABLE_PAGE_SIZE, job_submissions_limit: 1 },
@@ -117,6 +122,13 @@ export const RunList: React.FC = () => {
117122
}
118123
};
119124

125+
const noFleets = !isLoadingFleets && !fleetsData?.length;
126+
127+
const onCreateAFleet: ButtonProps['onClick'] = (event) => {
128+
event.preventDefault();
129+
goToUrl('https://dstack.ai/docs/quickstart/#create-a-fleet', true);
130+
};
131+
120132
return (
121133
<Table
122134
{...collectionProps}
@@ -130,50 +142,69 @@ export const RunList: React.FC = () => {
130142
columnDisplay={preferences.contentDisplay}
131143
preferences={<Preferences />}
132144
header={
133-
<Header
134-
variant="awsui-h1-sticky"
135-
actions={
136-
<SpaceBetween size="xs" direction="horizontal">
137-
<ButtonDropdown
138-
items={[
139-
{
140-
text: 'Dev environment',
141-
id: 'dev_env',
142-
href: `${ROUTES.RUNS.CREATE_DEV_ENV}${
143-
filteringRequestParams.project_name
144-
? `?project_name=${filteringRequestParams.project_name}`
145-
: ''
146-
}`,
147-
},
148-
]}
149-
onItemFollow={onFollowButtonDropdownLink}
145+
<>
146+
{noFleets && (
147+
<div className={styles.alertBox}>
148+
<Alert
149+
header={t('fleets.no_alert.title')}
150+
type="info"
151+
action={
152+
<Button iconName="external" formAction="none" onClick={onCreateAFleet}>
153+
{t('fleets.no_alert.button_title')}
154+
</Button>
155+
}
150156
>
151-
{t('common.new')}
152-
</ButtonDropdown>
153-
154-
<Button formAction="none" onClick={abortClickHandle} disabled={isDisabledAbortButton}>
155-
{t('common.abort')}
156-
</Button>
157-
158-
<Button formAction="none" onClick={stopClickHandle} disabled={isDisabledStopButton}>
159-
{t('common.stop')}
160-
</Button>
161-
162-
{/*<Button formAction="none" onClick={deleteClickHandle} disabled={isDisabledDeleteButton}>*/}
163-
{/* {t('common.delete')}*/}
164-
{/*</Button>*/}
165-
166-
<Button
167-
iconName="refresh"
168-
disabled={isLoading}
169-
ariaLabel={t('common.refresh')}
170-
onClick={refreshList}
171-
/>
172-
</SpaceBetween>
173-
}
174-
>
175-
{t('projects.runs')}
176-
</Header>
157+
{t('fleets.no_alert.description')}
158+
</Alert>
159+
</div>
160+
)}
161+
162+
<Header
163+
variant="awsui-h1-sticky"
164+
actions={
165+
<SpaceBetween size="xs" direction="horizontal">
166+
<ButtonDropdown
167+
disabled={!fleetsData?.length}
168+
items={[
169+
{
170+
text: 'Dev environment',
171+
id: 'dev_env',
172+
href: `${ROUTES.RUNS.CREATE_DEV_ENV}${
173+
filteringRequestParams.project_name
174+
? `?project_name=${filteringRequestParams.project_name}`
175+
: ''
176+
}`,
177+
},
178+
]}
179+
onItemFollow={onFollowButtonDropdownLink}
180+
>
181+
{t('common.new')}
182+
</ButtonDropdown>
183+
184+
<Button formAction="none" onClick={abortClickHandle} disabled={isDisabledAbortButton}>
185+
{t('common.abort')}
186+
</Button>
187+
188+
<Button formAction="none" onClick={stopClickHandle} disabled={isDisabledStopButton}>
189+
{t('common.stop')}
190+
</Button>
191+
192+
{/*<Button formAction="none" onClick={deleteClickHandle} disabled={isDisabledDeleteButton}>*/}
193+
{/* {t('common.delete')}*/}
194+
{/*</Button>*/}
195+
196+
<Button
197+
iconName="refresh"
198+
disabled={isLoading}
199+
ariaLabel={t('common.refresh')}
200+
onClick={refreshList}
201+
/>
202+
</SpaceBetween>
203+
}
204+
>
205+
{t('projects.runs')}
206+
</Header>
207+
</>
177208
}
178209
filter={
179210
<div className={styles.selectFilters}>

frontend/src/pages/Runs/List/styles.module.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
.alertBox {
2+
margin-bottom: 16px;
3+
}
14
.selectFilters {
25
display: flex;
36
flex-wrap: wrap;

frontend/src/services/fleet.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,4 @@ export const fleetApi = createApi({
6969
}),
7070
});
7171

72-
export const { useLazyGetFleetsQuery, useDeleteFleetMutation, useGetFleetDetailsQuery } = fleetApi;
72+
export const { useGetFleetsQuery, useLazyGetFleetsQuery, useDeleteFleetMutation, useGetFleetDetailsQuery } = fleetApi;

0 commit comments

Comments
 (0)