Skip to content

Commit 41d2add

Browse files
authored
Merge pull request #563 from devtron-labs/feat/pipeline-rbac
feat: add PipelineViewRBAC component in Logout card
2 parents c4fdc4e + 5f3520b commit 41d2add

File tree

13 files changed

+126
-14
lines changed

13 files changed

+126
-14
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devtron-labs/devtron-fe-common-lib",
3-
"version": "1.7.8",
3+
"version": "1.7.9",
44
"description": "Supporting common component library",
55
"type": "module",
66
"main": "dist/index.js",

src/Common/Constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export const ROUTES = {
9999
TELEMETRY_EVENT: 'telemetry/event',
100100
SERVER_INFO_API: 'server',
101101
ATTRIBUTES_USER: 'attributes/user',
102+
GET: 'get',
102103
UPDATE: 'update',
103104
ENVIRONMENT_LIST_MIN: 'env/autocomplete',
104105
CLUSTER: 'cluster',

src/Common/SegmentedControl/SegmentedControl.component.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const SegmentedControl = ({
2929
name,
3030
variant = SegmentedControlVariant.WHITE_ON_GRAY,
3131
size = ComponentSizeType.medium,
32+
isControlled = false,
3233
}: SegmentedControlProps) => (
3334
<StyledRadioGroup
3435
className={`${variant} ${SEGMENTED_CONTROL_SIZE_TO_CLASS_MAP[size]} ${rootClassName}`}
@@ -45,6 +46,7 @@ const SegmentedControl = ({
4546
showTippy={!!tooltips?.[index]}
4647
tippyContent={tooltips?.[index] ?? ''}
4748
dataTestId={`${name}-${tab.value}`}
49+
canSelect={!isControlled}
4850
>
4951
{tab.label}
5052
</StyledRadioGroup.Radio>

src/Common/SegmentedControl/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,8 @@ export interface SegmentedControlProps {
3737
* @default ComponentSizeType.medium
3838
*/
3939
size?: ComponentSizeType.medium | ComponentSizeType.large
40+
/**
41+
* @default false
42+
*/
43+
isControlled?: boolean
4044
}

src/Shared/Components/LogoutCard.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616

1717
import React from 'react'
1818
import { useHistory } from 'react-router-dom'
19-
import { getRandomColor } from '../../Common'
19+
import { useMainContext } from '@Shared/Providers'
20+
import { getRandomColor, stopPropagation } from '../../Common'
2021
import { ThemeSwitcher } from './ThemeSwitcher'
2122

2223
interface LogoutCardType {
@@ -28,6 +29,7 @@ interface LogoutCardType {
2829

2930
const LogoutCard = ({ className, userFirstLetter, setShowLogOutCard, showLogOutCard }: LogoutCardType) => {
3031
const history = useHistory()
32+
const { viewIsPipelineRBACConfiguredNode } = useMainContext()
3133

3234
const onLogout = () => {
3335
document.cookie = `argocd.token=; expires=Thu, 01-Jan-1970 00:00:01 GMT;path=/`
@@ -40,9 +42,9 @@ const LogoutCard = ({ className, userFirstLetter, setShowLogOutCard, showLogOutC
4042

4143
return (
4244
<div className="dc__transparent-div" onClick={toggleLogoutCard}>
43-
<div className={`logout-card ${className}`}>
44-
<div className="flexbox flex-justify p-16">
45-
<div className="logout-card-user ">
45+
<div className={`logout-card ${className}`} onClick={stopPropagation}>
46+
<div className="flexbox flex-justify py-16 px-12">
47+
<div className="logout-card-user">
4648
<p className="logout-card__name dc__ellipsis-right">{userFirstLetter}</p>
4749
<p className="logout-card__email dc__ellipsis-right">{userFirstLetter}</p>
4850
</div>
@@ -55,8 +57,11 @@ const LogoutCard = ({ className, userFirstLetter, setShowLogOutCard, showLogOutC
5557
</div>
5658
<div className="dc__border-top-n1 py-4">
5759
<ThemeSwitcher onChange={toggleLogoutCard} />
60+
61+
{viewIsPipelineRBACConfiguredNode}
62+
5863
<button
59-
className="dc__unset-button-styles px-8 py-6 fs-13 fw-4 lh-20 cr-5 dc__hover-n50 cursor w-100 flex left"
64+
className="dc__unset-button-styles px-12 py-6 fs-13 fw-4 lh-20 cr-5 dc__hover-n50 cursor w-100 flex left"
6065
data-testid="logout-button"
6166
onClick={onLogout}
6267
type="button"

src/Shared/Components/ThemeSwitcher/ThemeSwitcher.component.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const ThemeSwitcher = ({ onChange }: ThemeSwitcherProps) => {
3232
return {
3333
tabs: availableThemePreferences.map((value) => ({
3434
label: (
35-
<span className="dc__no-shrink icon-dim-20 flex dc__fill-available-space">
35+
<span className="dc__no-shrink icon-dim-16 flex dc__fill-available-space">
3636
{THEME_PREFERENCE_TO_ICON_MAP[value].icon}
3737
</span>
3838
),
@@ -53,15 +53,15 @@ const ThemeSwitcher = ({ onChange }: ThemeSwitcherProps) => {
5353
}
5454

5555
return (
56-
<div className="flex dc__content-space dc__gap-8 px-8 py-6" onClick={stopPropagation}>
56+
<div className="flex dc__content-space dc__gap-8 px-12 py-6" onClick={stopPropagation}>
5757
<p className="m-0 fs-13 fw-4 lh-20 cn-9">Theme</p>
5858
<SegmentedControl
5959
initialTab={themePreference}
6060
name="theme-preference-selector"
6161
onChange={handleThemeSwitch}
6262
tabs={tabs}
6363
tooltips={tooltips}
64-
size={ComponentSizeType.large}
64+
size={ComponentSizeType.medium}
6565
variant={SegmentedControlVariant.GRAY_ON_WHITE}
6666
/>
6767
</div>

src/Shared/Providers/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export interface MainContext {
4040
isAirgapped: boolean
4141
isSuperAdmin: boolean
4242
isManifestScanningEnabled: boolean
43+
isOrgLevelRBACViewEnforced: boolean
44+
viewIsPipelineRBACConfiguredNode: ReactNode
4345
}
4446

4547
export interface MainContextProviderProps {

src/Shared/Services/common.service.ts

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,18 @@
1414
* limitations under the License.
1515
*/
1616

17-
import { getUrlWithSearchParams, post, ROUTES } from '../../Common'
18-
import { GetPolicyApiUrlProps, GetResourceApiUrlProps } from './types'
17+
import { ViewIsPipelineRBACConfiguredRadioTabs } from '@Shared/types'
18+
import { get, getUrlWithSearchParams, post, ROUTES, showError } from '../../Common'
19+
import { USER_PREFERENCES_ATTRIBUTE_KEY } from './constants'
20+
import {
21+
GetPolicyApiUrlProps,
22+
GetResourceApiUrlProps,
23+
GetUserPreferencesParsedDTO,
24+
GetUserPreferencesQueryParamsType,
25+
UpdateUserPreferencesParsedValueType,
26+
UpdateUserPreferencesPayloadType,
27+
UserPreferencesType,
28+
} from './types'
1929

2030
export const getResourceApiUrl = <T>({ baseUrl, kind, version, suffix, queryParams }: GetResourceApiUrlProps<T>) =>
2131
getUrlWithSearchParams(`${baseUrl}/${kind}/${version}${suffix ? `/${suffix}` : ''}`, queryParams)
@@ -24,3 +34,55 @@ export const getPolicyApiUrl = <T>({ kind, version, queryParams, suffix }: GetPo
2434
getUrlWithSearchParams(`global/policy/${kind}/${version}${suffix ? `/${suffix}` : ''}`, queryParams)
2535

2636
export const saveCDPipeline = (request) => post(ROUTES.CD_CONFIG, request)
37+
38+
export const getUserPreferences = async (): Promise<UserPreferencesType> => {
39+
const queryParamsPayload: Pick<GetUserPreferencesQueryParamsType, 'key'> = {
40+
key: USER_PREFERENCES_ATTRIBUTE_KEY,
41+
}
42+
43+
const { result } = await get<{ value: string }>(
44+
getUrlWithSearchParams(`${ROUTES.ATTRIBUTES_USER}/${ROUTES.GET}`, queryParamsPayload),
45+
)
46+
47+
if (!result?.value) {
48+
return null
49+
}
50+
51+
const parsedResult: GetUserPreferencesParsedDTO = JSON.parse(result.value)
52+
53+
const pipelineRBACViewSelectedTab = parsedResult.viewPermittedEnvOnly
54+
? ViewIsPipelineRBACConfiguredRadioTabs.ACCESS_ONLY
55+
: ViewIsPipelineRBACConfiguredRadioTabs.ALL_ENVIRONMENTS
56+
57+
return {
58+
pipelineRBACViewSelectedTab,
59+
}
60+
}
61+
62+
export const updateUserPreferences = async (
63+
updatedUserPreferences: UserPreferencesType,
64+
shouldThrowError: boolean = false,
65+
): Promise<boolean> => {
66+
try {
67+
const value: UpdateUserPreferencesParsedValueType = {
68+
viewPermittedEnvOnly:
69+
updatedUserPreferences.pipelineRBACViewSelectedTab ===
70+
ViewIsPipelineRBACConfiguredRadioTabs.ACCESS_ONLY,
71+
}
72+
73+
const payload: UpdateUserPreferencesPayloadType = {
74+
key: USER_PREFERENCES_ATTRIBUTE_KEY,
75+
value: JSON.stringify(value),
76+
}
77+
78+
await post(`${ROUTES.ATTRIBUTES_USER}/${ROUTES.UPDATE}`, payload)
79+
return true
80+
} catch (error) {
81+
if (shouldThrowError) {
82+
throw error
83+
}
84+
85+
showError(error)
86+
return false
87+
}
88+
}

src/Shared/Services/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const USER_PREFERENCES_ATTRIBUTE_KEY = 'userPreferences'

0 commit comments

Comments
 (0)