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

Add workspace functionality #468

Open
wants to merge 88 commits into
base: master
Choose a base branch
from
Open

Add workspace functionality #468

wants to merge 88 commits into from

Conversation

nikochiko
Copy link
Member

@nikochiko nikochiko commented Sep 21, 2024

Q/A checklist

  • If you add new dependencies, did you update the lock file?
poetry lock --no-update
  • Run tests
ulimit -n unlimited && ./scripts/run-tests.sh
  • Do a self code review of the changes - Read the diff at least twice.
  • Carefully think about the stuff that might break because of this change - this sounds obvious but it's easy to forget to do "Go to references" on each function you're changing and see if it's used in a way you didn't expect.
  • The relevant pages still run when you press submit
  • The API for those pages still work (API tab)
  • The public API interface doesn't change if you didn't want it to (check API tab > docs page)
  • Do your UI changes (if applicable) look acceptable on mobile?
  • Ensure you have not regressed the import time unless you have a good reason to do so.
    You can visualize this using tuna:
python3 -X importtime -c 'import server' 2> out.log && tuna out.log

To measure import time for a specific library:

$ time python -c 'import pandas'

________________________________________________________
Executed in    1.15 secs    fish           external
   usr time    2.22 secs   86.00 micros    2.22 secs
   sys time    0.72 secs  613.00 micros    0.72 secs

To reduce import times, import libraries that take a long time inside the functions that use them instead of at the top of the file:

def my_function():
    import pandas as pd
    ...

Legal Boilerplate

Look, I get it. The entity doing business as “Gooey.AI” and/or “Dara.network” was incorporated in the State of Delaware in 2020 as Dara Network Inc. and is gonna need some rights from me in order to utilize my contributions in this PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Dara Network Inc can use, modify, copy, and redistribute my contributions, under its choice of terms.

routers/account.py Outdated Show resolved Hide resolved
@nikochiko
Copy link
Member Author

@devxpy PR is still draft, I haven't added the workspace dropdown in publish dialog. API keys are being created with workspace_id but still charged with the uid.

I added here for review on whatever is implemented (or we could deploy it for admins only)

workspaces/widgets.py Outdated Show resolved Hide resolved
@nikochiko
Copy link
Member Author

@nikochiko nikochiko self-assigned this Sep 23, 2024
@nikochiko nikochiko assigned devxpy and unassigned nikochiko Sep 25, 2024
Earlier: was showing a JSON array of strings
After this fix: shows a single string message
+ other UI changes in that tab
@nikochiko
Copy link
Member Author

tests are finally green 🟢

Comment on lines +387 to +407
if is_example:
self.render_author(pr.workspace)
elif (
self.current_sr.workspace
and not self.current_sr.workspace.is_personal
):
with gui.div(
className="d-flex align-items-center container-margin-reset"
):
self.render_author(self.current_sr.workspace)
gui.write(
'<i class="fa-light fa-chevron-right"></i>',
className="text-muted d-block mx-2",
unsafe_allow_html=True,
)
gui.write(
self.current_sr_user.full_name(),
className="d-block text-muted me-2",
)
else:
self.render_author(self.current_sr_user)
Copy link
Member Author

Choose a reason for hiding this comment

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

breadcrumbs - split this off

@nikochiko
Copy link
Member Author

workspace creation dialog - look into react-select multiselect createable https://react-select.com/creatable

Comment on lines 211 to 314
session: dict,
) -> Workspace | None:
step_2_ref = gui.use_confirm_dialog(
key="--create-workspace-step-2", close_on_confirm=False
)

if ref.is_open:
_render_workspace_creation_dialog_step_1(ref, user=user, session=session)
if step_2_ref.is_open:
_render_workspace_creation_dialog_step_2(step_2_ref, user=user, session=session)

if ref.pressed_confirm:
step_2_ref.set_open(True)
raise gui.RerunException()
if step_2_ref.pressed_confirm:
ref.set_open(False)
return get_current_workspace(user, session)


def _render_workspace_creation_dialog_step_1(
ref: gui.ConfirmDialogRef, *, user: AppUser, session: dict
):
from routers.account import account_route

with gui.confirm_dialog(
ref=ref,
modal_title="#### Create Team Workspace",
confirm_label="Create Workspace",
):
gui.caption(
"Workspaces allow you to collaborate with team members with a shared payment method."
)

workspace_name = gui.text_input(
"##### Name",
value=get_default_name_for_new_workspace(user),
)
gui.write("##### Billing")
gui.caption(
"Your first workspace gets 500 ($5) Credits. Add a payment method for shared billing."
)
add_payment_method_button = gui.button("Add Payment Method", type="link")

if not ref.pressed_confirm and not add_payment_method_button:
return

workspace = create_workspace_with_defaults(user, name=workspace_name)
set_current_workspace(session, workspace.id)

if add_payment_method_button:
raise gui.RedirectException(get_route_path(account_route))


def _render_workspace_creation_dialog_step_2(
ref: gui.ConfirmDialogRef, *, user: AppUser, session: dict
):
workspace = get_current_workspace(user, session)
with gui.confirm_dialog(
ref=ref,
modal_title=f"#### Invite members to {workspace.display_name()}",
confirm_label="Done",
cancel_className="d-none", # hack
):
gui.write("##### Invite Members")
with gui.div(className="d-flex"):
with gui.div(className="flex-grow-1"):
email = gui.text_input("")
pressed_invite = gui.button(f"{icons.send} Invite", type="tertiary")

if pressed_invite:
try:
WorkspaceInvite.objects.create_and_send_invite(
workspace=workspace,
email=email,
user=user,
defaults=dict(role=WorkspaceRole.ADMIN),
)
except ValidationError as e:
gui.error("\n".join(e.messages))
else:
gui.success("Invitation sent!")

email_domain = user.email and user.email.split("@")[-1]
if email_domain and email_domain.lower() not in COMMON_EMAIL_DOMAINS:
gui.write("##### Email Domain")
gui.caption(
"Anyone with this email domain will be automatically added as member to this workspace"
)
workspace.domain_name = gui.selectbox(
label="",
options=[email_domain],
format_func=lambda s: s and f"@{s}" or "&mdash;" * 3,
value=email_domain,
allow_none=True,
)

if ref.pressed_confirm:
if workspace.domain_name:
workspace.save(update_fields=["domain_name"])
ref.set_open(False)
Copy link
Member Author

Choose a reason for hiding this comment

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

skip for now

Copy link
Member Author

Choose a reason for hiding this comment

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

look at how django does this

@@ -127,6 +143,8 @@ class Workspace(SafeDeleteModel):

objects = WorkspaceQuerySet.as_manager()

api_hashids = hashids.Hashids(salt=settings.HASHIDS_API_SALT + "/workspaces")
Copy link
Member Author

Choose a reason for hiding this comment

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

get rid of this

@devxpy devxpy removed their assignment Nov 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants