settings_export: Add modal to select export_type before starting export.

This commit adds a modal which offers a way to select export_type
before making a POST request to start export.

Fixes part of #31201.
This commit is contained in:
Prakhar Pratyush 2024-10-08 16:12:54 +05:30 committed by Tim Abbott
parent 478cd9220c
commit 6e7cb8a8c4
4 changed files with 128 additions and 15 deletions

View File

@ -1054,3 +1054,16 @@ export const stream_post_policy_values = {
description: $t({defaultMessage: "Admins only"}),
},
} as const;
export const export_type_values = {
export_public: {
value: 1,
description: $t({defaultMessage: "Public data"}),
default: false,
},
export_full_with_consent: {
value: 2,
description: $t({defaultMessage: "Standard"}),
default: true,
},
};

View File

@ -3,18 +3,26 @@ import {z} from "zod";
import render_confirm_delete_data_export from "../templates/confirm_dialog/confirm_delete_data_export.hbs";
import render_admin_export_list from "../templates/settings/admin_export_list.hbs";
import render_start_export_modal from "../templates/start_export_modal.hbs";
import * as channel from "./channel";
import * as confirm_dialog from "./confirm_dialog";
import * as dialog_widget from "./dialog_widget";
import {$t_html} from "./i18n";
import {$t, $t_html} from "./i18n";
import * as ListWidget from "./list_widget";
import * as loading from "./loading";
import * as people from "./people";
import * as scroll_util from "./scroll_util";
import * as settings_config from "./settings_config";
import * as timerender from "./timerender";
import type {HTMLSelectOneElement} from "./types";
import * as ui_report from "./ui_report";
const export_consent_schema = z.object({
user_id: z.number(),
consented: z.boolean(),
});
const realm_export_schema = z.object({
id: z.number(),
export_time: z.number(),
@ -31,6 +39,9 @@ const meta = {
loaded: false,
};
let users_consented_for_export_count: number;
let total_users_count: number;
export function reset(): void {
meta.loaded = false;
}
@ -114,27 +125,94 @@ export function populate_exports_table(exports: RealmExport[]): void {
}
}
export function set_up(): void {
meta.loaded = true;
function show_start_export_modal(): void {
const html_body = render_start_export_modal({
export_type_values: settings_config.export_type_values,
});
$("#export-data").on("click", (e) => {
e.preventDefault();
e.stopPropagation();
function start_export(): void {
dialog_widget.show_dialog_spinner();
const $export_status = $("#export_status");
const export_type = Number.parseInt(
$<HTMLSelectOneElement>("select:not([multiple])#export_type").val()!,
10,
);
void channel.post({
url: "/json/export/realm",
data: {export_type},
success() {
dialog_widget.hide_dialog_spinner();
ui_report.success(
$t_html({defaultMessage: "Export started. Check back in a few minutes."}),
$export_status,
4000,
);
dialog_widget.close();
},
error(xhr) {
dialog_widget.hide_dialog_spinner();
ui_report.error($t_html({defaultMessage: "Export failed"}), xhr, $export_status);
dialog_widget.close();
},
});
}
function start_export_modal_post_render(): void {
$("#allow_private_data_export_stats").text(
$t(
{
defaultMessage:
"Exporting private data for {users_consented_for_export_count} users ({total_users_count} users total).",
},
{users_consented_for_export_count, total_users_count},
),
);
const $export_type = $<HTMLSelectOneElement>("select:not([multiple])#export_type");
$export_type.on("change", () => {
const selected_export_type = Number.parseInt($export_type.val()!, 10);
if (
selected_export_type ===
settings_config.export_type_values.export_full_with_consent.value
) {
$("#allow_private_data_export_stats").show();
} else {
$("#allow_private_data_export_stats").hide();
}
});
}
dialog_widget.launch({
html_heading: $t_html({defaultMessage: "Start export?"}),
html_body,
html_submit_button: $t_html({defaultMessage: "Start export"}),
id: "start-export-modal",
loading_spinner: true,
on_click: start_export,
post_render: start_export_modal_post_render,
});
}
export function set_up(): void {
meta.loaded = true;
void channel.get({
url: "/json/export/realm/consents",
success(raw_data) {
const data = z
.object({export_consents: z.array(export_consent_schema)})
.parse(raw_data);
total_users_count = data.export_consents.length;
users_consented_for_export_count = data.export_consents.filter(
(export_consent) => export_consent.consented,
).length;
},
});
$("#start-export-button").on("click", (e) => {
e.preventDefault();
e.stopPropagation();
show_start_export_modal();
});
// Do an initial population of the table

View File

@ -3,16 +3,15 @@
{{> ../help_link_widget link="/help/export-your-organization" }}
</h3>
<p>
{{t 'Exports all users, settings, and all data visible in public channels.' }}
{{t 'Any organization administrator can conduct an export.'}}
{{t 'Depending on the size of your organization, an export can take anywhere from seconds to an hour.' }}
</p>
<p>
{{t 'Your organizations data will be exported in a format designed for imports into Zulip Cloud or a self-hosted installation of Zulip.' }}
{{t 'You will be able to export all public data, and (optionally) private data from users who have given their permission.' }}
{{#tr}}
<z-link>Click here</z-link> to learn about exporting private channels and direct messages.
<z-link>Learn more</z-link> about other data export options.
{{#*inline "z-link"}}<a href="/help/export-your-organization" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
{{t 'Note that organizations are limited to five exports per week.' }}
</p>
<p>
{{t 'Depending on the size of your organization, an export can take anywhere from seconds to an hour.' }}
</p>
{{#if is_admin}}
@ -20,8 +19,8 @@
<span class="export_status_text"></span>
</div>
<form>
<button type="submit" class="button rounded sea-green" id="export-data">
{{t 'Start export of public data' }}
<button type="submit" class="button rounded sea-green" id="start-export-button">
{{t 'Start export' }}
</button>
</form>
{{/if}}

View File

@ -0,0 +1,23 @@
<p>
{{#tr}}
A public data export is a complete data export for your organization other than
<z-private-channel-link>private channel</z-private-channel-link> messages and
<z-direct-messages-link>direct messages</z-direct-messages-link>.
{{#*inline "z-private-channel-link"}}<a href="/help/channel-permissions" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{#*inline "z-direct-messages-link"}}<a href="/help/direct-messages" target="_blank" rel="noopener noreferrer">{{> @partial-block}}</a>{{/inline}}
{{/tr}}
</p>
<p>
{{t 'A standard export additionally includes private data accessible to users who have allowed administrators to export their private data.' }}
</p>
<form id="start-export-form">
<div class="input-group">
<label for="export_type" class="modal-field-label">{{t "Export type" }}</label>
<select id="export_type" class="modal_select bootstrap-focus-style">
{{#each export_type_values}}
<option {{#if this.default }}selected{{/if}} value="{{this.value}}">{{this.description}}</option>
{{/each}}
</select>
</div>
<p id="allow_private_data_export_stats"></p>
</form>