From 03ff779ca339fcd525b0ca7bb2cd364bc230a04a Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Fri, 15 May 2020 10:07:42 -0400 Subject: [PATCH] Moved src/utils out of src/ folder to utilities/ folder. (#7875) --- app/javascript/Search/Search.jsx | 2 +- app/javascript/analytics/client.js | 6 +-- app/javascript/chat/actions.js | 2 +- app/javascript/chat/chat.jsx | 15 ++++--- app/javascript/listings/listings.jsx | 4 +- app/javascript/packs/Onboarding.jsx | 2 +- .../packs/onboardingRedirectCheck.jsx | 8 ++-- app/javascript/readingList/readingList.jsx | 2 +- .../searchableItemList/searchableItemList.js | 2 +- app/javascript/shared/components/tags.jsx | 31 +++++++------- .../sidebar-widget/SidebarWidget.jsx | 10 ++--- .../__tests__/search.test.js | 2 +- .../connect}/getUnopenedChannels.jsx | 42 ++++++++++--------- app/javascript/utilities/connect/index.js | 2 + .../utils => utilities/connect}/pusher.js | 4 +- .../utils => utilities}/debounceAction.js | 0 .../{src/utils => utilities/http}/errors.js | 4 +- app/javascript/utilities/http/index.js | 1 + .../search.js => utilities/search/index.js} | 2 +- .../utils => utilities}/sendFollowUser.js | 6 +-- 20 files changed, 79 insertions(+), 68 deletions(-) rename app/javascript/{src/utils => utilities}/__tests__/search.test.js (99%) rename app/javascript/{src/utils => utilities/connect}/getUnopenedChannels.jsx (82%) create mode 100644 app/javascript/utilities/connect/index.js rename app/javascript/{src/utils => utilities/connect}/pusher.js (90%) rename app/javascript/{src/utils => utilities}/debounceAction.js (100%) rename app/javascript/{src/utils => utilities/http}/errors.js (82%) rename app/javascript/{src/utils/search.js => utilities/search/index.js} (98%) rename app/javascript/{src/utils => utilities}/sendFollowUser.js (89%) diff --git a/app/javascript/Search/Search.jsx b/app/javascript/Search/Search.jsx index 19e8c6874..ab5ebc3ed 100644 --- a/app/javascript/Search/Search.jsx +++ b/app/javascript/Search/Search.jsx @@ -6,7 +6,7 @@ import { hasInstantClick, preloadSearchResults, displaySearchResults, -} from '../src/utils/search'; +} from '../utilities/search'; import { SearchForm } from './SearchForm'; const GLOBAL_MINIMIZE_KEY = '0'; diff --git a/app/javascript/analytics/client.js b/app/javascript/analytics/client.js index 6b3457738..6fd14adc0 100644 --- a/app/javascript/analytics/client.js +++ b/app/javascript/analytics/client.js @@ -1,4 +1,4 @@ -import handleFetchAPIErrors from '../src/utils/errors'; +import { handleFetchAPIErrors } from '../utilities/http'; function callAnalyticsAPI(path, date, { organizationId, articleId }, callback) { let url = `${path}?start=${date.toISOString().split('T')[0]}`; @@ -12,10 +12,10 @@ function callAnalyticsAPI(path, date, { organizationId, articleId }, callback) { fetch(url) .then(handleFetchAPIErrors) - .then(response => response.json()) + .then((response) => response.json()) .then(callback) // eslint-disable-next-line no-console - .catch(error => console.error(error)); // we should come up with better error handling + .catch((error) => console.error(error)); // we should come up with better error handling } export function callHistoricalAPI( diff --git a/app/javascript/chat/actions.js b/app/javascript/chat/actions.js index 903706109..23938fa9f 100644 --- a/app/javascript/chat/actions.js +++ b/app/javascript/chat/actions.js @@ -1,4 +1,4 @@ -import { fetchSearch } from '../src/utils/search'; +import { fetchSearch } from '../utilities/search'; export function getAllMessages(channelId, messageOffset, successCb, failureCb) { fetch(`/chat_channels/${channelId}?message_offset=${messageOffset}`, { diff --git a/app/javascript/chat/chat.jsx b/app/javascript/chat/chat.jsx index 71d5cd7c4..35f7a2658 100644 --- a/app/javascript/chat/chat.jsx +++ b/app/javascript/chat/chat.jsx @@ -31,8 +31,8 @@ import ActionMessage from './actionMessage'; import Content from './content'; import VideoContent from './videoContent'; -import setupPusher from '../src/utils/pusher'; -import debounceAction from '../src/utils/debounceAction'; +import { setupPusher } from '../utilities/connect'; +import debounceAction from '../utilities/debounceAction'; export default class Chat extends Component { static propTypes = { @@ -206,8 +206,11 @@ export default class Chat extends Component { loadChannels = (channels, query) => { const { activeChannelId } = this.state; - const activeChannel = this.state.activeChannel || - channels.filter((channel) => channel.chat_channel_id === activeChannelId)[0]; + const activeChannel = + this.state.activeChannel || + channels.filter( + (channel) => channel.chat_channel_id === activeChannelId, + )[0]; if (activeChannelId && query.length === 0) { this.setState({ chatChannels: channels, @@ -282,7 +285,7 @@ export default class Chat extends Component { }; loadPaginatedChannels = (channels) => { - const {state} = this; + const { state } = this; const currentChannels = state.chatChannels; const currentChannelIds = currentChannels.map((channel) => channel.id); const newChannels = currentChannels; @@ -1113,7 +1116,7 @@ export default class Chat extends Component { toggleSearchShowing = () => { if (!this.state.searchShowing) { - setTimeout(function () { + setTimeout(() => { document.getElementById('chatchannelsearchbar').focus(); }, 100); } else { diff --git a/app/javascript/listings/listings.jsx b/app/javascript/listings/listings.jsx index 4d2202b6d..2333ac250 100644 --- a/app/javascript/listings/listings.jsx +++ b/app/javascript/listings/listings.jsx @@ -1,6 +1,6 @@ import { h, Component } from 'preact'; -import debounceAction from '../src/utils/debounceAction'; -import { fetchSearch } from '../src/utils/search'; +import debounceAction from '../utilities/debounceAction'; +import { fetchSearch } from '../utilities/search'; import ModalBackground from './components/ModalBackground'; import Modal from './components/Modal'; import AllListings from './components/AllListings'; diff --git a/app/javascript/packs/Onboarding.jsx b/app/javascript/packs/Onboarding.jsx index 58f02db70..49b54b6e0 100644 --- a/app/javascript/packs/Onboarding.jsx +++ b/app/javascript/packs/Onboarding.jsx @@ -1,6 +1,6 @@ import { h, render } from 'preact'; import { getUserDataAndCsrfToken } from '../chat/util'; -import getUnopenedChannels from '../src/utils/getUnopenedChannels'; +import { getUnopenedChannels } from '../utilities/connect'; HTMLDocument.prototype.ready = new Promise((resolve) => { if (document.readyState !== 'loading') { diff --git a/app/javascript/packs/onboardingRedirectCheck.jsx b/app/javascript/packs/onboardingRedirectCheck.jsx index 08050eeb9..1158841ea 100644 --- a/app/javascript/packs/onboardingRedirectCheck.jsx +++ b/app/javascript/packs/onboardingRedirectCheck.jsx @@ -1,7 +1,7 @@ import { getUserDataAndCsrfToken } from '../chat/util'; -import getUnopenedChannels from '../src/utils/getUnopenedChannels'; +import { getUnopenedChannels } from '../utilities/connect'; -HTMLDocument.prototype.ready = new Promise(resolve => { +HTMLDocument.prototype.ready = new Promise((resolve) => { if (document.readyState !== 'loading') { return resolve(); } @@ -36,7 +36,7 @@ document.ready.then( window.location = `${window.location.origin}/onboarding?referrer=${window.location}`; } }) - .catch(error => { + .catch((error) => { // eslint-disable-next-line no-console console.error('Error getting user and CSRF Token', error); }), @@ -53,7 +53,7 @@ window.InstantClick.on('change', () => { window.location = `${window.location.origin}/onboarding?referrer=${window.location}`; } }) - .catch(error => { + .catch((error) => { // eslint-disable-next-line no-console console.error('Error getting user and CSRF Token', error); }); diff --git a/app/javascript/readingList/readingList.jsx b/app/javascript/readingList/readingList.jsx index ff059640c..dfd76d77c 100644 --- a/app/javascript/readingList/readingList.jsx +++ b/app/javascript/readingList/readingList.jsx @@ -1,6 +1,6 @@ import { h, Component } from 'preact'; import { PropTypes } from 'preact-compat'; -import debounceAction from '../src/utils/debounceAction'; +import debounceAction from '../utilities/debounceAction'; import { defaultState, diff --git a/app/javascript/searchableItemList/searchableItemList.js b/app/javascript/searchableItemList/searchableItemList.js index 3507d3b4b..91486cb96 100644 --- a/app/javascript/searchableItemList/searchableItemList.js +++ b/app/javascript/searchableItemList/searchableItemList.js @@ -1,5 +1,5 @@ // Shared behavior between the reading list and history pages -import { fetchSearch } from '../src/utils/search'; +import { fetchSearch } from '../utilities/search'; // Provides the initial state for the component export function defaultState(options) { diff --git a/app/javascript/shared/components/tags.jsx b/app/javascript/shared/components/tags.jsx index 4d3988168..eadd786c7 100644 --- a/app/javascript/shared/components/tags.jsx +++ b/app/javascript/shared/components/tags.jsx @@ -1,6 +1,6 @@ import { h, Component } from 'preact'; import PropTypes from 'prop-types'; -import { fetchSearch } from '../../src/utils/search'; +import { fetchSearch } from '../../utilities/search'; const KEYS = { UP: 'ArrowUp', @@ -95,8 +95,8 @@ class Tags extends Component { const { defaultValue } = this.props; return defaultValue .split(',') - .map(item => item !== undefined && item.trim()) - .filter(item => item.length > 0); + .map((item) => item !== undefined && item.trim()) + .filter((item) => item.length > 0); } get isTopOfSearchResults() { @@ -159,7 +159,7 @@ class Tags extends Component { return [start, end]; }; - handleKeyDown = e => { + handleKeyDown = (e) => { const component = this; const { maxTags } = this.props; if (component.selected.length === maxTags && e.key === KEYS.COMMA) { @@ -205,7 +205,7 @@ class Tags extends Component { } }; - handleRulesClick = e => { + handleRulesClick = (e) => { e.preventDefault(); const { showingRulesForTag } = this.state; if (showingRulesForTag === e.target.dataset.content) { @@ -215,7 +215,7 @@ class Tags extends Component { } }; - handleTagClick = e => { + handleTagClick = (e) => { if (e.target.className === 'articleform__tagsoptionrulesbutton') { return; } @@ -229,7 +229,7 @@ class Tags extends Component { this.insertTag(e.currentTarget.dataset.content); }; - handleInput = e => { + handleInput = (e) => { let { value } = e.target; // If we start typing immediately after a comma, add a space // before what we typed. @@ -277,7 +277,7 @@ class Tags extends Component { return `${value.slice(0, position)} ${value.slice(position, value.length)}`; }; - handleTagEnter = e => { + handleTagEnter = (e) => { if (e.key === KEYS.RETURN) { this.handleTagClick(); } @@ -307,7 +307,7 @@ class Tags extends Component { search(query) { if (query === '') { - return new Promise(resolve => { + return new Promise((resolve) => { setTimeout(() => { this.resetSearchResults(); resolve(); @@ -319,15 +319,15 @@ class Tags extends Component { const dataHash = { name: query }; const responsePromise = fetchSearch('tags', dataHash); - return responsePromise.then(response => { + return responsePromise.then((response) => { if (listing === true) { const { additionalTags } = this.state; const { category } = this.props; - const additionalItems = (additionalTags[category] || []).filter(t => + const additionalItems = (additionalTags[category] || []).filter((t) => t.includes(query), ); const resultsArray = response.result; - additionalItems.forEach(t => { + additionalItems.forEach((t) => { if (!resultsArray.includes(t)) { resultsArray.push({ name: t }); } @@ -348,13 +348,13 @@ class Tags extends Component { } moveUpInSearchResults() { - this.setState(prevState => ({ + this.setState((prevState) => ({ selectedIndex: prevState.selectedIndex - 1, })); } moveDownInSearchResults() { - this.setState(prevState => ({ + this.setState((prevState) => ({ selectedIndex: prevState.selectedIndex + 1, })); } @@ -398,6 +398,7 @@ class Tags extends Component { className={`${classPrefix}__tagrules--${ showingRulesForTag === tag.name ? 'active' : 'inactive' }`} + // eslint-disable-next-line react/no-danger dangerouslySetInnerHTML={{ __html: tag.rules_html }} /> @@ -427,7 +428,7 @@ class Tags extends Component { { + ref={(t) => { this.textArea = t; return this.textArea; }} diff --git a/app/javascript/sidebar-widget/SidebarWidget.jsx b/app/javascript/sidebar-widget/SidebarWidget.jsx index 7c2c347a1..1b04d0fb6 100644 --- a/app/javascript/sidebar-widget/SidebarWidget.jsx +++ b/app/javascript/sidebar-widget/SidebarWidget.jsx @@ -1,5 +1,5 @@ import { h, Component } from 'preact'; -import sendFollowUser from '../src/utils/sendFollowUser'; +import sendFollowUser from '../utilities/sendFollowUser'; import SidebarUser from './sidebarUser'; class SidebarWidget extends Component { @@ -36,11 +36,11 @@ class SidebarWidget extends Component { }, credentials: 'same-origin', }) - .then(response => response.json()) - .then(json => { + .then((response) => response.json()) + .then((json) => { this.setState({ suggestedUsers: json }); }) - .catch(error => { + .catch((error) => { this.setState({ suggestedUsers: [] }); Honeybadger.notify(error); }); @@ -57,7 +57,7 @@ class SidebarWidget extends Component { ); followBtn.innerText = updatedUser.following ? '+ FOLLOW' : '✓ FOLLOWING'; - const toggleFollowState = newFollowState => { + const toggleFollowState = (newFollowState) => { updatedUser.following = newFollowState === 'followed'; updatedSuggestedUsers[userIndex] = updatedUser; this.setState({ suggestedUsers: updatedSuggestedUsers }); diff --git a/app/javascript/src/utils/__tests__/search.test.js b/app/javascript/utilities/__tests__/search.test.js similarity index 99% rename from app/javascript/src/utils/__tests__/search.test.js rename to app/javascript/utilities/__tests__/search.test.js index b7702f075..4585fc8bd 100644 --- a/app/javascript/src/utils/__tests__/search.test.js +++ b/app/javascript/utilities/__tests__/search.test.js @@ -7,7 +7,7 @@ import { fetchSearch, createSearchUrl, } from '../search'; -import '../../../../assets/javascripts/lib/xss'; +import '../../../assets/javascripts/lib/xss'; /* global globalThis */ diff --git a/app/javascript/src/utils/getUnopenedChannels.jsx b/app/javascript/utilities/connect/getUnopenedChannels.jsx similarity index 82% rename from app/javascript/src/utils/getUnopenedChannels.jsx rename to app/javascript/utilities/connect/getUnopenedChannels.jsx index 4b0913dda..01baccf8b 100644 --- a/app/javascript/src/utils/getUnopenedChannels.jsx +++ b/app/javascript/utilities/connect/getUnopenedChannels.jsx @@ -1,6 +1,8 @@ import { h, render, Component } from 'preact'; import PropTypes from 'prop-types'; -import setupPusher from './pusher'; +import { setupPusher } from './pusher'; + +/* global userData */ class UnopenedChannelNotice extends Component { propTypes = { @@ -38,16 +40,18 @@ class UnopenedChannelNotice extends Component { }; } - updateMessageNotification = unopenedChannels => { + updateMessageNotification = (unopenedChannels) => { const number = document.getElementById('connect-number'); this.setState({ unopenedChannels }); if (unopenedChannels.length > 0) { - if (unopenedChannels[0].adjusted_slug === "@"+userData().username) { + if (unopenedChannels[0].adjusted_slug === `@${userData().username}`) { return; } number.classList.remove('hidden'); number.innerHTML = unopenedChannels.length; - document.getElementById('connect-link').href = '/connect/' + unopenedChannels[0].adjusted_slug; + document.getElementById( + 'connect-link', + ).href = `/connect/${unopenedChannels[0].adjusted_slug}`; InstantClick.preload( document.getElementById('connect-link').href, 'force', @@ -61,13 +65,13 @@ class UnopenedChannelNotice extends Component { updateMessage = () => {}; - mentionedMessage = e => { + mentionedMessage = (e) => { if (window.location.pathname.startsWith('/connect')) { return; } - this.setState(prevState => ({ - unopenedChannels: prevState.unopenedChannels.map(unopenedChannel => + this.setState((prevState) => ({ + unopenedChannels: prevState.unopenedChannels.map((unopenedChannel) => unopenedChannel.adjusted_slug === e.chat_channel_adjusted_slug ? { ...unopenedChannel, request_type: 'mentioned' } : unopenedChannel, @@ -78,7 +82,7 @@ class UnopenedChannelNotice extends Component { this.hideNotice(); }; - messageOpened = e => { + messageOpened = (e) => { const { unopenedChannels } = this.state; if ( !window.location.pathname.startsWith('/connect') || @@ -87,12 +91,12 @@ class UnopenedChannelNotice extends Component { return; this.updateMessageNotification( unopenedChannels.filter( - unopenedChannel => unopenedChannel.adjusted_slug !== e.adjusted_slug, + (unopenedChannel) => unopenedChannel.adjusted_slug !== e.adjusted_slug, ), ); }; - receiveNewMessage = e => { + receiveNewMessage = (e) => { if ( (window.location.pathname.startsWith('/connect') && e.user_id === window.currentUser.id && @@ -105,7 +109,7 @@ class UnopenedChannelNotice extends Component { const newObj = { adjusted_slug: e.chat_channel_adjusted_slug }; const ifMessageExist = unopenedChannels.some( - channel => channel.adjusted_slug === newObj.adjusted_slug, + (channel) => channel.adjusted_slug === newObj.adjusted_slug, ); if ( @@ -116,7 +120,7 @@ class UnopenedChannelNotice extends Component { } if (ifMessageExist) { const index = unopenedChannels.findIndex( - channel => channel.adjusted_slug === newObj.adjusted_slug, + (channel) => channel.adjusted_slug === newObj.adjusted_slug, ); unopenedChannels[index].notified = false; } @@ -139,8 +143,8 @@ class UnopenedChannelNotice extends Component { hideNotice = () => { setTimeout(() => { - this.setState(prevState => ({ - unopenedChannels: prevState.unopenedChannels.map(unopenedChannel => + this.setState((prevState) => ({ + unopenedChannels: prevState.unopenedChannels.map((unopenedChannel) => !unopenedChannel.notified ? { ...unopenedChannel, notified: true } : unopenedChannel, @@ -150,20 +154,20 @@ class UnopenedChannelNotice extends Component { }, 7500); }; - fetchUnopenedChannel = successCb => { + fetchUnopenedChannel = (successCb) => { fetch('/chat_channels?state=unopened', { Accept: 'application/json', 'Content-Type': 'application/json', credentials: 'same-origin', }) - .then(response => response.json()) + .then((response) => response.json()) .then(successCb); }; render() { const { visible, unopenedChannels } = this.state; - if (visible && unopenedChannels.some(channel => !channel.notified)) { - const message = unopenedChannels.map(channel => { + if (visible && unopenedChannels.some((channel) => !channel.notified)) { + const message = unopenedChannels.map((channel) => { if (channel.notified) return null; return (
@@ -218,7 +222,7 @@ class UnopenedChannelNotice extends Component { } } -export default function getUnopenedChannels() { +export function getUnopenedChannels() { if (window.frameElement) { return; } diff --git a/app/javascript/utilities/connect/index.js b/app/javascript/utilities/connect/index.js new file mode 100644 index 000000000..00097da1e --- /dev/null +++ b/app/javascript/utilities/connect/index.js @@ -0,0 +1,2 @@ +export * from './getUnopenedChannels'; +export * from './pusher'; diff --git a/app/javascript/src/utils/pusher.js b/app/javascript/utilities/connect/pusher.js similarity index 90% rename from app/javascript/src/utils/pusher.js rename to app/javascript/utilities/connect/pusher.js index 01ad3d32f..b97e3d09b 100644 --- a/app/javascript/src/utils/pusher.js +++ b/app/javascript/utilities/connect/pusher.js @@ -1,7 +1,7 @@ // import Pusher from 'pusher-js'; -export default function setupPusher(key, callbackObjects) { - return import('pusher-js').then(_ => { +export function setupPusher(key, callbackObjects) { + return import('pusher-js').then((_) => { const { pusher = new Pusher(key, { authEndpoint: '/pusher/auth', diff --git a/app/javascript/src/utils/debounceAction.js b/app/javascript/utilities/debounceAction.js similarity index 100% rename from app/javascript/src/utils/debounceAction.js rename to app/javascript/utilities/debounceAction.js diff --git a/app/javascript/src/utils/errors.js b/app/javascript/utilities/http/errors.js similarity index 82% rename from app/javascript/src/utils/errors.js rename to app/javascript/utilities/http/errors.js index 290ad9458..a07500fcc 100644 --- a/app/javascript/src/utils/errors.js +++ b/app/javascript/utilities/http/errors.js @@ -1,5 +1,5 @@ // eslint-disable-next-line consistent-return -export default function handleFetchAPIErrors(response) { +export function handleFetchAPIErrors(response) { // pass along a correct response if (response.ok) { return response; @@ -8,7 +8,7 @@ export default function handleFetchAPIErrors(response) { // API errors contain the error message in {"error": "error message"} // but they could be unhandled 500 errors try { - response.json().then(data => { + response.json().then((data) => { throw new Error(data.error); }); } catch (e) { diff --git a/app/javascript/utilities/http/index.js b/app/javascript/utilities/http/index.js index 56e4b0555..efaf8a803 100644 --- a/app/javascript/utilities/http/index.js +++ b/app/javascript/utilities/http/index.js @@ -1 +1,2 @@ +export * from './errors'; export * from './request'; diff --git a/app/javascript/src/utils/search.js b/app/javascript/utilities/search/index.js similarity index 98% rename from app/javascript/src/utils/search.js rename to app/javascript/utilities/search/index.js index 357b472cd..12d57a30f 100644 --- a/app/javascript/src/utils/search.js +++ b/app/javascript/utilities/search/index.js @@ -1,7 +1,7 @@ // TODO: We should really be using the xss package by installing it in package.json // but for now filterXSS is global because of legacy JS -import { request } from '../../utilities/http'; +import { request } from '../http'; function getParameterByName(name, url = window.location.href) { const sanitizedName = name.replace(/[[\]]/g, '\\$&'); diff --git a/app/javascript/src/utils/sendFollowUser.js b/app/javascript/utilities/sendFollowUser.js similarity index 89% rename from app/javascript/src/utils/sendFollowUser.js rename to app/javascript/utilities/sendFollowUser.js index 8b08fc839..5ace59485 100644 --- a/app/javascript/src/utils/sendFollowUser.js +++ b/app/javascript/utilities/sendFollowUser.js @@ -14,12 +14,12 @@ export default function sendFollowUser(user, successCb) { body: formData, credentials: 'same-origin', }) - .then(response => response.json()) - .then(json => { + .then((response) => response.json()) + .then((json) => { successCb(json.outcome); // json is followed or unfollowed }) - .catch(error => { + .catch((error) => { // TODO: Add client-side error tracking. See https://github.com/thepracticaldev/dev.to/issues/2501 // for the discussion. console.log(error); // eslint-disable-line no-console