Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

[PROD] Next Release #100

Merged
merged 22 commits into from
Aug 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2d68c40
Implements #79 #80 #81 #82
MadOPcode Aug 6, 2021
57a794c
Rearranged payment actions menu items. Resolved some prop-types warni…
MadOPcode Aug 9, 2021
068a41d
Merge pull request #88 from MadOPcode/feature/payment-updates
maxceem Aug 10, 2021
345eb9e
Merge branch 'dev' into feature/payment-updates
maxceem Aug 10, 2021
ef948a0
Merge pull request #89 from topcoder-platform/feature/payment-updates
maxceem Aug 10, 2021
ff9e07d
Implemented reloading of working period data after BA update.
MadOPcode Aug 10, 2021
b9e544f
Made the working periods' table more compact.
MadOPcode Aug 10, 2021
a137ebf
Merge branch 'feature/payment-updates' of github.com:MadOPcode/micro-…
MadOPcode Aug 10, 2021
bdbe5b9
Added creation time column to payments' list.
MadOPcode Aug 11, 2021
4be0527
Removed unnecessary timezone-handling code.
MadOPcode Aug 11, 2021
fc388f9
Fixed tooltips for team names. Refactored payment cancelling. Added B…
MadOPcode Aug 12, 2021
e5e67b2
Merge pull request #91 from MadOPcode/feature/payment-updates
maxceem Aug 12, 2021
4004046
Merge pull request #96 from topcoder-platform/feature/payment-updates
maxceem Aug 12, 2021
765a616
increase server update data delay to 5 seconds
maxceem Aug 12, 2021
2b613d0
set notification platform to 'taas'
nqviet Aug 12, 2021
1b512f3
Merge pull request #97 from nqviet/dev
maxceem Aug 13, 2021
72c8dcd
fix(roles): set initial rates to 1000
cagdas001 Aug 13, 2021
dcdd3c0
Merge pull request #98 from cagdas001/dev
urwithat Aug 13, 2021
a401de6
Adds fixes for #80, #82. Implements #94, #95.
MadOPcode Aug 14, 2021
72bc207
Merge branch 'topcoder-platform:dev' into dev
MadOPcode Aug 14, 2021
db140e4
Follow up fixes for #99
MadOPcode Aug 14, 2021
95bf062
Merge pull request #99 from MadOPcode/dev
maxceem Aug 16, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"dev-https": "cross-env APPMODE=development webpack-dev-server --https --port 8502 --host 0.0.0.0",
"build": "webpack --mode=${APPMODE:-production} --env.config=${APPENV:-prod}",
"analyze": "webpack --mode=production --env.analyze=true",
"lint": "eslint src --ext js --ext jsx",
"lint": "eslint ./src --ext .js,.jsx",
"format": "prettier --write \"./**\"",
"test": "cross-env BABEL_ENV=test jest",
"watch-tests": "cross-env BABEL_ENV=test jest --watch",
Expand Down
5 changes: 5 additions & 0 deletions src/assets/images/icon-arrow-down-narrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
244 changes: 244 additions & 0 deletions src/components/ActionsMenu/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
import React, { useCallback, useMemo, useState } from "react";
import PT from "prop-types";
import cn from "classnames";
import { usePopper } from "react-popper";
import Button from "components/Button";
import Tooltip from "components/Tooltip";
import IconArrowDown from "../../assets/images/icon-arrow-down-narrow.svg";
import { useClickOutside } from "utils/hooks";
import { negate, stopPropagation } from "utils/misc";
import compStyles from "./styles.module.scss";

/**
* Displays a clickable button with a menu.
*
* @param {Object} props component properties
* @param {'primary'|'error'|'warning'} [props.handleColor] menu handle color
* @param {'small'|'medium'} [props.handleSize] menu handle size
* @param {string} [props.handleText] text to show inside menu handle
* @param {Array} props.items menu items
* @param {'absolute'|'fixed'} [props.popupStrategy] popup positioning strategy
* @param {boolean} [props.stopClickPropagation] whether to stop click event propagation
* @returns {JSX.Element}
*/
const ActionsMenu = ({
handleColor = "primary",
handleSize = "small",
handleText,
items = [],
popupStrategy = "absolute",
stopClickPropagation = false,
}) => {
const [isOpen, setIsOpen] = useState(false);
const [referenceElement, setReferenceElement] = useState(null);

const closeMenu = useCallback(() => {
setIsOpen(false);
}, []);

const toggleMenu = useCallback(() => {
setIsOpen(negate);
}, []);

return (
<div
className={compStyles.container}
onClick={stopClickPropagation ? stopPropagation : null}
role="button"
tabIndex={0}
>
<Button
color={handleColor}
size={handleSize}
style={handleText ? "rounded" : "circle"}
variant="contained"
onClick={isOpen ? null : toggleMenu}
className={cn(compStyles.handle, {
[compStyles.handleMenuOpen]: isOpen,
})}
innerRef={setReferenceElement}
>
{handleText ? <span>{handleText}&nbsp;</span> : null}
<IconArrowDown className={compStyles.iconArrowDown} />
</Button>
{isOpen && (
<Menu
close={closeMenu}
items={items}
referenceElement={referenceElement}
strategy={popupStrategy}
/>
)}
</div>
);
};

ActionsMenu.propTypes = {
handleColor: PT.oneOf(["primary", "error", "warning"]),
handleSize: PT.oneOf(["small", "medium"]),
handleText: PT.string,
items: PT.arrayOf(
PT.shape({
label: PT.string,
action: PT.func,
separator: PT.bool,
disabled: PT.bool,
hidden: PT.bool,
})
),
popupStrategy: PT.oneOf(["absolute", "fixed"]),
stopClickPropagation: PT.bool,
};

export default ActionsMenu;

/**
* Displays a list of provided action items.
*
* @param {Object} props component properties
* @returns {JSX.Element}
*/
const Menu = ({ close, items, referenceElement, strategy }) => {
const [popperElement, setPopperElement] = useState(null);
const [arrowElement, setArrowElement] = useState(null);
const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: "bottom",
strategy,
modifiers: [
{
name: "flip",
options: {
fallbackPlacements: ["bottom"],
},
},
{
name: "offset",
options: {
// use offset to move the dropdown slightly down
offset: [0, 5],
},
},
{
name: "arrow",
// padding should be equal to border-radius of the dropdown
options: { element: arrowElement, padding: 8 },
},
{
name: "preventOverflow",
options: {
// padding from browser edges
padding: 16,
},
},
{
name: "computeStyles",
options: {
// to fix bug in IE 11 https://github.com/popperjs/popper-core/issues/636
gpuAcceleration: false,
},
},
],
});

const onClickItem = useCallback(
(event) => {
let targetData = event.target.dataset;
let index = +targetData.actionIndex;
let item = items[index];
if (!item || targetData.disabled || item.separator) {
return;
}
close();
item.action?.();
},
[close, items]
);

useClickOutside(popperElement, close, []);

const menuItems = useMemo(() => {
return items.map((item, index) => {
if (item.hidden) {
return null;
} else if (item.separator) {
return <div key={index} className={compStyles.separator} />;
} else {
let disabled = !!item.disabled;
let reasonsDisabled = Array.isArray(item.disabled)
? item.disabled
: null;
let attrs = {
key: index,
"data-action-index": index,
onClick: onClickItem,
role: "button",
tabIndex: 0,
className: cn(
compStyles.item,
{ [compStyles.itemDisabled]: disabled },
item.className
),
};
if (disabled) {
attrs["data-disabled"] = true;
}
return (
<div {...attrs}>
{reasonsDisabled ? (
<Tooltip
content={
reasonsDisabled.length === 1 ? (
reasonsDisabled[0]
) : (
<ul>
{reasonsDisabled.map((text, index) => (
<li key={index}>{text}</li>
))}
</ul>
)
}
strategy="fixed"
>
{item.label}
</Tooltip>
) : (
item.label
)}
</div>
);
}
});
}, [items, onClickItem]);

return (
<div
className={compStyles.popover}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<div className={compStyles.items}>{menuItems}</div>
<div
ref={setArrowElement}
style={styles.arrow}
className={compStyles.popoverArrow}
/>
</div>
);
};

Menu.propTypes = {
close: PT.func.isRequired,
items: PT.arrayOf(
PT.shape({
label: PT.string,
action: PT.func,
checkDisabled: PT.func,
disabled: PT.bool,
separator: PT.bool,
hidden: PT.bool,
})
),
referenceElement: PT.object,
strategy: PT.oneOf(["absolute", "fixed"]),
};
80 changes: 80 additions & 0 deletions src/components/ActionsMenu/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
@import "styles/variables";

.container {
position: relative;
display: inline-block;
}

.handle {
display: inline-flex;
align-items: center;

> span {
+ .iconArrowDown {
margin-left: 8px;
}
}
}

.iconArrowDown {
display: inline-block;
width: 12px;
height: 8px;
}

.handleMenuOpen {
.iconArrowDown {
transform: rotate(180deg);
}
}

.popover {
z-index: 100;
border-radius: 8px;
// min-width: 175px;
background-color: #fff;
box-shadow: 0px 5px 25px #c6c6c6;
}

.popoverArrow {
top: -9px;
border: 10px solid transparent;
border-top: none;
border-bottom-color: #fff;
width: 0;
height: 0;
}

.items {
padding: 16px;
}

.separator {
border-top: 1px solid #e7e7e7;
margin: 5px 0;
}

.item {
padding: 5px 0;
font-size: 12px;
font-weight: bold;
letter-spacing: 0.8px;
text-align: left;
text-transform: uppercase;
white-space: nowrap;
color: $primary-text-color;
cursor: pointer;
}

.danger {
color: #ef476f;
}

.itemDisabled {
color: #bbb;
cursor: default;
}

.hidden {
display: none;
}
5 changes: 5 additions & 0 deletions src/components/Button/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import styles from "./styles.module.scss";
* @param {string} [props.className] class name added to root element
* @param {'primary'|'primary-dark'|'primary-light'|'error'|'warning'} [props.color]
* button color
* @param {Object|function} [props.innerRef] Ref object or function to accept the
* ref for <button> element
* @param {boolean} [props.isDisabled] if button is disabled
* @param {boolean} [props.isSelected] if button is selected
* @param {string} [props.name] button name
Expand All @@ -26,6 +28,7 @@ const Button = ({
children,
className,
color = "primary",
innerRef,
isDisabled = false,
isSelected = false,
name,
Expand All @@ -40,6 +43,7 @@ const Button = ({
data-value={value}
disabled={isDisabled}
name={name || ""}
ref={innerRef}
type={type}
className={cn(
styles.button,
Expand All @@ -66,6 +70,7 @@ Button.propTypes = {
"error",
"warning",
]),
innerRef: PT.oneOfType([PT.object, PT.func]),
isDisabled: PT.bool,
isSelected: PT.bool,
name: PT.string,
Expand Down
Loading