Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/client/app/components/csv/MetersCSVUploadComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { selectSelectedLanguage } from '../../redux/slices/appStateSlice'; //import for internationlization
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment can go but if you want it to stay then please place above the code line. Moving the comment applies to some other lines too. Also, OED would like a blank line after the MPL header comment. These apply to other files too.

import * as React from 'react';
import { Button, Col, Container, Form, FormGroup, Input, Label, Row } from 'reactstrap';
import { MetersCSVUploadPreferences } from '../../types/csvUploadForm';
Expand Down Expand Up @@ -45,6 +45,7 @@ export default function MetersCSVUploadComponent() {
// to the attempted destination URL.
const navigate = useNavigate();

const language = useAppSelector(selectSelectedLanguage); //get user's selected language for i18n
const [meterData, setMeterData] = React.useState<MetersCSVUploadPreferences>(MetersCSVUploadDefaults);
const [selectedFile, setSelectedFile] = React.useState<File | null>(null);
const [isValidFileType, setIsValidFileType] = React.useState<boolean>(false);
Expand Down Expand Up @@ -106,7 +107,8 @@ export default function MetersCSVUploadComponent() {
if (selectedFile) {
// show spinner before calling api, then stop it immediately after
setShowSpinner(true);
const { success, message } = await submitMeters(meterData, selectedFile, dispatch);
//pass language for server side translations
const { success, message } = await submitMeters(meterData, selectedFile, dispatch, language);
setShowSpinner(false);
if (success) {
showSuccessNotification(message);
Expand Down
6 changes: 3 additions & 3 deletions src/client/app/components/csv/ReadingsCSVUploadComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { selectSelectedLanguage } from '../../redux/slices/appStateSlice';//import for internationalization
import { range } from 'lodash';
import * as React from 'react';
import { useEffect, useState } from 'react';
Expand Down Expand Up @@ -32,7 +32,6 @@ import { useBlocker, useNavigate } from 'react-router-dom';
*/
export default function ReadingsCSVUploadComponent() {
const translate = useTranslate();

// boolean that updates if any change is made to any readings modal
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
const [showUnsavedWarning, setShowUnsavedWarning] = useState(false);
Expand All @@ -50,6 +49,7 @@ export default function ReadingsCSVUploadComponent() {
// to the attempted destination URL.
const navigate = useNavigate();

const language = useAppSelector(selectSelectedLanguage);//get user's selected language i18n
const dispatch = useAppDispatch();
// Check for admin status
const isAdmin = useAppSelector(selectIsAdmin);
Expand Down Expand Up @@ -194,7 +194,7 @@ export default function ReadingsCSVUploadComponent() {
if (selectedFile) {
// show spinner before calling api, then stop it immediately after
setShowSpinner(true);
const { success, message } = await submitReadings(readingsData, selectedFile, dispatch);
const { success, message } = await submitReadings(readingsData, selectedFile, dispatch, language); // passed language
setShowSpinner(false);
if (success) {
showSuccessNotification(message);
Expand Down
20 changes: 9 additions & 11 deletions src/client/app/utils/api/UploadCSVApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ interface ApiResponse {
}

export const submitReadings = async (uploadPreferences: ReadingsCSVUploadPreferences, readingsFile: File,
dispatch: Dispatch): Promise<ApiResponse> => {
dispatch: Dispatch, language: string): Promise<ApiResponse> => { //added language parameter for i18n
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be the type of the enum discussed in another comment? If so, I don't know if it should ripple to other places.

const backend = new ApiBackend();
const formData = new FormData();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you put back the comment that was removed from the next line. I realize no conversion is being done here but I think it was a warning about usage.

// The Boolean values in state must be converted to the submitted values of yes and no.
const uploadPreferencesForm: ReadingsCSVUploadPreferences = {
...uploadPreferences,
gzip: uploadPreferences.gzip,
Expand All @@ -37,11 +36,12 @@ export const submitReadings = async (uploadPreferences: ReadingsCSVUploadPrefere
for (const [preference, value] of Object.entries(uploadPreferencesForm)) {
formData.append(preference, value.toString());
}
formData.append('csvfile', readingsFile); // It is important for the server that the file is attached last.
formData.append('csvfile', readingsFile);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put back the removed comment. It can go above the line of code (as it should have been).


let message = '';
try {
message = await backend.doPostRequest<string>('/api/csv/readings', formData);
//sends langauge preference to server
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

langauge is misspelled.

message = await backend.doPostRequest<string>('/api/csv/readings', formData, {}, { 'Accept-Language': language });
dispatch(baseApi.util.invalidateTags(['Readings']));
return { success: true, message: message };
} catch (error) {
Expand All @@ -50,10 +50,9 @@ export const submitReadings = async (uploadPreferences: ReadingsCSVUploadPrefere
};

export const submitMeters = async (uploadPreferences: MetersCSVUploadPreferences, metersFile: File,
dispatch: Dispatch): Promise<ApiResponse> => {
dispatch: Dispatch, language: string): Promise<ApiResponse> => { //added language for i18n
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove all the comments saying you added something. It is okay to put in comments about what code is doing (as needed) but this one is associated with now and not for all time. I think it is okay to just remove.

const backend = new ApiBackend();
const formData = new FormData();
// The Boolean values in state must be converted to the submitted values of yes and no.
const uploadPreferencesForm: CSVUploadPreferences = {
...uploadPreferences,
gzip: uploadPreferences.gzip,
Expand All @@ -63,15 +62,14 @@ export const submitMeters = async (uploadPreferences: MetersCSVUploadPreferences
for (const [preference, value] of Object.entries(uploadPreferencesForm)) {
formData.append(preference, value.toString());
}
formData.append('csvfile', metersFile); // It is important for the server that the file is attached last.
formData.append('csvfile', metersFile);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, add back in comment.


try {
const response = await backend.doPostRequest<string>('/api/csv/meters', formData);
// Meter Data was sent to the DB, invalidate meters for now
//send langauge preference to server
const response = await backend.doPostRequest<string>('/api/csv/meters', formData, {}, { 'Accept-Language': language });
dispatch(baseApi.util.invalidateTags(['MeterData']));
// meters were invalidated so all meter changes will now reflect in Redux state, now return
return { success: true, message: response };
} catch (error) {
return { success: false, message: error.response.data };
}
};
};
45 changes: 33 additions & 12 deletions src/server/routes/csv.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
* meter and readings data.
*/


const { translate, getLanguageFromRequest } = require('../translations/translate');

const moment = require('moment');
const crypto = require('crypto');
const express = require('express');
Expand Down Expand Up @@ -101,13 +104,19 @@ router.use(function (req, res, next) {
// We need this extra middleware because multer does not provide an option to guard against the case where no file is uploaded.
router.use(function (req, res, next) {
if (!req.file) {
failure(req, res, new CSVPipelineError('No csv file was uploaded. A csv file must be submitted via the csvfile parameter.'));
//failure(req, res, new CSVPipelineError('No csv file was uploaded. A csv file must be submitted via the csvfile parameter.'));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the commented out code is the old code that can now be removed. Also, the indenting seems off and the following lines.

const language = getLanguageFromRequest(req);
const errorMessage = translate('csv.upload.error.no.file', language);
failure(req, res, new CSVPipelineError(errorMessage));

} else {
next();
}
});

router.post('/meters', validateMetersCsvUploadParams, async (req, res) => {
const language = getLanguageFromRequest(req);
const t = (key) => translate(key, language);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using very short names is prone to error. Could you refactor into a better name please.

const isGzip = normalizeBoolean(req.body.gzip);
const uploadedFilepath = req.file.path;
let csvFilepath;
Expand All @@ -120,15 +129,16 @@ router.post('/meters', validateMetersCsvUploadParams, async (req, res) => {
fileBuffer = zlib.gunzipSync(fileBuffer);
// We expect this directory to have been created by this stage of the pipeline.
const dir = `${__dirname}/../tmp/uploads/csvPipeline`;
csvFilepath = await saveCsv(fileBuffer, 'meters', dir);
csvFilepath = await saveCsv(fileBuffer, 'meters', dir,language); // pass lagnauge for translated error messages
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment above line and spelling issue. Also, formatting off (space missing after comma). Finally, I don't see language accepted in the called function.

log.info(`The unzipped file ${csvFilepath} was created to upload meters csv data`);
} else {
csvFilepath = uploadedFilepath;
}

const conn = getConnection();
await uploadMeters(req, res, csvFilepath, conn);
success(req, res, 'Successfully inserted the meters.');
await uploadMeters(req, res, csvFilepath, conn, language);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I'm going to stop commenting on this but I again don't see the new argument used in the calling function.

//success(req, res, 'Successfully inserted the meters.');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As other comment, remove old code.

success(req, res, t('csv.upload.meters.success'));
} catch (error) {
failure(req, res, error);

Expand All @@ -150,9 +160,15 @@ router.post('/meters', validateMetersCsvUploadParams, async (req, res) => {
});
}
}
});
});

router.post('/readings', validateReadingsCsvUploadParams, async (req, res) => {


Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is some space indenting but OED wants tabs. Also, there are extra blank lines. Finally see comment above about name.

const language = getLanguageFromRequest(req);
const t = (key) => translate(key, language);


const isGzip = normalizeBoolean(req.body.gzip);
const isRefreshReadings = normalizeBoolean(req.body.refreshReadings);
const uploadedFilepath = req.file.path;
Expand All @@ -168,13 +184,13 @@ router.post('/readings', validateReadingsCsvUploadParams, async (req, res) => {
fileBuffer = zlib.gunzipSync(fileBuffer);
// We expect this directory to have been created by this stage of the pipeline.
const dir = `${__dirname}/../tmp/uploads/csvPipeline`;
csvFilepath = await saveCsv(fileBuffer, 'readings', dir);
csvFilepath = await saveCsv(fileBuffer, 'readings', dir, language);
log.info(`The unzipped file ${csvFilepath} was created to upload readings csv data`);
} else {
csvFilepath = uploadedFilepath;
}
const conn = getConnection();
({ isAllReadingsOk, msgTotal } = await uploadReadings(req, res, csvFilepath, conn));
({ isAllReadingsOk, msgTotal } = await uploadReadings(req, res, csvFilepath, conn, language));
if (isRefreshReadings) {
// Refresh readings so show when daily data is used.
await refreshAllReadingViews();
Expand Down Expand Up @@ -202,14 +218,19 @@ router.post('/readings', validateReadingsCsvUploadParams, async (req, res) => {
}
let message;
if (isAllReadingsOk) {
message = '<h2>It looks like the insert of the readings was a success.</h2>'
//message = '<h2>It looks like the insert of the readings was a success.</h2>'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments above about commented out code. Also, the indenting is off.

//if (msgTotal !== '') {
// message += '<h3>However, note that the processing of the readings returned these warning(s):</h3>' + msgTotal;
message = `<h2>${t('csv.upload.readings.success.complete')}</h2>`;
if (msgTotal !== '') {
message += '<h3>However, note that the processing of the readings returned these warning(s):</h3>' + msgTotal;
}
message += `<h3>${t('csv.upload.readings.success.with.warnings')}</h3>` + msgTotal;
}
success(req, res, message);
} else {
message = '<h2>It looks like the insert of the readings had issues with some or all of the readings where' +
' the processing of the readings returned these warning(s)/error(s):</h2>' + msgTotal;
//message = '<h2>It looks like the insert of the readings had issues with some or all of the readings where' +
//' the processing of the readings returned these warning(s)/error(s):</h2>' + msgTotal;
message = `<h2>${t('csv.upload.readings.error.has.issues')}</h2>` + msgTotal;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove new blank line.

failure(req, res, message);
}
});
Expand Down
5 changes: 3 additions & 2 deletions src/server/services/pipeline-in-progress/loadCsvInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,15 @@ async function loadCsvInput(
honorDst = false,
relaxedParsing = false,
useMeterZone = false,
warnOnCumulativeReset = false
warnOnCumulativeReset = false,
language = 'en' //added for internationalization: language preference from user
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment above code. Also, maybe add why en was used here.

) {
try {
const dataRows = await readCsv(filePath, headerRow);
return loadArrayInput(dataRows, meterID, mapRowToModel, timeSort, readingRepetition,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the new argument of language as actually added to the function being called.

isCumulative, cumulativeReset, cumulativeResetStart, cumulativeResetEnd,
readingGap, readingLengthVariation, isEndOnly, shouldUpdate, conditionSet, conn,
honorDst, relaxedParsing, useMeterZone, warnOnCumulativeReset);
honorDst, relaxedParsing, useMeterZone, warnOnCumulativeReset, language);
} catch (err) {
log.error(`Error updating meter ${meterID} with data from ${filePath}: ${err}`, err);
}
Expand Down
Loading
Loading