Skip to content

Commit

Permalink
Merge branch 'main' into task-963-create-endpoints-to-handle-org-members
Browse files Browse the repository at this point in the history
  • Loading branch information
rajpatel24 committed Nov 13, 2024
2 parents 0401fc4 + 2f1d45e commit 1dec6eb
Show file tree
Hide file tree
Showing 76 changed files with 2,732 additions and 1,356 deletions.
41 changes: 26 additions & 15 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,22 @@
/jsapp/ @magicznyleszek
/patches/ @p2edwards
/static/ @magicznyleszek
/webpack/ @magicznyleszek
/.babelrc.json @magicznyleszek
/.browserslistrc @magicznyleszek
/.eslintignore @magicznyleszek
/.eslintrc.js @magicznyleszek
/.node-version @magicznyleszek
/.nvmrc @magicznyleszek
/.prettierrc.js @magicznyleszek
/.stylelintrc.js @magicznyleszek
/.swcrc @magicznyleszek
/.coffeelint.json @magicznyleszek
/package-lock.json @magicznyleszek
/package.json @magicznyleszek
/tsconfig.json @magicznyleszek
/static/js/ @magicznyleszek @p2edwards
/test/ @magicznyleszek @p2edwards
/webpack/ @magicznyleszek @p2edwards
/.babelrc.json @magicznyleszek @p2edwards
/.browserslistrc @magicznyleszek @p2edwards
/.eslintignore @magicznyleszek @p2edwards
/.eslintrc.js @magicznyleszek @p2edwards
/.node-version @magicznyleszek @p2edwards
/.nvmrc @magicznyleszek @p2edwards
/.prettierrc.js @magicznyleszek @p2edwards
/.stylelintrc.js @magicznyleszek @p2edwards
/.swcrc @magicznyleszek @p2edwards
/.coffeelint.json @magicznyleszek @p2edwards
/package-lock.json @magicznyleszek @p2edwards
/package.json @magicznyleszek @p2edwards
/tsconfig.json @magicznyleszek @p2edwards

# Billing
/jsapp/js/account/ @jamesrkiger
Expand All @@ -64,18 +66,25 @@
# Default owner
/dependencies/ @jnm @noliveleger
/hub/ @jnm @noliveleger
/hub/tests/ @jnm @noliveleger
/kobo/ @jnm @noliveleger
/kobo/apps/audit_log/ @rgraber
/kobo/apps/subsequences/ @Guitlle
/kpi/ @jnm @noliveleger
/test/ @jnm @noliveleger
/kpi/tests/ @jnm @noliveleger
/.coveragerc @jnm
/.dockerignore @jnm @noliveleger
/format-python.sh @noliveleger
/manage.py @jnm @noliveleger
/pip-compile.sh @jnm @noliveleger
/pyproject.toml @jnm @noliveleger

# Django Static Templates, HTML, JS, CSS
/kobo/apps/accounts/templates/ @magicznyleszek @p2edwards @jnm @noliveleger
/kpi/templates/ @magicznyleszek @p2edwards @jnm @noliveleger
/kpi/static/css/ @magicznyleszek @p2edwards
_registration.scss @magicznyleszek @p2edwards




Expand All @@ -84,7 +93,9 @@

/docker/ @bufke @jnm @noliveleger
/scripts/ @bufke @jnm @noliveleger
/scripts/*.js @magicznyleszek @p2edwards
/.github/ @bufke @jnm @noliveleger @magicznyleszek
/.github/workflows/npm-test.yml @bufke @jnm @noliveleger @magicznyleszek @p2edwards
/.gitlab-ci.yml @bufke
/Dockerfile @bufke @jnm @noliveleger

Expand Down
5 changes: 3 additions & 2 deletions hub/models/extra_user_detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,6 @@ def _sync_org_name(self):
except (KeyError, AttributeError):
organization_name = None

user_organization.name = organization_name
user_organization.save(update_fields=['name'])
if organization_name:
user_organization.name = organization_name
user_organization.save(update_fields=['name'])
3 changes: 2 additions & 1 deletion jsapp/js/components/common/button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ $button-border-radius: 6px;
left: calc(50% - #{$iconAlone * 0.5});
}

&.k-button--type-text {
// We need bigger specificity here to override paddings for has-label
&.k-button--type-text.k-button--type-text {
// We need the text button to align better with other UI elements, so we
// want to avoid the transparent space on both sides.
padding-left: 0;
Expand Down
7 changes: 4 additions & 3 deletions jsapp/js/components/header/mainHeader.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,10 @@ const MainHeader = class MainHeader extends React.Component<MainHeaderProps> {
</React.Fragment>
)}

<OrganizationBadge/>

<AccountMenu />
<div className={styles.accountSection}>
<OrganizationBadge />
<AccountMenu />
</div>

{!isLoggedIn && this.renderLoginButton()}
</MainHeaderBase>
Expand Down
6 changes: 6 additions & 0 deletions jsapp/js/components/header/mainHeader.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@
display: none;
}
}

.accountSection {
display: flex;
margin-left: auto;
position: relative;
}
1 change: 0 additions & 1 deletion jsapp/js/components/header/organizationBadge.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@
border-radius: 48px;
font-weight: 600;
font-size: .85em;
line-height: 12px;
margin-right: 20px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Libraries
import React, {useState, useEffect} from 'react';
import {useSearchParams} from 'react-router-dom';

// Partial components
import TransferProjectsInvite from './transferProjectsInvite.component';
import ProjectTransferInviteBanner from './projectTransferInviteBanner';

// Stores, hooks and utilities
import {
isInviteForLoggedInUser,
type TransferStatuses,
} from './transferProjects.api';

// Constants and types
import type {TransferInviteState} from './projectTransferInviteBanner';

/**
* This is a glue component that displays a modal from `TransferProjectsInvite`
* and a banner from `ProjectTransferInviteBanner` as an outcome of the modal
* action.
*/
export default function ProjectOwnershipTransferModalWithBanner() {
const [invite, setInvite] = useState<TransferInviteState>({
valid: false,
uid: '',
status: null,
name: '',
currentOwner: '',
});
const [isBannerVisible, setIsBannerVisible] = useState(true);
const [searchParams] = useSearchParams();

useEffect(() => {
const inviteParams = searchParams.get('invite');
if (inviteParams) {
isInviteForLoggedInUser(inviteParams).then((data) => {
setInvite({...invite, valid: data, uid: inviteParams});
});
} else {
setInvite({...invite, valid: false, uid: ''});
}
}, [searchParams]);

const setInviteDetail = (
newStatus: TransferStatuses.Accepted | TransferStatuses.Declined,
name: string,
currentOwner: string
) => {
setInvite({
...invite,
status: newStatus,
name: name,
currentOwner: currentOwner,
});
};

return (
<>
{isBannerVisible &&
<ProjectTransferInviteBanner
invite={invite}
onRequestClose={() => {setIsBannerVisible(false);}}
/>
}

{invite.valid && invite.uid !== '' && (
<TransferProjectsInvite
setInvite={setInviteDetail}
inviteUid={invite.uid}
/>
)}
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@use 'scss/colors';

.banner {
display: flex;
justify-content: space-between;
margin: 24px 24px 0;
padding: 12px;
background-color: colors.$kobo-light-blue;
border-radius: 5px;
align-items: center;
}

.bannerIcon {
padding-right: 18px;
}

.bannerButton {
margin-left: auto;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react';
import Icon from 'js/components/common/icon';
import Button from 'js/components/common/button';
import {TransferStatuses} from 'js/components/permissions/transferProjects/transferProjects.api';
import styles from './projectTransferInviteBanner.module.scss';

export interface TransferInviteState {
valid: boolean;
uid: string;
status: TransferStatuses.Accepted | TransferStatuses.Declined | null;
name: string;
currentOwner: string;
}

interface ProjectTransferInviteBannerProps {
invite: TransferInviteState;
onRequestClose: () => void;
}

/**
* Displays a banner about accepting or declining project transfer invitation.
*/
export default function ProjectTransferInviteBanner(props: ProjectTransferInviteBannerProps) {
if (props.invite.status) {
return (
<div className={styles.banner}>
<Icon
name='information'
color='blue'
className={styles.bannerIcon}
/>

{props.invite.status === TransferStatuses.Declined && (
<>
{t('You have declined the request of transfer ownership for ##PROJECT_NAME##. ##CURRENT_OWNER_NAME## will receive a notification that the transfer was incomplete.')
.replace('##PROJECT_NAME##', props.invite.name)
.replace('##CURRENT_OWNER_NAME##', props.invite.currentOwner)}
&nbsp;
{t('##CURRENT_OWNER_NAME## will remain the project owner.')
.replace('##CURRENT_OWNER_NAME##', props.invite.currentOwner)}
</>
)}

{props.invite.status === TransferStatuses.Accepted && (
<>
{t('You have accepted project ownership from ##CURRENT_OWNER_NAME## for ##PROJECT_NAME##. This process can take up to a few minutes to complete.')
.replace('##PROJECT_NAME##', props.invite.name)
.replace('##CURRENT_OWNER_NAME##', props.invite.currentOwner)}
</>
)}

<Button
type='text'
size='s'
startIcon='close'
onClick={() => {props.onRequestClose();}}
className={styles.bannerButton}
/>
</div>
);
}

return null;
}
Loading

0 comments on commit 1dec6eb

Please sign in to comment.