@@ -4,7 +4,7 @@ import '@patternfly/react-styles/css/utilities/Spacing/spacing.css';
44import '@patternfly/react-styles/css/utilities/Sizing/sizing.css' ;
55import '@patternfly/react-styles/css/utilities/Text/text.css' ;
66import '@patternfly/react-styles/css/utilities/Flex/flex.css' ;
7- import { Alert , Flex , FlexItem , Grid , GridItem , Spinner , Toolbar , ToolbarItem } from '@patternfly/react-core' ;
7+ import { Alert , Button , Flex , FlexItem , Grid , GridItem , HelperText , HelperTextItem , Modal , ModalBody , ModalFooter , ModalHeader , Spinner , Toolbar , ToolbarItem } from '@patternfly/react-core' ;
88import { RestService } from '@app/Services' ;
99import { deepClone , svgToPng } from '@app/Utils' ;
1010import {
@@ -15,20 +15,20 @@ import {
1515 RequestFilter ,
1616 TableResponse ,
1717 TableResult ,
18- UrlParams ,
18+ UrlParams
1919} from '@app/Types' ;
2020import ErrorState from '@patternfly/react-component-groups/dist/dynamic/ErrorState' ;
2121import {
2222 DashboardBarChart ,
2323 DashboardLineChart ,
2424 DashboardTable ,
2525 DashboardTopTable ,
26- DashboardTotalCards ,
26+ DashboardTotalCards
2727} from '@app/Dashboard' ;
2828import { CurrencySelector } from '@app/Components' ;
2929
3030import useFilterStore from '@app/Store/filterStore' ;
31- import useCommonStore from '@app/Store/commonStore' ;
31+ import useCommonStore from '@app/Store/commonStore' ;
3232import {
3333 useAutomatedProcessCost ,
3434 useFilterRetrieveError ,
@@ -51,7 +51,7 @@ const Dashboard: React.FunctionComponent = () => {
5151 const [ requestParams , setRequestParams ] = React . useState < RequestFilter > ( ) ;
5252 const [ paginationParams , setPaginationParams ] = React . useState < PaginationParams > ( {
5353 page : 1 ,
54- page_size : 10 ,
54+ page_size : 10
5555 } as PaginationParams ) ;
5656 const [ ordering , setOrdering ] = React . useState < string > ( 'name' ) ;
5757 const hourly_manual_costs = useManualCostAutomation ( ) ;
@@ -66,6 +66,7 @@ const Dashboard: React.FunctionComponent = () => {
6666 const saveEnableTemplateCreationTime = useCommonStore ( ( state ) => state . saveEnableTemplateCreationTime ) ;
6767 const setAutomatedProcessCost = useFilterStore ( ( state ) => state . setAutomatedProcessCost ) ;
6868 const setManualProcessCost = useFilterStore ( ( state ) => state . setManualProcessCost ) ;
69+ const maxPDFJobTemplates = useFilterStore ( ( state ) => state . max_pdf_job_templates ) ;
6970 const reloadData = useFilterStore ( ( state ) => state . reloadData ) ;
7071 const setReloadData = useFilterStore ( ( state ) => state . setReloadData ) ;
7172 const handelError = ( error : unknown ) => {
@@ -75,6 +76,7 @@ const Dashboard: React.FunctionComponent = () => {
7576 setTableLoading ( false ) ;
7677 }
7778 } ;
79+ const [ isPDFWarningModalOpen , setPDFWarningModalOpen ] = React . useState < boolean > ( false ) ;
7880
7981 const fetchServerReportDetails = ( signal : AbortSignal ) => {
8082 if ( ! requestParams ) {
@@ -112,7 +114,7 @@ const Dashboard: React.FunctionComponent = () => {
112114 RestService . fetchReports ( controller . current . signal , {
113115 ...requestParams ,
114116 ...paginationParams ,
115- ...{ ordering : ordering } ,
117+ ...{ ordering : ordering }
116118 } as UrlParams )
117119 . then ( ( tableResponse ) => {
118120 setTableData ( tableResponse ) ;
@@ -137,7 +139,7 @@ const Dashboard: React.FunctionComponent = () => {
137139 ( ) => {
138140 fetchServerTableData ( true , false ) ;
139141 } ,
140- parseInt ( refreshInterval ) * 1000 ,
142+ parseInt ( refreshInterval ) * 1000
141143 ) ;
142144 } ;
143145
@@ -244,28 +246,28 @@ const Dashboard: React.FunctionComponent = () => {
244246 {
245247 name : 'project_name' ,
246248 title : 'Project name' ,
247- isVisible : true ,
249+ isVisible : true
248250 } ,
249251 {
250252 name : 'count' ,
251253 title : 'Total no. of jobs' ,
252254 type : 'number' ,
253- isVisible : true ,
254- } ,
255+ isVisible : true
256+ }
255257 ] ;
256258
257259 const topUsersColumns : ColumnProps [ ] = [
258260 {
259261 name : 'user_name' ,
260262 title : 'User name' ,
261- isVisible : true ,
263+ isVisible : true
262264 } ,
263265 {
264266 name : 'count' ,
265267 title : 'Total no. of jobs' ,
266268 type : 'number' ,
267- isVisible : true ,
268- } ,
269+ isVisible : true
270+ }
269271 ] ;
270272
271273 const onInputFocus = ( ) => {
@@ -293,7 +295,7 @@ const Dashboard: React.FunctionComponent = () => {
293295 RestService . exportToPDF (
294296 { ...requestParams , ...{ ordering : ordering } } as RequestFilter & OrderingParams ,
295297 jobsChartPng ,
296- hostChartPng ,
298+ hostChartPng
297299 )
298300 . then ( ( ) => {
299301 setPdfLoading ( false ) ;
@@ -304,8 +306,12 @@ const Dashboard: React.FunctionComponent = () => {
304306 } ;
305307
306308 const onPdfBtnClick = ( ) => {
307- setPdfLoading ( true ) ;
308- setTimeout ( pdfDownload , 150 ) ;
309+ if ( tableData . count > maxPDFJobTemplates ) {
310+ setPDFWarningModalOpen ( true ) ;
311+ } else {
312+ setPdfLoading ( true ) ;
313+ setTimeout ( pdfDownload , 150 ) ;
314+ }
309315 } ;
310316
311317 const onEnableTemplateCreationTimeChange = async ( checked : boolean ) => {
@@ -324,12 +330,42 @@ const Dashboard: React.FunctionComponent = () => {
324330 < div >
325331 < div > This section lists the top five users of Ansible Automation Platform, with a breakdown of the total number of jobs run by each user.</ div >
326332 < ul >
327- < br />
328- < li > < strong > ○ NOTE:</ strong > Scheduled jobs can affect these results, because they do not represent a real, logged-in user. </ li >
333+ < br />
334+ < li > < strong > ○ NOTE:</ strong > Scheduled jobs can affect these results, because they do not represent a real, logged-in user.</ li >
329335 </ ul >
330336 </ div >
331337 ) ;
332338
339+ const pdfModalTitle = (
340+ < HelperText >
341+ < HelperTextItem variant = "error" style = { { fontSize : '20px' } } > PDF Download Failed: Data Volume Exceeded</ HelperTextItem >
342+ </ HelperText >
343+ ) ;
344+
345+ const pdfWarningModal = (
346+ < Modal
347+ isOpen = { isPDFWarningModalOpen }
348+ ouiaId = "DFWarningModal"
349+ aria-labelledby = "pdf-warning-modal-title"
350+ aria-describedby = "pdf-warning-modal-body"
351+ variant = { 'small' }
352+ >
353+ < ModalHeader title = { pdfModalTitle } labelId = "pdf-warning-modal-title" />
354+ < ModalBody id = "pdf-warning-modal-body" >
355+ < HelperText style = { { fontSize : '14px' } } >
356+ < HelperTextItem variant = { 'default' } > We were unable to generate your PDF because the selected report exceeds the maximum record limit.</ HelperTextItem >
357+ < HelperTextItem variant = { 'default' } > Please apply additional filters to narrow your data and retry.</ HelperTextItem >
358+ </ HelperText >
359+ </ ModalBody >
360+ < ModalFooter >
361+ < Button
362+ key = "close"
363+ variant = "link"
364+ onClick = { ( ) => { setPDFWarningModalOpen ( false ) } } > Close</ Button >
365+ </ ModalFooter >
366+ </ Modal >
367+ ) ;
368+
333369 // @ts -ignore
334370 return (
335371 < div >
@@ -354,13 +390,14 @@ const Dashboard: React.FunctionComponent = () => {
354390 />
355391 </ div >
356392 ) }
357- { logErrorMessage &&
358- < div className = { 'main-layout' } >
359- < Alert variant = "danger" isInline title = { logErrorMessage } />
360- </ div >
393+ { logErrorMessage &&
394+ < div className = { 'main-layout' } >
395+ < Alert variant = "danger" isInline title = { logErrorMessage } />
396+ </ div >
361397 }
362398 { ! loadDataError && ! filterError && ! logErrorMessage && (
363399 < div className = { 'main-layout' } >
400+ { pdfWarningModal }
364401 { ( loading || pdfLoading ) && (
365402 < div className = { 'loader' } >
366403 < Spinner className = { 'spinner' } diameter = "80px" aria-label = "Loader" />
0 commit comments