diff --git a/web/src/settings_config.ts b/web/src/settings_config.ts index ff4bd231f1..cfce2a678f 100644 --- a/web/src/settings_config.ts +++ b/web/src/settings_config.ts @@ -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, + }, +}; diff --git a/web/src/settings_exports.ts b/web/src/settings_exports.ts index 10677d12bd..7611688c4f 100644 --- a/web/src/settings_exports.ts +++ b/web/src/settings_exports.ts @@ -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( + $("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 = $("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 diff --git a/web/templates/settings/data_exports_admin.hbs b/web/templates/settings/data_exports_admin.hbs index 2fe6c8e473..06aa9682e7 100644 --- a/web/templates/settings/data_exports_admin.hbs +++ b/web/templates/settings/data_exports_admin.hbs @@ -3,16 +3,15 @@ {{> ../help_link_widget link="/help/export-your-organization" }}

- {{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.' }} -

-

+ {{t 'Your organization’s 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}} - Click here to learn about exporting private channels and direct messages. + Learn more about other data export options. {{#*inline "z-link"}}{{> @partial-block}}{{/inline}} {{/tr}} - {{t 'Note that organizations are limited to five exports per week.' }} +

+

+ {{t 'Depending on the size of your organization, an export can take anywhere from seconds to an hour.' }}

{{#if is_admin}} @@ -20,8 +19,8 @@
-
{{/if}} diff --git a/web/templates/start_export_modal.hbs b/web/templates/start_export_modal.hbs new file mode 100644 index 0000000000..d046ea6589 --- /dev/null +++ b/web/templates/start_export_modal.hbs @@ -0,0 +1,23 @@ +

+ {{#tr}} + A public data export is a complete data export for your organization other than + private channel messages and + direct messages. + {{#*inline "z-private-channel-link"}}{{> @partial-block}}{{/inline}} + {{#*inline "z-direct-messages-link"}}{{> @partial-block}}{{/inline}} + {{/tr}} +

+

+ {{t 'A standard export additionally includes private data accessible to users who have allowed administrators to export their private data.' }} +

+
+
+ + +
+

+