Skip to content

Rework organization page #8679

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

Merged
merged 22 commits into from
Jun 25, 2025
Merged

Conversation

hotzenklotz
Copy link
Member

@hotzenklotz hotzenklotz commented Jun 6, 2025

This PR refreshes the layout and styling of the organization page to be in inline with the account setting page.

Screenshot 2025-06-16 at 20 21 10 Screenshot 2025-06-16 at 20 21 16 Screenshot 2025-06-16 at 20 21 25

URL of deployed dev instance (used for testing):

  • https://___.webknossos.xyz

Steps to test:

  • Make sure to test various orga configs: Basic, Team, Power and variations on too many users, too much storage space, subscription exceeded etc.
  • Check light/dark mode

Issues:


(Please delete unneeded items, merge only when none are left open)

Copy link
Contributor

coderabbitai bot commented Jun 6, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@hotzenklotz hotzenklotz self-assigned this Jun 6, 2025
@philippotto philippotto changed the title Refresh organization page Rework organization page Jun 6, 2025
- Updated the navbar link for managing organizations to point to the overview page.
- Replaced `AccountSettingsTitle` with `SettingsTitle` in multiple views for consistency.
- Introduced `SettingsCard` component for better organization of settings-related UI.
- Added new views for organization notifications and overview, enhancing the organization management experience.
- Cleaned up unused code and improved the structure of organization-related components.
- Updated the CustomPlanUpgradeCard to include a MailOutlined icon and improved layout with responsive columns.
- Modified OrganizationNotificationsView to dispatch the updated organization state after saving notification settings.
- Added organization name editing functionality in OrganizationOverviewView with validation and state management.
- Refactored organization overview stats display for better readability and structure.
- Improved imports in organization-related components for consistency.
- Updated OrganizationController to include the current user's identity in the organization JSON response.
- Modified organization cards to export components for better reusability.
- Improved the upgrade plan modal by wrapping components in a ConfigProvider for consistent theming and layout adjustments.
- Refactored the modal body to use responsive columns for displaying upgrade options.

These changes aim to improve the user experience and maintainability of the organization management interface.
@hotzenklotz hotzenklotz marked this pull request as ready for review June 16, 2025 18:26
@hotzenklotz hotzenklotz requested a review from philippotto June 16, 2025 18:26
@hotzenklotz
Copy link
Member Author

@philippotto I branched of the account settings page PR for this feature to reuse some components. Please focus the review only on the updated orga page for now.

@@ -71,7 +73,12 @@ export function extendPricingPlan(organization: APIOrganization) {
}

export function upgradeUserQuota() {
renderIndependently((destroyCallback) => <UpgradeUserQuotaModal destroy={destroyCallback} />);
renderIndependently((destroyCallback) => (
<ConfigProvider theme={getAntdTheme(getSystemColorTheme())}>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit dirty. It would be cleaner to fetch the user and apply the correct light/dark theme. This workaround, however, at least applies the right theme colors for primary buttons etc and is a close enough heuristic to match the OS appearance.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why this is necessary. renderIndependently uses GlobalThemeProvider which reads the user object from the store and also creates a ConfigProvider wrapper?

@@ -630,7 +630,17 @@ class ReactRouter extends React.Component<Props> {
<SecuredRouteWithErrorBoundary
isAuthenticated={isAuthenticated}
path="/organizations/:organizationId"
render={() => <OrganizationEditView />}
render={() => <Redirect to="/organization" />}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left the legacy frontend route for backward compatibility. Maybe that is not really needed though.

Copy link
Member

@philippotto philippotto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool stuff 👍 I really like the overall look. I left some comments and found this during testing:

image

I'm in the basic plan. I cannot really see what other plans are available and what they offer. the box at the bottom probably describes all power features? but what about the team features? also the point "Everything from Power, Team and Basic plans" seems incorrect, because there is nothing better than power, right?

image

I don't understand this box. the label sas "plan & subscription", the tooltip talks about notification and the content is my name?

image

ideally, this would look similar to how the orga name can be edited.

renderIndependently((destroyCallback) => (
<ConfigProvider theme={getAntdTheme(getSystemColorTheme())}>
{" "}
…<UpgradeUserQuotaModal destroy={destroyCallback} />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is … on purpose here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -71,7 +73,12 @@ export function extendPricingPlan(organization: APIOrganization) {
}

export function upgradeUserQuota() {
renderIndependently((destroyCallback) => <UpgradeUserQuotaModal destroy={destroyCallback} />);
renderIndependently((destroyCallback) => (
<ConfigProvider theme={getAntdTheme(getSystemColorTheme())}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why this is necessary. renderIndependently uses GlobalThemeProvider which reads the user object from the store and also creates a ConfigProvider wrapper?

<Col span={12}>
<TeamPlanUpgradeCard
teamUpgradeCallback={() => {
sendUpgradePricingPlanEmail(PricingPlanEnum.Team);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't these calls be awaited before a success toast is shown?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

okButtonCallback={okButtonCallback}
destroy={destroyCallback}
/>
<ConfigProvider theme={getAntdTheme(getSystemColorTheme())}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

upgradeStorageQuota does the same, too? is it really necessary?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you were riright about renderIndepently. Maybe I was confused why light/dark mode was not working (perhaps I did not refresh the page... ) Anyway, they are not needed. Good reviewer!

return (
<Layout
style={{
minHeight: "calc(100vh - 64px)",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couldn't DEFAULT_NAVBAR_HEIGHT be used? if not: shouldn't we extract the 64?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -0,0 +1,66 @@
import { SettingsCard } from "admin/account/helpers/settings_card";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the file name should use danger_zone to be consistent with the casing in the module.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -0,0 +1,95 @@
import { MailOutlined, SaveOutlined } from "@ant-design/icons";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file exists with and without _view. one should probably be deleted?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleted

}

async function setOrganizationName(newOrgaName: string) {
const OrgaNameRegexPattern = /^[A-Za-z0-9\\-_\\. ß]+$/;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be moved to top level. casing is weird. should probably be UPPER_CASE.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

{
key: "owner",
title: "Owner",
value: "John Doe",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oopsie daisy

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Done

@hotzenklotz
Copy link
Member Author

hotzenklotz commented Jun 18, 2025

  1. I'm in the basic plan. I cannot really see what other plans are available and what they offer. the box at the bottom probably describes all power features? but what about the team features? also the point "Everything from Power, Team and Basic plans" seems incorrect, because there is nothing better than power, right?

That is odd. I can't reproduce that. my Basic plan looks like in the PR description...

I don't understand this box. the label says "plan & subscription", the tooltip talks about notification and the content is my name?

All the Cards on this page are about notifications. Who receives notifications about these different things. In some cases you can edit them; in other cases they are just informative.

Ideally, this would show the email address of the owner. But that is another fetch of the user and lookup. Let's see... what can be done.

@philippotto
Copy link
Member

That is odd. I can't reproduce that. my Basic plan looks like in the PR description...

probably because I used the dev instance and iswkorg was not true.

@philippotto
Copy link
Member

That is odd. I can't reproduce that. my Basic plan looks like in the PR description...

probably because I used the dev instance and iswkorg was not true.

still, this should show sensible stuff (e.g., for self-hosted instances).

@hotzenklotz
Copy link
Member Author

@philippotto I think I addressed all your feedback.

Regarding "custom" plans: I decided against showing any ad card for the moment. There are too many installation variations covered by "custom", so getting the wording right is hard. We can always add something later if we have a better understadning of the situation.

@hotzenklotz hotzenklotz mentioned this pull request Jun 23, 2025
7 tasks
@philippotto
Copy link
Member

philippotto commented Jun 24, 2025

Here are my testing findings. Some are nitpicks, but some others should be tackled in my opinion.

General

  • activeUsersCount is initialized to 1. this means that wrong data is shown while loading. it should show a spinner or "loading" or sth like that.
  • I'd move the "Everything from ... plans" lines to the top of the lists (otherwise my head starts comparing lists until I arrive at the end and notice that the plans are strict supersets.
  • storage always showed up as 0 B in use. probably independent of this PR, though...

Default config (no wkorg and custom plan)

  • After I edited the orga name, the "invalid date" message appeared.

image

  • "2 / null" is also a problem

  • Nitpick (feel free to ignore, but might be foreshadowing what could happen with different contents)
    image

Wkorg + Custom

all good

Wkorg + Basic

  • users and storage show the infinity symbol? it should be 3 users and 5 gb. I switched from custom to basic in the DB. maybe this is the reason?
    image
  • I'd replace the plus icon with an info icon here:
    image

Wkorg + Team

  • the upgrade storage space modal has a weird white space on the right (uses margin-right 30%). can't we use the full width? I assume the modal itself has a max-width anyway. the same for "Upgrade User Quota"
    image
  • the FAQ link should open in another tab:
    image

Wkorg + Power

  • this doesn't advertise for custom. is this on purpose? I understood your comment above so that custom plans won't have any advertisements, but getting to "custom" is a different story? but probably not a deal breaker for now.

@hotzenklotz
Copy link
Member Author

hotzenklotz commented Jun 24, 2025

storage always showed up as 0 B in use. probably independent of this PR, though...
users and storage show the infinity symbol? it should be 3 users and 5 gb. I switched from custom to basic in the DB. maybe this is the reason?

You have to explicitly set these values in the DB. There are columns in the Organisation table for that. Otherwise it defaults to null, i.e. infinity

@hotzenklotz
Copy link
Member Author

this doesn't advertise for custom. is this on purpose? I understood your comment above so that custom plans won't have any advertisements, but getting to "custom" is a different story? but probably not a deal breaker for now.

This is intentional. There is no clear definition on how to get to custom. There is not straight path "Power" --> "Custom".

@hotzenklotz
Copy link
Member Author

@philippotto I think I addressed all your points.

Copy link
Member

@philippotto philippotto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, lgtm, only see the one typo I commented.

Co-authored-by: Philipp Otto <philippotto@users.noreply.github.com>
@hotzenklotz hotzenklotz merged commit e489f9d into account-settings-page Jun 25, 2025
4 checks passed
@hotzenklotz hotzenklotz deleted the orga-settings-page branch June 25, 2025 08:25
hotzenklotz added a commit that referenced this pull request Jun 27, 2025
This PR adds a new "Account Settings" page to host various other
sub-pages for:
- changing email (soon)
- changing password
- appearance/theme
- passkeys (future)
- API Auth Token

<img width="1269" alt="Screenshot 2025-06-25 at 10 45 45"
src="https://github.com/user-attachments/assets/848cc79b-b636-4de1-b495-e15059e7d452"
/>
<img width="1268" alt="Screenshot 2025-06-25 at 10 45 54"
src="https://github.com/user-attachments/assets/fcfb3c08-8a58-450e-b50d-96bd58ed9f1a"
/>
<img width="1269" alt="Screenshot 2025-06-25 at 10 46 01"
src="https://github.com/user-attachments/assets/4a7da90e-a2ed-4a60-ac9b-ebff65d8e140"
/>


### URL of deployed dev instance (used for testing):
- https://accountsettingspage.webknossos.xyz/

### Steps to test:
- Go to new Account settings page
- Change PW 
- Try dark/light mode

### Issues:
- Blocked by #8671
- Blocked by #8679
- fixes #5408

------
(Please delete unneeded items, merge only when none are left open)
- [x] Updated
[changelog](../blob/master/CHANGELOG.unreleased.md#unreleased)
- [ ] Updated [migration
guide](../blob/master/MIGRATIONS.unreleased.md#unreleased) if applicable
- [ ] Updated [documentation](../blob/master/docs) if applicable
- [ ] Adapted [wk-libs python
client](https://github.com/scalableminds/webknossos-libs/tree/master/webknossos/webknossos/client)
if relevant API parts change
- [ ] Removed dev-only changes like prints and application.conf edits
- [x] Considered [common edge
cases](../blob/master/.github/common_edge_cases.md)
- [ ] Needs datastore update after deployment

---------

Co-authored-by: Philipp Otto <philippotto@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Philipp Otto <philipp.4096@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants