Skip to content

Commit ebafc09

Browse files
Merge branch 'qa' into PROD-1515_sorting
2 parents a6b0d3e + 0ede0a4 commit ebafc09

File tree

23 files changed

+145
-66
lines changed

23 files changed

+145
-66
lines changed

.circleci/config.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ workflows:
7575
filters:
7676
branches:
7777
only:
78-
- develop
78+
# - develop
79+
- qa
7980

8081
# Production builds are exectuted only on tagged commits to the
8182
# master branch.

src-ts/header/tool-selectors/tool-selectors-narrow/tool-selector-narrow/ToolSelectorNarrow.tsx

+10-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import classNames from 'classnames'
2-
import { FC } from 'react'
2+
import { FC, useContext } from 'react'
33
import { Link, useLocation } from 'react-router-dom'
44

5-
import { IconOutline, PlatformRoute, routeIsActive } from '../../../../lib'
5+
import { IconOutline, PlatformRoute, routeContext, RouteContextData, routeIsActive } from '../../../../lib'
66

77
import styles from './ToolSelectorNarrow.module.scss'
88

@@ -14,22 +14,23 @@ const isParamRoute: (route: string) => boolean = (route: string) => !!route.matc
1414

1515
const ToolSelectorNarrow: FC<ToolSelectorNarrowProps> = (props: ToolSelectorNarrowProps) => {
1616

17-
const route: PlatformRoute = props.route
18-
const path: string = props.route.route
17+
const { getPathFromRoute }: RouteContextData = useContext(routeContext)
18+
const toolRoute: PlatformRoute = props.route
19+
const toolPath: string = getPathFromRoute(toolRoute)
1920

2021
const baseClass: string = 'tool-selector-narrow'
21-
const isActive: boolean = routeIsActive(useLocation().pathname, path)
22+
const isActive: boolean = routeIsActive(useLocation().pathname, toolPath)
2223
const activeIndicaterClass: string = `${baseClass}-${isActive ? '' : 'in'}active`
23-
const hasChildren: boolean = !!route.children.some(child => !!child.route && !isParamRoute(child.route))
24+
const hasChildren: boolean = !!toolRoute.children.some(child => !!child.route && !isParamRoute(child.route))
2425

2526
return (
2627
<div className={styles[baseClass]}>
2728
<Link
2829
className={classNames(styles[`${baseClass}-link`], styles[activeIndicaterClass])}
29-
key={path}
30-
to={path}
30+
key={toolPath}
31+
to={toolPath}
3132
>
32-
{route.title}
33+
{toolRoute.title}
3334
{hasChildren && <IconOutline.ChevronRightIcon />}
3435
</Link>
3536
</div>

src-ts/header/tool-selectors/tool-selectors-wide/tool-selector-wide/ToolSelectorWide.tsx

+16-9
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,13 @@ import classNames from 'classnames'
22
import { FC, useContext } from 'react'
33
import { Link, useLocation } from 'react-router-dom'
44

5-
import { ToolTitle } from '../../../../config'
6-
import { PlatformRoute, routeContext, RouteContextData, routeIsActive, routeIsHome } from '../../../../lib'
5+
import {
6+
PlatformRoute,
7+
routeContext,
8+
RouteContextData,
9+
routeIsActive,
10+
routeIsHome,
11+
} from '../../../../lib'
712
import '../../../../lib/styles/index.scss'
813

914
import styles from './ToolSelectorWide.module.scss'
@@ -14,15 +19,17 @@ interface ToolSelectorWideProps {
1419

1520
const ToolSelectorWide: FC<ToolSelectorWideProps> = (props: ToolSelectorWideProps) => {
1621

17-
const { getPath, getPathFromRoute }: RouteContextData = useContext(routeContext)
18-
const currentPath: string = useLocation().pathname
22+
const { getPathFromRoute }: RouteContextData = useContext(routeContext)
23+
const activePath: string = useLocation().pathname
24+
const toolRoute: PlatformRoute = props.route
25+
const toolPath: string = getPathFromRoute(toolRoute)
26+
27+
const isActive: boolean = routeIsActive(activePath, toolPath)
1928

20-
// for now, the work tool should be active for all pages except the account
21-
const isActive: boolean = !routeIsActive(currentPath, getPath(ToolTitle.settings))
2229
const activeIndicatorClass: string = `tool-selector-wide-${isActive ? '' : 'in'}active`
2330

2431
// the tool link should be usable for all active routes except the home page
25-
const isLink: boolean = isActive && !routeIsHome(currentPath)
32+
const isLink: boolean = isActive && !routeIsHome(activePath)
2633

2734
return (
2835
<div className={classNames(
@@ -33,9 +40,9 @@ const ToolSelectorWide: FC<ToolSelectorWideProps> = (props: ToolSelectorWideProp
3340
<Link
3441
className='large-tab'
3542
tabIndex={-1}
36-
to={getPathFromRoute(props.route)}
43+
to={toolPath}
3744
>
38-
{props.route.title}
45+
{toolRoute.title}
3946
</Link>
4047
<div className={styles['active-indicator']}></div>
4148
</div>

src-ts/lib/functions/authentication-functions/authentication-url.config.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { EnvironmentConfig } from '../../../config'
2+
import { routeSelfServiceRoot } from '../../route-provider'
23

34
export const authentication: string = EnvironmentConfig.URL.ACCOUNTS_APP_CONNECTOR
45

56
export function login(fallback: string): string {
67
return `${authentication}?retUrl=${encodeURIComponent(window.location.href.match(/[^?]*/)?.[0] || fallback)}`
78
}
89

9-
export const logout: string = `${authentication}?logout=true&retUrl=${encodeURIComponent('https://' + window.location.host)}/self-service`
10+
export const logout: string = `${authentication}?logout=true&retUrl=${encodeURIComponent('https://' + window.location.host)}${routeSelfServiceRoot}`
1011

1112
export function signup(fallback: string): string {
1213
return `${login(fallback)}&regSource=tcBusiness&mode=signUp`

src-ts/lib/portal/Portal.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { createPortal } from 'react-dom'
33

44
interface PortalProps {
55
children: ReactNode
6+
className?: string,
67
portalId?: string
78
portalNode?: HTMLElement
89
portalRef?: MutableRefObject<HTMLElement>,
@@ -13,6 +14,7 @@ const Portal: FC<PortalProps> = (
1314
portalId,
1415
portalNode,
1516
children,
17+
className,
1618
portalRef,
1719
}: PortalProps) => {
1820

@@ -26,9 +28,12 @@ const Portal: FC<PortalProps> = (
2628
}
2729

2830
const backupHtmlNode: HTMLElement = document.createElement('div')
31+
if (className) {
32+
backupHtmlNode.classList.add(className)
33+
}
2934
document.body.appendChild(backupHtmlNode)
3035
return backupHtmlNode
31-
}, [portalNode]) as HTMLElement
36+
}, [portalNode, className]) as HTMLElement
3237

3338
useEffect(() => {
3439
return () => {
@@ -41,6 +46,7 @@ const Portal: FC<PortalProps> = (
4146
if (portalRef) {
4247
portalRef.current = portalNode ?? defaultPortalNode
4348
}
49+
4450
return createPortal(children, portalNode ?? defaultPortalNode)
4551
}
4652

+21-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
11
export const routeRoot: string = '/work/dashboard'
2+
export const routeSelfServiceRoot: string = '/self-service'
3+
export const routeSelfServiceStart: string = `${routeSelfServiceRoot}/wizard`
24

35
export function routeIsActive(activePath: string, pathName: string, rootPath?: string): boolean {
4-
return activePath?.startsWith(pathName)
5-
&& (pathName !== rootPath || activePath === rootPath)
6+
let isActive: boolean = isActivePath(activePath, pathName, rootPath)
7+
8+
// temporarilily, if the path we're testing against is the work tool
9+
// also check if the current path is self-service
10+
if (!isActive && pathName.startsWith(routeRoot)) {
11+
isActive = isActivePath(activePath, routeSelfServiceRoot)
12+
}
13+
14+
return isActive
615
}
716

817
export function routeIsHome(activePath: string): boolean {
918
// TODO: make the alternate home route configurable
10-
return [routeRoot, '/self-service'].some(route => activePath === route)
19+
return [routeRoot, routeSelfServiceRoot].some(route => activePath === route)
20+
}
21+
22+
export function routeWorkDetails(workId: string): string {
23+
return `${routeSelfServiceRoot}/work-items/${workId}`
24+
}
25+
26+
function isActivePath(activePath: string, pathName: string, rootPath?: string): boolean {
27+
return activePath?.startsWith(pathName)
28+
&& (pathName !== rootPath || activePath === rootPath)
1129
}

src-ts/lib/styles/variables/_palette.scss

+2-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ $blue-100: #2C95D7;
118118
$blue-75: #50ADE8;
119119
$blue-50: #83C5EE;
120120
$blue-25: #BAE1F9;
121-
$blue-15: #EAF6FD;
121+
$blue-15: #D6EDFC;
122+
$blue-10: #EAF6FD;
122123
// dark
123124
$blue-120: #2984BD;
124125
$blue-140: #16679A;

src-ts/lib/svgs/index.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import { ReactComponent as SocialIconLinkedin } from './social-linkedin-icon.svg
1010
import { ReactComponent as SocialIconTwitter } from './social-tw-icon.svg'
1111
import { ReactComponent as SocialIconYoutube } from './social-yt-icon.svg'
1212
import { ReactComponent as TooltipArrowIcon } from './tooltip-arrow.svg'
13-
import { ReactComponent as WorkTypeDataExplorationIcon } from './work-type-data-exploration.svg'
14-
import { ReactComponent as WorkTypeUnknownIcon } from './work-type-unknown.svg'
15-
import { ReactComponent as WorkTypeWebsiteDesignIcon } from './work-type-website-design.svg'
13+
import { ReactComponent as WorkTypeCategoryDataIcon } from './work-type-category-data.svg'
14+
import { ReactComponent as WorkTypeCategoryDesignIcon } from './work-type-category-design.svg'
15+
import { ReactComponent as WorkTypeCategoryUnknownIcon } from './work-type-category-unknown.svg'
1616

1717
export { ActiveTabTipIcon }
1818
export { IconOutline }
@@ -24,6 +24,6 @@ export { SocialIconLinkedin }
2424
export { SocialIconTwitter }
2525
export { SocialIconYoutube }
2626
export { TooltipArrowIcon }
27-
export { WorkTypeDataExplorationIcon }
28-
export { WorkTypeUnknownIcon }
29-
export { WorkTypeWebsiteDesignIcon }
27+
export { WorkTypeCategoryDataIcon }
28+
export { WorkTypeCategoryDesignIcon }
29+
export { WorkTypeCategoryUnknownIcon }

src-ts/lib/tabs-navbar/TabsNavbar.module.scss

+9-7
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33

44
.tabs-wrapper {
55
display: flex;
6-
align-items: center;
7-
background: $blue-15;
6+
background: $blue-10;
87
border-bottom: 1px solid $black-20;
98
margin-bottom: $pad-md;
109

@@ -22,17 +21,20 @@
2221

2322
&:global(.active) {
2423
color: $black-100;
24+
background-color: $blue-25;
25+
2526
.tab-label {
2627
@include font-weight-bold;
2728
}
2829
}
2930

30-
&:hover {
31+
&:global(.active) ~ .active-icon > svg path:last-child {
32+
fill: $blue-25;
33+
}
34+
35+
&:hover:not(:global(.active)) {
3136
color: $black-100;
32-
background-color: $blue-25;
33-
&:global(.active) ~ .active-icon > svg path:last-child {
34-
fill: $blue-25;
35-
}
37+
background-color: $blue-15;
3638
}
3739
}
3840

src-ts/lib/tabs-navbar/TabsNavbar.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const TabsNavbar: FC<TabsNavbarProps> = (props: TabsNavbarProps) => {
5959
if (initialTab && props.tabs.find(tab => tab.id === initialTab)) {
6060
handleActivateTab(initialTab)
6161
} else if (props.defaultActive) {
62+
setTabOpened(props.defaultActive)
6263
updateOffset(props.defaultActive)
6364
}
6465
}, [handleActivateTab, props.defaultActive])

src-ts/lib/tooltip/Tooltip.module.scss

+8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
@use '../styles/typography';
22
@import '../styles/includes';
33

4+
.tooltip-portal {
5+
position: absolute;
6+
top: -100vh;
7+
left: -100vw;
8+
z-index: 1000;
9+
pointer-events: none;
10+
}
11+
412
.tooltip {
513
display: inline-block;
614
position: relative;

src-ts/lib/tooltip/Tooltip.tsx

+7-7
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const Tooltip: FC<TooltipProps> = ({
4545

4646
const portalRef: MutableRefObject<any> = useRef(undefined)
4747
const triggerRef: MutableRefObject<any> = useRef(undefined)
48+
const tooltipRef: MutableRefObject<any> = useRef(undefined)
4849
const [tooltipOpen, setTooltipOpen]: [boolean, Dispatch<SetStateAction<boolean>>] = useState<boolean>(false)
4950
const { width: windowWidth, height: windowHeight }: WindowSize = useWindowSize()
5051

@@ -58,20 +59,19 @@ const Tooltip: FC<TooltipProps> = ({
5859

5960
useEffect(() => {
6061

61-
if (!tooltipOpen || !portalRef?.current) {
62+
if (!tooltipOpen || !portalRef?.current || !tooltipRef?.current) {
6263
return
6364
}
6465

6566
const triggerEl: HTMLElement = triggerRef.current
6667
const box: DOMRect = triggerEl.getBoundingClientRect()
68+
const left: number = Math.max(box.left, windowWidth - (box.left + tooltipRef.current.getBoundingClientRect().width))
69+
6770
Object.assign(portalRef.current.style, {
6871
height: `${box.width}px`,
69-
left: `${box.left}px`,
70-
pointerEvents: 'none',
71-
position: 'absolute',
72+
left: `${left}px`,
7273
top: `${box.top + window.scrollY}px`,
7374
width: `${box.width + window.scrollX}px`,
74-
zIndex: 1000,
7575
})
7676
}, [
7777
tooltipOpen,
@@ -89,8 +89,8 @@ const Tooltip: FC<TooltipProps> = ({
8989
{trigger}
9090
</div>
9191
{tooltipOpen && (
92-
<Portal portalRef={portalRef}>
93-
<div className={classNames(styles['tooltip-open'], `posy-${positionY}`, `posx-${positionX}`, className)}>
92+
<Portal portalRef={portalRef} className={styles['tooltip-portal']}>
93+
<div className={classNames(styles['tooltip-open'], `posy-${positionY}`, `posx-${positionX}`, className)} ref={tooltipRef}>
9494
<div className={styles['tooltip-arrow']}>
9595
<TooltipArrowIcon />
9696
</div>

src-ts/lib/work-provider/work-functions/index.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
export {
22
type Work,
3+
workFactoryCreate,
4+
workFactoryGetStatus,
35
type WorkProgress,
46
type WorkProgressStep,
57
type WorkSolution,
68
WorkStatus,
79
WorkType,
8-
workFactoryCreate,
9-
workFactoryGetStatus,
10+
WorkTypeCategory,
1011
} from './work-factory'
1112
export {
1213
type Challenge,

src-ts/lib/work-provider/work-functions/work-factory/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export * from './work-progress.model'
22
export * from './work-progress-step.model'
33
export * from './work-status.enum'
44
export * from './work-solution.model'
5+
export * from './work-type-category.enum'
56
export * from './work-type.enum'
67
export {
78
create as workFactoryCreate,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export enum WorkTypeCategory {
2+
data = 'Data',
3+
design = 'Design',
4+
dev = 'Development',
5+
qa = 'QA',
6+
unknown = '',
7+
}

src-ts/lib/work-provider/work-functions/work-factory/work.factory.ts

+19
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { ChallengeStatus } from './challenge-status.enum'
1515
import { WorkProgressStep } from './work-progress-step.model'
1616
import { WorkProgress } from './work-progress.model'
1717
import { WorkStatus } from './work-status.enum'
18+
import { WorkTypeCategory } from './work-type-category.enum'
1819
import { WorkType } from './work-type.enum'
1920
import { Work } from './work.model'
2021

@@ -38,6 +39,7 @@ export function create(challenge: Challenge): Work {
3839
submittedDate,
3940
title: challenge.name,
4041
type,
42+
typeCategory: getTypeCategory(type),
4143
}
4244
}
4345

@@ -231,3 +233,20 @@ function getType(challenge: Challenge): WorkType {
231233
const output: WorkType = !!workTypeKey ? WorkType[workTypeKey] : WorkType.unknown
232234
return output
233235
}
236+
237+
function getTypeCategory(type: WorkType): WorkTypeCategory {
238+
239+
switch (type) {
240+
241+
case WorkType.data:
242+
case WorkType.findData:
243+
return WorkTypeCategory.data
244+
245+
case WorkType.design:
246+
return WorkTypeCategory.design
247+
248+
// TOOD: other categories: qa and dev
249+
default:
250+
return WorkTypeCategory.unknown
251+
}
252+
}

0 commit comments

Comments
 (0)