diff --git a/.gitignore b/.gitignore index 5d3738f9a7..c65eff3204 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ logs/* *.swp # ignore personal ide settings folders .vscode/ +client/jsconfig.json # Mobile Tools for Java (J2ME) .mtj.tmp/ diff --git a/anet-dictionary.yml b/anet-dictionary.yml index 5c911bbe6e..83bf050b4d 100644 --- a/anet-dictionary.yml +++ b/anet-dictionary.yml @@ -47,7 +47,7 @@ fields: longName: label: Objective / Effort description placeholder: Enter an objective / effort description, example .... - componentClass: textarea + as: textarea style: height: 400px topLevel: @@ -59,7 +59,7 @@ fields: longName: label: Description of this Objective placeholder: Enter a description for this Objective, example .... - componentClass: textarea + as: textarea style: height: 400px assessments: @@ -85,7 +85,7 @@ fields: longName: label: Effort description placeholder: Enter an effort description, example .... - componentClass: textarea + as: textarea style: height: 400px assessments: @@ -148,6 +148,18 @@ fields: RED: label: Red color: '#ff8279' + customFieldEnum2: + label: Project future + enum: + BLUE: + label: Blue + color: '#0000ff' + WHITE: + label: White + color: '#ffffff' + BLACK: + label: Black + color: '#000000' taskedOrganizations: label: Tasked organizations placeholder: Search for an organization... @@ -199,7 +211,7 @@ fields: label: Questions helpText: JSON that defines the assessment (you need to know what you are doing) placeholder: Fill in valid JSON - componentClass: textarea + as: textarea style: height: 200px @@ -270,13 +282,13 @@ fields: helpText: Basic / Intermediate / Advanced visibleWhen: $[?(@ && @.multipleButtons && @.multipleButtons.indexOf('train') != -1)] levels: - - color: lightGray + - color: yellow endValue: 3 label: beginner beginner beginner beginner beginner beginner beginner beginner beginner beginner - - color: lightGray + - color: orange endValue: 7 label: intermediate - - color: lightGray + - color: blue endValue: 10 label: advanced advanced advanced advanced trainingDate: @@ -469,7 +481,7 @@ fields: label: Textarea field placeholder: Placeholder text for textarea field helpText: Help text for textarea field - componentClass: textarea + as: textarea style: height: 200px visibleWhen: $[?(@ && @.colourOptions === 'GREEN')] @@ -572,7 +584,7 @@ fields: label: Textarea field placeholder: Placeholder text for textarea field helpText: Help text for textarea field - componentClass: textarea + as: textarea style: height: 200px visibleWhen: $[?(@ && @.colourOptions === 'GREEN')] @@ -653,7 +665,7 @@ fields: label: Textarea field placeholder: Placeholder text for textarea field helpText: Help text for textarea field - componentClass: textarea + as: textarea style: height: 200px visibleWhen: $[?(@ && @.colourOptions === 'GREEN')] @@ -735,7 +747,7 @@ fields: label: Textarea field placeholder: Placeholder text for textarea field helpText: Help text for textarea field - componentClass: textarea + as: textarea style: height: 200px visibleWhen: $[?(@ && @.colourOptions === 'GREEN')] @@ -1158,7 +1170,7 @@ fields: color: '#c2ffb3' "2": label: two - color: '#ff8279' + color: '#ffe396' "3": label: three color: '#ff8279' diff --git a/client/config/webpack.common.js b/client/config/webpack.common.js index 350a773eff..98515d8f99 100644 --- a/client/config/webpack.common.js +++ b/client/config/webpack.common.js @@ -3,11 +3,9 @@ const CircularDependencyPlugin = require("circular-dependency-plugin") const ContextReplacementPlugin = require("webpack/lib/ContextReplacementPlugin") const CopyWebpackPlugin = require("copy-webpack-plugin") const ESLintPlugin = require("eslint-webpack-plugin") -const MiniCssExtractPlugin = require("mini-css-extract-plugin") const webpack = require("webpack") const paths = require("./paths") -const devMode = process.env.NODE_ENV !== "production" const commonConfig = { module: { rules: [ @@ -71,7 +69,7 @@ const commonConfig = { { test: /\.css$/, use: [ - devMode ? "style-loader" : MiniCssExtractPlugin.loader, + "style-loader", { loader: "css-loader", options: { importLoaders: 1 } }, "postcss-loader" ] @@ -135,7 +133,7 @@ module.exports = { // new webpack.optimize.CommonsChunkPlugin({ // name: 'manifest' // }) - ].concat(devMode ? [] : [new MiniCssExtractPlugin()]), + ], cache: { type: "filesystem", buildDependencies: { diff --git a/client/package.json b/client/package.json index ba2b514e7b..bbfd32be94 100644 --- a/client/package.json +++ b/client/package.json @@ -87,9 +87,10 @@ "jest": "27.2.5", "js-yaml": "4.1.0", "json-loader": "0.5.7", - "mini-css-extract-plugin": "2.4.2", "moment-timezone": "0.5.33", "postcss": "8.3.9", + "postcss-calc": "8.0.0", + "postcss-custom-properties": "12.0.0", "postcss-flexbugs-fixes": "5.0.2", "postcss-loader": "6.1.1", "prettier-eslint-cli": "5.0.1", @@ -122,7 +123,7 @@ "@projectstorm/react-diagrams-core": "6.6.1", "@projectstorm/react-diagrams-defaults": "6.6.1", "@projectstorm/react-diagrams-routing": "6.6.1", - "bootstrap": "3.4.1", + "bootstrap": "5.1.3", "change-case": "4.1.2", "classnames": "2.3.1", "closest": "0.0.1", @@ -155,8 +156,7 @@ "prop-types": "15.7.2", "react": "16.14.0", "react-avatar-edit": "1.1.0", - "react-bootstrap": "0.33.1", - "react-confirm-bootstrap": "5.3.1", + "react-bootstrap": "2.0.0-rc.1", "react-container-dimensions": "1.4.1", "react-dom": "16.14.0", "react-moment-proptypes": "1.8.1", @@ -214,6 +214,7 @@ "json" ], "moduleNameMapper": { + "^d3$": "/node_modules/d3/dist/d3.min.js", "^.+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/config/jest/FileStub.js", "^.+\\.css$": "/config/jest/CSSStub.js" }, diff --git a/client/postcss.config.js b/client/postcss.config.js index 053933fdc0..df9ddfffcf 100644 --- a/client/postcss.config.js +++ b/client/postcss.config.js @@ -1,3 +1,13 @@ module.exports = { - plugins: [require("autoprefixer"), require("postcss-flexbugs-fixes")] + plugins: [ + require("postcss-custom-properties")({ + preserve: false, // completely reduce all css vars + importFrom: [ + "src/fullcalendar-vars.css" // look here for the new values + ] + }), + require("postcss-calc"), + require("autoprefixer"), + require("postcss-flexbugs-fixes") + ] } diff --git a/client/src/bootstrapOverrides.css b/client/src/bootstrapOverrides.css new file mode 100644 index 0000000000..e22aeb3e5d --- /dev/null +++ b/client/src/bootstrapOverrides.css @@ -0,0 +1,91 @@ +:root { + --anet-blue: rgb(0, 113, 188); + --anet-blue-dark: rgb(0, 92, 153); +} + +.btn { + font-size: 0.9rem; +} + +.btn-primary { + background-color: var(--anet-blue); + border-color: var(--anet-blue); +} +.btn-primary:hover { + background-color: var(--anet-blue-dark); + border-color: var(--anet-blue-dark); +} +.btn-check:checked + .btn-primary, +.btn-check:active + .btn-primary, +.btn-primary:active, +.btn-primary.active, +.show > .btn-primary.dropdown-toggle { + background-color: var(--anet-blue-dark); + border-color: var(--anet-blue-dark); +} +.btn-check:focus + .btn-primary, +.btn-primary:focus { + background-color: var(--anet-blue-dark); + border-color: var(--anet-blue-dark); +} +.btn-primary:disabled, +.btn-primary.disabled { + background-color: var(--anet-blue); + border-color: var(--anet-blue); +} + +.btn-outline-primary { + color: var(--anet-blue); + border-color: var(--anet-blue); +} +.btn-outline-primary:hover { + color: white; + background-color: var(--anet-blue); + border-color: var(--anet-blue); +} + +.btn-link { + color: var(--anet-blue); + font-size: 15px; +} +.btn-link:hover { + color: var(--anet-blue-dark); +} + +.nav-link { + color: var(--anet-blue); +} +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + background-color: var(--anet-blue); +} + +.dropdown-item.active, +.dropdown-item:active { + background-color: var(--anet-blue); +} + +.page-link { + color: var(--anet-blue); +} +.page-item.active .page-link { + background-color: var(--anet-blue); + border-color: var(--anet-blue); +} + +.form-check-input:checked { + background-color: var(--anet-blue); + border-color: var(--anet-blue); +} + +.bg-primary { + background-color: var(--anet-blue) !important; +} + +/* Use bootstrap 3 styling for blockquotes */ +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eeeeee; +} diff --git a/client/src/components/AdvancedSearch.js b/client/src/components/AdvancedSearch.js index 32a9deea24..4cd338efc2 100644 --- a/client/src/components/AdvancedSearch.js +++ b/client/src/components/AdvancedSearch.js @@ -1,4 +1,3 @@ -import { Classes, Menu, MenuItem } from "@blueprintjs/core" import { Popover2, Popover2InteractionKind } from "@blueprintjs/popover2" import "@blueprintjs/popover2/lib/css/blueprint-popover2.css" import styled from "@emotion/styled" @@ -18,9 +17,10 @@ import React, { useState } from "react" import { Button, Col, - ControlLabel, - FormControl, - FormGroup + Dropdown, + FormGroup, + FormLabel, + Row } from "react-bootstrap" import { connect } from "react-redux" import { useHistory } from "react-router-dom" @@ -74,20 +74,18 @@ const AdvancedSearch = ({ existingKeys.length < Object.keys(filterDefs).length const advancedSearchMenuContent = ( - + {Object.keys(filterDefs).map(filterKey => ( - addFilter(filterKey)} - text={filterKey} - shouldDismissPopover={false} - /> + // shouldDismissPopover={false} + > + {filterKey} + ))} - + ) const possibleFilterTypes = Object.keys(ALL_FILTERS).filter(type => @@ -99,7 +97,7 @@ const AdvancedSearch = ({ {() => (
- + {possibleFilterTypes.map(type => (
- + {/* */} -
+
{filters.map( filter => filterDefs[filter.key] && ( @@ -196,7 +192,7 @@ const AdvancedSearch = ({ } }} > - @@ -210,18 +206,15 @@ const AdvancedSearch = ({ }} > @@ -332,7 +332,7 @@ const AssignPositionModal = ({ person, showModal, onCancel, onSuccess }) => { } setRemoveUser(false) }} - bsStyle="primary" + variant="primary" > Save diff --git a/client/src/components/AvatarComponent.js b/client/src/components/AvatarComponent.js index d3385ab256..e6f46687e9 100644 --- a/client/src/components/AvatarComponent.js +++ b/client/src/components/AvatarComponent.js @@ -1,6 +1,6 @@ +import PropTypes from "prop-types" import React from "react" import Avatar from "react-avatar-edit" -import PropTypes from "prop-types" // More info about this component: https://github.com/kirill3333/react-avatar const AvatarComponent = ({ onChangePreview }) => { @@ -8,11 +8,11 @@ const AvatarComponent = ({ onChangePreview }) => { ) diff --git a/client/src/components/AvatarEditModal.js b/client/src/components/AvatarEditModal.js index 08e4e2a2f7..54683df4fc 100644 --- a/client/src/components/AvatarEditModal.js +++ b/client/src/components/AvatarEditModal.js @@ -8,18 +8,31 @@ const AvatarEditModal = ({ title, onAvatarUpdate }) => { const [currentPreview, setCurrentPreview] = useState(null) return ( -
- +
+ - + {title} - - + + +
diff --git a/client/src/components/Calendar.css b/client/src/components/Calendar.css index 25b6a99f9d..ce2de54909 100644 --- a/client/src/components/Calendar.css +++ b/client/src/components/Calendar.css @@ -1,49 +1,13 @@ -.fc .fc-button, -.fc .fc-button-primary{ - color: black; - background-color: white; - border-color: #ccc; -} +/* Override @fullcalendar styles (variables are in fullcalendar-vars.css) */ -.fc .fc-button-primary:disabled, -.fc .fc-button-primary:active, +.fc .fc-button-primary:not(:disabled):active, .fc .fc-button-primary:not(:disabled).fc-button-active { - color: #fff; - opacity: unset; - background-color: #337ab7; - border-color: #ccc; -} - -.fc .fc-button:not(:disabled):hover { - color: black; - background-color: #ccc; - border-color: #ccc; - } - -.fc .fc-button:focus, -.fc .fc-button-primary:not(:disabled):active:focus, -.fc .fc-button-primary:not(:disabled).fc-button-active:focus { - -webkit-box-shadow: unset; - box-shadow: unset; -} - -.fc .fc-list-empty { - padding: 8px 4px; - border-width: 1px 0 0; - border-color: #ccc; + color: var(--fc-button-active-text-color); } - -.fc .fc-list-empty .fc-list-empty-cushion { - margin: 0; +.fc .fc-button-primary:not(:disabled):hover { + color: var(--fc-button-hover-text-color); } - -a.fc-col-header-cell-cushion, a.fc-col-header-cell-cushion:hover, a.fc-col-header-cell-cushion:focus, -a.fc-list-day-text, a.fc-list-day-text:hover, a.fc-list-day-text:focus { - text-decoration: none; - cursor: default; - color: #363636; -} - -.fc-event { - min-height: 20px; +.fc .fc-button-primary:disabled { + color: var(--fc-button-disabled-text-color); + background-color: var(--fc-button-disabled-bg-color); } diff --git a/client/src/components/Compact.js b/client/src/components/Compact.js index 6d224ea72e..7e1e4a23ac 100644 --- a/client/src/components/Compact.js +++ b/client/src/components/Compact.js @@ -382,7 +382,7 @@ const RowLabelS = styled.th` export const CompactRowContentS = styled.td` padding: 4px 1rem; - & .form-control-static { + & .form-control-plaintext { margin-bottom: 0; padding-top: 0; } diff --git a/client/src/components/ConfirmDestructive.js b/client/src/components/ConfirmDestructive.js index 528da1a5b0..f0fcda1999 100644 --- a/client/src/components/ConfirmDestructive.js +++ b/client/src/components/ConfirmDestructive.js @@ -1,47 +1,54 @@ -import "components/react-confirm-bootstrap.css" +import TriggerableConfirm from "components/TriggerableConfirm" import PropTypes from "prop-types" import React from "react" -import { Button } from "react-bootstrap" -import Confirm from "react-confirm-bootstrap" const ConfirmDestructive = ({ onConfirm, operation, objectType, objectDisplay, - bsStyle, + variant, buttonLabel, - children, - ...otherProps + buttonSize, + buttonClassName, + buttonDisabled, + buttonId, + children }) => { - const confirmText = `Yes, I am sure that I want to ${operation} ${objectType} ${objectDisplay}` + const confirmText = "Yes, I am sure" + const cancelText = "No, I am not entirely sure at this point" const title = `Confirm to ${operation} ${objectType}` - const body = `Are you sure you want to ${operation} this ${objectType}? This cannot be undone.` + const body = `Are you sure you want to ${operation} ${objectType} ${objectDisplay}? This cannot be undone.` return ( - - - + {children} + ) } ConfirmDestructive.propTypes = { onConfirm: PropTypes.func.isRequired, - objectType: PropTypes.string.isRequired, operation: PropTypes.string.isRequired, + objectType: PropTypes.string.isRequired, objectDisplay: PropTypes.string.isRequired, - bsStyle: PropTypes.string, + variant: PropTypes.string, buttonLabel: PropTypes.string, + buttonSize: PropTypes.string, + buttonClassName: PropTypes.string, + buttonDisabled: PropTypes.bool, + buttonId: PropTypes.string, children: PropTypes.node } ConfirmDestructive.defaultProps = { diff --git a/client/src/components/CreateButton.js b/client/src/components/CreateButton.js index 6d50f4c6f5..f00c34e34e 100644 --- a/client/src/components/CreateButton.js +++ b/client/src/components/CreateButton.js @@ -1,7 +1,7 @@ import AppContext from "components/AppContext" import * as Models from "models" import React, { useContext } from "react" -import { Button, DropdownButton, MenuItem } from "react-bootstrap" +import { Button, Dropdown, DropdownButton } from "react-bootstrap" import { useHistory } from "react-router-dom" const DEFAULT_ACTIONS = [Models.Report] @@ -25,23 +25,17 @@ const CreateButton = () => { if (modelClasses.length > 1) { return ( - + {modelClasses.map((modelClass, i) => { const name = modelClass.displayName() || modelClass.resourceName return ( - onSelect(modelClass)} > New {name} - + ) })} @@ -50,9 +44,10 @@ const CreateButton = () => { const modelClass = modelClasses[0] return (