1- /*
2- * License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
3- */
4-
5- import { Stack , Typography } from '@mui/joy' ;
6- import React , { useEffect } from 'react' ;
7- import PropTypes from 'prop-types' ;
8-
9- import { ALERT , alertManager } from './AlertManager.js' ;
10- import { AlertResultView } from './AlertResultView.jsx' ;
11- import { makeBannerTitle } from '../../ui/Banner.jsx' ;
12- import { getActionFromUrl } from '../../core/History.js' ;
13- import { dispatchAddSaga } from '../../core/MasterSaga.js' ;
14- import { FieldGroup } from '../../ui/FieldGroup.jsx' ;
15- import { FileUpload } from '../../ui/FileUpload.jsx' ;
16- import { dispatchTableSearch } from '../../tables/TablesCntlr.js' ;
17- import { getWorkspaceConfig , initWorkspace } from '../../visualize/WorkspaceCntlr.js' ;
18- import { setIf as setIfUndefined } from '../../util/WebUtil.js' ;
19- import App from 'firefly/ui/App.jsx' ;
20- import { cloneDeep } from 'lodash/lang.js' ;
1+ import React , { useEffect , useRef } from 'react' ;
2+ import { useStoreConnector } from 'firefly/ui/SimpleComponent' ;
3+ import { getField , setField } from 'firefly/fieldGroup/FieldGroupUtils' ;
214import { showInfoPopup } from 'firefly/ui/PopupUtil' ;
5+ import { Stack , Typography } from '@mui/joy' ;
6+ import { FieldGroup } from 'firefly/ui/FieldGroup' ;
7+ import { FileUpload } from 'firefly/ui/FileUpload' ;
8+ import { LoadingMessage } from 'firefly/visualize/ui/FileUploadViewPanel' ;
9+ import { dispatchHideDropDown } from 'firefly/core/LayoutCntlr' ;
10+ import { IMAGES , TABLES } from 'firefly/ui/FileUploadUtil' ;
11+ import { findSingleAxisImages , getSelectedRows , makeSummaryModel } from 'firefly/ui/FileUploadProcessor' ;
12+ import { FileAnalysisType } from 'firefly/data/FileAnalysis' ;
2213import { makeFileRequest } from 'firefly/tables/TableRequestUtil' ;
14+ import { ALERT } from './AlertIDs.js' ;
15+ import { dispatchTableSearch } from 'firefly/tables/TablesCntlr' ;
2316import WebPlotRequest from 'firefly/visualize/WebPlotRequest' ;
2417import RangeValues from 'firefly/visualize/RangeValues' ;
2518import { dispatchPlotImage } from 'firefly/visualize/ImagePlotCntlr' ;
26- import { findSingleAxisImages , getSelectedRows , makeSummaryModel } from 'firefly/ui/FileUploadProcessor' ;
27- import { IMAGES , TABLES } from 'firefly/ui/FileUploadUtil' ;
28- import { FileAnalysisType } from 'firefly/data/FileAnalysis' ;
29- import { getField } from '../../fieldGroup/FieldGroupUtils' ;
30- import { LoadingMessage } from 'firefly/visualize/ui/FileUploadViewPanel' ;
31- import { flux } from 'firefly/core/ReduxFlux.js' ;
32- import { dispatchHideDropDown , getLayouInfo , SHOW_DROPDOWN } from 'firefly/core/LayoutCntlr.js' ;
33- import { dispatchNotifyRemoteAppReady , dispatchOnAppReady , dispatchSetMenu } from 'firefly/core/AppDataCntlr.js' ;
34- import { useStoreConnector } from 'firefly/ui/SimpleComponent.jsx' ;
19+ import { dispatchComponentStateChange } from 'firefly/core/ComponentCntlr' ;
20+ import { ROUTER } from 'firefly/templates/router/RouteHelper' ;
3521
3622const vFileKey = ALERT . FG_UPLOAD ;
37- const DEFAULT_TITLE = 'Alert Viewer' ;
38-
39- /**
40- * Alert Viewer - Upload FITS files and view in custom layout
41- * @param {Object } p
42- * @param {Array } p.menu - menu items
43- * @param {Array } p.dropdownPanels - dropdown panels
44- * @param {string } p.appTitle - application title
45- * @param {Object } p.slotProps - slot properties
46- * @param {Object } p.appProps - additional app properties
47- */
48- export function AlertViewer ( { menu, dropdownPanels= [ ] , appTitle, slotProps, ...appProps } ) {
49-
50- useEffect ( ( ) => {
51- dispatchAddSaga ( alertManager , { views : 'tables | images | xyplots' } ) ;
52- getWorkspaceConfig ( ) && initWorkspace ( ) ;
53- dispatchOnAppReady ( ( state ) => onReady ( { state, menu} ) ) ;
54- } , [ ] ) ;
55-
56- const { showTables, showImages, showXyPlots, error} = useStoreConnector ( ( ) => {
57- const layoutInfo = getLayouInfo ( ) ;
58- return {
59- showTables : layoutInfo ?. showTables ,
60- showImages : layoutInfo ?. showImages ,
61- showXyPlots : layoutInfo ?. showXyPlots ,
62- error : layoutInfo ?. error
63- } ;
64- } ) ;
65-
66- const title = makeBannerTitle ( appTitle || DEFAULT_TITLE ) ;
67-
68- const mSlotProps = cloneDeep ( slotProps || { } ) ;
69- setIfUndefined ( mSlotProps , 'drawer.allowMenuHide' , false ) ;
70- setIfUndefined ( mSlotProps , 'banner.title' , title ) ;
71-
72- return (
73- < App slotProps = { mSlotProps }
74- dropdownPanels = { [ ...dropdownPanels , < UploadPanel key = 'AlertUpload' name = 'AlertUpload' /> ] }
75- appTitle = { appTitle } { ...appProps }
76- >
77- < MainView { ...{ error, showTables, showImages, showXyPlots} } />
78- </ App >
79- ) ;
80- }
81-
82- AlertViewer . propTypes = {
83- title : PropTypes . string ,
84- menu : PropTypes . arrayOf ( PropTypes . object ) ,
85- appTitle : PropTypes . string ,
86- appIcon : PropTypes . element ,
87- footer : PropTypes . element ,
88- dropdownPanels : PropTypes . arrayOf ( PropTypes . element ) ,
89- slotProps : PropTypes . object ,
90- style : PropTypes . object
91- } ;
9223
93- const MainView = ( { error, showTables, showImages, showXyPlots} ) => {
94- if ( error ) {
95- return (
96- < div style = { { display : 'flex' , width : '100%' , marginTop : 20 , justifyContent : 'center' , alignItems : 'baseline' } } >
97- < div style = { { display : 'inline-flex' , border : '1px solid #a3aeb9' , padding :20 , fontSize :'150%' } } >
98- < div > { error } </ div >
99- </ div >
100- </ div >
101- ) ;
102- }
24+ export const UploadPanel = ( ) => {
25+ const instruction = 'Enter a URL to a FITS file to upload and view in the Alert Viewer.' ;
26+ const [ isLoading , setIsLoading ] = React . useState ( false ) ;
10327
104- //show result view if we have tables or images, otherwise landing page
105- return ( showTables || showImages || showXyPlots ) ? < AlertResultView /> : < LandingView /> ;
106- } ;
28+ const lastProcessedRef = useRef ( '' ) ;
10729
108- const LandingView = ( ) => {
109- return (
110- < Stack sx = { { width : 1 , height : 1 , justifyContent : 'center' , alignItems : 'center' , p : 4 } } >
111- < Stack spacing = { 3 } sx = { { maxWidth : 600 , textAlign : 'center' } } >
112- < Typography level = 'h1' > Alert Viewer</ Typography >
113- < Typography level = 'body-lg' >
114- Upload FITS files to view in a custom layout with 2 tables side-by-side and 3 images below.
115- </ Typography >
116- < Typography level = 'body-md' color = 'neutral' >
117- Click the "Upload" tab above or drag and drop files here to get started.
118- </ Typography >
119- </ Stack >
120- </ Stack >
121- ) ;
122- } ;
30+ const onLoading = ( loading ) => {
31+ setIsLoading ( loading ) ;
12332
124- function onReady ( { menu} ) {
125- if ( menu ) {
126- dispatchSetMenu ( { menuItems : menu } ) ;
127- }
128- const { hasImages, hasTables, hasXyPlots} = getLayouInfo ( ) ;
129- if ( ! ( hasImages || hasTables || hasXyPlots ) ) {
130- const goto = getActionFromUrl ( ) || { type : SHOW_DROPDOWN } ;
131- if ( goto ) flux . process ( goto ) ;
132- }
133- dispatchNotifyRemoteAppReady ( ) ;
134- }
33+ if ( loading ) {
34+ //clear ONLY the stale server-side outputs from the previous upload.
35+ //keep displayValue (the URL string) so the input stays populated.
36+ setField ( vFileKey , 'fitsUrl' , {
37+ value : undefined , //server file key (stale)
38+ analysisResult : undefined , //stale analysis JSON
39+ message : undefined , //stale error
40+ } ) ;
13541
136- let lastProcessedAnalysisResult = '' ;
137- export const UploadPanel = ( ) => {
138- const instruction = 'Enter a URL to a FITS file to upload and view in the Alert Viewer.' ;
139- const [ isLoading , setIsLoading ] = React . useState ( false ) ;
42+ lastProcessedRef . current = '' ;
43+ }
44+ } ;
14045
14146 //pull the fitsUrl field from the store (this is how FileUploadViewPanel does it)
14247 const { fld} = useStoreConnector ( ( ) => {
14348 return { fld : getField ( vFileKey , 'fitsUrl' ) } ;
14449 } ) ;
14550
146- const onLoading = ( loading ) => { setIsLoading ( loading ) ; } ;
147-
14851 //when analysisResult exists, run loader and close dropdown
14952 useEffect ( ( ) => {
15053 const analysisResult = fld ?. analysisResult ;
@@ -157,9 +60,11 @@ export const UploadPanel = () => {
15760 }
15861 if ( ! analysisResult ) return ;
15962
160- //avoid re-running if store has same value
161- if ( analysisResult === lastProcessedAnalysisResult ) return ;
162- lastProcessedAnalysisResult = analysisResult ;
63+ const fileLocation = fld ?. value ?? '' ;
64+ const key = `${ fileLocation } ::${ analysisResult } ` ;
65+
66+ if ( key === lastProcessedRef . current ) return ;
67+ lastProcessedRef . current = key ;
16368
16469 let report ;
16570 try {
@@ -170,7 +75,7 @@ export const UploadPanel = () => {
17075 }
17176
17277 //file location/source on the server
173- const fileLocation = fld ?. value ;
78+ // const fileLocation = fld?.value;
17479 if ( ! fileLocation ) {
17580 showInfoPopup ( 'Upload analysis returned, but no server file key was found (fitsUrl.value).' , 'Upload Error' ) ;
17681 return ;
@@ -209,6 +114,7 @@ export const UploadPanel = () => {
209114UploadPanel . propTypes = { } ;
210115
211116function loadFromReportAndHide ( fileLocation , report , uploadedFileName ) {
117+ console . log ( 'in loadFromReportAndHide, fileLocation: ' , fileLocation , 'report: ' , report , 'uploadedFileName: ' , uploadedFileName ) ;
212118 try {
213119 if ( ! report ?. parts ) {
214120 showInfoPopup ( 'Could not analyze the uploaded file.' , 'File Analysis Error' ) ;
@@ -291,6 +197,7 @@ function loadFromReportAndHide(fileLocation, report, uploadedFileName) {
291197 wpRequest . setTitle ( desc || `${ uploadedFileName } [ext ${ extNum } ]` ) ;
292198
293199 dispatchPlotImage ( { plotId, wpRequest, viewerId, setNewPlotAsActive : i === 0 } ) ;
200+ dispatchComponentStateChange ( ROUTER , { RESULTS : '/results' } ) ;
294201 }
295202
296203 } catch ( error ) {
0 commit comments