Skip to content

Commit

Permalink
Merge pull request #466 from WildMeOrg/develop
Browse files Browse the repository at this point in the history
PRs for v1.1.0 release
  • Loading branch information
Atticus29 committed Oct 6, 2022
2 parents cab8412 + b5a2b32 commit a111929
Show file tree
Hide file tree
Showing 136 changed files with 4,550 additions and 2,077 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"react/destructuring-assignment": 0,
"react/forbid-prop-types": 0,
"react/jsx-wrap-multilines": 0,
"react/style-prop-object": [2, { "allow": ["FormattedNumber"] }],
"react-hooks/exhaustive-deps": 1,
"import/prefer-default-export": 0,
"function-paren-newline": 0,
Expand Down
14 changes: 14 additions & 0 deletions docs/contribution-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ All displayed text must support translation - for this we use `react-intl`. Tran

If you want to help translate the project, that is very much appreciated and needed, but please don't do it by manually editing files in `/locale`. Your changes will wind up getting overwritten by Lokalise.

## Lodash

We frequently use a utility library called [lodash](https://lodash.com/docs/). When importing a utility function, be sure to use named imports rather than importing the entire library to reduce our bundle size. One incorrect import will cause the entire library to be bundled with the application.

```
import _ from 'lodash-es'; // incorrect, please don't do this
_.random(10);
import { random } from 'lodash-es'; // correct!
random(10);
```

In situations where a lodash utility and a native utility exist, we should use the native utility unless there is a reason to use lodash (eg. native JS `map` instead of `_.map()`).

## Conventions

- Any file with a React component should have the suffix `.jsx`
Expand Down
157 changes: 110 additions & 47 deletions locale/en.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codex-frontend",
"version": "1.0.2",
"version": "1.1.0",
"description": "",
"main": "index.js",
"scripts": {
Expand All @@ -10,6 +10,7 @@
"lint": "NODE_ENV=development BABEL_ENV=development ./node_modules/.bin/eslint --fix \"src/**/*.{js,jsx}\"",
"format": "./node_modules/.bin/prettier --write \"src/**/*.{js,jsx}\"",
"test": "echo \"Error: no test specified\" && exit 1",
"print-unused-keys": "node ./scripts/printUnusedKeys.js",
"clean": "rm -rf dist",
"build": "npm run clean && NODE_ENV=production webpack --config ./config/webpack/webpack.common.js",
"prepare": "husky install"
Expand Down Expand Up @@ -68,6 +69,7 @@
"eslint-plugin-react": "~7.28.0",
"eslint-plugin-react-hooks": "~4.3.0",
"file-loader": "^6.2.0",
"find-in-files": "^0.5.0",
"html-webpack-plugin": "^5.0.0",
"husky": "^7.0.4",
"lint-staged": ">=8",
Expand Down
45 changes: 45 additions & 0 deletions scripts/printUnusedKeys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const { find } = require('find-in-files');
const englishTranslations = require('../locale/en.json');

const translationKeys = Object.keys(englishTranslations);
let unusedCount = 0;

function getLinesWithMatch(lines, substring) {
return lines.filter(line => line.includes(substring));
}

async function printUnusedKeys() {
/* eslint-disable */
for await (const translationKey of translationKeys) {
const results = await find(translationKey, './src');
const matches = Object.values(results);
const trueMatches = matches.filter(match => {
const matchingLines = match?.line || [];
const linesWithSingleQuoteMatch = getLinesWithMatch(
matchingLines,
`"${translationKey}"`,
);
const linesWithDoubleQuoteMatch = getLinesWithMatch(
matchingLines,
`\'${translationKey}\'`,
);
return (
linesWithSingleQuoteMatch.length > 0 ||
linesWithDoubleQuoteMatch.length > 0
);
});
if (trueMatches.length === 0) {
unusedCount += 1;
console.log(`"${translationKey}" may be unused.`);
}
}
/* eslint-enable */
console.log(
`Script finished. ${unusedCount} potentially unused translation keys found.`,
);
}

console.log(
'FYI, this script takes forever to run! Recommendation is to leave it running overnight or in the background.',
);
printUnusedKeys();
40 changes: 26 additions & 14 deletions src/AuthenticatedSwitch.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ import ControlPanel from './pages/controlPanel/ControlPanel';
import AssignEncounters from './pages/assignEncounters/AssignEncounters';
import CreateIndividual from './pages/createIndividual/CreateIndividual';
import Individual from './pages/individual/Individual';
import IndividualGallery from './pages/individualGallery/IndividualGallery';
// import PictureBook from './pages/individual/PictureBook';
import Sighting from './pages/sighting/Sighting';
import AssetGroupSighting from './pages/sighting/AssetGroupSighting';
import Splash from './pages/splash/Splash';
import SocialGroups from './pages/socialGroups/SocialGroups';
import SocialGroup from './pages/socialGroups/SocialGroup';
import AssetGroup from './pages/assetGroup/AssetGroup';
import PendingCitizenScienceSightings from './pages/pendingCitizenScienceSightings/PendingCitizenScienceSightings';
import User from './pages/user/User';
Expand All @@ -39,7 +42,7 @@ import AuditLog from './pages/devTools/AuditLog';
import Welcome from './pages/auth/Welcome';
import EmailVerified from './pages/auth/EmailVerified';
import Home from './pages/home/Home';
import Settings from './pages/settings/Settings';
import Preferences from './pages/preferences/Preferences';
import ResendVerificationEmail from './pages/auth/ResendVerificationEmail';
import Footer from './components/Footer';
import { defaultCrossfadeDuration } from './constants/defaults';
Expand Down Expand Up @@ -94,36 +97,42 @@ export default function AuthenticatedSwitch({
<SiteSetup />
) : (
<Switch location={location}>
<Route path="/admin/front-page" exact>
<Route path="/settings/front-page" exact>
<SplashSettings />
</Route>
<Route path="/admin/front-page/preview">
<Route path="/settings/front-page/preview">
<Splash />
</Route>
<Route path="/admin/status">
<Route path="/settings/status">
<SiteStatus />
</Route>
<Route path="/admin/users">
<Route path="/settings/users">
<UserManagement />
</Route>
<Route path="/admin/actions">
<Route path="/settings/actions">
<AdminActions />
</Route>
<Route path="/admin/fields/save-custom-field/:type?/:id?">
<Route path="/settings/fields/save-custom-field/:type?/:id?">
<SaveCustomField />
</Route>
<Route path="/admin/fields">
<Route path="/settings/fields">
<FieldManagement />
</Route>
<Route path="/admin/settings">
<Route path="/settings/general">
<GeneralSettings />
</Route>
<Route path="/email_verified">
<EmailVerified />
<Route path="/settings/social-groups">
<SocialGroups />
</Route>
<Route path="/settings/preferences">
<Preferences />
</Route>
<Route path="/admin">
<Route path="/settings">
<ControlPanel />
</Route>
<Route path="/email_verified">
<EmailVerified />
</Route>
<Route path="/create-individual">
<CreateIndividual />
</Route>
Expand All @@ -133,6 +142,9 @@ export default function AuthenticatedSwitch({
{/* <Route path="/individuals/picturebook">
<PictureBook />
</Route> */}
<Route path="/individuals/:guid/gallery">
<IndividualGallery />
</Route>
<Route path="/individuals/:id">
<Individual />
</Route>
Expand Down Expand Up @@ -172,8 +184,8 @@ export default function AuthenticatedSwitch({
<Route path="/users">
<Users />
</Route>
<Route path="/settings">
<Settings />
<Route path="/social-groups/:guid">
<SocialGroup />
</Route>
<Route path="/bulk-import/success/:id">
<BulkImportSuccess />
Expand Down
8 changes: 2 additions & 6 deletions src/components/ActionIcon.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import IconButton from '@material-ui/core/IconButton';
import EditIcon from '@material-ui/icons/Edit';
import ViewIcon from '@material-ui/icons/Launch';
import DeleteIcon from '@material-ui/icons/Delete';
import RemoveCircleIcon from '@material-ui/icons/RemoveCircle';
import DownloadIcon from '@material-ui/icons/GetApp';
import CopyIcon from '@material-ui/icons/FileCopy';
import RestoreIcon from '@material-ui/icons/Restore';

import Link from './Link';

Expand All @@ -22,11 +22,7 @@ const variantMap = {
},
revoke: {
labelId: 'MUTUAL_REVOKE',
component: DeleteIcon,
},
restore: {
labelId: 'RESTORE',
component: RestoreIcon,
component: RemoveCircleIcon,
},
delete: {
labelId: 'DELETE',
Expand Down
14 changes: 2 additions & 12 deletions src/components/AuthenticatedAppHeader/ActionsPane.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import Popover from '@material-ui/core/Popover';
import MenuItem from '@material-ui/core/MenuItem';
import MenuList from '@material-ui/core/MenuList';
import Divider from '@material-ui/core/Divider';
import SettingsIcon from '@material-ui/icons/Settings';
import PublicIcon from '@material-ui/icons/SupervisedUserCircle';
import ControlPanelIcon from '@material-ui/icons/PermDataSetting';
import BulkImportIcon from '@material-ui/icons/PostAdd';
Expand All @@ -27,22 +26,13 @@ const actions = [
{
id: 'pending-citizen-science-sightings',
href: '/pending-citizen-science-sightings',
permissionsTest: userData =>
userData?.is_admin || userData?.is_data_manager,
permissionsTest: userData => userData?.is_admin,
messageId: 'PENDING_CITIZEN_SCIENCE_SIGHTINGS',
icon: PublicIcon,
},
{
id: 'settings',
href: '/settings',
messageId: 'SETTINGS_AND_PRIVACY',
icon: SettingsIcon,
},
{
id: 'control-panel',
href: '/admin',
permissionsTest: userData =>
userData?.is_admin || userData?.is_user_manager,
href: '/settings',
messageId: 'CONTROL_PANEL',
icon: ControlPanelIcon,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ export default function NotificationPaneDisplayText({
theirIndividualName,
theirIndividualGuid,
formattedDeadline,
otherUserGuidForManagerNotifications,
otherUserNameForManagerNotifications,
managerName,
timeSince,
}) {
const theme = useTheme();
Expand Down Expand Up @@ -54,6 +57,17 @@ export default function NotificationPaneDisplayText({
</span>
),
formattedDeadline,
otherUserNameForManagerNotifications: (
<span>
<Link
newTab
href={`/users/${otherUserGuidForManagerNotifications}`}
>
{otherUserNameForManagerNotifications}
</Link>
</span>
),
managerName,
}}
/>
<Text
Expand Down
17 changes: 16 additions & 1 deletion src/components/AuthenticatedAppHeader/NotificationsPane.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default function NotificationsPane({
refreshNotifications,
shouldOpen,
setShouldOpen,
currentUserGuid,
}) {
const intl = useIntl();
const queryClient = useQueryClient();
Expand Down Expand Up @@ -85,7 +86,14 @@ export default function NotificationsPane({
theirIndividualName,
theirIndividualGuid,
formattedDeadline,
} = getNotificationProps(intl, notification);
otherUserGuidForManagerNotifications,
otherUserNameForManagerNotifications,
managerName,
} = getNotificationProps(
intl,
notification,
currentUserGuid,
);
const deriveButtonPath = get(
currentNotificationSchema,
'deriveButtonPath',
Expand Down Expand Up @@ -130,6 +138,13 @@ export default function NotificationsPane({
theirIndividualName={theirIndividualName}
theirIndividualGuid={theirIndividualGuid}
formattedDeadline={formattedDeadline}
otherUserGuidForManagerNotifications={
otherUserGuidForManagerNotifications
}
otherUserNameForManagerNotifications={
otherUserNameForManagerNotifications
}
managerName={managerName}
timeSince={timeSince}
/>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/components/AuthenticatedAppHeader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export default function AppHeader() {
refreshNotifications={refreshNotifications}
shouldOpen={shouldOpenNotificationPane}
setShouldOpen={setShouldOpenNotificationPane}
currentUserGuid={meData?.guid}
/>
<HeaderButton
onClick={e => setUserMenuAnchorEl(e.currentTarget)}
Expand Down
12 changes: 7 additions & 5 deletions src/components/BannerLogo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ export default function BannerLogo({
>
<div style={{ display: 'flex', alignItems: 'center' }}>
{logo ? (
<img
alt={`Logo for ${siteName}`}
src={logo}
style={{ height: 52, flexShrink: 0 }}
/>
<div>
<img
alt={`Logo for ${siteName}`}
src={logo}
style={{ height: 52, flexShrink: 0 }}
/>
</div>
) : (
<InstanceLogo
style={{
Expand Down
2 changes: 1 addition & 1 deletion src/components/SettingsBreadcrumbs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default function SettingsBreadcrumbs({
<Link href="/" style={linkStyles}>
<Text id="HOME" />
</Link>
<Link href="/admin" style={linkStyles}>
<Link href="/settings" style={linkStyles}>
<Text id="CONTROL_PANEL" />
</Link>
<Text id={currentPageTextId}>{currentPageText}</Text>
Expand Down
Loading

0 comments on commit a111929

Please sign in to comment.