-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3bc70c8
commit 9d137ed
Showing
9 changed files
with
488 additions
and
165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* When importing RPE values, other apps might allow diferent RPE values, but hee in weightxreps we only allow | ||
* RPE from 6 to 10 and only .5 as "in between" | ||
* | ||
* @param {number} rpeValue | ||
* @returns {number} the RPE in the valid range WXR logs accept | ||
*/ | ||
export function fixRPE( rpeValue ) | ||
{ | ||
if( isNaN(rpeValue) || rpeValue<6 || rpeValue>10 ) | ||
{ | ||
return 0; | ||
} | ||
|
||
return Math.round(rpeValue * 2) / 2; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
import { ImportFromWXR } from "./import-from-wxr" | ||
import Joi from "joi"; | ||
|
||
|
||
|
||
/** | ||
* Config for a CVS improter | ||
* | ||
* @typedef {Object} CVSParserConfig | ||
* @property {bool} askWeightUnitToUser if we should ask the user for the weight unit used in the file | ||
* @property {( firstRow:any, assumeUseKg:boolean )=>Object} startState Create the start state that will be used as initial state. | ||
* @property { (state:Object, row:any)=>void} processRow Process a row from the CVS | ||
* @property {Boolean} canContinueInCaseOfError if it can continue in case of error | ||
* @property {(state:Object)=>string} stateAsLog turns the state into a weightxreps log | ||
* @property {Joi.ObjectSchema<any>} schema Schema for a row | ||
* @property {boolean} verifyEachRow if true, every row will be verified against the schema, else, only the first one. | ||
*/ | ||
|
||
|
||
/** | ||
* Handles the importing of the CVS and uses the config to delegate the implementation of the details. | ||
* | ||
* @param {CVSParserConfig} config details on how to parse the cvs | ||
* @param {File} file the CVS file | ||
* @param {(status:string)=>void} informStatus Send informative text to this function so the user knows wtf is going on. | ||
* @returns {Promise<string>} The result is a workout log as if it was typed in the lovely workout editor of this site. | ||
*/ | ||
const formatCVS = async (config, file, informStatus) => { | ||
|
||
var usekg = true; | ||
|
||
if( config.askWeightUnitToUser === true ) | ||
{ | ||
informStatus("Are the weights are in kilograms?"); | ||
|
||
if( !window.confirm("WEIGHT UNIT\n\nThe weights in the file are in (kg)Kilograms? (If you cancel then (lbs)Pounds will be assumed)\n\nAccept = KG\nCancel = LB")) | ||
{ | ||
usekg = false; | ||
} | ||
} | ||
|
||
informStatus("Prepearing to parse cvs"); | ||
|
||
const Papa = await import(/* webpackChunkName: "papaparse" */"papaparse"); | ||
|
||
return new Promise(( resolve, reject )=>{ | ||
|
||
|
||
informStatus("Parsing starts..."); | ||
|
||
let log = ""; | ||
let rowsDone = 0; | ||
let abortedError; | ||
let ignoreErrors; | ||
let userWasPrompted = false; | ||
var state; | ||
let errorsIgnored = 0; | ||
|
||
Papa.parse(file, { | ||
delimiter:",", | ||
header:true, | ||
encoding:"utf-8", | ||
skipEmptyLines:"greedy", | ||
|
||
chunk: function(results, parser ) | ||
{ | ||
for (let i = 0; i < results.data.length; i++) | ||
{ | ||
const row = results.data[i]; | ||
|
||
try | ||
{ | ||
if( rowsDone==0 || config.verifyEachRow ) | ||
{ | ||
// | ||
// verify each row to make sure the schema matches what we expect... | ||
// | ||
let validationResult = config.schema.validate(row, {allowUnknown:true, presence:"required"}); | ||
if( validationResult.error ) //validate each row.... | ||
{ | ||
console.error(validationResult.error); | ||
throw new Error("Unexpected row format. Bad .csv mabe..."); | ||
} | ||
} | ||
|
||
if(!state) | ||
{ | ||
state = config.startState(row, usekg); | ||
} | ||
|
||
config.processRow( state, row ); | ||
} | ||
catch(e) | ||
{ | ||
if( config.canContinueInCaseOfError && !userWasPrompted ) | ||
{ | ||
userWasPrompted = true; | ||
|
||
if( window.confirm("WHAT TO DO?\n\nThere was an error parsing some portion(s) of the file. Do you wan't to ignore it and continue tyring to import the file?\n\nAccept = IGNORE ERRORS/ CONTINUE\nCancel = ABORT") ) | ||
{ | ||
ignoreErrors = true; | ||
} | ||
} | ||
|
||
if( ignoreErrors ) | ||
{ | ||
//nothing... | ||
errorsIgnored++; | ||
} | ||
else | ||
{ | ||
abortedError = e; | ||
parser.abort(); | ||
return; | ||
} | ||
} | ||
|
||
}; | ||
|
||
rowsDone+=results.data.length; | ||
informStatus(`Parsed ${rowsDone} rows...`); | ||
}, | ||
|
||
complete: ()=>{ | ||
|
||
if( abortedError ) | ||
{ | ||
reject(`The file you attempt to import has errors, can't proceed :( Details: ${abortedError.message}`); | ||
return; | ||
} | ||
|
||
try | ||
{ | ||
log = config.stateAsLog(state); | ||
} | ||
catch(e) | ||
{ | ||
reject( e.message ); | ||
return; | ||
} | ||
|
||
if( !log || log=="" ) | ||
{ | ||
reject("Nothing was imported, no data was found in the file."); | ||
return; | ||
} | ||
|
||
informStatus("Parsing complete..."); | ||
|
||
if( errorsIgnored>0 ) | ||
{ | ||
alert(`The cvs was parsed! But we skipped (${errorsIgnored}) rows with errors.\n %${ ((rowsDone-errorsIgnored)/rowsDone*100).toFixed(1) } of the cvs was parsed successfully.`); | ||
} | ||
|
||
resolve( log ); | ||
}, | ||
error: err => reject(`Error parsing cvs --> ${err.message}`) | ||
}); | ||
|
||
}); | ||
} | ||
|
||
|
||
/** | ||
* @param {{ config:CVSParserConfig, fileInputLabel:string }} param0 | ||
* @returns | ||
*/ | ||
export const ImportFromCVS = ({ config, fileInputLabel, fileInputFileExtensions })=>{ | ||
|
||
return <ImportFromWXR formatFile={ formatCVS.bind(null,config) } fileInputLabel={fileInputLabel} fileInputFileExtensions=".csv"/> | ||
} |
Oops, something went wrong.