diff --git a/src/components/AdminPane/HOCs/WithChallengeResultParents/WithChallengeResultParents.jsx b/src/components/AdminPane/HOCs/WithChallengeResultParents/WithChallengeResultParents.jsx index 55b64047a..b8cd3d7dd 100644 --- a/src/components/AdminPane/HOCs/WithChallengeResultParents/WithChallengeResultParents.jsx +++ b/src/components/AdminPane/HOCs/WithChallengeResultParents/WithChallengeResultParents.jsx @@ -1,4 +1,3 @@ -import _each from "lodash/each"; import _filter from "lodash/filter"; import _uniqBy from "lodash/uniqBy"; import { Component } from "react"; @@ -23,10 +22,16 @@ const WithChallengeResultParents = function (WrappedComponent) { : this.props.projects; const projectsWithChallengeSearchResults = new Set(); - _each(this.props.filteredChallenges, (c) => { + + for (const c of this.props.filteredChallenges) { projectsWithChallengeSearchResults.add(c.parent); - _each(c.virtualParents, (vp) => projectsWithChallengeSearchResults.add(vp)); - }); + + if (c.virtualParents) { + for (const vp of c.virtualParents) { + projectsWithChallengeSearchResults.add(vp); + } + } + } // Include both project results and projects that have challenge results. return _uniqBy( diff --git a/src/components/AdminPane/HOCs/WithComboSearch/WithComboSearch.js b/src/components/AdminPane/HOCs/WithComboSearch/WithComboSearch.js index a5f1f18ba..d3d18e322 100644 --- a/src/components/AdminPane/HOCs/WithComboSearch/WithComboSearch.js +++ b/src/components/AdminPane/HOCs/WithComboSearch/WithComboSearch.js @@ -1,5 +1,3 @@ -import _each from "lodash/each"; -import _toPairs from "lodash/toPairs"; import WithSearch from "../../../HOCs/WithSearch/WithSearch"; /** @@ -18,10 +16,9 @@ import WithSearch from "../../../HOCs/WithSearch/WithSearch"; const WithComboSearch = (WrappedComponent, searches) => { let Combo = WrappedComponent; - _each( - _toPairs(searches), - (searchConfig) => (Combo = WithSearch(Combo, searchConfig[0], searchConfig[1])), - ); + for (const [searchName, searchFunction] of Object.entries(searches)) { + Combo = WithSearch(Combo, searchName, searchFunction); + } return Combo; }; diff --git a/src/components/AdminPane/HOCs/WithComputedMetrics/WithComputedMetrics.jsx b/src/components/AdminPane/HOCs/WithComputedMetrics/WithComputedMetrics.jsx index 8ffa4b590..86f9e83be 100644 --- a/src/components/AdminPane/HOCs/WithComputedMetrics/WithComputedMetrics.jsx +++ b/src/components/AdminPane/HOCs/WithComputedMetrics/WithComputedMetrics.jsx @@ -1,9 +1,7 @@ -import _each from "lodash/each"; import _fromPairs from "lodash/fromPairs"; import _isEmpty from "lodash/isEmpty"; import _isObject from "lodash/isObject"; import _map from "lodash/map"; -import _values from "lodash/values"; import PropTypes from "prop-types"; import { Component } from "react"; import { TaskPriority } from "../../../../services/Task/TaskPriority/TaskPriority"; @@ -21,7 +19,7 @@ export default function (WrappedComponent) { _fromPairs(_map(metrics, (value, label) => [label, (1.0 * value) / total])); updateTotals = (actions, totalTasks, taskMetrics) => { - _each(actions, (value, label) => { + for (const [label, value] of Object.entries(actions)) { if (label === "avgTimeSpent") { taskMetrics.totalTimeSpent = Number.isFinite(taskMetrics.totalTimeSpent) ? taskMetrics.totalTimeSpent + value * actions.tasksWithTime @@ -36,7 +34,7 @@ export default function (WrappedComponent) { ? taskMetrics.percentages[label] + percentage : percentage; } - }); + } }; render() { @@ -72,7 +70,7 @@ export default function (WrappedComponent) { taskMetricsByPriority.percentages = {}; taskMetricsByPriority.averages = {}; - _each(_values(TaskPriority), (priority) => { + for (const priority of Object.values(TaskPriority)) { taskMetricsByPriority[priority] = { percentages: {}, averages: {} }; for (let challenge of challenges) { @@ -92,7 +90,7 @@ export default function (WrappedComponent) { taskMetricsByPriority[priority].percentages, totalChallenges, ); - }); + } } return ( diff --git a/src/components/AdminPane/HOCs/WithCurrentProject/WithCurrentProject.jsx b/src/components/AdminPane/HOCs/WithCurrentProject/WithCurrentProject.jsx index 859d3bfb8..2e49d77a2 100644 --- a/src/components/AdminPane/HOCs/WithCurrentProject/WithCurrentProject.jsx +++ b/src/components/AdminPane/HOCs/WithCurrentProject/WithCurrentProject.jsx @@ -1,4 +1,3 @@ -import _each from "lodash/each"; import _filter from "lodash/filter"; import _find from "lodash/find"; import _isObject from "lodash/isObject"; @@ -152,13 +151,15 @@ export const WithCurrentProject = function (WrappedComponent, options = {}) { // the child challenges have parent projects that haven't been // fetched yet. We need to fetch those so we can show their names. const missingProjects = []; - _each(result?.entities?.challenges, (challenge) => { - if (!_isObject(challenge.parent)) { - if (!this.props.entities.projects[challenge.parent]) { - missingProjects.push(challenge.parent); + if (result?.entities?.challenges) { + for (const challenge of Object.values(result.entities.challenges)) { + if (!_isObject(challenge.parent)) { + if (!this.props.entities.projects[challenge.parent]) { + missingProjects.push(challenge.parent); + } } } - }); + } if (missingProjects.length > 0) { this.props.fetchProjectsById(missingProjects); } diff --git a/src/components/AdminPane/HOCs/WithManageableProjects/WithManageableProjects.jsx b/src/components/AdminPane/HOCs/WithManageableProjects/WithManageableProjects.jsx index 7da698207..c15ec8156 100644 --- a/src/components/AdminPane/HOCs/WithManageableProjects/WithManageableProjects.jsx +++ b/src/components/AdminPane/HOCs/WithManageableProjects/WithManageableProjects.jsx @@ -1,4 +1,3 @@ -import _each from "lodash/each"; import _isEqual from "lodash/isEqual"; import _omit from "lodash/omit"; import _values from "lodash/values"; @@ -59,11 +58,13 @@ const WithManageableProjects = function (WrappedComponent, includeChallenges = f // Since we only fetched a small portion of the total projects in the // database we need to make sure we also fetch the projects that are pinned. let missingProjects = []; - _each(this.props.pinnedProjects, (pinnedProject) => { + + for (const pinnedProject of this.props.pinnedProjects) { if (!this.props.entities.projects[pinnedProject]) { missingProjects.push(pinnedProject); } - }); + } + if (missingProjects.length > 0) { this.props.fetchProjectsById(missingProjects); diff --git a/src/components/AdminPane/HOCs/WithTaskPropertyStyleRules/WithTaskPropertyStyleRules.jsx b/src/components/AdminPane/HOCs/WithTaskPropertyStyleRules/WithTaskPropertyStyleRules.jsx index b88fcb0ea..76ff3ee69 100644 --- a/src/components/AdminPane/HOCs/WithTaskPropertyStyleRules/WithTaskPropertyStyleRules.jsx +++ b/src/components/AdminPane/HOCs/WithTaskPropertyStyleRules/WithTaskPropertyStyleRules.jsx @@ -1,5 +1,4 @@ import _cloneDeep from "lodash/cloneDeep"; -import _each from "lodash/each"; import _fill from "lodash/fill"; import _filter from "lodash/filter"; import _isEmpty from "lodash/isEmpty"; @@ -127,8 +126,8 @@ export const WithTaskPropertyStyleRules = function (WrappedComponent) { render() { const errors = this.state.validationErrors; - _each(this.state.styleRules, (rule, index) => { - _each(rule.styles, (style) => { + for (const [index, rule] of this.state.styleRules.entries()) { + for (const style of rule.styles) { if (style.styleName && !style.styleValue) { // Missing style value errors[index].push(PROPERTY_RULE_ERRORS.missingStyleValue); @@ -136,15 +135,10 @@ export const WithTaskPropertyStyleRules = function (WrappedComponent) { // Missing syle name errors[index].push(PROPERTY_RULE_ERRORS.missingStyleName); } - }); - }); - - let hasAnyStyleErrors = false; - _each(errors, (e) => { - if (!_isEmpty(e)) { - hasAnyStyleErrors = true; } - }); + } + + let hasAnyStyleErrors = errors.some((e) => !_isEmpty(e)); return ( { * Remove preset category top-level fields from the challenge */ export const prunePresetCategories = (challengeData, activeCategories) => { - _each(activeCategories, (categoryName) => delete challengeData[categoryName]); + for (const categoryName of activeCategories) { + delete challengeData[categoryName]; + } }; /** @@ -97,14 +96,14 @@ export const prunePresetCategories = (challengeData, activeCategories) => { */ export const categorizePresetStrings = (presetStrings) => { const categorized = {}; - _each(presetStrings, (preset) => { - // eslint-disable-next-line no-unused-vars - const parentCategory = _find(_toPairs(idPresets), ([categoryName, category]) => { - return category.members.indexOf(preset) !== -1; + + for (const preset of presetStrings) { + const parentCategory = Object.entries(idPresets).find(([_, category]) => { + return category.members.includes(preset); }); if (!parentCategory) { - return; + continue; } const categoryName = parentCategory[0]; @@ -112,7 +111,7 @@ export const categorizePresetStrings = (presetStrings) => { categorized[categoryName] = []; } categorized[categoryName].push(preset); - }); + } return categorized; }; diff --git a/src/components/ChallengeProgress/ChallengeProgress.jsx b/src/components/ChallengeProgress/ChallengeProgress.jsx index 080ebc507..e29479cd9 100644 --- a/src/components/ChallengeProgress/ChallengeProgress.jsx +++ b/src/components/ChallengeProgress/ChallengeProgress.jsx @@ -1,7 +1,6 @@ import { ResponsiveBar } from "@nivo/bar"; import classNames from "classnames"; import _chunk from "lodash/chunk"; -import _each from "lodash/each"; import _isEqual from "lodash/isEqual"; import _isObject from "lodash/isObject"; import _map from "lodash/map"; @@ -224,12 +223,13 @@ export class ChallengeProgress extends Component { calculateChallengeStats(taskActions, orderedStatuses, localizedStatuses) { let challengeStats = {}; - _each(orderedStatuses, (status) => { + + for (const status of orderedStatuses) { challengeStats[localizedStatuses[keysByStatus[status]]] = { count: taskActions[keysByStatus[status]], percent: this.percent(taskActions[keysByStatus[status]], taskActions.total), }; - }); + } return challengeStats; } @@ -240,12 +240,12 @@ export class ChallengeProgress extends Component { [availableLabel]: this.percent(taskActions.available, taskActions.total), }; - _each(orderedStatuses, (status) => { + for (const status of orderedStatuses) { completionData[localizedStatuses[keysByStatus[status]]] = this.percent( taskActions[keysByStatus[status]], taskActions.total, ); - }); + } return completionData; } diff --git a/src/components/CommentList/CommentList.jsx b/src/components/CommentList/CommentList.jsx index 744547565..492e6154d 100644 --- a/src/components/CommentList/CommentList.jsx +++ b/src/components/CommentList/CommentList.jsx @@ -1,6 +1,5 @@ import classNames from "classnames"; import { parseISO } from "date-fns"; -import _each from "lodash/each"; import _isObject from "lodash/isObject"; import _map from "lodash/map"; import _reverse from "lodash/reverse"; @@ -33,20 +32,18 @@ export default class CommentList extends Component { // Show in descending order, with the most recent comment first. let sortedComments = []; - if (this.props.comments?.length !== 0) { - commentDates = new Map(); - _each(this.props.comments, (comment) => - commentDates.set(comment.id, parseISO(comment.created)), + if (this.props.comments?.length > 0) { + commentDates = new Map( + this.props.comments.map((comment) => [comment.id, parseISO(comment.created)]), ); // Show in descending order, with the most recent comment first. sortedComments = _reverse( _sortBy(this.props.comments, (comment) => commentDates.get(comment.id).getTime()), ); - } else { - commentDates = new Map(); - _each(this.props.taskComments, (comment) => - commentDates.set(comment.id, parseISO(comment.created)), + } else if (this.props.taskComments?.length > 0) { + commentDates = new Map( + this.props.taskComments.map((comment) => [comment.id, parseISO(comment.created)]), ); // Show in descending order, with the most recent comment first. diff --git a/src/components/CountrySelector/CountrySelector.jsx b/src/components/CountrySelector/CountrySelector.jsx index d858073e4..fcaaf2f8b 100644 --- a/src/components/CountrySelector/CountrySelector.jsx +++ b/src/components/CountrySelector/CountrySelector.jsx @@ -1,6 +1,3 @@ -import _each from "lodash/each"; -import _map from "lodash/map"; -import _sortBy from "lodash/sortBy"; import PropTypes from "prop-types"; import { Component } from "react"; import { FormattedMessage, injectIntl } from "react-intl"; @@ -63,14 +60,14 @@ const CountryButton = function (props) { }; const ListCountryItems = function (props) { - const countryList = _sortBy( - _each(supportedCountries(), (country) => { + const countryList = supportedCountries() + .map((country) => { country.name = props.intl.formatMessage(countryMessages[country.countryCode]); - }), - "name", - ); + return country; + }) + .sort((a, b) => a.name.localeCompare(b.name)); - const menuItems = _map(countryList, (country) => ( + const menuItems = countryList.map((country) => (
  • props.pickCountry(country.countryCode, props.closeDropdown)}> {country.name} diff --git a/src/components/HOCs/WithConfigurableColumns/WithConfigurableColumns.jsx b/src/components/HOCs/WithConfigurableColumns/WithConfigurableColumns.jsx index fe5c6d7fc..eeb9fa86e 100644 --- a/src/components/HOCs/WithConfigurableColumns/WithConfigurableColumns.jsx +++ b/src/components/HOCs/WithConfigurableColumns/WithConfigurableColumns.jsx @@ -1,5 +1,4 @@ import _clone from "lodash/clone"; -import _each from "lodash/each"; import _find from "lodash/find"; import _get from "lodash/get"; import _isEqual from "lodash/isEqual"; @@ -69,7 +68,8 @@ export default function ( // allColumns that is not already in the addedColumn list. const availableColumns = {}; let availableColumnsKeys = _pull(_keys(allColumns), ...addedColumnsKeys); - _each(availableColumnsKeys, (column) => { + + for (const column of availableColumnsKeys) { availableColumns[column] = allColumns[column]; let message = column; @@ -79,28 +79,24 @@ export default function ( } availableColumns[column].message = message; - }); + } // Next if we are including task properties as columns we need to add those if (includeTaskPropertyKeys) { - // For all the task property keys we want to add them to the - // availableColumns if they are not already in the addedColumns. - // As we add them, we indicate they are a task property with a : in - // front (this lets us treat them as strings when necessary, such as in - // the user settings, but still lets us identify them as task properties). - _each(this.props.taskPropertyKeys, (propKey) => { + for (const propKey of this.props.taskPropertyKeys) { if (!_find(addedColumnsKeys, (k) => k === `:${propKey}`)) { // Task Properties get italicized to visually distinguish them availableColumns[`:${propKey}`] = { message: {propKey}, }; } - }); + } } // Now we need to internalize the addedColumns as well. const addedColumns = {}; - _each(addedColumnsKeys, (column) => { + + for (const column of addedColumnsKeys) { if (allColumns[column]) { addedColumns[column] = allColumns[column]; if (columnMessages[`${column}Label`]) { @@ -118,7 +114,7 @@ export default function ( addedColumns[column] = { message: column }; } } - }); + } // Store our newly setup columns. this.setState({ availableColumns, addedColumns }); @@ -156,7 +152,7 @@ export default function ( // our key, then we will stick the columnKey on the end. let keyAdded = false; - _each(this.state.availableColumns, (value, key) => { + for (const [key, value] of Object.entries(this.state.availableColumns)) { // If our columnKey to add is not a task property column and we are // starting to copy over the :taskPropertyColumns in the list then // we insert our new columnKey first before continuing on. @@ -165,7 +161,7 @@ export default function ( keyAdded = true; } newColumns[key] = value; - }); + } // if !keyAdded then the columnKey didn't get added in the list yet, either // because it's a task property column itself or the list doesn't contain @@ -186,12 +182,12 @@ export default function ( // Fetch the item from the originalIndex let savedItem = null; - _each(this.state.addedColumns, (column, key) => { + for (const [key, column] of Object.entries(this.state.addedColumns)) { if (index === originalIndex) { savedItem = { key: key, column: column }; } index += 1; - }); + } // Insert item at new index. To do this we will run through our column // list and copy each one to the newColumnMap. If we run across the @@ -201,7 +197,7 @@ export default function ( // moving item is being moved up or down. const newColumnMap = {}; index = 0; - _each(this.state.addedColumns, (column, key) => { + for (const [key, column] of Object.entries(this.state.addedColumns)) { if (index === newIndex) { // Our item is being moved up in the list. if (newIndex < originalIndex) { @@ -217,7 +213,7 @@ export default function ( newColumnMap[key] = column; } index += 1; - }); + } this.setState({ addedColumns: newColumnMap }); }; diff --git a/src/components/HOCs/WithCurrentTask/WithCurrentTask.jsx b/src/components/HOCs/WithCurrentTask/WithCurrentTask.jsx index dda9c8ebf..8da47360a 100644 --- a/src/components/HOCs/WithCurrentTask/WithCurrentTask.jsx +++ b/src/components/HOCs/WithCurrentTask/WithCurrentTask.jsx @@ -1,4 +1,3 @@ -import _each from "lodash/each"; import _isPlainObject from "lodash/isPlainObject"; import _isString from "lodash/isString"; import _omit from "lodash/omit"; @@ -310,9 +309,9 @@ export const mapDispatchToProps = (dispatch, ownProps) => { saveTaskTags: (task, tags) => { if (task.bundleId) { dispatch(fetchTaskBundle(task.bundleId), false).then((taskBundle) => { - _each(taskBundle.tasks, (task) => { + for (const task of taskBundle.tasks) { dispatch(updateTaskTags(task.id, tags)); - }); + } }); } else { dispatch(updateTaskTags(task.id, tags)); diff --git a/src/components/HOCs/WithFilterCriteria/WithFilterCriteria.jsx b/src/components/HOCs/WithFilterCriteria/WithFilterCriteria.jsx index 6eb5e524d..e0565e477 100644 --- a/src/components/HOCs/WithFilterCriteria/WithFilterCriteria.jsx +++ b/src/components/HOCs/WithFilterCriteria/WithFilterCriteria.jsx @@ -1,7 +1,6 @@ import { format } from "date-fns"; import _cloneDeep from "lodash/cloneDeep"; import _debounce from "lodash/debounce"; -import _each from "lodash/each"; import _isEmpty from "lodash/isEmpty"; import _isEqual from "lodash/isEqual"; import _keys from "lodash/keys"; @@ -212,7 +211,14 @@ export const WithFilterCriteria = function ( // These values will come in as comma-separated strings and need to be turned // into number arrays - _each(["status", "reviewStatus", "metaReviewStatus", "priorities", "boundingBox"], (key) => { + const keysToSplit = [ + "status", + "reviewStatus", + "metaReviewStatus", + "priorities", + "boundingBox", + ]; + for (const key of keysToSplit) { if (criteria[key] !== undefined && key === "boundingBox") { if (typeof criteria[key] === "string") { criteria[key] = criteria[key].split(",").map((x) => parseFloat(x)); @@ -222,7 +228,7 @@ export const WithFilterCriteria = function ( criteria.filters[key] = criteria.filters[key].split(",").map((x) => _toInteger(x)); } } - }); + } if (!criteria?.filters?.status) { this.updateIncludedFilters(props); @@ -249,7 +255,14 @@ export const WithFilterCriteria = function ( // These values will come in as comma-separated strings and need to be turned // into number arrays - _each(["status", "reviewStatus", "metaReviewStatus", "priorities", "boundingBox"], (key) => { + const keysToSplit = [ + "status", + "reviewStatus", + "metaReviewStatus", + "priorities", + "boundingBox", + ]; + for (const key of keysToSplit) { if (criteria[key] !== undefined && key === "boundingBox") { if (typeof criteria[key] === "string") { criteria[key] = criteria[key].split(",").map((x) => parseFloat(x)); @@ -259,7 +272,7 @@ export const WithFilterCriteria = function ( criteria.filters[key] = criteria.filters[key].split(",").map((x) => _toInteger(x)); } } - }); + } if (!criteria?.filters?.status) { this.updateIncludedFilters(props); diff --git a/src/components/HOCs/WithFilteredClusteredTasks/WithFilteredClusteredTasks.jsx b/src/components/HOCs/WithFilteredClusteredTasks/WithFilteredClusteredTasks.jsx index f42a404b6..b9a49d614 100644 --- a/src/components/HOCs/WithFilteredClusteredTasks/WithFilteredClusteredTasks.jsx +++ b/src/components/HOCs/WithFilteredClusteredTasks/WithFilteredClusteredTasks.jsx @@ -1,6 +1,5 @@ import _assignWith from "lodash/assignWith"; import _cloneDeep from "lodash/cloneDeep"; -import _each from "lodash/each"; import _filter from "lodash/filter"; import _fromPairs from "lodash/fromPairs"; import _isEmpty from "lodash/isEmpty"; @@ -325,7 +324,8 @@ export default function WithFilteredClusteredTasks( // These values will come in as comma-separated strings and need to be turned // into number arrays - _each(["status", "reviewStatus", "metaReviewStatus", "priorities"], (key) => { + const keysToSplit = ["status", "reviewStatus", "metaReviewStatus", "priorities"]; + for (const key of keysToSplit) { if (criteria?.filters?.[key] !== undefined && !this.props.taskId) { if (typeof criteria.filters[key] === "string") { criteria.filters[key] = criteria.filters[key].split(",").map((x) => _toInteger(x)); @@ -341,7 +341,7 @@ export default function WithFilteredClusteredTasks( } loadFromSavedFilters = true; } - }); + } if (useURLFilters || loadFromSavedFilters) { const filteredTasks = this.filterTasks( @@ -362,9 +362,9 @@ export default function WithFilteredClusteredTasks( : (initialFilters?.statuses ?? _fromPairs(_map(TaskStatus, (status) => [status, false]))); - _each(criteria.filters.status, (status) => { + for (const status of criteria.filters.status) { includeStatuses[status] = true; - }); + } this.setState( Object.assign( diff --git a/src/components/HOCs/WithMapBoundedTasks/WithMapBoundedTasks.jsx b/src/components/HOCs/WithMapBoundedTasks/WithMapBoundedTasks.jsx index 91d405f4d..7b4ac6175 100644 --- a/src/components/HOCs/WithMapBoundedTasks/WithMapBoundedTasks.jsx +++ b/src/components/HOCs/WithMapBoundedTasks/WithMapBoundedTasks.jsx @@ -1,4 +1,3 @@ -import _each from "lodash/each"; import _filter from "lodash/filter"; import _find from "lodash/find"; import _map from "lodash/map"; @@ -66,7 +65,10 @@ export const WithMapBoundedTasks = function (WrappedComponent, mapType, matchCha } const allowedChallenges = new Set(); - _each(this.props.challenges, (challenge) => allowedChallenges.add(challenge.id)); + + for (const challenge of this.props.challenges) { + allowedChallenges.add(challenge.id); + } const filteredTasks = _filter(mapBoundedTasks.tasks, (task) => allowedChallenges.has(task.parentId), diff --git a/src/components/HOCs/WithPagedProjects/WithPagedProjects.jsx b/src/components/HOCs/WithPagedProjects/WithPagedProjects.jsx index 8e392b44f..6332daed5 100644 --- a/src/components/HOCs/WithPagedProjects/WithPagedProjects.jsx +++ b/src/components/HOCs/WithPagedProjects/WithPagedProjects.jsx @@ -1,5 +1,4 @@ import _differenceBy from "lodash/differenceBy"; -import _each from "lodash/each"; import _filter from "lodash/filter"; import _find from "lodash/find"; import _isEmpty from "lodash/isEmpty"; @@ -58,10 +57,7 @@ export default function ( // Now we want pinned projects first followed by the rest of the sorted projects pagedProjects = pinnedProjects.concat(pagedProjects); } else { - // Otherwise sort by the fuzzy search score. We want to promote high - // challenge scores to their parent projects so they show up in an - // appropriate place in the list - _each(this.props.filteredChallenges, (c) => { + for (const c of this.props.filteredChallenges) { const parent = _find( pagedProjects, (p) => p.id === (_isObject(c.parent) ? c.parent.id : c.parent), @@ -69,7 +65,7 @@ export default function ( if (parent && (!parent.score || c.score > parent.score)) { parent.score = c.score; } - }); + } pagedProjects = _sortBy(pagedProjects, (p) => p.score); pagedProjects = _slice(pagedProjects, 0, numberResultsToShow); diff --git a/src/components/HOCs/WithPublicWidgetWorkspaces/WithPublicWidgetWorkspaces.jsx b/src/components/HOCs/WithPublicWidgetWorkspaces/WithPublicWidgetWorkspaces.jsx index a44709f41..0889f1e79 100644 --- a/src/components/HOCs/WithPublicWidgetWorkspaces/WithPublicWidgetWorkspaces.jsx +++ b/src/components/HOCs/WithPublicWidgetWorkspaces/WithPublicWidgetWorkspaces.jsx @@ -1,5 +1,4 @@ import _assign from "lodash/assign"; -import _each from "lodash/each"; import { Component } from "react"; import { Redirect } from "react-router"; import { generateWidgetId, widgetDescriptor } from "../../../services/Widget/Widget"; @@ -63,7 +62,7 @@ export const WithPublicWidgetWorkspacesInternal = function ( // Generate a simple layout if none provided, with one widget per row if (configuration.layout.length === 0) { let nextY = 0; - _each(configuration.widgets, (widgetConf, index) => { + for (const [index, widgetConf] of configuration.widgets.entries()) { configuration.layout.push({ i: `${index}`, x: 0, @@ -77,11 +76,11 @@ export const WithPublicWidgetWorkspacesInternal = function ( }); nextY += widgetConf.defaultHeight; - }); + } } else { // A layout was provided. If heights and/or widths were omitted or don't meet // current minimums, fill them in from the widget descriptors - _each(configuration.layout, (widgetLayout, index) => { + for (const [index, widgetLayout] of configuration.layout.entries()) { if (!configuration.widgets || !configuration.widgets[index]) { return; } @@ -105,7 +104,7 @@ export const WithPublicWidgetWorkspacesInternal = function ( ) { widgetLayout.h = descriptor.minHeight; } - }); + } } return configuration; diff --git a/src/components/HOCs/WithSearchRoute/WithSearchRoute.jsx b/src/components/HOCs/WithSearchRoute/WithSearchRoute.jsx index e8142472e..23d5fa3b5 100644 --- a/src/components/HOCs/WithSearchRoute/WithSearchRoute.jsx +++ b/src/components/HOCs/WithSearchRoute/WithSearchRoute.jsx @@ -1,5 +1,4 @@ import _debounce from "lodash/debounce"; -import _each from "lodash/each"; import _isEmpty from "lodash/isEmpty"; import PropTypes from "prop-types"; import queryString from "query-string"; @@ -159,11 +158,11 @@ export const WithSearchRoute = function (WrappedComponent, searchGroup) { export const executeRouteSearch = (routeCriteria, searchString) => { const searchCriteria = queryString.parse(searchString); - _each(searchCriteria, (value, key) => { + for (const [key, value] of Object.entries(searchCriteria)) { if (routeCriteria[key] && !_isEmpty(value)) { routeCriteria[key](value); } - }); + } }; /** @@ -177,17 +176,9 @@ export const debouncedUpdateHistory = _debounce( ); export const addSearchCriteriaToRoute = (history, newCriteria) => { - const searchCriteria = queryString.parse(history.location.search); - - _each(newCriteria, (value, key) => { - if (value === undefined) { - delete searchCriteria[key]; - } else { - searchCriteria[key] = value; - } - }); - - const newRoute = `${history.location.pathname}?${queryString.stringify(searchCriteria)}`; + const oldCriteria = queryString.parse(history.location.search); + const newQueryString = queryString.stringify({ ...oldCriteria, ...newCriteria }); + const newRoute = `${history.location.pathname}?${newQueryString}`; debouncedUpdateHistory(history, newRoute); }; @@ -220,9 +211,9 @@ export const addBoundsToRoute = (history, boundsType, bounds, locationFilter) => export const removeSearchCriteriaFromRoute = (history, criteriaKeys) => { const searchCriteria = queryString.parse(history.location.search); - _each(criteriaKeys, (key) => { + for (const key of criteriaKeys) { delete searchCriteria[key]; - }); + } const newRoute = `${history.location.pathname}?${queryString.stringify(searchCriteria)}`; history.replace(newRoute); diff --git a/src/components/HOCs/WithSelectedClusteredTasks/WithSelectedClusteredTasks.jsx b/src/components/HOCs/WithSelectedClusteredTasks/WithSelectedClusteredTasks.jsx index 1accb9927..fc94a2c7d 100644 --- a/src/components/HOCs/WithSelectedClusteredTasks/WithSelectedClusteredTasks.jsx +++ b/src/components/HOCs/WithSelectedClusteredTasks/WithSelectedClusteredTasks.jsx @@ -1,5 +1,3 @@ -import _each from "lodash/each"; -import _isEmpty from "lodash/isEmpty"; import { Component } from "react"; /** @@ -41,7 +39,11 @@ export default function WithSelectedClusteredTasks(WrappedComponent) { * of tasks (or single-task clusters) */ selectTasks = (tasks) => { - if (_isEmpty(tasks) || (this.state.allSelected && this.state.deselectedTasks.size === 0)) { + if ( + !tasks || + tasks.length === 0 || + (this.state.allSelected && this.state.deselectedTasks.size === 0) + ) { // Nothing to do return; } @@ -50,15 +52,19 @@ export default function WithSelectedClusteredTasks(WrappedComponent) { // otherwise we need to remove from the deselectedTasks map if (!this.state.allSelected) { const selectedTasks = new Map(this.state.selectedTasks); - _each(tasks, (task) => selectedTasks.set(task.id, task)); + + for (const task of tasks) { + selectedTasks.set(task.id, task); + } + this.setState({ selectedTasks }); } else { const deselectedTasks = new Map(this.state.deselectedTasks); - _each(tasks, (task) => { - if (deselectedTasks.has(task.id)) { - deselectedTasks.delete(task.id); - } - }); + + for (const task of tasks) { + deselectedTasks.delete(task.id); + } + this.setState({ deselectedTasks }); } }; @@ -68,7 +74,11 @@ export default function WithSelectedClusteredTasks(WrappedComponent) { * array of tasks (or single-task clusters) */ deselectTasks = (tasks) => { - if (_isEmpty(tasks) || (!this.state.allSelected && this.state.selectedTasks.size === 0)) { + if ( + !tasks || + tasks.length === 0 || + (this.state.allSelected && this.state.deselectedTasks.size === 0) + ) { // Nothing to do return; } @@ -77,15 +87,19 @@ export default function WithSelectedClusteredTasks(WrappedComponent) { // otherwise we need to remove from the selectedTasks map if (this.state.allSelected) { const deselectedTasks = new Map(this.state.deselectedTasks); - _each(tasks, (task) => deselectedTasks.set(task.id, task)); + + for (const task of tasks) { + deselectedTasks.set(task.id, task); + } + this.setState({ deselectedTasks }); } else { const selectedTasks = new Map(this.state.selectedTasks); - _each(tasks, (task) => { - if (selectedTasks.has(task.id)) { - selectedTasks.delete(task.id); - } - }); + + for (const task of tasks) { + selectedTasks.delete(task.id); + } + this.setState({ selectedTasks }); } }; diff --git a/src/components/HOCs/WithTaskMarkers/WithTaskMarkers.jsx b/src/components/HOCs/WithTaskMarkers/WithTaskMarkers.jsx index 5ccaff824..8572197c9 100644 --- a/src/components/HOCs/WithTaskMarkers/WithTaskMarkers.jsx +++ b/src/components/HOCs/WithTaskMarkers/WithTaskMarkers.jsx @@ -1,5 +1,3 @@ -import _each from "lodash/each"; -import _get from "lodash/get"; import _isObject from "lodash/isObject"; import { Component } from "react"; import AsMappableTask from "../../../interactions/Task/AsMappableTask"; @@ -17,7 +15,7 @@ import { TaskStatus } from "../../../services/Task/TaskStatus/TaskStatus"; export default function WithTaskMarkers(WrappedComponent, tasksProp = "clusteredTasks") { class _WithTaskMarkers extends Component { render() { - const challengeTasks = _get(this.props, tasksProp); + const challengeTasks = this.props[tasksProp]; // Only create markers for allowed statuses OR [created, skipped, or too-hard tasks] const allowedStatuses = this.props.allowedStatuses || [ @@ -27,13 +25,9 @@ export default function WithTaskMarkers(WrappedComponent, tasksProp = "clustered ]; const markers = []; - if (_isObject(challengeTasks)) { - if (Array.isArray(challengeTasks.tasks) && challengeTasks.tasks.length > 0) { - _each(challengeTasks.tasks, (task) => { - if (allowedStatuses.indexOf(task.status) === -1) { - return; - } - + if (_isObject(challengeTasks) && Array.isArray(challengeTasks.tasks)) { + for (const task of challengeTasks.tasks) { + if (allowedStatuses.includes(task.status)) { const nearestToCenter = AsMappableTask(task).nearestPointToCenter(); markers.push({ position: [ @@ -52,7 +46,7 @@ export default function WithTaskMarkers(WrappedComponent, tasksProp = "clustered reviewStatus: task.reviewStatus, }, }); - }); + } } } diff --git a/src/components/HOCs/WithTaskPropertyKeys/WithTaskPropertyKeys.jsx b/src/components/HOCs/WithTaskPropertyKeys/WithTaskPropertyKeys.jsx index 343e1a442..ba2417efc 100644 --- a/src/components/HOCs/WithTaskPropertyKeys/WithTaskPropertyKeys.jsx +++ b/src/components/HOCs/WithTaskPropertyKeys/WithTaskPropertyKeys.jsx @@ -10,7 +10,8 @@ import { fetchPropertyKeys } from "../../../services/Challenge/Challenge"; export const WithTaskPropertyKeys = function (WrappedComponent) { return class extends Component { state = { - taskPropertyKeys: null, + taskPropertyKeys: [], + loadingPropertyKeys: false, }; getTaskPropertyKeys = () => { @@ -21,15 +22,11 @@ export const WithTaskPropertyKeys = function (WrappedComponent) { fetchPropertyKeys(challengeId) .then((results) => { this.setState({ loadingPropertyKeys: false, taskPropertyKeys: _sortBy(results) }); - return results; }) .catch((error) => { console.log(error); this.setState({ loadingPropertyKeys: false, taskPropertyKeys: [] }); }); - return []; - } else { - return []; } }; diff --git a/src/components/TaskAnalysisTable/TaskAnalysisTable.jsx b/src/components/TaskAnalysisTable/TaskAnalysisTable.jsx index 393f5279f..89d291281 100644 --- a/src/components/TaskAnalysisTable/TaskAnalysisTable.jsx +++ b/src/components/TaskAnalysisTable/TaskAnalysisTable.jsx @@ -2,7 +2,6 @@ import { differenceInSeconds, parseISO } from "date-fns"; import _compact from "lodash/compact"; import _concat from "lodash/concat"; import _debounce from "lodash/debounce"; -import _each from "lodash/each"; import _filter from "lodash/filter"; import _get from "lodash/get"; import _isEmpty from "lodash/isEmpty"; @@ -117,10 +116,7 @@ export class TaskAnalysisTableInternal extends Component { direction: tableState.sorted[0].desc ? "DESC" : "ASC", }; - const filters = {}; - _each(tableState.filtered, (pair) => { - filters[pair.id] = pair.value; - }); + const filters = Object.fromEntries(tableState.filtered.map(({ id, value }) => [id, value])); this.props.updateCriteria({ sortCriteria, diff --git a/src/components/TaskClusterMap/MapMarkers.jsx b/src/components/TaskClusterMap/MapMarkers.jsx index 5b83c3c8f..d55f94572 100644 --- a/src/components/TaskClusterMap/MapMarkers.jsx +++ b/src/components/TaskClusterMap/MapMarkers.jsx @@ -1,6 +1,5 @@ import _cloneDeep from "lodash/cloneDeep"; import _compact from "lodash/compact"; -import _each from "lodash/each"; import _filter from "lodash/filter"; import _isEmpty from "lodash/isEmpty"; import _isEqual from "lodash/isEqual"; @@ -149,14 +148,15 @@ const Markers = (props) => { } const refreshed = new Map(); - _each(props.taskMarkers, (marker) => { + + for (const marker of props.taskMarkers) { if (spidered.has(marker.options.taskId)) { refreshed.set(marker.options.taskId, { ...spidered.get(marker.options.taskId), icon: marker.icon, }); } - }); + } setSpidered(refreshed); }; @@ -209,7 +209,9 @@ const Markers = (props) => { centerPointPx, CLUSTER_ICON_PIXELS, ); - _each([...updateSpidered.values()], (s) => (s.position = map.layerPointToLatLng(s.positionPx))); + for (const s of updateSpidered.values()) { + s.position = map.layerPointToLatLng(s.positionPx); + } setSpidered(updateSpidered); }; diff --git a/src/components/TaskHistoryList/TaskHistoryList.jsx b/src/components/TaskHistoryList/TaskHistoryList.jsx index ed2ecdedc..9b28861fc 100644 --- a/src/components/TaskHistoryList/TaskHistoryList.jsx +++ b/src/components/TaskHistoryList/TaskHistoryList.jsx @@ -1,5 +1,4 @@ import classNames from "classnames"; -import _each from "lodash/each"; import _find from "lodash/find"; import _kebabCase from "lodash/kebabCase"; import _map from "lodash/map"; @@ -66,116 +65,79 @@ export class TaskHistoryList extends Component { let userType = null; let errorTags = null; - _each( - _sortBy(this.props.taskHistory, (h) => new Date(h.timestamp)), - (log, index) => { - // We are moving on to a new set of actions so let's push - // this set of entries - if ( - lastTimestamp !== null && - (entries.length > 0 || startedAtEntry) && - Math.abs(new Date(log.timestamp) - lastTimestamp) > 1000 - ) { - combinedLogs.push({ - timestamp: lastTimestamp, - duration: duration, - entry: entries, - username: username, - status: updatedStatus, - userType: userType, - errorTags: errorTags, - }); - if (startedAtEntry) { - combinedLogs.push(startedAtEntry); - startedAtEntry = null; - } - entries = []; - updatedStatus = null; - duration = null; - userType = null; - errorTags = null; + const sortedLogs = _sortBy(this.props.taskHistory, (h) => new Date(h.timestamp)); + for (const [index, log] of sortedLogs.entries()) { + // We are moving on to a new set of actions so let's push + // this set of entries + if ( + lastTimestamp !== null && + (entries.length > 0 || startedAtEntry) && + Math.abs(new Date(log.timestamp) - lastTimestamp) > 1000 + ) { + combinedLogs.push({ + timestamp: lastTimestamp, + duration: duration, + entry: entries, + username: username, + status: updatedStatus, + userType: userType, + errorTags: errorTags, + }); + if (startedAtEntry) { + combinedLogs.push(startedAtEntry); + startedAtEntry = null; } - lastTimestamp = new Date(log.timestamp); - - switch (log.actionType) { - case TaskHistoryAction.comment: - logEntry = commentEntry(log, this.props, index); - username = log?.user?.username; - break; - case TaskHistoryAction.review: - case TaskHistoryAction.metaReview: - if (log.reviewStatus === TaskReviewStatus.needed) { - username = - TaskHistoryAction.review === log.actionType - ? log?.reviewRequestedBy?.username - : log?.metaReviewRequestedBy?.username; - logEntry = reviewEntry(log, this.props, index); - } else { - logEntry = null; - const isMetaReview = log.actionType === TaskHistoryAction.metaReview; - updatedStatus = ( - - ); - username = - log.reviewStatus === TaskReviewStatus.disputed || - log.reviewStatus === TaskReviewStatus.needed - ? log?.reviewRequestedBy?.username - : log?.reviewedBy?.username; - userType = - log.actionType === TaskHistoryAction.metaReview - ? META_REVIEWER_TYPE - : REVIEWER_TYPE; - errorTags = log.errorTags; - if (log.startedAt) { - duration = new Date(log.timestamp) - new Date(log.startedAt); - - //add an additional entry for when review was started - const startedReviewAtEntry = { - timestamp: log.startedAt, - ignoreAtticOffset: true, - entry: [ -
  • -
    - - {username} - {" "} - -
    -
  • , - ], - }; - - combinedLogs.push(startedReviewAtEntry); - } - } - break; - case TaskHistoryAction.update: - logEntry = updateEntry(log, this.props, index); - username = log?.user?.username; - break; - case TaskHistoryAction.status: - default: + entries = []; + updatedStatus = null; + duration = null; + userType = null; + errorTags = null; + } + lastTimestamp = new Date(log.timestamp); + + switch (log.actionType) { + case TaskHistoryAction.comment: + logEntry = commentEntry(log, this.props, index); + username = log?.user?.username; + break; + case TaskHistoryAction.review: + case TaskHistoryAction.metaReview: + if (log.reviewStatus === TaskReviewStatus.needed) { + username = + TaskHistoryAction.review === log.actionType + ? log?.reviewRequestedBy?.username + : log?.metaReviewRequestedBy?.username; + logEntry = reviewEntry(log, this.props, index); + } else { logEntry = null; - username = log?.user?.username; - userType = MAPPER_TYPE; - updatedStatus = statusEntry(log, this.props, index); - if (log.startedAt || log.oldStatus === TASK_STATUS_CREATED) { - // Add a "Started At" entry into the history - startedAtEntry = { - timestamp: log.startedAt || log.timestamp, + const isMetaReview = log.actionType === TaskHistoryAction.metaReview; + updatedStatus = ( + + ); + username = + log.reviewStatus === TaskReviewStatus.disputed || + log.reviewStatus === TaskReviewStatus.needed + ? log?.reviewRequestedBy?.username + : log?.reviewedBy?.username; + userType = + log.actionType === TaskHistoryAction.metaReview ? META_REVIEWER_TYPE : REVIEWER_TYPE; + errorTags = log.errorTags; + if (log.startedAt) { + duration = new Date(log.timestamp) - new Date(log.startedAt); + + //add an additional entry for when review was started + const startedReviewAtEntry = { + timestamp: log.startedAt, ignoreAtticOffset: true, entry: [
  • @@ -186,21 +148,54 @@ export class TaskHistoryList extends Component { > {username} {" "} - +
  • , ], }; - } - if (log.startedAt) { - duration = new Date(log.timestamp) - new Date(log.startedAt); + combinedLogs.push(startedReviewAtEntry); } - break; - } - entries.unshift(logEntry); - }, - ); + } + break; + case TaskHistoryAction.update: + logEntry = updateEntry(log, this.props, index); + username = log?.user?.username; + break; + case TaskHistoryAction.status: + default: + logEntry = null; + username = log?.user?.username; + userType = MAPPER_TYPE; + updatedStatus = statusEntry(log, this.props, index); + if (log.startedAt || log.oldStatus === TASK_STATUS_CREATED) { + // Add a "Started At" entry into the history + startedAtEntry = { + timestamp: log.startedAt || log.timestamp, + ignoreAtticOffset: true, + entry: [ +
  • +
    + + {username} + {" "} + +
    +
  • , + ], + }; + } + + if (log.startedAt) { + duration = new Date(log.timestamp) - new Date(log.startedAt); + } + break; + } + entries.unshift(logEntry); + } if (entries.length > 0) { combinedLogs.push({ @@ -219,7 +214,8 @@ export class TaskHistoryList extends Component { } const contributors = []; - _each(combinedLogs, (log) => { + + for (const log of combinedLogs) { // Don't add a contributor twice if ( log.userType && @@ -227,7 +223,7 @@ export class TaskHistoryList extends Component { ) { contributors.push(log); } - }); + } const contributorEntries = (
      diff --git a/src/components/TaskPane/TaskMap/TaskMap.jsx b/src/components/TaskPane/TaskMap/TaskMap.jsx index e3b6a2c8f..f1b8f44d8 100644 --- a/src/components/TaskPane/TaskMap/TaskMap.jsx +++ b/src/components/TaskPane/TaskMap/TaskMap.jsx @@ -5,7 +5,6 @@ import classNames from "classnames"; import L from "leaflet"; import _clone from "lodash/clone"; import _compact from "lodash/compact"; -import _each from "lodash/each"; import _flatten from "lodash/flatten"; import _isEmpty from "lodash/isEmpty"; import _isObject from "lodash/isObject"; @@ -195,7 +194,8 @@ export const TaskMapContent = (props) => { // multiple features in a layer could match. Detect them and then // put them into an intuitive order const intraLayerMatches = []; - _each(layer._layers, (featureLayer) => { + + for (const featureLayer of Object.values(layer._layers)) { if (featureLayer.toGeoJSON) { const featureGeojson = featureLayer.toGeoJSON(); // Look for an overlap between the click and the feature. However, since marker @@ -232,7 +232,7 @@ export const TaskMapContent = (props) => { }); } } - }); + } if (intraLayerMatches.length > 0) { for (const match of orderedFeatureLayers(intraLayerMatches)) { @@ -467,9 +467,9 @@ export const TaskMapContent = (props) => { const generateDirectionalityMarkers = () => { const markers = []; const allFeatures = features; - _each(allFeatures, (feature, featureIndex) => { + for (const [featureIndex, feature] of allFeatures.entries()) { if (!feature.properties || !feature.properties.oneway) { - return; + continue; } const styles = AsSimpleStyleableFeature( @@ -500,7 +500,7 @@ export const TaskMapContent = (props) => { ); } } - }); + } setDirectionalityIndicators({ id: "directionality-indicators", diff --git a/src/components/TaskPropertyQueryBuilder/TaskPropertyRules.js b/src/components/TaskPropertyQueryBuilder/TaskPropertyRules.js index de17a9973..773ec5f4f 100644 --- a/src/components/TaskPropertyQueryBuilder/TaskPropertyRules.js +++ b/src/components/TaskPropertyQueryBuilder/TaskPropertyRules.js @@ -1,4 +1,3 @@ -import _each from "lodash/each"; import _filter from "lodash/filter"; import _slice from "lodash/slice"; import _values from "lodash/values"; @@ -276,11 +275,11 @@ export const validatePropertyRules = (rule, errors = []) => { } if (rule.valueType === "number") { - _each(rule.value, (v) => { + for (const v of Array.isArray(rule.value) ? rule.value : [rule.value]) { if (isNaN(v)) { errors.push(PROPERTY_RULE_ERRORS.notNumericValue); } - }); + } } } } diff --git a/src/components/Widgets/TaskHistoryWidget/TaskHistoryWidget.jsx b/src/components/Widgets/TaskHistoryWidget/TaskHistoryWidget.jsx index bc4ab56c9..6530d90ec 100644 --- a/src/components/Widgets/TaskHistoryWidget/TaskHistoryWidget.jsx +++ b/src/components/Widgets/TaskHistoryWidget/TaskHistoryWidget.jsx @@ -1,4 +1,3 @@ -import _each from "lodash/each"; import _remove from "lodash/remove"; import { Component, createRef } from "react"; import { FormattedMessage } from "react-intl"; @@ -63,7 +62,7 @@ export default class TaskHistoryWidget extends Component { let earliestDate = null; const usernames = []; - _each(this.props.task.history, (log) => { + for (const log of this.props.task.history) { if (!earliestDate || log.timestamp < earliestDate) { earliestDate = log.timestamp; } @@ -72,7 +71,7 @@ export default class TaskHistoryWidget extends Component { if (username && usernames.indexOf(username) === -1) { usernames.push(username); } - }); + } viewOSMCha(this.bbox(), earliestDate, usernames); }; diff --git a/src/interactions/Task/AsCooperativeWork.js b/src/interactions/Task/AsCooperativeWork.js index 9dd4bcb22..96706c026 100644 --- a/src/interactions/Task/AsCooperativeWork.js +++ b/src/interactions/Task/AsCooperativeWork.js @@ -1,9 +1,6 @@ import _compact from "lodash/compact"; -import _each from "lodash/each"; import _isEmpty from "lodash/isEmpty"; import _map from "lodash/map"; -import _toPairs from "lodash/toPairs"; -import _values from "lodash/values"; import { CooperativeType } from "../../services/Challenge/CooperativeType/CooperativeType"; /** @@ -120,41 +117,41 @@ export class AsCooperativeWork { } const diff = {}; - _each(osmElements.get(independentOperation.data.id).tag, (tag) => { + for (const tag of osmElements.get(independentOperation.data.id).tag) { diff[tag.k] = { name: tag.k, value: tag.v, newValue: tag.v, status: "unchanged", }; - }); + } - _each(independentOperation.data.operations, (dependentOperation) => { + for (const dependentOperation of independentOperation.data.operations) { switch (dependentOperation.operation) { case "setTags": - _each(_toPairs(dependentOperation.data), (tagComponents) => { - const diffEntry = diff[tagComponents[0]]; + for (const [key, value] of Object.entries(dependentOperation.data)) { + const diffEntry = diff[key]; if (!diffEntry) { // New tag - diff[tagComponents[0]] = { - name: tagComponents[0], + diff[key] = { + name: key, value: null, - newValue: tagComponents[1], + newValue: value, status: "added", }; - } else if (diffEntry.value !== tagComponents[1]) { + } else if (diffEntry.value !== value) { // Modified tag - diffEntry.newValue = tagComponents[1]; + diffEntry.newValue = value; diffEntry.status = "changed"; } else { - diffEntry.newValue = tagComponents[1]; + diffEntry.newValue = value; diffEntry.status = "resolved"; } - }); + } break; case "unsetTags": - _each(dependentOperation.data, (tagName) => { - const diffEntry = diff[tagName]; + for (const key of dependentOperation.data) { + const diffEntry = diff[key]; if (diffEntry) { // Delete tag diffEntry.newValue = null; @@ -163,12 +160,12 @@ export class AsCooperativeWork { diffEntry.newValue = null; diffEntry.status = "resolved"; } - }); + } break; default: break; } - }); + } return diff; }), @@ -201,21 +198,21 @@ export class AsCooperativeWork { if (tagEdits) { // Work from tag edits instead of dependent operations - _each(_values(tagEdits), (edit) => { + for (const edit of Object.values(tagEdits)) { if (edit.status === "added" || edit.status === "changed") { change.updates[edit.name] = edit.newValue; } else if (edit.status === "removed") { change.deletes.push(edit.name); } - }); + } } else { - _each(independentOperation.data.operations, (dependentOperation) => { + for (const dependentOperation of independentOperation.data.operations) { if (dependentOperation.operation === "setTags") { change.updates = Object.assign(change.updates, dependentOperation.data); } else if (dependentOperation.operation === "unsetTags") { change.deletes = change.deletes.concat(dependentOperation.data); } - }); + } } if (_isEmpty(change.updates) && _isEmpty(change.deletes)) { diff --git a/src/interactions/TaskCluster/AsSpiderableMarkers.js b/src/interactions/TaskCluster/AsSpiderableMarkers.js index bf03d9d20..740cfd46f 100644 --- a/src/interactions/TaskCluster/AsSpiderableMarkers.js +++ b/src/interactions/TaskCluster/AsSpiderableMarkers.js @@ -1,6 +1,5 @@ import { Point } from "leaflet"; import _cloneDeep from "lodash/cloneDeep"; -import _each from "lodash/each"; const MAX_CIRCLE_MARKERS = 8; const CIRCLE_START_ANGLE = (Math.PI * 2) / 12; @@ -31,7 +30,7 @@ export class AsSpiderableMarkers { const legLengthPx = circumferencePx / (Math.PI * 2); // radius from circumference const angleStep = (Math.PI * 2) / affectedMarkers.length; - _each(affectedMarkers, (marker, index) => { + for (const [index, marker] of affectedMarkers.entries()) { const relocatedMarker = _cloneDeep(marker); const angle = CIRCLE_START_ANGLE + index * angleStep; relocatedMarker.originalPosition = relocatedMarker.position; @@ -40,7 +39,7 @@ export class AsSpiderableMarkers { centerPointPx.y + legLengthPx * Math.sin(angle), ); spideredMarkers.set(relocatedMarker.options.taskId, relocatedMarker); - }); + } return spideredMarkers; } @@ -51,7 +50,7 @@ export class AsSpiderableMarkers { let legLengthPx = SPIRAL_LENGTH_START; let angle = 0; - _each(affectedMarkers, (marker, index) => { + for (const [index, marker] of affectedMarkers.entries()) { const relocatedMarker = _cloneDeep(marker); angle += SPIRAL_FOOT_SEPARATION / legLengthPx + index * 0.0005; relocatedMarker.originalPosition = relocatedMarker.position; @@ -61,7 +60,7 @@ export class AsSpiderableMarkers { ); legLengthPx += Math.PI * 2 * (SPIRAL_LENGTH_FACTOR / angle); spideredMarkers.set(relocatedMarker.options.taskId, relocatedMarker); - }); + } return spideredMarkers; } diff --git a/src/interactions/TaskFeature/AsSimpleStyleableFeature.js b/src/interactions/TaskFeature/AsSimpleStyleableFeature.js index 74b15596e..c8ddeeee6 100644 --- a/src/interactions/TaskFeature/AsSimpleStyleableFeature.js +++ b/src/interactions/TaskFeature/AsSimpleStyleableFeature.js @@ -2,7 +2,6 @@ import L from "leaflet"; import "leaflet-vectoricon"; import { getType } from "@turf/invariant"; import _compact from "lodash/compact"; -import _each from "lodash/each"; import _filter from "lodash/filter"; import _flatten from "lodash/flatten"; import _fromPairs from "lodash/fromPairs"; @@ -140,9 +139,9 @@ export class AsSimpleStyleableFeature { return; } - _each(lineStyles, (styleValue, styleName) => { + for (const [styleName, styleValue] of Object.entries(lineStyles)) { layer.setStyle({ [simplestyleLineToLeafletMapping[styleName]]: styleValue }); - }); + } } /** @@ -177,7 +176,7 @@ export class AsSimpleStyleableFeature { let useCustomMarker = false; - _each(pointStyles, (styleValue, styleName) => { + for (const [styleName, styleValue] of Object.entries(pointStyles)) { switch (styleName) { case "marker-color": useCustomMarker = true; @@ -206,7 +205,7 @@ export class AsSimpleStyleableFeature { default: break; } - }); + } // If the layer already has one of our svg markers, make sure to clean it // up or else Leaflet has a tendencey to render dup markers diff --git a/src/interactions/User/AsManager.js b/src/interactions/User/AsManager.js index 80ba9d984..c88d770d2 100644 --- a/src/interactions/User/AsManager.js +++ b/src/interactions/User/AsManager.js @@ -1,4 +1,3 @@ -import _each from "lodash/each"; import _filter from "lodash/filter"; import _isObject from "lodash/isObject"; import _map from "lodash/map"; @@ -142,20 +141,23 @@ export class AsManager extends AsEndUser { const projectChallenges = new Set(); - _each(challenges, (challenge) => { + for (const challenge of challenges) { // handle both normalized and denormalized challenges if (projectIds.indexOf(challenge?.parent?.id ?? challenge.parent) !== -1) { projectChallenges.add(challenge); } - _each(challenge.virtualParents, (vp) => { - if (projectIds.indexOf(_isObject(vp) ? vp.id : vp) !== -1) { - if (!projectChallenges.has(challenge)) { - projectChallenges.add(challenge); + if (challenge.virtualParents) { + for (const vp of challenge.virtualParents) { + if (projectIds.indexOf(_isObject(vp) ? vp.id : vp) !== -1) { + if (!projectChallenges.has(challenge)) { + projectChallenges.add(challenge); + } } } - }); - }); + } + } + return [...projectChallenges]; } diff --git a/src/pages/Inbox/Inbox.jsx b/src/pages/Inbox/Inbox.jsx index 2c251be47..36ddb3f18 100644 --- a/src/pages/Inbox/Inbox.jsx +++ b/src/pages/Inbox/Inbox.jsx @@ -1,6 +1,5 @@ import classNames from "classnames"; import Fuse from "fuse.js"; -import _each from "lodash/each"; import _kebabCase from "lodash/kebabCase"; import _map from "lodash/map"; import _reject from "lodash/reject"; @@ -247,13 +246,13 @@ const columns = (tableProps) => [ , ]; - _each(NotificationType, (type) => { + for (const [name, value] of Object.entries(NotificationType)) { options.push( - , ); - }); + } return ( { , ]; - _each(TaskPriority, (priority) => { + for (const [name, value] of Object.entries(TaskPriority)) { options.push( - , ); - }); + } return (