Skip to content

Commit c989d97

Browse files
authored
Merge pull request #533 from AppQuality/UN-744-state-dropdown
Un 744 state dropdown
2 parents 090a86b + af3cc41 commit c989d97

File tree

22 files changed

+453
-41
lines changed

22 files changed

+453
-41
lines changed

src/app/theme.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,47 @@ export const SEVERITY_HUES: Record<Severities, string> = {
1616
medium: CHARTS_COLOR_PALETTE.blueRoyal,
1717
low: CHARTS_COLOR_PALETTE.darkPine,
1818
};
19+
// temporary fix for the bug state colors
20+
export const BUG_STATE_COLORS: Record<
21+
BugState,
22+
{ stroke: string; color: string }
23+
> = {
24+
'to do': {
25+
stroke: baseTheme.palette.grey[400],
26+
color: baseTheme.palette.white,
27+
},
28+
pending: {
29+
stroke: baseTheme.palette.grey[400],
30+
color: baseTheme.palette.grey[400],
31+
},
32+
'to be imported': {
33+
stroke: baseTheme.palette.azure[400],
34+
color: baseTheme.palette.azure[400],
35+
},
36+
open: {
37+
stroke: baseTheme.palette.azure[400],
38+
color: baseTheme.palette.azure[400],
39+
},
40+
'to be retested': {
41+
stroke: baseTheme.palette.yellow[400],
42+
color: baseTheme.palette.yellow[400],
43+
},
44+
solved: {
45+
stroke: baseTheme.palette.green[600],
46+
color: baseTheme.palette.green[600],
47+
},
48+
'not a bug': {
49+
stroke: baseTheme.palette.grey[600],
50+
color: baseTheme.palette.grey[600],
51+
},
52+
};
1953

2054
const theme = {
2155
...baseTheme,
2256
colors: {
2357
...baseTheme.colors,
2458
bySeverity: SEVERITY_COLORS,
59+
byBugState: BUG_STATE_COLORS,
2560
bySeverityHues: SEVERITY_HUES,
2661
darkPine: CHARTS_COLOR_PALETTE.darkPine,
2762
},
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import {
2+
Dropdown,
3+
Select,
4+
Item,
5+
Menu,
6+
Skeleton,
7+
Tooltip,
8+
Separator,
9+
} from '@appquality/unguess-design-system';
10+
import { Field } from '@zendeskgarden/react-dropdowns';
11+
import { useEffect, useState } from 'react';
12+
import {
13+
Bug,
14+
useGetCampaignsByCidCustomStatusesQuery,
15+
usePatchCampaignsByCidBugsAndBidMutation,
16+
} from 'src/features/api';
17+
import styled from 'styled-components';
18+
import { theme as globalTheme } from 'src/app/theme';
19+
import { useTranslation } from 'react-i18next';
20+
import { BugStateIcon } from 'src/common/components/BugStateIcon';
21+
import { getBugStateLabel } from 'src/common/components/utils/getBugStateLabel';
22+
import { Label } from './Label';
23+
24+
const StyledItem = styled(Item)`
25+
display: flex;
26+
align-items: center;
27+
28+
> svg {
29+
margin-right: ${({ theme }) => theme.space.xs};
30+
}
31+
`;
32+
33+
const SelectedItem = styled.div`
34+
display: flex;
35+
align-items: center;
36+
37+
> svg {
38+
margin-right: ${({ theme }) => theme.space.xs};
39+
}
40+
`;
41+
42+
type DropdownItem = {
43+
id: number;
44+
text: string;
45+
slug: string;
46+
icon: React.ReactNode;
47+
};
48+
49+
const BugStateDropdown = ({ bug }: { bug: Bug }) => {
50+
const { t } = useTranslation();
51+
const { custom_status } = bug;
52+
const [selectedItem, setSelectedItem] = useState<DropdownItem | undefined>();
53+
const [options, setOptions] = useState<DropdownItem[]>([]);
54+
const [patchBug] = usePatchCampaignsByCidBugsAndBidMutation();
55+
const {
56+
data: cpBugStates,
57+
isLoading,
58+
isFetching,
59+
isError,
60+
} = useGetCampaignsByCidCustomStatusesQuery({
61+
cid: bug.campaign_id.toString(),
62+
});
63+
64+
const sortStates = (a: DropdownItem, b: DropdownItem) => {
65+
if (a.id < b.id) return -1;
66+
if (a.id > b.id) return 1;
67+
return 0;
68+
};
69+
70+
useEffect(() => {
71+
if (cpBugStates) {
72+
setOptions(
73+
cpBugStates
74+
.map((bugState) => ({
75+
id: bugState.id,
76+
slug: bugState.name,
77+
text: getBugStateLabel(bugState.name as BugState, t),
78+
icon: (
79+
<BugStateIcon
80+
{...globalTheme.colors.byBugState[bugState.name as BugState]}
81+
/>
82+
),
83+
}))
84+
.sort(sortStates)
85+
);
86+
}
87+
}, [cpBugStates]);
88+
89+
useEffect(() => {
90+
setSelectedItem(
91+
options.find((bugStatus) => bugStatus.id === custom_status.id)
92+
);
93+
}, [custom_status, options]);
94+
95+
if (isError) return null;
96+
97+
return (
98+
<div>
99+
<Label style={{ marginBottom: globalTheme.space.xxs }}>
100+
{t('__BUGS_PAGE_BUG_DETAIL_STATE_LABEL')}
101+
</Label>
102+
{isLoading || isFetching ? (
103+
<Skeleton
104+
height="30px"
105+
style={{ borderRadius: globalTheme.borderRadii.md }}
106+
/>
107+
) : (
108+
<Dropdown
109+
selectedItem={selectedItem}
110+
onSelect={async (item: DropdownItem) => {
111+
await patchBug({
112+
cid: bug.campaign_id.toString(),
113+
bid: bug.id.toString(),
114+
body: {
115+
custom_status_id: item.id,
116+
},
117+
});
118+
setSelectedItem(item);
119+
}}
120+
downshiftProps={{
121+
itemToString: (item: DropdownItem) => item && item.slug,
122+
}}
123+
>
124+
<Field>
125+
{bug.status.id === 4 ? (
126+
<Tooltip
127+
appendToNode={document.body}
128+
type="light"
129+
content={t('__BUGS_PAGE_BUG_DETAIL_NEED_REVIEW_TOOLTIP')}
130+
>
131+
<Select isCompact disabled>
132+
<SelectedItem>
133+
{t('__BUGS_PAGE_BUG_DETAIL_NEED_REVIEW')}
134+
</SelectedItem>
135+
</Select>
136+
</Tooltip>
137+
) : (
138+
<Select isCompact>
139+
<SelectedItem>
140+
{selectedItem?.icon} {selectedItem?.text}
141+
</SelectedItem>
142+
</Select>
143+
)}
144+
</Field>
145+
<Menu>
146+
{options &&
147+
options.map((item, i) => (
148+
<>
149+
{i === 5 && <Separator />}
150+
<StyledItem key={item.slug} value={item}>
151+
{item.icon} {item.text}
152+
</StyledItem>
153+
</>
154+
))}
155+
</Menu>
156+
</Dropdown>
157+
)}
158+
</div>
159+
);
160+
};
161+
162+
export default BugStateDropdown;

src/common/components/BugDetail/Priority.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,6 @@ const StyledItem = styled(Item)`
2828
}
2929
`;
3030

31-
const Container = styled.div`
32-
display: inline-block;
33-
width: 100%;
34-
margin-top: ${({ theme }) => theme.space.md};
35-
`;
36-
3731
const SelectedItem = styled.div`
3832
display: flex;
3933
align-items: center;
@@ -97,7 +91,7 @@ const Priority = ({ bug }: { bug: Bug }) => {
9791
if (isError) return null;
9892

9993
return (
100-
<Container>
94+
<div>
10195
<Label style={{ marginBottom: globalTheme.space.xxs }}>
10296
{t('__BUGS_PAGE_BUG_DETAIL_PRIORITY_LABEL')}
10397
</Label>
@@ -141,7 +135,7 @@ const Priority = ({ bug }: { bug: Bug }) => {
141135
</Menu>
142136
</Dropdown>
143137
)}
144-
</Container>
138+
</div>
145139
);
146140
};
147141

src/common/components/BugDetail/Tags.tsx

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,9 @@ import {
66
useGetCampaignsByCidTagsQuery,
77
usePatchCampaignsByCidBugsAndBidMutation,
88
} from 'src/features/api';
9-
import styled from 'styled-components';
109
import { theme as globalTheme } from 'src/app/theme';
1110
import { useEffect, useState } from 'react';
1211
import { Label } from './Label';
13-
import 'src/common/components/BugDetail/responsive-grid.css';
14-
15-
const Container = styled.div`
16-
display: inline-block;
17-
width: 100%;
18-
margin-top: ${({ theme }) => theme.space.xs};
19-
`;
2012

2113
export default ({
2214
bug,
@@ -72,7 +64,7 @@ export default ({
7264
if (isErrorCampaignTags) return null;
7365

7466
return (
75-
<Container className="responsive-container">
67+
<div>
7668
<Label style={{ marginBottom: globalTheme.space.xxs }}>
7769
{t('__BUGS_PAGE_BUG_DETAIL_TAGS_LABEL')}
7870
</Label>
@@ -155,6 +147,6 @@ export default ({
155147
/>
156148
</div>
157149
)}
158-
</Container>
150+
</div>
159151
);
160152
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { ReactComponent as CircleFill } from 'src/assets/icons/circle-full-fill.svg';
2+
import styled from 'styled-components';
3+
4+
export const BugStateIcon = styled(CircleFill)<{ height?: string }>`
5+
width: auto;
6+
height: 100%;
7+
max-height: 11px;
8+
margin: 0 2px;
9+
overflow: visible;
10+
stroke-width: 2;
11+
`;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { TFunction } from 'react-i18next';
2+
3+
export const getBugStateLabel = (state: BugState, t: TFunction): string => {
4+
switch (state.toLowerCase()) {
5+
case 'to do':
6+
return t('__BUG_STATE_TO_DO');
7+
case 'pending':
8+
return t('__BUG_STATE_PENDING');
9+
case 'to be imported':
10+
return t('__BUG_STATE_TO_BE_IMPORTED');
11+
case 'open':
12+
return t('__BUG_STATE_OPEN');
13+
case 'to be retested':
14+
return t('__BUG_STATE_TO_BE_RETESTED');
15+
case 'solved':
16+
return t('__BUG_STATE_SOLVED');
17+
case 'not a bug':
18+
return t('__BUG_STATE_NOT_A_BUG');
19+
default:
20+
return t('__BUG_STATE_TO_DO');
21+
}
22+
};

0 commit comments

Comments
 (0)