Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/add user design #981

Merged
merged 12 commits into from
Nov 24, 2023
2 changes: 1 addition & 1 deletion db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -1046,7 +1046,7 @@ func (db database) CreateOrEditOrganization(m Organization) (Organization, error
func (db database) GetOrganizationUsers(uuid string) ([]OrganizationUsersData, error) {
ms := []OrganizationUsersData{}

err := db.db.Raw(`SELECT org.org_uuid, org.created as user_created, person.* FROM public.organization_users AS org LEFT OUTER JOIN public.people AS person ON org.owner_pub_key = person.owner_pub_key WHERE org.org_uuid = '` + uuid + `' OR org.organization = '` + uuid + `' ORDER BY org.created DESC`).Find(&ms).Error
err := db.db.Raw(`SELECT org.org_uuid, org.created as user_created, person.* FROM public.organization_users AS org LEFT OUTER JOIN public.people AS person ON org.owner_pub_key = person.owner_pub_key WHERE org.org_uuid = '` + uuid + `' ORDER BY org.created DESC`).Find(&ms).Error

return ms, err
}
Expand Down
57 changes: 54 additions & 3 deletions frontend/app/src/helpers/__test__/helpers.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import crypto from 'crypto';
import moment from 'moment';
import {
extractGithubIssueFromUrl,
extractRepoAndIssueFromIssueUrl,
Expand All @@ -6,10 +8,10 @@ import {
toCapitalize,
userHasRole,
spliceOutPubkey,
userHasManageBountyRoles
userHasManageBountyRoles,
RolesCategory,
handleDisplayRole
} from '../helpers-extended';
import crypto from 'crypto';
import moment from 'moment';

beforeAll(() => {
// for test randomString
Expand Down Expand Up @@ -210,4 +212,53 @@ describe('testing helpers', () => {
expect(pub).toBe(pubkey);
});
});

describe('format roles', () => {
test('should correctly set the default data roles for the first assigned user', () => {
const displayedRoles: RolesCategory[] = [];
const result = handleDisplayRole(displayedRoles);
expect(result.newDisplayedRoles).toEqual([]);
expect(result.tempDataRole).toEqual({});
});

test('should correctly update the status of a role if it is present in the default roles', () => {
const displayedRoles: RolesCategory[] = [
{ name: 'Manage bounties', roles: [], status: false },
{ name: 'Fund organization', roles: [], status: false },
{ name: 'Withdraw from organization', roles: [], status: false },
{ name: 'View transaction history', roles: [], status: false }
];
const result = handleDisplayRole(displayedRoles);
expect(result.newDisplayedRoles).toEqual([
{ name: 'Manage bounties', roles: [], status: true },
{ name: 'Fund organization', roles: [], status: true },
{ name: 'Withdraw from organization', roles: [], status: true },
{ name: 'View transaction history', roles: [], status: true }
]);
expect(result.tempDataRole).toEqual({});
});

test('should correctly update the tempDataRole object with the data roles of a role if it is present in the default roles', () => {
const displayedRoles: RolesCategory[] = [
{ name: 'Manage bounties', roles: ['role1', 'role2'], status: false },
{ name: 'Fund organization', roles: ['role3'], status: false },
{ name: 'Withdraw from organization', roles: ['role4'], status: false },
{ name: 'View transaction history', roles: ['role5'], status: false }
];
const result = handleDisplayRole(displayedRoles);
expect(result.newDisplayedRoles).toEqual([
{ name: 'Manage bounties', roles: ['role1', 'role2'], status: true },
{ name: 'Fund organization', roles: ['role3'], status: true },
{ name: 'Withdraw from organization', roles: ['role4'], status: true },
{ name: 'View transaction history', roles: ['role5'], status: true }
]);
expect(result.tempDataRole).toEqual({
role1: true,
role2: true,
role3: true,
role4: true,
role5: true
});
});
});
});
60 changes: 60 additions & 0 deletions frontend/app/src/helpers/helpers-extended.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,45 @@ export type Roles =

export const ManageBountiesGroup = ['ADD BOUNTY', 'UPDATE BOUNTY', 'DELETE BOUNTY', 'PAY BOUNTY'];

export interface RolesCategory {
name: string;
roles: string[];
status: boolean;
}

export const s_RolesCategories = [
{
name: 'Manage organization',
roles: ['EDIT ORGANIZATION'],
status: false
},
{
name: 'Manage bounties',
roles: ManageBountiesGroup,
status: false
},
{
name: 'Fund organization',
roles: ['ADD BUDGET'],
status: false
},
{
name: 'Withdraw from organization',
roles: ['WITHDRAW BUDGET'],
status: false
},
{
name: 'View transaction history',
roles: ['VIEW REPORT'],
status: false
},
{
name: 'Update members',
roles: ['ADD USER', 'UPDATE USER', 'DELETE USER', 'ADD ROLES'],
status: false
}
];

export const userHasRole = (
bountyRoles: any[],
userRoles: any[],
Expand Down Expand Up @@ -239,3 +278,24 @@ export const spliceOutPubkey = (userAddress: string): string => {

return userAddress;
};

export function handleDisplayRole(displayedRoles: RolesCategory[]) {
// Set default data roles for first assign user
const defaultRole = {
'Manage bounties': true,
'Fund organization': true,
'Withdraw from organization': true,
'View transaction history': true
};

const tempDataRole: { [id: string]: boolean } = {};
const newDisplayedRoles = displayedRoles.map((role: RolesCategory) => {
if (defaultRole[role.name]) {
role.status = true;
role.roles.forEach((dataRole: string) => (tempDataRole[dataRole] = true));
}
return role;
});

return { newDisplayedRoles, tempDataRole };
}
50 changes: 25 additions & 25 deletions frontend/app/src/people/widgetViews/AboutView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,33 @@ import QrBar from '../utils/QrBar';
import { renderMarkdown } from '../utils/RenderMarkdown';

const Badge = styled.div`
display:flex;
justify-content:center;
align-items:center;
margin-left:10px;
height:20px;
color:#ffffff;
background: #1DA1F2;
border-radius: 32px;
font-weight: bold;
font-size: 8px;
line-height: 9px;
padding 0 10px;
display: flex;
justify-content: center;
align-items: center;
margin-left: 10px;
height: 20px;
color: #ffffff;
background: #1da1f2;
border-radius: 32px;
font-weight: bold;
font-size: 8px;
line-height: 9px;
padding: 0 10px;
`;
const CodeBadge = styled.div`
display:flex;
justify-content:center;
align-items:center;
margin-right:10px;
height:26px;
color:#5078F2;
background: #DCEDFE;
border-radius: 32px;
font-weight: bold;
font-size: 12px;
line-height: 13px;
padding 0 10px;
margin-bottom:10px;
display: flex;
justify-content: center;
align-items: center;
margin-right: 10px;
height: 26px;
color: #5078f2;
background: #dcedfe;
border-radius: 32px;
font-weight: bold;
font-size: 12px;
line-height: 13px;
padding: 0 10px;
margin-bottom: 10px;
`;
const ItemRow = styled.div`
display: flex;
Expand Down
28 changes: 26 additions & 2 deletions frontend/app/src/people/widgetViews/OrganizationDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
ViewBudgetWrap,
ViewBudgetTextWrap
} from './organization/style';
import AssignUserRoles from './organization/AssignUserRole';

let interval;

Expand Down Expand Up @@ -68,6 +69,7 @@ const OrganizationDetails = (props: {
const [toasts, setToasts]: any = useState([]);
const [invoiceStatus, setInvoiceStatus] = useState(false);
const { path, url } = useRouteMatch();
const [isOpenAssignRoles, setIsOpenAssignRoles] = useState<boolean>(false);

const isOrganizationAdmin = props.org?.owner_pubkey === ui.meInfo?.owner_pubkey;

Expand All @@ -86,7 +88,7 @@ const OrganizationDetails = (props: {
function addToast(title: string, color: 'danger' | 'success') {
setToasts([
{
id: '1',
id: `${Math.random()}`,
title,
color
}
Expand All @@ -101,6 +103,7 @@ const OrganizationDetails = (props: {
if (uuid) {
const users = await main.getOrganizationUsers(uuid);
setUsers(users);
return users;
}
}, [main, uuid]);

Expand Down Expand Up @@ -193,14 +196,24 @@ const OrganizationDetails = (props: {
setIsOpenWithdrawBudget(false);
};

const closeAssignRolesHandler = () => {
setIsOpenAssignRoles(false);
};

const onSubmitUser = async (body: any) => {
setIsLoading(true);

body.org_uuid = uuid;

const res = await main.addOrganizationUser(body);
if (res.status === 200) {
await getOrganizationUsers();
addToast('User added to organization successfully', 'success');
const recentUsers = await getOrganizationUsers();
const user = recentUsers?.filter((user: Person) => user.owner_pubkey === body.owner_pubkey);
if (user?.length === 1) {
setUser(user[0]);
setIsOpenAssignRoles(true);
}
} else {
addToast('Error: could not add user', 'danger');
}
Expand Down Expand Up @@ -452,6 +465,17 @@ const OrganizationDetails = (props: {
loading={loading}
/>
)}
{isOpenAssignRoles && (
<AssignUserRoles
close={closeAssignRolesHandler}
isOpen={isOpenAssignRoles}
loading={loading}
onSubmit={submitRoles}
user={user}
setLoading={setIsLoading}
addToast={addToast}
/>
)}
{isOpenRoles && (
<RolesModal
uuid={uuid}
Expand Down
Loading
Loading