diff --git a/src/components/AggregationPanel/AggregationPanel.js b/src/components/AggregationPanel/AggregationPanel.js index 1b64c0adb0..bd1ead90e3 100644 --- a/src/components/AggregationPanel/AggregationPanel.js +++ b/src/components/AggregationPanel/AggregationPanel.js @@ -38,16 +38,20 @@ const AggregationPanel = ({ } }, [errorAggregatedData, setSelectedObjectId, setErrorAggregatedData]); - const isLoading = useMemo(() => - depth === 0 && selectedObjectId && isLoadingCloudFunction && showAggregatedData, - [depth, selectedObjectId, isLoadingCloudFunction, showAggregatedData] + const isLoading = useMemo( + () => depth === 0 && selectedObjectId && isLoadingCloudFunction && showAggregatedData, + [depth, selectedObjectId, isLoadingCloudFunction, showAggregatedData] ); - const shouldShowAggregatedData = useMemo(() => - depth === 0 - ? (selectedObjectId && showAggregatedData && Object.keys(data).length !== 0 && Object.keys(errorAggregatedData).length === 0) - : true, - [depth, selectedObjectId, showAggregatedData, data, errorAggregatedData] + const shouldShowAggregatedData = useMemo( + () => + depth === 0 + ? selectedObjectId && + showAggregatedData && + Object.keys(data).length !== 0 && + Object.keys(errorAggregatedData).length === 0 + : true, + [depth, selectedObjectId, showAggregatedData, data, errorAggregatedData] ); const fetchNestedData = useCallback(async () => { @@ -137,8 +141,13 @@ const AggregationPanel = ({ if (depth > 0) { return (
-
- {panelTitle} +
+ + {panelTitle} +
{isExpanded && ( - )} - {isExpanded ? '▼' : '▲'} + {isExpanded ? '▼' : '▲'}
{isExpanded && ( @@ -160,7 +168,8 @@ const AggregationPanel = ({
) : ( - nestedData && nestedData.panel.segments.map((segment, index) => + nestedData && + nestedData.panel.segments.map((segment, index) => renderSegmentContent(segment, index) ) )} @@ -178,14 +187,10 @@ const AggregationPanel = ({
) : shouldShowAggregatedData ? (
- {data.panel.segments.map((segment, index) => - renderSegmentContent(segment, index) - )} + {data.panel.segments.map((segment, index) => renderSegmentContent(segment, index))}
) : ( -
- No object selected. -
+
No object selected.
)} ); diff --git a/src/components/AggregationPanel/AggregationPanelComponents.js b/src/components/AggregationPanel/AggregationPanelComponents.js index d81ca31569..d85d05eee6 100644 --- a/src/components/AggregationPanel/AggregationPanelComponents.js +++ b/src/components/AggregationPanel/AggregationPanelComponents.js @@ -12,7 +12,13 @@ export const TextElement = ({ text }) => ( export const KeyValueElement = ({ item, appName }) => (
{item.key}: - {item.url ? {item.value} : {item.value}} + {item.url ? ( + + {item.value} + + ) : ( + {item.value} + )}
); @@ -80,10 +86,10 @@ export const ButtonElement = ({ item, showNote }) => { .then(response => response.json()) .then(data => { const formattedData = JSON.stringify(data, null, 2); - showNote(`${formattedData}`,false) + showNote(`${formattedData}`, false); }) .catch(error => { - showNote(`${error}`,true) + showNote(`${error}`, true); }); }; diff --git a/src/components/BrowserCell/BrowserCell.react.js b/src/components/BrowserCell/BrowserCell.react.js index a9c364e44d..f78b7998af 100644 --- a/src/components/BrowserCell/BrowserCell.react.js +++ b/src/components/BrowserCell/BrowserCell.react.js @@ -578,7 +578,7 @@ export default class BrowserCell extends Component { markRequiredFieldRow, handleCellClick, selectedCells, - setShowAggregatedData + setShowAggregatedData, } = this.props; const classes = [...this.state.classes]; diff --git a/src/components/BrowserRow/BrowserRow.react.js b/src/components/BrowserRow/BrowserRow.react.js index 0e6f40a694..7a3df557db 100644 --- a/src/components/BrowserRow/BrowserRow.react.js +++ b/src/components/BrowserRow/BrowserRow.react.js @@ -79,7 +79,7 @@ export default class BrowserRow extends Component { type="checkbox" checked={selection['*'] || selection[obj.id]} onChange={e => selectRow(obj.id, e.target.checked)} - onMouseDown={(e) => onMouseDownRowCheckBox(e.target.checked)} + onMouseDown={e => onMouseDownRowCheckBox(e.target.checked)} /> {order.map(({ name, width, visible }, j) => { diff --git a/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.react.js b/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.react.js index 1287e62ae5..a1daee294f 100644 --- a/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.react.js +++ b/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.react.js @@ -25,7 +25,7 @@ export default class DataBrowserHeaderBar extends React.Component { selected, isDataLoaded, setSelectedObjectId, - setCurrent + setCurrent, } = this.props; const elements = [
@@ -50,11 +50,11 @@ export default class DataBrowserHeaderBar extends React.Component { !preventSort && (type === 'String' || type === 'Number' || type === 'Date' || type === 'Boolean') ) { - onClick = () =>{ + onClick = () => { updateOrdering((order === 'descending' ? '' : '-') + name); setSelectedObjectId(null); - setCurrent(null) - } + setCurrent(null); + }; } let className = styles.wrap; @@ -83,7 +83,7 @@ export default class DataBrowserHeaderBar extends React.Component { const finalStyle = {}; if (headers.length % 2) { finalStyle.background = '#726F85'; - } else{ + } else { finalStyle.background = '#66637A'; } diff --git a/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.scss b/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.scss index ba42c5694e..a69e8eba73 100644 --- a/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.scss +++ b/src/components/DataBrowserHeaderBar/DataBrowserHeaderBar.scss @@ -8,7 +8,8 @@ @import 'stylesheets/globals.scss'; .bar { - position: absolute; + position: sticky; + z-index: 10; top: 0; left: 0; height: 0; diff --git a/src/components/Filter/Filter.react.js b/src/components/Filter/Filter.react.js index 29397f4213..67592444ec 100644 --- a/src/components/Filter/Filter.react.js +++ b/src/components/Filter/Filter.react.js @@ -61,7 +61,8 @@ function changeConstraint(schema, currentClassName, filters, index, newConstrain class: currentClassName, field: field, constraint: newConstraint, - compareTo: (compareType && prevCompareTo) ? prevCompareTo : Filters.DefaultComparisons[compareType], + compareTo: + compareType && prevCompareTo ? prevCompareTo : Filters.DefaultComparisons[compareType], }); return filters.set(index, newFilter); } @@ -88,7 +89,7 @@ const Filter = ({ const [compare, setCompare] = useState(false); const hasCompareTo = filters.some(filter => filter.get('compareTo') !== undefined); - if(compare !== hasCompareTo){ + if (compare !== hasCompareTo) { setCompare(hasCompareTo); } const currentApp = React.useContext(CurrentApp); @@ -108,7 +109,7 @@ const Filter = ({ gap: '10px', padding: '12px 15px 0px 15px', color: '#343445', - 'font-weight': '600' + 'font-weight': '600', }} >
Class
diff --git a/src/components/Label/Label.react.js b/src/components/Label/Label.react.js index d48f5d276c..b2b3bb0021 100644 --- a/src/components/Label/Label.react.js +++ b/src/components/Label/Label.react.js @@ -15,7 +15,8 @@ const Label = props => { return (
+ style={{ padding: '0 ' + padding, ...props.style }} + >
{props.text}
{props.description ?
{props.description}
: null}
diff --git a/src/components/Toolbar/Toolbar.react.js b/src/components/Toolbar/Toolbar.react.js index 670cd205dc..e5e6642534 100644 --- a/src/components/Toolbar/Toolbar.react.js +++ b/src/components/Toolbar/Toolbar.react.js @@ -15,7 +15,7 @@ import { useNavigate, useNavigationType, NavigationType } from 'react-router-dom const POPOVER_CONTENT_ID = 'toolbarStatsPopover'; -const Stats = ({ data, classwiseCloudFunctions, className, appId , appName}) => { +const Stats = ({ data, classwiseCloudFunctions, className, appId, appName }) => { const [selected, setSelected] = React.useState(null); const [open, setOpen] = React.useState(false); const buttonRef = React.useRef(); @@ -98,7 +98,12 @@ const Stats = ({ data, classwiseCloudFunctions, className, appId , appName}) => setSelected(statsOptions[0]); }, []); - const rightMarginStyle = classwiseCloudFunctions && classwiseCloudFunctions[`${appId}${appName}`] && classwiseCloudFunctions[`${appId}${appName}`][className] ? '120px' : 'initial'; + const rightMarginStyle = + classwiseCloudFunctions && + classwiseCloudFunctions[`${appId}${appName}`] && + classwiseCloudFunctions[`${appId}${appName}`][className] + ? '120px' + : 'initial'; return ( <> @@ -140,22 +145,29 @@ const Toolbar = props => {
- {props?.selectedData?.length ? : null} + {props?.selectedData?.length ? ( + + ) : null}
{props.children}
- {props.classwiseCloudFunctions && props.classwiseCloudFunctions[`${props.appId}${props.appName}`] && props.classwiseCloudFunctions[`${props.appId}${props.appName}`][props.className] && ( - diff --git a/src/dashboard/Dashboard.js b/src/dashboard/Dashboard.js index 0aebec1f25..96be0559be 100644 --- a/src/dashboard/Dashboard.js +++ b/src/dashboard/Dashboard.js @@ -180,7 +180,6 @@ export default class Dashboard extends React.Component { configLoadingState: AsyncStatus.FAILED, }); }); - } render() { @@ -216,14 +215,14 @@ export default class Dashboard extends React.Component { const SettingsRoute = ( }> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> ); diff --git a/src/dashboard/DashboardView.react.js b/src/dashboard/DashboardView.react.js index 00ceb39223..061bcbf1de 100644 --- a/src/dashboard/DashboardView.react.js +++ b/src/dashboard/DashboardView.react.js @@ -195,16 +195,18 @@ export default class DashboardView extends React.Component { } */ - const settingsSections = [{ - name: 'Dashboard', - link: '/settings/dashboard' - }]; + const settingsSections = [ + { + name: 'Dashboard', + link: '/settings/dashboard', + }, + ]; if (this.context.enableSecurityChecks) { settingsSections.push({ name: 'Security', link: '/settings/security', - }) + }); } // Settings - nothing remotely like this in parse-server yet. Maybe it will arrive soon. diff --git a/src/dashboard/Data/Browser/Browser.react.js b/src/dashboard/Data/Browser/Browser.react.js index 93b01a308d..245a4080f0 100644 --- a/src/dashboard/Data/Browser/Browser.react.js +++ b/src/dashboard/Data/Browser/Browser.react.js @@ -275,7 +275,8 @@ class Browser extends DashboardView { useMasterKey: true, }; const appName = this.props.params.appId; - const cloudCodeFunction = this.state.classwiseCloudFunctions[`${appId}${appName}`]?.[className][0].cloudCodeFunction; + const cloudCodeFunction = + this.state.classwiseCloudFunctions[`${appId}${appName}`]?.[className][0].cloudCodeFunction; Parse.Cloud.run(cloudCodeFunction, params, options).then( result => { if (result && result.panel && result.panel && result.panel.segments) { @@ -285,7 +286,7 @@ class Browser extends DashboardView { isLoading: false, errorAggregatedData: 'Improper JSON format', }); - this.showNote(this.state.errorAggregatedData,true) + this.showNote(this.state.errorAggregatedData, true); } }, error => { @@ -293,7 +294,7 @@ class Browser extends DashboardView { isLoading: false, errorAggregatedData: error.message, }); - this.showNote(this.state.errorAggregatedData,true) + this.showNote(this.state.errorAggregatedData, true); } ); } @@ -331,18 +332,19 @@ class Browser extends DashboardView { data.apps.forEach(app => { const appName = app.appName; classMap[`${app.appId}${appName}`] = {}; - app.infoPanel && app.infoPanel.forEach(panel => { - panel.classes.forEach(className => { - if (!classMap[`${app.appId}${appName}`][className]) { - classMap[`${app.appId}${appName}`][className] = []; - } - classMap[`${app.appId}${appName}`][className].push({ - title: panel.title, - cloudCodeFunction: panel.cloudCodeFunction, - classes: panel.classes, + app.infoPanel && + app.infoPanel.forEach(panel => { + panel.classes.forEach(className => { + if (!classMap[`${app.appId}${appName}`][className]) { + classMap[`${app.appId}${appName}`][className] = []; + } + classMap[`${app.appId}${appName}`][className].push({ + title: panel.title, + cloudCodeFunction: panel.cloudCodeFunction, + classes: panel.classes, + }); }); }); - }); }); this.setState({ classwiseCloudFunctions: classMap }); @@ -1160,7 +1162,11 @@ class Browser extends DashboardView { }, ]); window.open( - generatePath(this.context, `browser/${className}?filters=${encodeURIComponent(filters)}`, true), + generatePath( + this.context, + `browser/${className}?filters=${encodeURIComponent(filters)}`, + true + ), '_blank' ); } @@ -1369,7 +1375,7 @@ class Browser extends DashboardView { if (error.code === Parse.Error.AGGREGATE_ERROR) { if (error.errors.length == 1) { errorDeletingNote = - 'Error deleting ' + className + ' with id \'' + error.errors[0].object.id + '\''; + 'Error deleting ' + className + ' with id \'' + error.errors[0].object.id + '\''; } else if (error.errors.length < toDeleteObjectIds.length) { errorDeletingNote = 'Error deleting ' + @@ -1537,17 +1543,19 @@ class Browser extends DashboardView { this.setState(prevState => ({ processedScripts: prevState.processedScripts + 1, })); - const note = (typeof response === 'object' ? JSON.stringify(response) : response) || `Ran script "${script.title}" on "${object.id}".`; + const note = + (typeof response === 'object' ? JSON.stringify(response) : response) || + `Ran script "${script.title}" on "${object.id}".`; this.showNote(note); } this.refresh(); } catch (e) { this.showNote(e.message, true); console.log(`Could not run ${script.title}: ${e}`); - } finally{ - this.setState(({ + } finally { + this.setState({ processedScripts: 0, - })); + }); } } @@ -2069,7 +2077,7 @@ class Browser extends DashboardView { setAggregationPanelData={this.setAggregationPanelData} setErrorAggregatedData={this.setErrorAggregatedData} errorAggregatedData={this.state.errorAggregatedData} - appName = {this.props.params.appId} + appName={this.props.params.appId} /> ); } diff --git a/src/dashboard/Data/Browser/Browser.scss b/src/dashboard/Data/Browser/Browser.scss index 97948cb9a0..215f04a1a3 100644 --- a/src/dashboard/Data/Browser/Browser.scss +++ b/src/dashboard/Data/Browser/Browser.scss @@ -14,7 +14,6 @@ right: 0; bottom: 0; overflow: auto; - padding-top: 30px; } body:global(.expanded) { diff --git a/src/dashboard/Data/Browser/BrowserTable.react.js b/src/dashboard/Data/Browser/BrowserTable.react.js index 59dc53d5da..c710227e80 100644 --- a/src/dashboard/Data/Browser/BrowserTable.react.js +++ b/src/dashboard/Data/Browser/BrowserTable.react.js @@ -574,30 +574,28 @@ export default class BrowserTable extends React.Component { 'overflow-x': this.props.isResizing ? 'hidden' : 'auto', }} > -
- checked).length === - this.props.data.length - } - selectAll={checked => - this.props.data.forEach(({ id }) => this.props.selectRow(id, checked)) - } - headers={headers} - updateOrdering={this.props.updateOrdering} - readonly={!!this.props.relation || !!this.props.isUnique} - handleDragDrop={this.props.handleHeaderDragDrop} - onResize={this.props.handleResize} - onAddColumn={this.props.onAddColumn} - preventSchemaEdits={this.context.preventSchemaEdits} - isDataLoaded={!!this.props.data} - setSelectedObjectId={this.props.setSelectedObjectId} - setCurrent={this.props.setCurrent} - /> - {table} -
+ checked).length === + this.props.data.length + } + selectAll={checked => + this.props.data.forEach(({ id }) => this.props.selectRow(id, checked)) + } + headers={headers} + updateOrdering={this.props.updateOrdering} + readonly={!!this.props.relation || !!this.props.isUnique} + handleDragDrop={this.props.handleHeaderDragDrop} + onResize={this.props.handleResize} + onAddColumn={this.props.onAddColumn} + preventSchemaEdits={this.context.preventSchemaEdits} + isDataLoaded={!!this.props.data} + setSelectedObjectId={this.props.setSelectedObjectId} + setCurrent={this.props.setCurrent} + /> + {table} ); } diff --git a/src/dashboard/Data/Browser/BrowserToolbar.react.js b/src/dashboard/Data/Browser/BrowserToolbar.react.js index f6b0057443..cfd1c51083 100644 --- a/src/dashboard/Data/Browser/BrowserToolbar.react.js +++ b/src/dashboard/Data/Browser/BrowserToolbar.react.js @@ -81,7 +81,7 @@ const BrowserToolbar = ({ isPanelVisible, classwiseCloudFunctions, appId, - appName + appName, }) => { const selectionLength = Object.keys(selection).length; const isPendingEditCloneRows = editCloneRows && editCloneRows.length > 0; @@ -279,7 +279,7 @@ const BrowserToolbar = ({ isPanelVisible={isPanelVisible} classwiseCloudFunctions={classwiseCloudFunctions} appId={appId} - appName = {appName} + appName={appName} > {onAddRow && ( diff --git a/src/dashboard/Data/Browser/DataBrowser.react.js b/src/dashboard/Data/Browser/DataBrowser.react.js index fbc7c6968a..9747a699b6 100644 --- a/src/dashboard/Data/Browser/DataBrowser.react.js +++ b/src/dashboard/Data/Browser/DataBrowser.react.js @@ -87,7 +87,7 @@ export default class DataBrowser extends React.Component { allClassesSchema: this.getAllClassesSchema(props.schema, props.classes), selectedCells: { list: new Set(), rowStart: -1, rowEnd: -1, colStart: -1, colEnd: -1 }, firstSelectedCell: null, - selectedData: [] + selectedData: [], }); } else if ( Object.keys(props.columns).length !== Object.keys(this.props.columns).length || @@ -103,7 +103,11 @@ export default class DataBrowser extends React.Component { this.setState({ order }); } if (props && props.className) { - if (!props.classwiseCloudFunctions?.[`${props.app.applicationId}${props.appName}`]?.[props.className]) { + if ( + !props.classwiseCloudFunctions?.[`${props.app.applicationId}${props.appName}`]?.[ + props.className + ] + ) { this.setState({ isPanelVisible: false }); this.setState({ selectedObjectId: undefined }); } @@ -133,10 +137,10 @@ export default class DataBrowser extends React.Component { ) { this.setState({ selectedObjectId: undefined, - showAggregatedData: false + showAggregatedData: false, }); this.props.setAggregationPanelData({}); - if(this.props.errorAggregatedData != {}){ + if (this.props.errorAggregatedData != {}) { this.props.setErrorAggregatedData({}); } } @@ -189,16 +193,20 @@ export default class DataBrowser extends React.Component { if (!this.state.isPanelVisible) { this.props.setAggregationPanelData({}); this.props.setLoading(false); - if(this.props.errorAggregatedData != {}){ + if (this.props.errorAggregatedData != {}) { this.props.setErrorAggregatedData({}); } } if (!this.state.isPanelVisible && this.state.selectedObjectId) { - if(this.props.errorAggregatedData != {}){ + if (this.props.errorAggregatedData != {}) { this.props.setErrorAggregatedData({}); } - this.props.callCloudFunction(this.state.selectedObjectId, this.props.className,this.props.app.applicationId); + this.props.callCloudFunction( + this.state.selectedObjectId, + this.props.className, + this.props.app.applicationId + ); } } @@ -229,7 +237,7 @@ export default class DataBrowser extends React.Component { selectedObjectId: undefined, }); this.props.setAggregationPanelData({}); - if(this.props.errorAggregatedData != {}){ + if (this.props.errorAggregatedData != {}) { this.props.setErrorAggregatedData({}); } } @@ -360,11 +368,15 @@ export default class DataBrowser extends React.Component { }, }); this.setState({ - selectedObjectId:this.props.data[this.state.current.row].id, - showAggregatedData:true - }) - if(prevObjectID !== this.state.selectedObjectId && this.state.isPanelVisible){ - this.props.callCloudFunction(this.state.selectedObjectId,this.props.className,this.props.app.applicationId) + selectedObjectId: this.props.data[this.state.current.row].id, + showAggregatedData: true, + }); + if (prevObjectID !== this.state.selectedObjectId && this.state.isPanelVisible) { + this.props.callCloudFunction( + this.state.selectedObjectId, + this.props.className, + this.props.app.applicationId + ); } e.preventDefault(); break; @@ -405,7 +417,11 @@ export default class DataBrowser extends React.Component { showAggregatedData: true, }); if (prevObjectID !== this.state.selectedObjectId && this.state.isPanelVisible) { - this.props.callCloudFunction(this.state.selectedObjectId, this.props.className,this.props.app.applicationId); + this.props.callCloudFunction( + this.state.selectedObjectId, + this.props.className, + this.props.app.applicationId + ); } e.preventDefault(); @@ -624,8 +640,8 @@ export default class DataBrowser extends React.Component { setErrorAggregatedData={this.props.setErrorAggregatedData} setSelectedObjectId={this.setSelectedObjectId} selectedObjectId={this.state.selectedObjectId} - appName = {this.props.appName} - className = {this.props.className} + appName={this.props.appName} + className={this.props.className} /> @@ -660,7 +676,7 @@ export default class DataBrowser extends React.Component { togglePanel={this.togglePanelVisibility} isPanelVisible={this.state.isPanelVisible} appId={this.props.app.applicationId} - appName = {this.props.appName} + appName={this.props.appName} {...other} /> diff --git a/src/dashboard/Data/Browser/ExecuteScriptRowsDialog.react.js b/src/dashboard/Data/Browser/ExecuteScriptRowsDialog.react.js index 5daf2c3e9e..8fa7709bbc 100644 --- a/src/dashboard/Data/Browser/ExecuteScriptRowsDialog.react.js +++ b/src/dashboard/Data/Browser/ExecuteScriptRowsDialog.react.js @@ -54,7 +54,11 @@ export default class ExecuteScriptRowsDialog extends React.Component { open icon="gears" iconSize={40} - title={selectionLength > 1 ? `Run script on ${selectionLength} selected rows` : 'Run script on selected row'} + title={ + selectionLength > 1 + ? `Run script on ${selectionLength} selected rows` + : 'Run script on selected row' + } submitText="Run" inProgressText={`Executed ${processedScripts} of ${selectionLength} rows`} onClose={this.props.onCancel} diff --git a/src/dashboard/Data/Config/Config.react.js b/src/dashboard/Data/Config/Config.react.js index c130791561..02d3f6d5fc 100644 --- a/src/dashboard/Data/Config/Config.react.js +++ b/src/dashboard/Data/Config/Config.react.js @@ -244,7 +244,7 @@ class Config extends TableView { return data; } - saveParam({ name, value, type, masterKeyOnly }) { + saveParam({ name, value, type, masterKeyOnly }) { this.props.config .dispatch(ActionTypes.SET, { param: name, @@ -257,28 +257,39 @@ class Config extends TableView { const limit = this.context.cloudConfigHistoryLimit; const applicationId = this.context.applicationId; let transformedValue = value; - if(type === 'Date') { - transformedValue = {__type: 'Date', iso: value}; + if (type === 'Date') { + transformedValue = { __type: 'Date', iso: value }; } - if(type === 'File') { - transformedValue = {name: value._name, url: value._url}; + if (type === 'File') { + transformedValue = { name: value._name, url: value._url }; } const configHistory = localStorage.getItem(`${applicationId}_configHistory`); - if(!configHistory) { - localStorage.setItem(`${applicationId}_configHistory`, JSON.stringify({ - [name]: [{ - time: new Date(), - value: transformedValue - }] - })); + if (!configHistory) { + localStorage.setItem( + `${applicationId}_configHistory`, + JSON.stringify({ + [name]: [ + { + time: new Date(), + value: transformedValue, + }, + ], + }) + ); } else { const oldConfigHistory = JSON.parse(configHistory); - localStorage.setItem(`${applicationId}_configHistory`, JSON.stringify({ - ...oldConfigHistory, - [name]: !oldConfigHistory[name] ? - [{time: new Date(), value: transformedValue}] - : [{time: new Date(), value: transformedValue}, ...oldConfigHistory[name]].slice(0, limit || 100) - })); + localStorage.setItem( + `${applicationId}_configHistory`, + JSON.stringify({ + ...oldConfigHistory, + [name]: !oldConfigHistory[name] + ? [{ time: new Date(), value: transformedValue }] + : [ + { time: new Date(), value: transformedValue }, + ...oldConfigHistory[name], + ].slice(0, limit || 100), + }) + ); } }, () => { @@ -291,10 +302,11 @@ class Config extends TableView { this.props.config.dispatch(ActionTypes.DELETE, { param: name }).then(() => { this.setState({ showDeleteParameterDialog: false }); }); - const configHistory = localStorage.getItem('configHistory') && JSON.parse(localStorage.getItem('configHistory')); - if(configHistory) { + const configHistory = + localStorage.getItem('configHistory') && JSON.parse(localStorage.getItem('configHistory')); + if (configHistory) { delete configHistory[name]; - if(Object.keys(configHistory).length === 0) { + if (Object.keys(configHistory).length === 0) { localStorage.removeItem('configHistory'); } else { localStorage.setItem('configHistory', JSON.stringify(configHistory)); diff --git a/src/dashboard/Data/Config/ConfigDialog.react.js b/src/dashboard/Data/Config/ConfigDialog.react.js index 447ba6a2a8..1f11799f62 100644 --- a/src/dashboard/Data/Config/ConfigDialog.react.js +++ b/src/dashboard/Data/Config/ConfigDialog.react.js @@ -196,23 +196,27 @@ export default class ConfigDialog extends React.Component { ))} ); - const configHistory = localStorage.getItem(`${this.context.applicationId}_configHistory`) && JSON.parse(localStorage.getItem(`${this.context.applicationId}_configHistory`))[this.state.name]; + const configHistory = + localStorage.getItem(`${this.context.applicationId}_configHistory`) && + JSON.parse(localStorage.getItem(`${this.context.applicationId}_configHistory`))[ + this.state.name + ]; const handleIndexChange = index => { - if(this.state.type === 'Date'){ + if (this.state.type === 'Date') { return; } let value = configHistory[index].value; - if(this.state.type === 'File'){ + if (this.state.type === 'File') { const fileJSON = { __type: 'File', name: value.name, - url: value.url + url: value.url, }; const file = Parse.File.fromJSON(fileJSON); this.setState({ selectedIndex: index, value: file }); return; } - if(typeof value === 'object'){ + if (typeof value === 'object') { value = JSON.stringify(value); } this.setState({ selectedIndex: index, value }); @@ -281,8 +285,7 @@ export default class ConfigDialog extends React.Component { /> ) : null } - { - configHistory?.length > 0 && + {configHistory?.length > 0 && ( } input={ - - {configHistory.map((value, i) => + + {configHistory.map((value, i) => ( - )} + ))} } className={styles.addColumnToggleWrapper} /> - } + )} ); } diff --git a/src/dashboard/Settings/Security/Security.react.js b/src/dashboard/Settings/Security/Security.react.js index 19b0f3ad28..34615d70f8 100644 --- a/src/dashboard/Settings/Security/Security.react.js +++ b/src/dashboard/Settings/Security/Security.react.js @@ -40,16 +40,20 @@ export default class Security extends TableView { renderRow(security) { return ( - + {security.check} - {security.i !== undefined ? '' : (security.status === 'success' ? '✅' : '❌')} + {security.i !== undefined ? '' : security.status === 'success' ? '✅' : '❌'} {security.issue} - + {security.solution} @@ -74,7 +78,15 @@ export default class Security extends TableView { } renderEmpty() { - return {this.state.error}} icon="gears" cta="Reload" action={() => this.reload()} />; + return ( + {this.state.error}} + icon="gears" + cta="Reload" + action={() => this.reload()} + /> + ); } tableData() { @@ -83,18 +95,18 @@ export default class Security extends TableView { data.push({ check: 'Overall status', status: this.state.data.state, - header: true + header: true, }), - data.push({i: -1}) + data.push({ i: -1 }); } for (let i = 0; i < this.state.data?.groups?.length; i++) { - const group = this.state.data.groups[i] + const group = this.state.data.groups[i]; data.push({ check: group.name, status: group.state, issue: '', solution: '', - header: true + header: true, }); for (const check of group.checks) { data.push({ @@ -105,7 +117,7 @@ export default class Security extends TableView { }); } if (i !== this.state.data.groups.length - 1) { - data.push({i}); + data.push({ i }); } } return data; @@ -113,11 +125,13 @@ export default class Security extends TableView { async reload() { if (!this.context.enableSecurityChecks) { - this.setState({ error: 'Enable Dashboard option `enableSecurityChecks` to run security check.' }); + this.setState({ + error: 'Enable Dashboard option `enableSecurityChecks` to run security check.', + }); return; } this.setState({ loading: true }); - const result = await Parse._request('GET', 'security', {}, { useMasterKey: true }).catch((e) => { + const result = await Parse._request('GET', 'security', {}, { useMasterKey: true }).catch(e => { this.setState({ error: e?.message || e }); }); this.setState({ loading: false, data: result?.report || {} }); diff --git a/src/lib/ParseApp.js b/src/lib/ParseApp.js index f46755f084..18e4ab02bc 100644 --- a/src/lib/ParseApp.js +++ b/src/lib/ParseApp.js @@ -49,7 +49,7 @@ export default class ParseApp { scripts, classPreference, enableSecurityChecks, - cloudConfigHistoryLimit + cloudConfigHistoryLimit, }) { this.name = appName; this.createdAt = created_at ? new Date(created_at) : new Date();