From a358de29d40e3953c7094a91ed3fe5c8c1761d41 Mon Sep 17 00:00:00 2001 From: Jeremy Sampson Date: Thu, 1 Aug 2024 08:38:31 -0600 Subject: [PATCH] v2.10.0 (#77) * package sync, docker based test build and test execution * add docker based environment * update dockerignore * add env params to docker build command * prepare v2.10.0 --- .dockerignore | 7 +++ build.Dockerfile | 14 ++++++ index.js | 1 - jest.config.js | 8 +++- lib/components/NeonPage/NeonPage.d.ts | 3 ++ lib/components/NeonPage/NeonPage.js | 27 ++++++++++- package-lock.json | 48 +++++++++---------- package.json | 24 +++++++--- scripts/jest-global-setup.js | 5 ++ .../__snapshots__/DownloadStepForm.jsx.snap | 2 +- .../__tests__/__snapshots__/UserCard.jsx.snap | 2 +- .../components/NeonPage/NeonPage.jsx | 36 +++++++++++++- .../components/NeonPage/StyleGuide.jsx | 46 ++++++++++++++++++ 13 files changed, 186 insertions(+), 37 deletions(-) create mode 100644 .dockerignore create mode 100644 build.Dockerfile delete mode 100644 index.js create mode 100644 scripts/jest-global-setup.js diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..d71e6f1c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.git +node_modules +build +test-coverage +reference + +.DS_Store diff --git a/build.Dockerfile b/build.Dockerfile new file mode 100644 index 00000000..7d4e9724 --- /dev/null +++ b/build.Dockerfile @@ -0,0 +1,14 @@ +FROM node:22.5-alpine + +EXPOSE 3000 +EXPOSE 3010 + +WORKDIR /app +COPY . ./build-temp + +WORKDIR /app/build-temp +RUN npm ci + +WORKDIR /app +RUN mv ./build-temp/node_modules ./ +RUN rm -rf ./build-temp diff --git a/index.js b/index.js deleted file mode 100644 index ca9e8d6f..00000000 --- a/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require("./src/"); diff --git a/jest.config.js b/jest.config.js index c9d36ea6..af3de0db 100644 --- a/jest.config.js +++ b/jest.config.js @@ -7,10 +7,13 @@ module.exports = { moduleNameMapper: { '@stomp/stompjs': '/src/__mocks__/fileMock.js', '@stomp/rx-stomp': '/src/__mocks__/fileMock.js', - '(pdfjs-dist/legacy/build/pdf.worker)': '/src/__mocks__/constructorMock.js', + '(pdfjs-dist/build/pdf.worker.mjs)': '/src/__mocks__/constructorMock.js', '\\.(css|less)$': '/src/__mocks__/styleMock.js', '\\.(svg)$': '/src/__mocks__/svgMock.js', - 'react-markdown': '/node_modules/react-markdown/react-markdown.min.js', + 'react-markdown': [ + '/node_modules/react-markdown/react-markdown.min.js', + '/../node_modules/react-markdown/react-markdown.min.js', + ], }, transform: { '\\.(js|jsx|ts|tsx)$': 'babel-jest', @@ -21,6 +24,7 @@ module.exports = { transformIgnorePatterns: [ "node_modules/(?!(dateformat|remark-gfm|micromark-.+|decode-named-character-reference|character-entities|mdast-.*|escape-string-regexp|unist-util-.*|markdown-.*|ccount|d3-[a-z]+)/)", ], + globalSetup: '/scripts/jest-global-setup.js', setupFiles: [ 'jest-canvas-mock', ], diff --git a/lib/components/NeonPage/NeonPage.d.ts b/lib/components/NeonPage/NeonPage.d.ts index 22f53e77..25c6d948 100644 --- a/lib/components/NeonPage/NeonPage.d.ts +++ b/lib/components/NeonPage/NeonPage.d.ts @@ -30,6 +30,7 @@ declare namespace NeonPage { export const progress: PropTypes.Requireable; export const resetStateAfterRuntimeError: PropTypes.Requireable<(...args: any[]) => any>; export { children as sidebarContent }; + export const sidebarContentResponsive: PropTypes.Requireable; export const sidebarContainerClassName: PropTypes.Requireable; export const sidebarLinks: PropTypes.Requireable<(PropTypes.InferProps<{ name: PropTypes.Validator; @@ -83,6 +84,8 @@ declare namespace NeonPage { export function resetStateAfterRuntimeError_1(): void; export { resetStateAfterRuntimeError_1 as resetStateAfterRuntimeError }; export const sidebarContent: null; + const sidebarContentResponsive_1: boolean; + export { sidebarContentResponsive_1 as sidebarContentResponsive }; const sidebarContainerClassName_1: null; export { sidebarContainerClassName_1 as sidebarContainerClassName }; const sidebarLinks_1: null; diff --git a/lib/components/NeonPage/NeonPage.js b/lib/components/NeonPage/NeonPage.js index e8f043d5..c49c8e6d 100644 --- a/lib/components/NeonPage/NeonPage.js +++ b/lib/components/NeonPage/NeonPage.js @@ -354,6 +354,7 @@ const NeonPage = props => { progress, resetStateAfterRuntimeError, sidebarContent, + sidebarContentResponsive, sidebarContainerClassName: sidebarContainerClassNameProp, sidebarLinks, sidebarLinksAdditionalContent, @@ -685,7 +686,7 @@ const NeonPage = props => { } : {}; const sidebarClassName = sidebarContainerClassNameProp ? "".concat(classes.sidebarContainer, " ").concat(sidebarContainerClassNameProp) : classes.sidebarContainer; // Arbitrary Content Sidebar (no automatic skeleton) - if (hasSidebarContent) { + if (hasSidebarContent && !sidebarContentResponsive) { return /*#__PURE__*/_react.default.createElement("div", { ref: sidebarRef, className: sidebarClassName, @@ -721,6 +722,28 @@ const NeonPage = props => { className: classes.sidebarSubtitle }, sidebarSubtitle))); }; + // Arbitrary Content Sidebar (no automatic skeleton) + if (hasSidebarContent) { + return /*#__PURE__*/_react.default.createElement("div", { + ref: sidebarRef, + className: sidebarClassName, + style: sidebarContainerStyle + }, /*#__PURE__*/_react.default.createElement("div", { + className: !sidebarUnsticky && !belowMd ? "".concat(classes.sidebarInnerStickyContainer, " neon__sidebar-sticky") : null + }, /*#__PURE__*/_react.default.createElement("div", { + className: classes.sidebarTitleContainer + }, renderSidebarTitle(), !belowMd ? null : /*#__PURE__*/_react.default.createElement(_IconButton.default, { + size: "small", + onClick: () => setSidebarExpanded(!sidebarExpanded) + }, sidebarExpanded ? /*#__PURE__*/_react.default.createElement(_ExpandLess.default, { + fontSize: "large" + }) : /*#__PURE__*/_react.default.createElement(_ExpandMore.default, { + fontSize: "large" + }))), !belowMd || sidebarExpanded ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_Divider.default, { + className: classes.sidebarDivider, + style: _extends({}, dividerStyle) + }), sidebarContent) : null)); + } // Render Single Sidebar Link const renderLink = function (link) { let standalone = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; @@ -861,6 +884,7 @@ NeonPage.propTypes = { progress: _propTypes.default.number, resetStateAfterRuntimeError: _propTypes.default.func, sidebarContent: children, + sidebarContentResponsive: _propTypes.default.bool, sidebarContainerClassName: _propTypes.default.string, sidebarLinks: _propTypes.default.arrayOf(_propTypes.default.shape({ name: _propTypes.default.string.isRequired, @@ -895,6 +919,7 @@ NeonPage.defaultProps = { progress: null, resetStateAfterRuntimeError: () => {}, sidebarContent: null, + sidebarContentResponsive: false, sidebarContainerClassName: null, sidebarLinks: null, sidebarLinksAdditionalContent: null, diff --git a/package-lock.json b/package-lock.json index da3ff36e..0b019f9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "portal-core-components", - "version": "2.9.2", + "version": "2.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "portal-core-components", - "version": "2.9.2", + "version": "2.10.0", "dependencies": { "@date-io/moment": "^1.3.13", "@fortawesome/fontawesome-svg-core": "^6.6.0", @@ -83,7 +83,7 @@ "@babel/preset-typescript": "^7.24.7", "@jest/globals": "^29.7.0", "@testing-library/react-hooks": "^8.0.1", - "@typescript-eslint/parser": "^7.16.1", + "@typescript-eslint/parser": "^7.17.0", "commander": "^12.1.0", "cssnano": "^7.0.4", "eslint": "^8.57.0", @@ -92,11 +92,11 @@ "eslint-plugin-jsx-a11y": "^6.9.0", "eslint-plugin-react": "^7.35.0", "express": "^4.19.2", - "html-loader": "^5.0.0", + "html-loader": "^5.1.0", "jest-canvas-mock": "^2.5.2", "jsdom": "^24.1.1", "node-fetch": "^3.3.2", - "postcss": "^8.4.39", + "postcss": "^8.4.40", "prettier": "^3.3.3", "react-scripts": "^5.0.1", "react-test-renderer": "^17.0.2", @@ -108,7 +108,7 @@ "cssnano": "^7.0.4", "jsdom": "^24.1.1", "node-fetch": "^3.3.2", - "postcss": "^8.4.39", + "postcss": "^8.4.40", "prettier": "^3.3.3", "worker-loader": "^3.0.8" }, @@ -2822,9 +2822,9 @@ } }, "node_modules/@emotion/cache": { - "version": "11.13.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.0.tgz", - "integrity": "sha512-hPV345J/tH0Cwk2wnU/3PBzORQ9HeX+kQSbwI+jslzpRCHE6fSGTohswksA/Ensr8znPzwfzKZCmAM9Lmlhp7g==", + "version": "11.13.1", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", + "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", "license": "MIT", "dependencies": { "@emotion/memoize": "^0.9.0", @@ -11365,9 +11365,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.0.tgz", - "integrity": "sha512-Vb3xHHYnLseK8vlMJQKJYXJ++t4u1/qJ3vykuVrVjvdiOEhYyT1AuP4x03G8EnPmYvYOhe9T+dADTmthjRQMkA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.1.tgz", + "integrity": "sha512-FKbOCOQ5QRB3VlIbl1LZQefWIYwszlBloaXcY2rbfpu9ioJnNh3TK03YtIDKDo3WKBi8u+YV4+Fn2CkEozgf4w==", "dev": true, "license": "ISC" }, @@ -14272,9 +14272,9 @@ "license": "MIT" }, "node_modules/html-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.0.0.tgz", - "integrity": "sha512-puaGKdjdVVIFRtgIC2n5dt5bt0N5j6heXlAQZ4Do1MLjHmOT1gCE1Ogg7XZNeJlnOVHHsrZKGs5dfh+XwZ3XPw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-5.1.0.tgz", + "integrity": "sha512-Jb3xwDbsm0W3qlXrCZwcYqYGnYz55hb6aoKQTlzyZPXsPpi6tHXzAfqalecglMQgNvtEfxrCQPaKT90Irt5XDA==", "dev": true, "license": "MIT", "dependencies": { @@ -23911,9 +23911,9 @@ } }, "node_modules/postcss": { - "version": "8.4.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", - "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "version": "8.4.40", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", + "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", "dev": true, "funding": [ { @@ -24469,9 +24469,9 @@ } }, "node_modules/postcss-load-config/node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", + "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", "dev": true, "license": "ISC", "bin": { @@ -28109,9 +28109,9 @@ "license": "MIT" }, "node_modules/tailwindcss": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.6.tgz", - "integrity": "sha512-1uRHzPB+Vzu57ocybfZ4jh5Q3SdlH7XW23J5sQoM9LhE9eIOlzxer/3XPSsycvih3rboRsvt0QCmzSrqyOYUIA==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.7.tgz", + "integrity": "sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index b0f9126c..3e61683f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "portal-core-components", - "version": "2.9.2", + "version": "2.10.0", "main": "./lib/index.js", "private": true, "homepage": "http://localhost:3010/core-components", @@ -73,7 +73,7 @@ "cssnano": "^7.0.4", "jsdom": "^24.1.1", "node-fetch": "^3.3.2", - "postcss": "^8.4.39", + "postcss": "^8.4.40", "prettier": "^3.3.3", "worker-loader": "^3.0.8" }, @@ -112,7 +112,7 @@ "@babel/preset-typescript": "^7.24.7", "@jest/globals": "^29.7.0", "@testing-library/react-hooks": "^8.0.1", - "@typescript-eslint/parser": "^7.16.1", + "@typescript-eslint/parser": "^7.17.0", "commander": "^12.1.0", "cssnano": "^7.0.4", "eslint": "^8.57.0", @@ -121,11 +121,11 @@ "eslint-plugin-jsx-a11y": "^6.9.0", "eslint-plugin-react": "^7.35.0", "express": "^4.19.2", - "html-loader": "^5.0.0", + "html-loader": "^5.1.0", "jest-canvas-mock": "^2.5.2", "jsdom": "^24.1.1", "node-fetch": "^3.3.2", - "postcss": "^8.4.39", + "postcss": "^8.4.40", "prettier": "^3.3.3", "react-scripts": "^5.0.1", "react-test-renderer": "^17.0.2", @@ -151,7 +151,19 @@ "lib:post-clean-styleGuides": "rm ./lib/components/**/StyleGuide.*", "lib:post-clean-img": "rm -r ./lib/components/SiteMap/png && rm -r ./lib/components/SiteMap/svg_source && rm -r ./lib/components/DataThemeIcon/svg_source", "lib:post-clean-tests": "rm -r ./lib/*/__tests__ && rm -r ./lib/*/*/__tests__", - "checks": "npm run lint && npm run test && npm run lib && npm run build" + "checks": "npm run lib && npm run lint && npm run test && npm run build", + "checks:docker": "npm run build:docker-image && npm run lib:docker && npm run test:docker && npm run build:docker", + "start:docker": "docker run --rm --tty --interactive --volume=/$(pwd):/app/src --volume=/app/src/node_modules --workdir=/app/src --publish=3010:3010 portal-core-components:latest-builder npm run start", + "start:docker-prod": "docker run --rm --tty --interactive --volume=/$(pwd):/app/src --volume=/app/src/node_modules --workdir=/app/src --publish=3000:3000 portal-core-components:latest-builder npm run start:prod", + "build:docker-clean": "docker image rm portal-core-components:latest-builder", + "build:docker-build-image": "docker buildx build --no-cache --tag portal-core-components:latest-builder --file ./build.Dockerfile .", + "build:docker-image": "(npm run build:docker-clean || true) && npm run build:docker-build-image", + "build:docker": "docker run --rm --tty --interactive --env GENERATE_SOURCEMAP=false --env NODE_OPTIONS=--max_old_space_size=4096 --volume=/$(pwd):/app/src --volume=/app/src/node_modules --workdir=/app/src portal-core-components:latest-builder npm run build", + "lib:docker": "docker run --rm --tty --interactive --volume=/$(pwd):/app/src --volume=/app/src/node_modules --workdir=/app/src portal-core-components:latest-builder npm run lib", + "test:docker": "docker run --rm --tty --interactive --volume=/$(pwd):/app/src --volume=/app/src/node_modules --workdir=/app/src portal-core-components:latest-builder npm run test:docker-command", + "test:docker-update-snapshots": "docker run --rm --tty --interactive --volume=/$(pwd):/app/src --volume=/app/src/node_modules --workdir=/app/src portal-core-components:latest-builder npm run test:docker-command-update-snapshots", + "test:docker-command": "npm run lint && npm run test", + "test:docker-command-update-snapshots": "npm run lint && npm run test:updateSnapshots" }, "browserslist": { "production": [ diff --git a/scripts/jest-global-setup.js b/scripts/jest-global-setup.js new file mode 100644 index 00000000..05de598c --- /dev/null +++ b/scripts/jest-global-setup.js @@ -0,0 +1,5 @@ +const jestGlobalSetup = async () => { + process.env.TZ = 'UTC'; +}; + +export default jestGlobalSetup; diff --git a/src/lib_components/components/DownloadStepForm/__tests__/__snapshots__/DownloadStepForm.jsx.snap b/src/lib_components/components/DownloadStepForm/__tests__/__snapshots__/DownloadStepForm.jsx.snap index 6ae50553..4822033c 100644 --- a/src/lib_components/components/DownloadStepForm/__tests__/__snapshots__/DownloadStepForm.jsx.snap +++ b/src/lib_components/components/DownloadStepForm/__tests__/__snapshots__/DownloadStepForm.jsx.snap @@ -861,7 +861,7 @@ exports[`DownloadStepForm Step summary renders correctly 1`] = ` - 3 sites — Dec 2019 - Dec 2019 + 3 sites — Jan 2020 - Jan 2020 diff --git a/src/lib_components/components/NeonAuth/__tests__/__snapshots__/UserCard.jsx.snap b/src/lib_components/components/NeonAuth/__tests__/__snapshots__/UserCard.jsx.snap index 0dfdfc15..bf9fb494 100644 --- a/src/lib_components/components/NeonAuth/__tests__/__snapshots__/UserCard.jsx.snap +++ b/src/lib_components/components/NeonAuth/__tests__/__snapshots__/UserCard.jsx.snap @@ -89,7 +89,7 @@ exports[`NeonAuth - UserCard Renders with a lastLogin prop 1`] = ` diff --git a/src/lib_components/components/NeonPage/NeonPage.jsx b/src/lib_components/components/NeonPage/NeonPage.jsx index 64537a96..af8400c5 100644 --- a/src/lib_components/components/NeonPage/NeonPage.jsx +++ b/src/lib_components/components/NeonPage/NeonPage.jsx @@ -371,6 +371,7 @@ const NeonPage = (props) => { progress, resetStateAfterRuntimeError, sidebarContent, + sidebarContentResponsive, sidebarContainerClassName: sidebarContainerClassNameProp, sidebarLinks, sidebarLinksAdditionalContent, @@ -721,7 +722,7 @@ const NeonPage = (props) => { ? `${classes.sidebarContainer} ${sidebarContainerClassNameProp}` : classes.sidebarContainer; // Arbitrary Content Sidebar (no automatic skeleton) - if (hasSidebarContent) { + if (hasSidebarContent && !sidebarContentResponsive) { return (
{sidebarContent} @@ -755,6 +756,37 @@ const NeonPage = (props) => {
); }; + // Arbitrary Content Sidebar (no automatic skeleton) + if (hasSidebarContent) { + return ( +
+
+
+ {renderSidebarTitle()} + {!belowMd ? null : ( + setSidebarExpanded(!sidebarExpanded)}> + {( + sidebarExpanded + ? + : + )} + + )} +
+ {(!belowMd || sidebarExpanded) ? ( + <> + + {sidebarContent} + + ) : null} +
+
+ ); + } // Render Single Sidebar Link const renderLink = (link, standalone = false) => { if (!link) { return null; } @@ -957,6 +989,7 @@ NeonPage.propTypes = { progress: PropTypes.number, resetStateAfterRuntimeError: PropTypes.func, sidebarContent: children, + sidebarContentResponsive: PropTypes.bool, sidebarContainerClassName: PropTypes.string, sidebarLinks: PropTypes.arrayOf( PropTypes.shape({ @@ -1006,6 +1039,7 @@ NeonPage.defaultProps = { progress: null, resetStateAfterRuntimeError: () => { }, sidebarContent: null, + sidebarContentResponsive: false, sidebarContainerClassName: null, sidebarLinks: null, sidebarLinksAdditionalContent: null, diff --git a/src/lib_components/components/NeonPage/StyleGuide.jsx b/src/lib_components/components/NeonPage/StyleGuide.jsx index 1a582348..6bf172b0 100644 --- a/src/lib_components/components/NeonPage/StyleGuide.jsx +++ b/src/lib_components/components/NeonPage/StyleGuide.jsx @@ -212,6 +212,19 @@ const propRows = [

), }, + // sidebarContentResponsive + { + name: 'sidebarContentResponsive', + type: 'boolean', + default: 'false', + description: ( +

+ When the sidebarContent is set and the responsive behavior of the sidebar + is desired, set this property to true. Otherwise, by default, the behavior + of the sidebar is up to the implementation of the sidebarContent. +

+ ), + }, // sidebarContainerClassName { name: 'sidebarContainerClassName', @@ -526,6 +539,39 @@ import NeonPage from 'portal-core-components/lib/components/NeonPage'; `} + + Sidebar Content + + + Use the sidebarContent prop to set custom sidebar content. + + +
+ Sidebar Content)} + sidebarContentResponsive + > + Content + +
+
+ + {` +Sidebar Content)} + sidebarContentResponsive +> + Content + + `} + + Breadcrumbs