Server availability and version notification
This commit is contained in:
1 parent
7768c79c20
commit
e35254cb6f
5 files changed
+102
-19
No files matched your search
@@ -33,6 +33,7 @@ import * as localCache from "./local-cache";
|
|||||||
import { PermissionSet } from "./types";
|
import { PermissionSet } from "./types";
|
||||||
import { authSimple } from "./ui/api-functions";
|
import { authSimple } from "./ui/api-functions";
|
||||||
import * as init from "./init";
|
import * as init from "./init";
|
||||||
|
import { version as VERSION } from "../package.json";
|
||||||
|
|
||||||
declare module "koa" {
|
declare module "koa" {
|
||||||
interface Request {
|
interface Request {
|
||||||
@@ -64,6 +65,7 @@ koa.use(async (ctx, next) => {
|
|||||||
const configSnapshot = await localCache.getCurrentSnapshot();
|
const configSnapshot = await localCache.getCurrentSnapshot();
|
||||||
ctx.state.configSnapshot = configSnapshot;
|
ctx.state.configSnapshot = configSnapshot;
|
||||||
ctx.set("X-Config-Snapshot", configSnapshot);
|
ctx.set("X-Config-Snapshot", configSnapshot);
|
||||||
|
ctx.set("GenieACS-Version", VERSION);
|
||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -143,6 +145,10 @@ koa.use(async (ctx, next) => {
|
|||||||
koa.use(koaBodyParser());
|
koa.use(koaBodyParser());
|
||||||
router.use("/api", api.routes(), api.allowedMethods());
|
router.use("/api", api.routes(), api.allowedMethods());
|
||||||
|
|
||||||
|
router.get("/status", ctx => {
|
||||||
|
ctx.body = "OK";
|
||||||
|
});
|
||||||
|
|
||||||
router.get("/init", async ctx => {
|
router.get("/init", async ctx => {
|
||||||
const status = await init.getStatus();
|
const status = await init.getStatus();
|
||||||
if (Object.keys(localCache.getUsers(ctx.state.configSnapshot)).length) {
|
if (Object.keys(localCache.getUsers(ctx.state.configSnapshot)).length) {
|
||||||
@@ -207,6 +213,7 @@ router.get("/", async ctx => {
|
|||||||
ui: localCache.getUiConfig(ctx.state.configSnapshot)
|
ui: localCache.getUiConfig(ctx.state.configSnapshot)
|
||||||
})};
|
})};
|
||||||
window.configSnapshot = ${JSON.stringify(ctx.state.configSnapshot)};
|
window.configSnapshot = ${JSON.stringify(ctx.state.configSnapshot)};
|
||||||
|
window.genieacsVersion = ${JSON.stringify(VERSION)};
|
||||||
window.username = ${JSON.stringify(
|
window.username = ${JSON.stringify(
|
||||||
ctx.state.user ? ctx.state.user.username : ""
|
ctx.state.user ? ctx.state.user.username : ""
|
||||||
)};
|
)};
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ declare global {
|
|||||||
username: string;
|
username: string;
|
||||||
clientConfig: any;
|
clientConfig: any;
|
||||||
configSnapshot: string;
|
configSnapshot: string;
|
||||||
|
genieacsVersion: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,3 +19,4 @@
|
|||||||
|
|
||||||
export default window.clientConfig;
|
export default window.clientConfig;
|
||||||
export const configSnapshot = window.configSnapshot;
|
export const configSnapshot = window.configSnapshot;
|
||||||
|
export const genieacsVersion = window.genieacsVersion;
|
||||||
+26
-2
@@ -17,9 +17,27 @@
|
|||||||
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import * as notifications from "./notifications";
|
||||||
|
|
||||||
export let codeMirror;
|
export let codeMirror;
|
||||||
export let yaml;
|
export let yaml;
|
||||||
|
|
||||||
|
let note;
|
||||||
|
|
||||||
|
function onError(): void {
|
||||||
|
if (!note) {
|
||||||
|
note = notifications.push(
|
||||||
|
"error",
|
||||||
|
"Error loading JS resource, please reload the page",
|
||||||
|
{
|
||||||
|
Reload: () => {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function loadCodeMirror(): Promise<void> {
|
export function loadCodeMirror(): Promise<void> {
|
||||||
if (codeMirror) return Promise.resolve();
|
if (codeMirror) return Promise.resolve();
|
||||||
|
|
||||||
@@ -36,7 +54,10 @@ export function loadCodeMirror(): Promise<void> {
|
|||||||
codeMirror = modules[0];
|
codeMirror = modules[0];
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch(reject);
|
.catch(err => {
|
||||||
|
onError();
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +70,9 @@ export function loadYaml(): Promise<void> {
|
|||||||
yaml = module;
|
yaml = module;
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch(reject);
|
.catch(err => {
|
||||||
|
onError();
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
+67
-17
@@ -23,13 +23,13 @@ import { or, and, not, evaluate, subset } from "../lib/common/expression";
|
|||||||
import memoize from "../lib/common/memoize";
|
import memoize from "../lib/common/memoize";
|
||||||
import { QueryOptions, Expression } from "../lib/types";
|
import { QueryOptions, Expression } from "../lib/types";
|
||||||
import * as notifications from "./notifications";
|
import * as notifications from "./notifications";
|
||||||
import { configSnapshot } from "./config";
|
import { configSnapshot, genieacsVersion } from "./config";
|
||||||
|
|
||||||
const memoizedStringify = memoize(stringify);
|
const memoizedStringify = memoize(stringify);
|
||||||
const memoizedEvaluate = memoize(evaluate);
|
const memoizedEvaluate = memoize(evaluate);
|
||||||
|
|
||||||
let fulfillTimestamp = 0;
|
let fulfillTimestamp = 0;
|
||||||
let refreshNotification;
|
let connectionNotification, configNotification, versionNotification;
|
||||||
|
|
||||||
const queries = {
|
const queries = {
|
||||||
filter: new WeakMap(),
|
filter: new WeakMap(),
|
||||||
@@ -89,6 +89,71 @@ class QueryResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkConnection(): void {
|
||||||
|
m.request({
|
||||||
|
url: "/status",
|
||||||
|
method: "GET",
|
||||||
|
background: true,
|
||||||
|
extract: xhr => {
|
||||||
|
if (xhr.status !== 200) {
|
||||||
|
if (!connectionNotification) {
|
||||||
|
connectionNotification = notifications.push(
|
||||||
|
"warning",
|
||||||
|
"Server is unreachable",
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (connectionNotification) {
|
||||||
|
notifications.dismiss(connectionNotification);
|
||||||
|
connectionNotification = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const configChanged =
|
||||||
|
xhr.getResponseHeader("x-config-snapshot") !== configSnapshot;
|
||||||
|
const versionChanged =
|
||||||
|
xhr.getResponseHeader("genieacs-version") !== genieacsVersion;
|
||||||
|
|
||||||
|
if (!configNotification !== !configChanged) {
|
||||||
|
if (configNotification) {
|
||||||
|
notifications.dismiss(configNotification);
|
||||||
|
configNotification = null;
|
||||||
|
} else {
|
||||||
|
configNotification = notifications.push(
|
||||||
|
"warning",
|
||||||
|
"Configuration has been modified, please reload the page",
|
||||||
|
{
|
||||||
|
Reload: () => {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!versionNotification !== !versionChanged) {
|
||||||
|
if (versionNotification) {
|
||||||
|
notifications.dismiss(versionNotification);
|
||||||
|
versionNotification = null;
|
||||||
|
} else {
|
||||||
|
versionNotification = notifications.push(
|
||||||
|
"warning",
|
||||||
|
"Server has been updated, please reload the page",
|
||||||
|
{
|
||||||
|
Reload: () => {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setInterval(checkConnection, 3000);
|
||||||
|
|
||||||
export async function xhrRequest(
|
export async function xhrRequest(
|
||||||
options: { url: string } & m.RequestOptions<{}>
|
options: { url: string } & m.RequestOptions<{}>
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
@@ -99,21 +164,6 @@ export async function xhrRequest(
|
|||||||
xhr: XMLHttpRequest,
|
xhr: XMLHttpRequest,
|
||||||
_options?: { url: string } & m.RequestOptions<{}>
|
_options?: { url: string } & m.RequestOptions<{}>
|
||||||
): any => {
|
): any => {
|
||||||
if (
|
|
||||||
!refreshNotification &&
|
|
||||||
configSnapshot !== xhr.getResponseHeader("x-config-snapshot")
|
|
||||||
) {
|
|
||||||
refreshNotification = notifications.push(
|
|
||||||
"warning",
|
|
||||||
"Configuration has been modified, please reload the page",
|
|
||||||
{
|
|
||||||
Reload: () => {
|
|
||||||
window.location.reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof extract === "function") return extract(xhr, _options);
|
if (typeof extract === "function") return extract(xhr, _options);
|
||||||
|
|
||||||
let response: any;
|
let response: any;
|
||||||
|
|||||||
Reference in new issue
Block a user