Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/alerts.ts
1496 views
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { notification } from "antd";
7
import { ReactElement } from "react";
8
9
import {
10
defaults,
11
hash_string,
12
server_seconds_ago,
13
server_time,
14
} from "@cocalc/util/misc";
15
16
import { webapp_client } from "./webapp-client";
17
18
type NotificationType = "error" | "default" | "success" | "info" | "warning";
19
20
const default_timeout: { [key: string]: number } = {
21
error: 9,
22
default: 6,
23
success: 5,
24
info: 7,
25
};
26
27
const last_shown = {};
28
29
interface AlertMessageOptions {
30
type?: NotificationType;
31
title?: string | ReactElement<any>;
32
message?: string | ReactElement<any> | Error;
33
block?: boolean;
34
timeout?: number;
35
}
36
37
export function alert_message(opts: AlertMessageOptions = {}) {
38
opts = defaults(opts, {
39
type: "default",
40
title: undefined,
41
message: "",
42
block: undefined,
43
timeout: undefined, // time in seconds
44
});
45
if (opts.type == null) throw Error("bug"); // make typescript happy.
46
if (opts.timeout == null) {
47
let t: number | undefined = default_timeout[opts.type];
48
if (t == null) {
49
t = 5;
50
}
51
opts.timeout = t;
52
}
53
54
// Don't show the exact same alert message more than once per 5s.
55
// This prevents a screenful of identical useless messages, which
56
// is just annoying and useless.
57
if (opts.message instanceof Error) {
58
opts.message = `${opts.message}`;
59
} else if (opts.message === "string") {
60
const hash = hash_string(opts.message + opts.type);
61
if (last_shown[hash] >= server_seconds_ago(5)) {
62
return;
63
}
64
last_shown[hash] = server_time();
65
}
66
67
const f =
68
opts.type == "default" ? notification.open : notification[opts.type];
69
if (f == null) {
70
alert(`BUG: Unknown alert_message type ${opts.type}.`);
71
return;
72
}
73
f({
74
message: opts.title != null ? opts.title : "",
75
description: stripExcessiveError(opts.message),
76
duration: opts.block ? 0 : opts.timeout,
77
});
78
79
if (opts.type === "error") {
80
// Send the same error message to the backend hub so
81
// that us developers know what errors people are hitting.
82
// There really should be no situation where users *regularly*
83
// get error alert messages.
84
webapp_client.tracking_client.log_error(opts.message);
85
}
86
}
87
88
// for testing/development
89
/*
90
alert_message({ type: "error", message: "This is an error" });
91
alert_message({ type: "default", message: "This is a default alert" });
92
alert_message({ type: "warning", message: "This is a warning alert" });
93
alert_message({ type: "success", message: "This is a success alert" });
94
alert_message({ type: "info", message: "This is an info alert" });
95
*/
96
97
function stripExcessiveError(s) {
98
if (typeof s != "string") {
99
return s;
100
}
101
s = s.trim();
102
if (s.startsWith("Error: Error:")) {
103
s = s.slice("Error: ".length);
104
}
105
return s;
106
}
107
108