Skip to content

Commit

Permalink
Refactor code to ensure dataCube has a timeAttribute
Browse files Browse the repository at this point in the history
  • Loading branch information
mirkan1 committed May 7, 2024
1 parent 0db6564 commit 7e9e0a4
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,8 @@ export class CubeView extends React.Component<CubeViewProps, CubeViewState> {

componentWillMount() {
const { hash, dataCube, initTimekeeper } = this.props;
if (!dataCube) {
throw new Error("Data cube is required.");
}
if (!dataCube) throw new Error("Data cube is required.");
if (!dataCube.timeAttribute) throw new Error("DataCube must have a timeAttribute");

this.setState({
timekeeper: initTimekeeper || Timekeeper.EMPTY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ export class Essence extends ImmutableRecord<EssenceValue>(defaultEssence) {
} = parameters;

if (!dataCube) throw new Error("Essence must have a dataCube");
if (!dataCube.timeAttribute) throw new Error("DataCube must have a timeAttribute");

const { visResolve, visualization, splits } = resolveVisualization(parameters);

Expand Down
20 changes: 10 additions & 10 deletions client/app/pages/models/ModelsList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ function ModelsListActions({ model, editModel, editConfigModel, deleteModel }) {
}
}
return <>
<Button type="ghost" icon="setting" className="m-2 inline" onClick={() => editConfigModel(model)}>
Edit config
</Button>
<Button type="dashed" icon="edit" className="m-2 inline" onClick={() => editModel(model)}>
Edit
</Button>
<Button type="danger" icon="delete" className="m-2 inline" onClick={event => handleDeleteModel(event)}>
Delete
</Button>
</>;
<Button type="ghost" icon="setting" className="m-2 inline" onClick={() => editConfigModel(model)}>
Edit config
</Button>
<Button type="dashed" icon="edit" className="m-2 inline" onClick={() => editModel(model)}>
Edit
</Button>
<Button type="danger" icon="delete" className="m-2 inline" onClick={event => handleDeleteModel(event)}>
Delete
</Button>
</>;
}

ModelsListActions.propTypes = {
Expand Down
6 changes: 3 additions & 3 deletions client/app/pages/models/components/EditableModelConfig.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,14 @@ export default function EditableModelConfig({model, saveConfig}) {
const handleSaveConfig = (callback) => {
const yamlContent = item;
if (!yamlContent.includes("timeAttribute") || yamlContent.includes("timeAttribute: null")) {
alert("your time attribute variable is null");
alert("timeAttribute cannot be null");
return;
}
const timeAttribute = yamlContent.split("timeAttribute: ")[1].split("\n")[0];
const attributes = yamlContent.split("attributes:")[1].split("dimensions:")[0];
// if timeAttribute is not in attributes, then alert
if (!attributes.includes(timeAttribute)) {
alert("your time attribute variable is not in attributes list");
alert("timeAttribute is not in the attributes list");
return;
}
// if timeAttribute's type is not TIME then alert
Expand All @@ -231,7 +231,7 @@ export default function EditableModelConfig({model, saveConfig}) {
if (attribute.includes(timeAttribute)) {
const attributeType = attribute.split("type: ")[1].split("\n")[0];
if (attributeType !== "TIME") {
alert("your time attribute variable's type is not a time or timestamp");
alert("timeAttribute must be time or timestamp");
return;
}
}
Expand Down
66 changes: 48 additions & 18 deletions client/app/pages/reports/components/ReportPageHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -267,28 +267,53 @@ export default function ReportPageHeader(props) {
[report, props.onChange, updateReport]
);

const getModel = (modelId) => {
return models.find(m => m.id === modelId);
}

const getModelDataCube = async (modelId) => {
const settings = await getSettings(modelId);
const model = getModel(modelId);
if (!model || !settings) return {};
const dataCubes = settings.appSettings.dataCubes
return dataCubes.find(m => m.name === model.table);
}


const getSettings = async (modelId) => {
var settings;
if (report.isJustLanded) {
settings = { appSettings: report.appSettings, timekeeper: {} };
} else {
settings = await Model.getReporterConfig(modelId);
}
return settings;
}

const handleModelChange = useCallback(
async (modelId, signal) => {
try {
var res;
if (report.isJustLanded) {
res = { appSettings: report.appSettings, timekeeper: {} };
} else {
res = await Model.getReporterConfig(modelId);
const modelDataCube = await getModelDataCube(modelId);
if (!modelDataCube.timeAttribute) {
// Revert previous changes like make selected model name to previous one and so on
return updateReport({}, { successMessage: null, errorMessage: "DataCube must have a timeAttribute" }); // show message only on error
}
const model = models.find(m => m.id === modelId);
const settings = await getSettings(modelId);
const model = getModel(modelId);
if (model && model.id !== report.model_id) {
replaceHash(model, window.location.hash.split("/4/")[1]);
}
recordEvent("update", "report", report.id, { modelId });
var updates = {
model_id: modelId,
appSettings: res.appSettings,
timekeeper: res.timekeeper,
appSettings: settings.appSettings,
timekeeper: settings.timekeeper,
isJustLanded: false,
};
if (report.data_source_id || selectedDataSource) {
updates.data_source_id = report.data_source_id || selectedDataSource
if (report.data_source_id) {
updates.data_source_id = report.data_source_id;
} else if (selectedDataSource) {
updates.data_source_id = selectedDataSource;
}
if (signal && signal.aborted) return;
props.onChange(extend(report.clone(), { ...updates }));
Expand Down Expand Up @@ -434,11 +459,13 @@ export default function ReportPageHeader(props) {
const abortController = new AbortController();
const signal = abortController.signal;

const setData = async (dataSourceId, model_id) => {
const setData = async (dataSourceId, modelId) => {
if (signal.aborted) return;
await handleDataSourceChange(dataSourceId, signal);
if (signal.aborted) return;
await handleModelChange(model_id, signal)
if (signal.aborted) return;
const modelDataCube = await getModelDataCube(modelId);
if (!modelDataCube.timeAttribute) return null;
await handleModelChange(modelId, signal)
.then(() => {
if (signal.aborted) return;
setTimeout(() => {
Expand Down Expand Up @@ -475,12 +502,15 @@ export default function ReportPageHeader(props) {
}, [dataSourcesLoaded]);

useEffect(() => {
if (modelsLoaded && !selectedModel) {
if (models.length) {
handleModelChange(models[0].id);
replaceHash(models[0], window.location.hash.split("/4/")[1]);
}
const firstEncounterModelSetter = async (report, models) => {
const modelId = models[0].id;
const modelDataCube = await getModelDataCube(modelId);
if (!modelDataCube.timeAttribute) return null;
handleModelChange(modelId);
const model = getModel(modelId);
replaceHash(model, window.location.hash.split("/4/")[1]);
}
if (modelsLoaded && !selectedModel && models.length) firstEncounterModelSetter(report, models);
}, [modelsLoaded]);

return (
Expand Down
22 changes: 14 additions & 8 deletions client/app/pages/reports/hooks/useUpdateReport.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,15 @@ function confirmOverwrite() {
});
}

function showNotification(error) {
const notificationOptions = {};
if (error instanceof SaveReportConflictError) {
notificationOptions.duration = null;
}
if (!error || error.message === 'No changes made') return;
notification.error(error.message, error.detailedMessage, notificationOptions);
}

function doSaveReport(data, { canOverwrite = false, errorMessage = "Report could not be saved" } = {}) {
if (isObject(data.options) && data.options.parameters) {
data.options = {
Expand Down Expand Up @@ -85,6 +94,10 @@ export default function useUpdateReport(report, onChange) {
// Don't save new report with partial data
if (report.isNew && report.isNew()) {
handleChange(extend(report.clone(), data));
if (errorMessage) {
const error = new SaveReportError(errorMessage);
showNotification(error);
}
return;
}
data = { ...data, id: report.id, version: report.version };
Expand Down Expand Up @@ -124,14 +137,7 @@ export default function useUpdateReport(report, onChange) {
)
);
})
.catch(error => {
const notificationOptions = {};
if (error instanceof SaveReportConflictError) {
notificationOptions.duration = null;
}
if (!error || error.message === 'No changes made') return;
notification.error(error.message, error.detailedMessage, notificationOptions);
});
.catch(error => showNotification(error));
},
[report, handleChange]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ export class Essence extends ImmutableRecord<EssenceValue>(defaultEssence) {
} = parameters;

if (!dataCube) throw new Error("Essence must have a dataCube");
if (!dataCube.timeAttribute) throw new Error("DataCube must have a timeAttribute");

const { visResolve, visualization, splits } = resolveVisualization(parameters);

Expand Down

0 comments on commit 7e9e0a4

Please # to comment.