Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/alerts.ts
5808 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
46
if (opts.type == null) throw Error("bug"); // make typescript happy.
47
48
if (opts.timeout == null) {
49
let t: number | undefined = default_timeout[opts.type];
50
if (t == null) {
51
t = 5;
52
}
53
opts.timeout = t;
54
}
55
56
// Don't show the exact same alert message more than once per 5s.
57
// This prevents a screen full of identical useless messages, which
58
// is just annoying and useless.
59
if (opts.message instanceof Error) {
60
opts.message = `${opts.message}`;
61
} else if (opts.message === "string") {
62
const hash = hash_string(opts.message + opts.type);
63
if (last_shown[hash] >= server_seconds_ago(5)) {
64
return;
65
}
66
last_shown[hash] = server_time();
67
}
68
69
const f =
70
opts.type == "default" ? notification.open : notification[opts.type];
71
if (f == null) {
72
alert(`BUG: Unknown alert_message type ${opts.type}.`);
73
return;
74
}
75
76
f({
77
message: opts.title != null ? opts.title : "",
78
description: stripExcessiveError(opts.message),
79
duration: opts.block ? 0 : opts.timeout,
80
});
81
82
if (opts.type === "error") {
83
// Send the same error message to the backend hub so
84
// that us developers know what errors people are hitting.
85
// There really should be no situation where users *regularly*
86
// get error alert messages.
87
webapp_client.tracking_client.log_error(opts.message);
88
}
89
}
90
91
// for testing/development
92
/*
93
alert_message({ type: "error", message: "This is an error" });
94
alert_message({ type: "default", message: "This is a default alert" });
95
alert_message({ type: "warning", message: "This is a warning alert" });
96
alert_message({ type: "success", message: "This is a success alert" });
97
alert_message({ type: "info", message: "This is an info alert" });
98
*/
99
100
function stripExcessiveError(s) {
101
if (typeof s != "string") {
102
return s;
103
}
104
s = s.trim();
105
if (s.startsWith("Error: Error:")) {
106
s = s.slice("Error: ".length);
107
}
108
return s;
109
}
110
111