-
Notifications
You must be signed in to change notification settings - Fork 2
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
base: master
Are you sure you want to change the base?
Conversation
@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) |
I don't have access to this firestore collection https://console.firebase.google.com/u/0/v1/r/project/gooey-test-runner-1/firestore/indexes?create_composite=ClRwcm9qZWN0cy9nb29leS10ZXN0LXJ1bm5lci0xL2RhdGFiYXNlcy8oZGVmYXVsdCkvY29sbGVjdGlvbkdyb3Vwcy9hcGlfa2V5cy9pbmRleGVzL18QARoQCgx3b3Jrc3BhY2VfaWQQARoOCgpjcmVhdGVkX2F0EAEaDAoIX19uYW1lX18QAQ&pli=1 would need an index for |
tests are finally green 🟢 |
…vailable from email domain
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) |
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.
breadcrumbs - split this off
workspace creation dialog - look into react-select multiselect createable https://react-select.com/creatable |
workspaces/widgets.py
Outdated
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 "—" * 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) |
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.
skip for now
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.
look at how django does this
workspaces/models.py
Outdated
@@ -127,6 +143,8 @@ class Workspace(SafeDeleteModel): | |||
|
|||
objects = WorkspaceQuerySet.as_manager() | |||
|
|||
api_hashids = hashids.Hashids(salt=settings.HASHIDS_API_SALT + "/workspaces") |
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.
get rid of this
Q/A checklist
You can visualize this using tuna:
To measure import time for a specific library:
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:
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.