-
-
Notifications
You must be signed in to change notification settings - Fork 184
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(organizations): add Organization Settings route TASK-981 #5299
Merged
Merged
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
c6fda11
refactor(router): rename RequireOrgPermissions
Akuukis 5db756a
wip: dump skeleton of organizations settings page
Akuukis 15c6d81
Merge branch 'main' into kalvis/organizations-settings
magicznyleszek cde2230
use mmo label
magicznyleszek b5e980f
Merge branch 'main' into kalvis/organizations-settings
magicznyleszek cb07f7f
organization settings more work
magicznyleszek bf09e84
Merge branch 'main' into kalvis/organizations-settings
magicznyleszek 35f3f6d
disable changing settings fields for non admin/non owner
magicznyleszek 7b4c42a
add save button, handle permissions to edit things
magicznyleszek 6d9ec12
move planName to subscriptionStore
magicznyleszek 902a982
use plan name in OrganizationSettingsRoute
magicznyleszek 54714c9
remove comment
magicznyleszek 8789179
improve TODO comments
magicznyleszek b3a2443
improve comments, linter fixes
magicznyleszek 14c9f06
Merge branch 'main' into kalvis/organizations-settings
magicznyleszek f88d64f
Merge branch 'main' into kalvis/organizations-settings
magicznyleszek 67e6d0a
use better placeholders
magicznyleszek be201d6
Merge branch 'main' into kalvis/organizations-settings
magicznyleszek c11cfde
cleanup Organization types, add usePatchOrganization mutation hook an…
magicznyleszek e5b3059
Merge branch 'main' into kalvis/organizations-settings
magicznyleszek 83b74a0
Merge branch 'main' into leszek/task-1219-org-settings-mutating
magicznyleszek 9edc623
Merge branch 'leszek/task-1219-org-settings-mutating' into kalvis/org…
magicznyleszek 984f205
use single source of truth for organization types
magicznyleszek 147365a
some code review fixes
magicznyleszek 8ffd210
finish hooking up, split out OrganizationSettingsForm
magicznyleszek b0faa7a
don't require passing orgUrl in usePatchOrganization
magicznyleszek 931a2fa
add export
magicznyleszek 7c92e19
add prepend url false
magicznyleszek cd52acf
deduplicate organization type const
magicznyleszek 2b23d07
Merge branch 'leszek/task-1219-org-settings-mutating' into kalvis/org…
magicznyleszek a23c908
use simpler usePatchOrganization, merge files
magicznyleszek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
170 changes: 168 additions & 2 deletions
170
jsapp/js/account/organization/OrganizationSettingsRoute.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,173 @@ | ||
import React from 'react'; | ||
// Libraries | ||
import {useState, useEffect} from 'react'; | ||
|
||
// Partial components | ||
import LoadingSpinner from 'jsapp/js/components/common/loadingSpinner'; | ||
import InlineMessage from 'jsapp/js/components/common/inlineMessage'; | ||
import Button from 'jsapp/js/components/common/button'; | ||
import TextBox from 'jsapp/js/components/common/textBox'; | ||
import KoboSelect from 'jsapp/js/components/common/koboSelect'; | ||
|
||
// Stores, hooks and utilities | ||
import useWhenStripeIsEnabled from 'js/hooks/useWhenStripeIsEnabled.hook'; | ||
import {OrganizationUserRole, useOrganizationQuery, usePatchOrganization} from 'js/account/organization/organizationQuery'; | ||
import subscriptionStore from 'js/account/subscriptionStore'; | ||
import envStore from 'js/envStore'; | ||
import {getSimpleMMOLabel} from './organization.utils'; | ||
|
||
// Constants and types | ||
import {ORGANIZATION_TYPES, type OrganizationTypeName} from 'jsapp/js/account/organization/organizationQuery'; | ||
|
||
// Styles | ||
import styles from 'js/account/organization/organizationSettingsRoute.module.scss'; | ||
|
||
/** | ||
* Renders few fields with organization related settings, like name or website | ||
* (with some logic in regards to their visibility). If user has necessary role, | ||
* they can edit available fields. | ||
*/ | ||
export default function OrganizationSettingsRoute() { | ||
const orgQuery = useOrganizationQuery(); | ||
const [subscriptions] = useState(() => subscriptionStore); | ||
const [isStripeEnabled, setIsStripeEnabled] = useState(false); | ||
const patchOrganization = usePatchOrganization(); | ||
|
||
// All displayed fields | ||
const [name, setName] = useState<string>(''); | ||
const [website, setWebsite] = useState<string>(''); | ||
const [orgType, setOrgType] = useState<OrganizationTypeName | null>(null); | ||
|
||
useEffect(() => { | ||
if (orgQuery.data) { | ||
setName(orgQuery.data.name); | ||
setWebsite(orgQuery.data.website); | ||
setOrgType(orgQuery.data.organization_type); | ||
} | ||
}, [orgQuery.data]); | ||
|
||
useWhenStripeIsEnabled(() => { | ||
setIsStripeEnabled(true); | ||
}, []); | ||
|
||
const isUserAdminOrOwner = ( | ||
orgQuery.data?.request_user_role && | ||
[OrganizationUserRole.admin, OrganizationUserRole.owner] | ||
.includes(orgQuery.data?.request_user_role) | ||
); | ||
|
||
function handleSave(e: React.FormEvent) { | ||
e.preventDefault(); | ||
patchOrganization.mutateAsync({name, website}); | ||
} | ||
|
||
function handleChangeName(newName: string) { | ||
setName(newName); | ||
} | ||
|
||
function handleChangeWebsite(newWebsite: string) { | ||
setWebsite(newWebsite); | ||
} | ||
|
||
const mmoLabel = getSimpleMMOLabel( | ||
envStore.data, | ||
subscriptionStore.activeSubscriptions[0], | ||
false, | ||
true | ||
); | ||
const mmoLabelLowercase = mmoLabel.toLowerCase(); | ||
|
||
if (orgQuery.isLoading) { | ||
return <LoadingSpinner />; | ||
} | ||
|
||
let deletionMessage = t('To delete this ##team/org##, please contact the server administrator.') | ||
.replaceAll('##team/org##', mmoLabelLowercase); | ||
if (isStripeEnabled) { | ||
deletionMessage = t("To delete this ##team/org##, you need to cancel your current ##plan name## plan. At the end of the plan period your ##team/org##'s projects will be converted to projects owned by your personal account.") | ||
.replaceAll('##team/org##', mmoLabelLowercase) | ||
.replace('##plan name##', subscriptions.planName); | ||
} | ||
|
||
const currentTypeLabel = orgType === null ? '' : ORGANIZATION_TYPES[orgType]?.label; | ||
|
||
return ( | ||
<div>Organization settings view to be implemented</div> | ||
<form className={styles.orgSettingsRoot} onSubmit={handleSave}> | ||
<header className={styles.orgSettingsHeader}> | ||
<h2 className={styles.orgSettingsHeaderText}> | ||
{t('##team/org## details').replace('##team/org##', mmoLabel)} | ||
</h2> | ||
</header> | ||
|
||
<section className={styles.fieldsRow}> | ||
{/* | ||
On all instances, both owner and admins should be able to edit | ||
organization name. | ||
*/} | ||
<TextBox | ||
className={styles.field} | ||
label={t('##team/org## name').replace('##team/org##', mmoLabel)} | ||
value={name} | ||
required | ||
onChange={handleChangeName} | ||
disabled={!isUserAdminOrOwner || orgQuery.isPending || patchOrganization.isPending} | ||
errors={name === ''} | ||
/> | ||
|
||
{/* | ||
On Stripe-enabled instances, both owner and admins should be able to | ||
edit organization website. On non-Stripe enabled instances it is not | ||
visible. | ||
*/} | ||
{isStripeEnabled && ( | ||
<TextBox | ||
className={styles.field} | ||
type='url' | ||
label={t('##team/org## website').replace('##team/org##', mmoLabel)} | ||
value={website} | ||
required | ||
onChange={handleChangeWebsite} | ||
disabled={!isUserAdminOrOwner || orgQuery.isPending || patchOrganization.isPending} | ||
errors={website === ''} | ||
/> | ||
)} | ||
</section> | ||
|
||
{/* | ||
On Stripe-enabled instances, both owner and admins should be able to | ||
view organization type. On non-Stripe enabled instances it is not | ||
visible. | ||
*/} | ||
{isStripeEnabled && orgType && ( | ||
<section className={styles.fieldsRow}> | ||
<KoboSelect | ||
className={styles.fieldLong} | ||
name='org-settings-type' | ||
type='outline' | ||
size='l' | ||
isDisabled // always disabled | ||
label={t('##team/org## type').replace('##team/org##', mmoLabel)} | ||
options={[{ | ||
Akuukis marked this conversation as resolved.
Show resolved
Hide resolved
|
||
value: 'orgType', | ||
label: currentTypeLabel, | ||
}]} | ||
selectedOption='orgType' | ||
onChange={() => null} | ||
/> | ||
</section> | ||
)} | ||
|
||
<section className={styles.fieldsRow}> | ||
<Button | ||
type='primary' | ||
size='m' | ||
label={t('Save')} | ||
isDisabled={!isUserAdminOrOwner} | ||
isPending={orgQuery.isPending || patchOrganization.isPending} | ||
isSubmit | ||
/> | ||
</section> | ||
|
||
<InlineMessage type='default' message={deletionMessage} /> | ||
</form> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
jsapp/js/account/organization/organizationSettingsRoute.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
@use 'scss/mixins'; | ||
@use 'scss/colors'; | ||
@use 'scss/breakpoints'; | ||
@use 'js/components/common/textBox.module'; | ||
|
||
$s-field-width: 285px; | ||
|
||
.orgSettingsRoot { | ||
padding: 20px; | ||
overflow-y: auto; | ||
height: 100%; | ||
} | ||
|
||
header.orgSettingsHeader { | ||
@include mixins.centerRowFlex; | ||
margin: 24px 0; | ||
|
||
&:not(:first-child) { | ||
margin-top: 44px; | ||
} | ||
} | ||
|
||
h2.orgSettingsHeaderText { | ||
color: colors.$kobo-storm; | ||
text-transform: uppercase; | ||
font-size: 18px; | ||
font-weight: 700; | ||
flex: 1; | ||
margin: 0; | ||
} | ||
|
||
.fieldsRow { | ||
display: flex; | ||
align-items: baseline; | ||
flex-wrap: wrap; | ||
gap: 16px; | ||
|
||
&:not(:first-child) { | ||
margin-top: 16px; | ||
} | ||
} | ||
|
||
.field { | ||
max-width: $s-field-width; | ||
width: 100%; | ||
} | ||
|
||
.fieldLong { | ||
// When we display two fields in one row, and long field in other, we want | ||
// them to align nicely, thus: | ||
max-width: $s-field-width + 16px + $s-field-width; | ||
width: 100%; | ||
} | ||
|
||
@include breakpoints.breakpoint(mediumAndUp) { | ||
.orgSettingsRoot { | ||
padding: 50px; | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
more of a linter thing, but don't use
let
and mutation if possible. Here one way to rewrite itor