CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/alerts.ts
Views: 687
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: 8,
22
default: 4,
23
success: 4,
24
info: 6,
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: 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
function check_for_clock_skew() {
89
const local_time = Date.now();
90
const s = Math.ceil(
91
Math.abs(
92
webapp_client.time_client.server_time().valueOf() - local_time.valueOf()
93
) / 1000
94
);
95
if (s > 120) {
96
return alert_message({
97
type: "error",
98
timeout: 9999,
99
message: `Your computer's clock is off by about ${s} seconds! You MUST set it correctly then refresh your browser. Expect nothing to work until you fix this.`,
100
});
101
}
102
}
103
104
// Wait until after the page is loaded and clock sync'd before checking for skew.
105
setTimeout(check_for_clock_skew, 60000);
106
107
// for testing/development
108
/*
109
alert_message({ type: "error", message: "This is an error" });
110
alert_message({ type: "default", message: "This is a default alert" });
111
alert_message({ type: "warning", message: "This is a warning alert" });
112
alert_message({ type: "success", message: "This is a success alert" });
113
alert_message({ type: "info", message: "This is an info alert" });
114
*/
115
116