diff --git a/view/admin/app.js b/view/admin/app.js index 04929e96dd..9ee6afe3a0 100644 --- a/view/admin/app.js +++ b/view/admin/app.js @@ -7,7 +7,7 @@ */ /** - * view/admin/index.js + * view/admin/app.js * * Passes store and history to the rendered Root element. */ diff --git a/view/admin/utils/getFormData.js b/view/admin/utils/getFormData.js index e7dd2b11f9..b804c8369a 100644 --- a/view/admin/utils/getFormData.js +++ b/view/admin/utils/getFormData.js @@ -35,10 +35,12 @@ function fromBooleanInput(inputs, jsonData) { for (let j = ZERO; j < arr.length; j++) { intArr.push(parseInt(arr[j], 10)); } + jsonData[inputs[i].name] = intArr; } } } + return jsonData; } @@ -56,8 +58,9 @@ function fromTextInput(inputs, jsonData, alterDataFunc) { const name = inputs[i].name; const lastIndex = name.lastIndexOf('_'); const key = name.substring(ZERO, lastIndex); + // get the number after _ - const index = parseInt(name.substring(lastIndex+ONE, name.length), 10); + const index = parseInt(name.substring(lastIndex + ONE, name.length), 10); if (inputs[i].getAttribute('type') === 'text' && key) { delete jsonData[name]; // ie. okRange_1 @@ -67,10 +70,12 @@ function fromTextInput(inputs, jsonData, alterDataFunc) { if (!jsonData[key]) { jsonData[key] = []; } + jsonData[key][index] = intVal; // ie. 1, 2, 12.45 } } } + return jsonData; } @@ -80,9 +85,19 @@ function fromTextInput(inputs, jsonData, alterDataFunc) { * @returns {Object} with keys to particular DOM elements */ function getInputsAndSelects(form) { - const inputs = form.getElementsByTagName('input'); + let inputs = []; + const allInputs = form.getElementsByTagName('input'); const selects = form.getElementsByTagName('select'); const fieldSets = form.getElementsByTagName('fieldset'); + for (let i = allInputs.length - 1; i >= 0; i--) { + for (let j = fieldSets.length - 1; j >= 0; j--) { + // add to array if input is not in any fieldset + if (!fieldSets[j].contains(allInputs[i])) { + inputs.push(allInputs[i]); + } + } + } + return { inputs, fieldSets, inputsAndSelects: [...inputs, ...selects] }; } @@ -99,9 +114,11 @@ function addData(fieldSets) { let dataObject = {}; dataObject[objName] = []; const rows = fieldSets[i].getElementsByClassName('slds-form-element__row'); + // for each row, make new object for (let j = rows.length - ONE; j >= ZERO; j--) { const innerInputs = rows[j].getElementsByTagName('input'); + // if there's one field per row, // check whether input name === fieldset name, // if so add input value to dataObject @@ -112,13 +129,17 @@ function addData(fieldSets) { for (let k = innerInputs.length - ONE; k >= ZERO; k--) { tempObj[innerInputs[k].name] = innerInputs[k].value; } + dataObject[objName].push(tempObj); } + tempObj = {}; // reset } + // add fieldSet data to JSON jsonData[objName] = dataObject[objName]; } + return jsonData; } @@ -131,8 +152,10 @@ function addData(fieldSets) { */ function getFormData(form, aspectRangeFormat, propertyMetaData) { const { inputs, fieldSets, inputsAndSelects } = getInputsAndSelects(form); + // for tags, relatedLinks const jsonData = addData(fieldSets); + // check propertyMetaData for customOutput, // if so, get value by customValueQuery for (let i = propertyMetaData.length - ONE; i >= ZERO; i--) { @@ -143,9 +166,11 @@ function getFormData(form, aspectRangeFormat, propertyMetaData) { } for (let i = inputsAndSelects.length - ONE; i >= ZERO; i--) { + // add all values together, wkthout duplicates if (inputsAndSelects[i].name && !jsonData.hasOwnProperty(inputsAndSelects[i].name)) { + // do not include radio button values jsonData[inputsAndSelects[i].name] = inputsAndSelects[i].value; } @@ -154,14 +179,11 @@ function getFormData(form, aspectRangeFormat, propertyMetaData) { if (aspectRangeFormat === 'BOOLEAN') { fromBooleanInput(inputs, jsonData); } else if (aspectRangeFormat === 'NUMERIC') { - fromTextInput(inputs, jsonData, function(value) { - return parseFloat(value); - }); + fromTextInput(inputs, jsonData, (value) => parseFloat(value)); } else if (aspectRangeFormat === 'PERCENT') { - fromTextInput(inputs, jsonData, function(value) { - return value/100; - }); + fromTextInput(inputs, jsonData, (value) => value / 100); } + return jsonData; } @@ -203,7 +225,7 @@ function checkValidation(propertyMetadata, jsonData) { } } } - }).reduce(function(accumulatorObj, propertyMetadataObj) { + }).reduce((accumulatorObj, propertyMetadataObj) => { const name = propertyMetadataObj.propertyName; accumulatorObj[name] = jsonData[name]; return accumulatorObj; diff --git a/view/perspective/CreatePerspective.js b/view/perspective/CreatePerspective.js index b0f412d64d..89c1ad84dc 100644 --- a/view/perspective/CreatePerspective.js +++ b/view/perspective/CreatePerspective.js @@ -73,17 +73,19 @@ class CreatePerspective extends React.Component { retval = el; break; } + el = el.parentNode; } + return retval; } -/** - * Gets the style object, given a state - * @param {object} state of an instance of this react element - * @param {string} dropdownKey The key to the property in state - * @returns {Object} the style object - */ + /** + * Gets the style object, given a state + * @param {object} state of an instance of this react element + * @param {string} dropdownKey The key to the property in state + * @returns {Object} the style object + */ static getDropdownStyle(state, dropdownKey) { return state.dropdownConfig ? state.dropdownConfig[dropdownKey].dropDownStyle : {}; @@ -92,12 +94,11 @@ class CreatePerspective extends React.Component { componentDidMount() { const { values, name, isEditing, params } = this.props; if (isEditing) { + // operating on a named, saved perspective if (values && Array.isArray(values.perspectives) && values.perspectives.length) { const perspective = values.perspectives.filter((pers) => pers.name === name)[0]; - console.log('perspective is', perspective) this.setState({ - // defaults name, lenses: perspective.lens.name || '', subjects: perspective.rootSubject || '', @@ -114,36 +115,39 @@ class CreatePerspective extends React.Component { }); } } else { - // unnamed perspective defined in url - this.setState({ - // defaults - name: '', - lenses: params.lenses || '', - subjects: params.subjects || '', - statusFilterType: params.statusFilterType || 'EXCLUDE', - statusFilter: params.statusFilter || [], - subjectTagFilter: params.subjectTagFilter || [], - subjectTagFilterType: params.subjectTagFilterType || 'EXCLUDE', - aspectTagFilter: params.aspectTagFilter || [], - aspectTagFilterType: params.aspectTagFilterType || 'EXCLUDE', - aspectFilter: params.aspectFilter || [], - aspectFilterType: params.aspectFilterType || 'EXCLUDE', - }, () => { - this.updateDropdownConfig(params); - }); + + // unnamed perspective defined in url + this.setState({ + name: '', + lenses: params.lenses || '', + subjects: params.subjects || '', + statusFilterType: params.statusFilterType || 'EXCLUDE', + statusFilter: params.statusFilter || [], + subjectTagFilter: params.subjectTagFilter || [], + subjectTagFilterType: params.subjectTagFilterType || 'EXCLUDE', + aspectTagFilter: params.aspectTagFilter || [], + aspectTagFilterType: params.aspectTagFilterType || 'EXCLUDE', + aspectFilter: params.aspectFilter || [], + aspectFilterType: params.aspectFilterType || 'EXCLUDE', + }, () => { + this.updateDropdownConfig(params); + }); } } updateDropdownConfig(perspective) { + // attach config to keys, keys to dropdownConfig const { dropdownConfig } = this.state; const { values, BLOCK_SIZE } = this.props; let stateObject = getStateDataOnly(this.state); for (let key in stateObject) { - let value = this.state[key]; //default + let value = this.state[key]; + // if perspective passed in, may amend value based on key let config = getConfig(values, key, value); + // if this dropdown is multi-pill, move the dropdown menu lower let marginTop = !config.isArray ? ZERO : value.length * BLOCK_SIZE; config.dropDownStyle = { marginTop }, @@ -151,7 +155,7 @@ class CreatePerspective extends React.Component { dropdownConfig[key] = config; } - this.setState({dropdownConfig }); + this.setState({ dropdownConfig }); } handleRadioButtonClick(event) { @@ -159,6 +163,7 @@ class CreatePerspective extends React.Component { event.target, 'slds-button-group', ); + const filterType = buttonGroup.title; const stateRule = {}; stateRule[filterType] = event.target.textContent.toUpperCase(); @@ -167,12 +172,14 @@ class CreatePerspective extends React.Component { showError(error) { let displayError = error; + // if error message is from the API, parse it for content if (typeof error === 'object') { displayError = 'status code: ' + error.status + '. Error: ' + JSON.parse(error.response.text).errors[ZERO].message; } + this.setState({ error: displayError }); } @@ -182,7 +189,6 @@ class CreatePerspective extends React.Component { onInputValueChange(event) { const { name, value } = event; - // update state let stateRule = {}; stateRule[name] = value; this.setState(stateRule); @@ -199,27 +205,34 @@ class CreatePerspective extends React.Component { const fieldElem = findCommonAncestor(event.target, 'slds-form-element__control'); const dropdownTitle = fieldElem.title; const valueInState = this.state[dropdownTitle]; + // copy config into new object let newState = { dropdownConfig: this.state.dropdownConfig }; + // pills if (newState.dropdownConfig[dropdownTitle].isArray) { const styleObj = getDropdownStyle(newState, dropdownTitle); if (valueInState) { + // remove pill from array of pills newState[dropdownTitle] = filteredArray(valueInState, labelContent); styleObj.marginTop -= this.props.BLOCK_SIZE; } else { + // no pill, set default marginTop styleObj.marginTop = 0; } } else { + // single pill newState[dropdownTitle] = ''; } + // add selected option to available options in dropdown if (newState.dropdownConfig[dropdownTitle].options.indexOf(labelContent) < 0) { newState.dropdownConfig[dropdownTitle].options.push(labelContent); } + // sort in-place by alphabetical order. newState.dropdownConfig[dropdownTitle].options.sort(); this.setState(newState); @@ -235,10 +248,13 @@ class CreatePerspective extends React.Component { const dropdownTitle = fieldElem.title; const valueInState = this.state[dropdownTitle]; const config = this.state.dropdownConfig[dropdownTitle]; + // copy config into new object let newState = { dropdownConfig: this.state.dropdownConfig }; + // if expected value is string newState[dropdownTitle] = valueToAppend; + // if expected value is array if (config.isArray) { newState.dropdownConfig[dropdownTitle].dropDownStyle.marginTop += BLOCK_SIZE; @@ -248,17 +264,22 @@ class CreatePerspective extends React.Component { } else { newState[dropdownTitle] = [valueToAppend]; } - } else { // single pill input + } else { + + // single pill input // close the dropdown config.close = true; + // field had value, // add replaced value into options if (valueInState) { config.options.push(valueInState); } } + // remove selected option from available options in dropdown const arr = filteredArray(config.options || [], valueToAppend); + // order options alphabetically config.options = arr.sort(); newState = Object.assign(this.state, newState); @@ -269,6 +290,7 @@ class CreatePerspective extends React.Component { doCreate() { const { values, sendResource, isEditing, name } = this.props; const postObject = getStateDataOnly(this.state); + if (!postObject.lenses.length) { this.showError('Please enter a valid lens.'); } else if (!postObject.subjects.length) { @@ -276,32 +298,40 @@ class CreatePerspective extends React.Component { } else if (!postObject.name.length) { this.showError('Please enter a name for this perspective.'); } else { + // check if lens field is uid. if not, need to get uid for lens name const regexpUUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; if (!regexpUUID.test(postObject.lenses)) { let lens = values.lenses.filter((_lens) => { return _lens.name === postObject.lenses; }); + if (!lens.length) { this.showError('Please enter a valid lens name. No lens with name ' + postObject.lenses + ' found'); } + postObject.lenses = lens[ZERO].id; } + // for create perspectives, rename key lenses --> lensId, // and perspectives --> name. Start with deep copy values obj postObject.lensId = postObject.lenses; postObject.rootSubject = postObject.subjects; delete postObject.lenses; delete postObject.subjects; + // go to created perspective page let method = 'POST'; // default postObject.url = '/v1/perspectives'; + if (isEditing) { method = 'PUT'; + // use the original perspective name - postObject.url = postObject.url + '/' + name + postObject.url = postObject.url + '/' + name; } + sendResource(method, postObject, this.showError); } } @@ -320,6 +350,7 @@ class CreatePerspective extends React.Component { ; for (let key in dropdownConfig) { + // if no default value, no pill let pillOutput = ''; const value = this.state[key]; @@ -331,6 +362,7 @@ class CreatePerspective extends React.Component { onClick: this.handleRadioButtonClick, }; } + // if display value is array, use multi pill // else single pill // showInputElem {Bool} if true, show additional @@ -351,6 +383,7 @@ class CreatePerspective extends React.Component { />; } } + const _config = Object.assign({}, dropdownConfig[key], { showInputElem }); dropdownObj[key] = ( @@ -358,6 +391,7 @@ class CreatePerspective extends React.Component { ); } + const errorMessage = this.state.error ? : @@ -366,7 +400,7 @@ class CreatePerspective extends React.Component { return ( { return str.toUpperCase(); }); } @@ -65,7 +67,6 @@ function filteredArray(arr, removeThis) { }); } - /** * Returns array of objects with tags * @param {Array} array The array of reosurces to get tags from. @@ -74,7 +75,7 @@ function filteredArray(arr, removeThis) { function getTagsFromResources(array) { // get all tags let cumulativeArr = []; - for (var i = array.length - 1; i >= 0; i--) { + for (let i = array.length - 1; i >= 0; i--) { if (array[i].tags.length) { cumulativeArr.push(...array[i].tags); } @@ -96,12 +97,13 @@ function getTagsFromResources(array) { function getOptions(options, value) { let leftovers = []; // populate from options if (Array.isArray(value)) { - for (var i = options.length - 1; i >= 0; i--) { + for (let i = options.length - 1; i >= 0; i--) { if (value.indexOf(options[i]) < 0) { leftovers.push(options[i]); } } } + return leftovers; } @@ -148,8 +150,8 @@ function getConfig(values, key, value) { convertedText.replace(' Filter', '') + 's'; let options = getArray('name', values[key]); config.options = getOptions(options, value); - console.log(key, values[key], options, value, config.options) } + delete config.placeholderText; }