mirror of https://github.com/zulip/zulip.git
demo-orgs: Add UI for converting to permanent organization.
Adds warning banner to the organization settings overlay/tabs for demo organizations. For owners, clicking on the link in the banner opens a modal to convert the demo organization into a permanent organization. For admins that are not owners, clicking on the link will go to the help center article on demo organizations. Non-admin users will not see the warning banner. The modal for converting a demo organization requires the owner to have set their email address. Once the owner's email address is set, then the organization can be made permanent by changing the subdomain of the organization. The deletion date for the demo organization will be removed as part of updating the subdomain. The organization owner must also have updated the organization type to be any value other than unsepecified to convert the demo organization to a permanent organization. The modal's submit button will be disabled if that is the value for the organization type in the form. The demo organizations created in the dev environment now have their organization type set to unspecified on creation. This is a part of #19523. Co-authored by: Lauryn Menard <lauryn@zulip.com>
This commit is contained in:
parent
de4e369ece
commit
f3465dea08
|
@ -62,15 +62,35 @@ and set a password for their account.
|
||||||
|
|
||||||
## Convert a demo organization to a permanent organization
|
## Convert a demo organization to a permanent organization
|
||||||
|
|
||||||
|
{!owner-only.md!}
|
||||||
|
|
||||||
|
If you'd like to keep your demo organization user and message history,
|
||||||
|
you can convert it to a permanent Zulip organization. You'll need to
|
||||||
|
choose a new subdomain for your new permanent organization URL.
|
||||||
|
|
||||||
|
Also, as part of the process of converting a demo organization to a
|
||||||
|
permanent organization:
|
||||||
|
|
||||||
|
* Users will be logged out of existing sessions on the web, mobile and
|
||||||
|
desktop apps and need to log in again.
|
||||||
|
* Any [API clients](/api) or [integrations](/integrations/) will need
|
||||||
|
to be updated to point to the new organization URL.
|
||||||
|
|
||||||
{start_tabs}
|
{start_tabs}
|
||||||
|
|
||||||
{settings_tab|organization-profile}
|
{settings_tab|organization-profile}
|
||||||
|
|
||||||
1. Click the **Convert organization** link at the end of the red
|
1. Click the **Convert to make it permanent** link at the end of the
|
||||||
"This is a demo organization" notice on top.
|
"This demo organization will be automatically deleted ..." notice.
|
||||||
|
|
||||||
1. Enter the URL you would like to use for the organization and click
|
1. Enter the subdomain you would like to use for the new organization
|
||||||
**Convert**.
|
URL and click **Convert**.
|
||||||
|
|
||||||
|
!!! warn ""
|
||||||
|
|
||||||
|
**Note:** You will be logged out when the demo organization is
|
||||||
|
successfully converted to a permanent Zulip organization and be
|
||||||
|
redirected to new organization URL log-in page.
|
||||||
|
|
||||||
{end_tabs}
|
{end_tabs}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ IGNORED_PHRASES = [
|
||||||
r"keyword",
|
r"keyword",
|
||||||
r"streamname",
|
r"streamname",
|
||||||
r"user@example\.com",
|
r"user@example\.com",
|
||||||
|
r"acme",
|
||||||
# Fragments of larger strings
|
# Fragments of larger strings
|
||||||
r"your subscriptions on your Streams page",
|
r"your subscriptions on your Streams page",
|
||||||
r"Add global time<br />Everyone sees global times in their own time zone\.",
|
r"Add global time<br />Everyone sees global times in their own time zone\.",
|
||||||
|
|
|
@ -82,6 +82,7 @@ EXEMPT_FILES = make_set(
|
||||||
"web/src/custom_profile_fields_ui.js",
|
"web/src/custom_profile_fields_ui.js",
|
||||||
"web/src/dark_theme.ts",
|
"web/src/dark_theme.ts",
|
||||||
"web/src/debug.ts",
|
"web/src/debug.ts",
|
||||||
|
"web/src/demo_organizations_ui.js",
|
||||||
"web/src/deprecated_feature_notice.ts",
|
"web/src/deprecated_feature_notice.ts",
|
||||||
"web/src/desktop_integration.js",
|
"web/src/desktop_integration.js",
|
||||||
"web/src/dialog_widget.ts",
|
"web/src/dialog_widget.ts",
|
||||||
|
|
|
@ -4,6 +4,7 @@ import render_admin_tab from "../templates/settings/admin_tab.hbs";
|
||||||
import render_settings_organization_settings_tip from "../templates/settings/organization_settings_tip.hbs";
|
import render_settings_organization_settings_tip from "../templates/settings/organization_settings_tip.hbs";
|
||||||
|
|
||||||
import * as bot_data from "./bot_data";
|
import * as bot_data from "./bot_data";
|
||||||
|
import * as demo_organizations_ui from "./demo_organizations_ui";
|
||||||
import {$t, get_language_name, language_list} from "./i18n";
|
import {$t, get_language_name, language_list} from "./i18n";
|
||||||
import {page_params} from "./page_params";
|
import {page_params} from "./page_params";
|
||||||
import {realm_user_settings_defaults} from "./realm_user_settings_defaults";
|
import {realm_user_settings_defaults} from "./realm_user_settings_defaults";
|
||||||
|
@ -232,6 +233,11 @@ export function build_page() {
|
||||||
settings_invites.update_invite_user_panel();
|
settings_invites.update_invite_user_panel();
|
||||||
insert_tip_box();
|
insert_tip_box();
|
||||||
|
|
||||||
|
if (page_params.demo_organization_scheduled_deletion_date && page_params.is_admin) {
|
||||||
|
demo_organizations_ui.insert_demo_organization_warning();
|
||||||
|
demo_organizations_ui.handle_demo_organization_conversion();
|
||||||
|
}
|
||||||
|
|
||||||
$("#id_realm_bot_creation_policy").val(page_params.realm_bot_creation_policy);
|
$("#id_realm_bot_creation_policy").val(page_params.realm_bot_creation_policy);
|
||||||
|
|
||||||
$("#id_realm_digest_weekday").val(options.realm_digest_weekday);
|
$("#id_realm_digest_weekday").val(options.realm_digest_weekday);
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
import $ from "jquery";
|
||||||
|
|
||||||
|
import render_convert_demo_organization_form from "../templates/settings/convert_demo_organization_form.hbs";
|
||||||
|
import render_demo_organization_warning from "../templates/settings/demo_organization_warning.hbs";
|
||||||
|
|
||||||
|
import * as channel from "./channel";
|
||||||
|
import * as dialog_widget from "./dialog_widget";
|
||||||
|
import {$t} from "./i18n";
|
||||||
|
import * as keydown_util from "./keydown_util";
|
||||||
|
import {get_demo_organization_deadline_days_remaining} from "./navbar_alerts";
|
||||||
|
import {page_params} from "./page_params";
|
||||||
|
import * as settings_config from "./settings_config";
|
||||||
|
import * as settings_data from "./settings_data";
|
||||||
|
import * as settings_org from "./settings_org";
|
||||||
|
|
||||||
|
export function insert_demo_organization_warning() {
|
||||||
|
const days_remaining = get_demo_organization_deadline_days_remaining();
|
||||||
|
const rendered_demo_organization_warning = render_demo_organization_warning({
|
||||||
|
is_demo_organization: page_params.demo_organization_scheduled_deletion_date,
|
||||||
|
is_owner: page_params.is_owner,
|
||||||
|
days_remaining,
|
||||||
|
});
|
||||||
|
$(".organization-box").find(".settings-section").prepend(rendered_demo_organization_warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function handle_demo_organization_conversion() {
|
||||||
|
$(".convert-demo-organization-button").on("click", () => {
|
||||||
|
if (!page_params.is_owner) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const email_set = !settings_data.user_email_not_configured();
|
||||||
|
const parts = new URL(page_params.realm_uri).hostname.split(".");
|
||||||
|
parts.shift();
|
||||||
|
const domain = parts.join(".");
|
||||||
|
const html_body = render_convert_demo_organization_form({
|
||||||
|
realm_domain: domain,
|
||||||
|
user_has_email_set: email_set,
|
||||||
|
realm_org_type_values: settings_org.get_org_type_dropdown_options(),
|
||||||
|
});
|
||||||
|
|
||||||
|
function demo_organization_conversion_post_render() {
|
||||||
|
const $convert_submit_button = $(
|
||||||
|
"#demo-organization-conversion-modal .dialog_submit_button",
|
||||||
|
);
|
||||||
|
$convert_submit_button.prop("disabled", true);
|
||||||
|
$("#add_organization_type").val(page_params.realm_org_type);
|
||||||
|
|
||||||
|
if (!email_set) {
|
||||||
|
// Disable form fields if demo organization owner email not set.
|
||||||
|
$("#add_organization_type").prop("disabled", true);
|
||||||
|
$("#new_subdomain").prop("disabled", true);
|
||||||
|
} else {
|
||||||
|
// Disable submit button if either form field blank.
|
||||||
|
$("#convert-demo-organization-form").on("input change", () => {
|
||||||
|
const string_id = $("#new_subdomain").val().trim();
|
||||||
|
const org_type = $("#add_organization_type").val();
|
||||||
|
$convert_submit_button.prop(
|
||||||
|
"disabled",
|
||||||
|
string_id === "" ||
|
||||||
|
Number.parseInt(org_type, 10) ===
|
||||||
|
settings_config.all_org_type_values.unspecified.code,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function submit_subdomain() {
|
||||||
|
const $string_id = $("#new_subdomain");
|
||||||
|
const $organization_type = $("#add_organization_type");
|
||||||
|
const data = {
|
||||||
|
string_id: $string_id.val(),
|
||||||
|
org_type: $organization_type.val(),
|
||||||
|
};
|
||||||
|
const opts = {
|
||||||
|
success_continuation(data) {
|
||||||
|
window.location.href = data.realm_uri;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
dialog_widget.submit_api_request(channel.patch, "/json/realm", data, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog_widget.launch({
|
||||||
|
html_heading: $t({defaultMessage: "Make organization permanent"}),
|
||||||
|
html_body,
|
||||||
|
on_click: submit_subdomain,
|
||||||
|
post_render: demo_organization_conversion_post_render,
|
||||||
|
html_submit_button: $t({defaultMessage: "Convert"}),
|
||||||
|
id: "demo-organization-conversion-modal",
|
||||||
|
loading_spinner: true,
|
||||||
|
help_link:
|
||||||
|
"/help/demo-organizations#convert-a-demo-organization-to-a-permanent-organization",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Treat Enter with convert demo organization link as a click.
|
||||||
|
$(".demo-organization-warning").on(
|
||||||
|
"keyup",
|
||||||
|
".convert-demo-organization-button[role=button]",
|
||||||
|
function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (keydown_util.is_enter_event(e)) {
|
||||||
|
$(this).trigger("click");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
|
@ -587,6 +587,30 @@ div.overlay {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.demo-organization-warning {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
background-color: hsl(4deg 35% 90%);
|
||||||
|
border: 1px solid hsl(3deg 57% 33% / 40%);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: hsl(4deg 58% 33%);
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.convert-demo-organization-button {
|
||||||
|
&:focus {
|
||||||
|
outline: 1px solid hsl(200deg 100% 25%);
|
||||||
|
outline-offset: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* We are mostly consistent in how we style
|
/* We are mostly consistent in how we style
|
||||||
unread counts, except for starred messages.
|
unread counts, except for starred messages.
|
||||||
This is the common section.
|
This is the common section.
|
||||||
|
|
|
@ -13,6 +13,19 @@
|
||||||
@extend .placeholder;
|
@extend .placeholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.demo-organization-warning {
|
||||||
|
background-color: hsl(0deg 60% 19%);
|
||||||
|
border-color: hsl(3deg 73% 74% / 40%);
|
||||||
|
color: hsl(3deg 73% 80%);
|
||||||
|
|
||||||
|
.convert-demo-organization-button {
|
||||||
|
&:focus {
|
||||||
|
color: hsl(200deg 79% 66%);
|
||||||
|
outline-color: hsl(200deg 79% 66%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
& a:hover {
|
& a:hover {
|
||||||
color: hsl(200deg 79% 66%);
|
color: hsl(200deg 79% 66%);
|
||||||
|
|
||||||
|
|
|
@ -628,6 +628,12 @@ input[type="checkbox"] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#convert-demo-organization-form {
|
||||||
|
.domain_label {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#profile-settings {
|
#profile-settings {
|
||||||
.custom-profile-fields-form .custom_user_field label,
|
.custom-profile-fields-form .custom_user_field label,
|
||||||
.full-name-change-container label,
|
.full-name-change-container label,
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
<div id="convert-demo-organization-form">
|
||||||
|
<div class="tip">
|
||||||
|
{{#unless user_has_email_set}}
|
||||||
|
{{#tr}}
|
||||||
|
You must <z-link>configure your email</z-link> to access this feature.
|
||||||
|
{{#*inline "z-link"}}<a href="/help/demo-organizations#configure-email-for-demo-organization-owner" target="_blank" rel="noopener noreferrer">{{> @partial-block }}</a>{{/inline}}
|
||||||
|
{{/tr}}
|
||||||
|
{{else}}
|
||||||
|
{{t "All users will need to log in again at your new organization URL." }}
|
||||||
|
{{/unless}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>{{t "You can convert this demo organization to a permanent Zulip organization. All users and message history will be preserved." }}</p>
|
||||||
|
<form class="subdomain-setting">
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="organization_type" class="dropdown-title">{{t "Organization type" }}
|
||||||
|
{{> ../help_link_widget link="/help/organization-type" }}
|
||||||
|
</label>
|
||||||
|
<select name="organization_type" id="add_organization_type" class="modal_select bootstrap-focus-style">
|
||||||
|
{{#each realm_org_type_values}}
|
||||||
|
<option value="{{this.code}}">{{this.description}}</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<label for="string_id" class="title inline-block">{{t "Organization URL" }}</label>
|
||||||
|
<div id="subdomain_input_container">
|
||||||
|
<input id="new_subdomain" type="text" class="modal_text_input" autocomplete="off" name="string_id" placeholder="{{t 'acme' }}"/>
|
||||||
|
<label for="string_id" class="domain_label">.{{ realm_domain }}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
|
@ -0,0 +1,15 @@
|
||||||
|
{{#if is_demo_organization }}
|
||||||
|
<div class="demo-organization-warning">
|
||||||
|
{{#if is_owner }}
|
||||||
|
{{#tr}}
|
||||||
|
This demo organization will be automatically deleted in {days_remaining} days, unless it's <z-link>converted into a permanent organization</z-link>.
|
||||||
|
{{#*inline "z-link"}}<a class="convert-demo-organization-button" role="button" tabindex=0>{{> @partial-block}}</a>{{/inline}}
|
||||||
|
{{/tr}}
|
||||||
|
{{else}}
|
||||||
|
{{#tr}}
|
||||||
|
This demo organization will be automatically deleted in {days_remaining} days, unless it's <z-link>converted into a permanent organization</z-link>.
|
||||||
|
{{#*inline "z-link"}}<a href="/help/demo-organizations" target="_blank" rel="noopener noreferrer">{{> @partial-block }}</a>{{/inline}}
|
||||||
|
{{/tr}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
Loading…
Reference in New Issue