This commit is contained in:
Simon Larsen
2022-11-10 19:43:43 +00:00
parent 5debddfc77
commit d723881bb7
31 changed files with 232 additions and 142 deletions

View File

@@ -0,0 +1 @@
PORT=3003

View File

@@ -16,7 +16,10 @@ app.use(ExpressStatic(path.join(__dirname, 'public')));
app.use(`/${APP_NAME}`, ExpressStatic(path.join(__dirname, 'public')));
app.use([`/${APP_NAME}/assets`,`/${APP_NAME}/${APP_NAME}/assets`], ExpressStatic(path.join(__dirname, 'dist')));
app.use(
[`/${APP_NAME}/assets`, `/${APP_NAME}/${APP_NAME}/assets`],
ExpressStatic(path.join(__dirname, 'dist'))
);
app.get('/*', (_req: ExpressRequest, res: ExpressResponse) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
@@ -26,7 +29,6 @@ const init: Function = async (): Promise<void> => {
try {
// init the app
await App(APP_NAME);
} catch (err) {
logger.error('App Init Failed:');
logger.error(err);

View File

@@ -1,14 +1,18 @@
import React, { FunctionComponent } from 'react';
import BasicModelForm from 'CommonUI/src/Components/Forms/BasicModelForm';
import React, { FunctionComponent, useState } from 'react';
import ModelForm, { FormType } from 'CommonUI/src/Components/Forms/ModelForm';
import User from 'Model/Models/User';
import FormValues from 'CommonUI/src/Components/Forms/Types/FormValues';
import Route from 'Common/Types/API/Route';
import FormFieldSchemaType from 'CommonUI/src/Components/Forms/Types/FormFieldSchemaType';
import OneUptimeLogo from 'CommonUI/src/Images/logos/OneUptimePNG/7.png';
import Link from 'CommonUI/src/Components/Link/Link';
import { FORGOT_PASSWORD_API_URL } from '../Utils/ApiPaths';
import URL from 'Common/Types/API/URL';
const ForgotPassword: FunctionComponent = () => {
const user: User = new User();
const apiUrl: URL = FORGOT_PASSWORD_API_URL;
const [isSuccess, setIsSuccess] = useState<boolean>(false);
return (
<div className="auth-page">
@@ -20,9 +24,11 @@ const ForgotPassword: FunctionComponent = () => {
<div className="auth-full-page-content d-flex p-sm-5 p-4">
<div className="w-100">
<div className="d-flex flex-column h-100">
<div className="auth-content my-auto">
<div className="mt-4 text-center" style={{marginBottom: "40px"}}>
<div
className="mt-4 text-center"
style={{ marginBottom: '40px' }}
>
<img
style={{ height: '40px' }}
src={`/accounts/public/${OneUptimeLogo}`}
@@ -30,18 +36,25 @@ const ForgotPassword: FunctionComponent = () => {
</div>
<div className="text-center">
<h5 className="mb-0">
Reset Password
Forgot Password
</h5>
<p className="text-muted mt-2 mb-0">
{!isSuccess && <p className="text-muted mt-2 mb-0">
Please enter your email and the
password reset link will be sent
to you.{' '}
</p>
</p>}
{isSuccess && <p className="text-muted mt-2 mb-0">
We have emailed you the password reset link. Please do not forget to check spam.{' '}
</p>}
</div>
<BasicModelForm<User>
model={user}
{!isSuccess && <ModelForm<User>
modelType={User}
id="login-form"
apiUrl={apiUrl}
fields={[
{
field: {
@@ -53,12 +66,13 @@ const ForgotPassword: FunctionComponent = () => {
required: true,
},
]}
onSubmit={(
_values: FormValues<User>
) => { }}
onSuccess={() => {
setIsSuccess(true);
}}
submitButtonText={
'Send Password Reset Link'
}
formType={FormType.Create}
maxPrimaryButtonWidth={true}
footer={
<div className="actions pointer text-center mt-4 underline-on-hover fw-semibold">
@@ -75,7 +89,7 @@ const ForgotPassword: FunctionComponent = () => {
</p>
</div>
}
/>
/>}
<div className="mt-5 text-center">
<p className="text-muted mb-0">

View File

@@ -23,9 +23,11 @@ const LoginPage: FunctionComponent = () => {
<div className="auth-full-page-content d-flex p-sm-5 p-4">
<div className="w-100">
<div className="d-flex flex-column h-100">
<div className="auth-content my-auto">
<div className="mt-4 text-center" style={{marginBottom: "40px"}}>
<div
className="mt-4 text-center"
style={{ marginBottom: '40px' }}
>
<img
style={{ height: '40px' }}
src={`/accounts/public/${OneUptimeLogo}`}

View File

@@ -24,9 +24,11 @@ const RegisterPage: FunctionComponent = () => {
<div className="auth-full-page-content d-flex p-sm-5 p-4">
<div className="w-100">
<div className="d-flex flex-column h-100">
<div className="auth-content my-auto">
<div className="mt-4 text-center" style={{marginBottom: "40px"}}>
<div
className="mt-4 text-center"
style={{ marginBottom: '40px' }}
>
<img
style={{ height: '40px' }}
src={`/accounts/public/${OneUptimeLogo}`}

View File

@@ -20,9 +20,11 @@ const SsoLoginPage: FunctionComponent = () => {
<div className="auth-full-page-content d-flex p-sm-5 p-4">
<div className="w-100">
<div className="d-flex flex-column h-100">
<div className="auth-content my-auto">
<div className="mt-4 text-center" style={{marginBottom: "40px"}}>
<div
className="mt-4 text-center"
style={{ marginBottom: '40px' }}
>
<img
style={{ height: '40px' }}
src={`/accounts/public/${OneUptimeLogo}`}

View File

@@ -14,9 +14,11 @@ const VerifyEmail: FunctionComponent = () => {
<div className="auth-full-page-content d-flex p-sm-5 p-4">
<div className="w-100">
<div className="d-flex flex-column h-100">
<div className="auth-content my-auto">
<div className="mt-4 text-center" style={{ marginBottom: "40px" }}>
<div
className="mt-4 text-center"
style={{ marginBottom: '40px' }}
>
<img
style={{ height: '40px' }}
src={`/accounts/public/${OneUptimeLogo}`}

View File

@@ -8,3 +8,8 @@ export const SIGNUP_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
export const LOGIN_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
new Route('/login')
);
export const FORGOT_PASSWORD_API_URL: URL = URL.fromURL(IDENTITY_URL).addRoute(
new Route('/forgot-password')
);

View File

@@ -26,9 +26,8 @@ export default class Hostname extends DatabaseProperty {
}
}
public static isValid(value: string): boolean {
const re: RegExp = /^[a-zA-Z-\d!#$&'*+,/:;=?@[\].]*$/;
const re: RegExp = /^[a-zA-Z-\d!#$&'*+,/:;=?@[\].]*$/;
const isValid: boolean = re.test(value);
if (!isValid) {
return false;

View File

@@ -35,7 +35,7 @@ export default class Email extends DatabaseProperty {
if (Email.isValid(value)) {
this._email = value;
} else {
throw new BadDataException('Email is not in valid format.');
throw new BadDataException(`Email ${value} is not in valid format.`);
}
}

View File

@@ -1,6 +1,6 @@
enum EmailTemplateType {
ForgotPassword = "ForgotPassword.hbs",
WelomeEmail="WelcomeEmail.hbs"
ForgotPassword = 'ForgotPassword.hbs',
WelomeEmail = 'WelcomeEmail.hbs',
}
export default EmailTemplateType;

View File

@@ -11,7 +11,6 @@ export default class Port extends DatabaseProperty {
return this._port;
}
public set port(value: PositiveNumber) {
if (Port.isValid(value)) {
this._port = value;
} else {
@@ -24,7 +23,7 @@ export default class Port extends DatabaseProperty {
try {
port = Number.parseInt(port.toString(), 10);
} catch (error) {
return false;
return false;
}
}
@@ -33,10 +32,9 @@ export default class Port extends DatabaseProperty {
}
if (port >= 0 && port <= 65535) {
return true
} else {
return false;
return true;
}
return false;
}
public constructor(port: number | string) {

View File

@@ -24,4 +24,18 @@ HOME_HOSTNAME={{ .Env.HOME_HOSTNAME }}
BILLING_PRIVATE_KEY={{ .Env.BILLING_PRIVATE_KEY }}
DOMAIN={{ .Env.DOMAIN }}
HTTP_PROTOCOL={{ .Env.HTTP_PROTOCOL }}
HTTP_PROTOCOL={{ .Env.HTTP_PROTOCOL }}
REALTIME_ROUTE={{ .Env.REALTIME_ROUTE }}
MAIL_ROUTE={{ .Env.MAIL_ROUTE }}
DASHBOARD_ROUTE={{ .Env.DASHBOARD_ROUTE }}
DASHBOARD_API_ROUTE={{ .Env.DASHBOARD_API_ROUTE }}
PROBE_API_ROUTE={{ .Env.PROBE_API_ROUTE }}
DATA_INGESTOR_ROUTE={{ .Env.DATA_INGESTOR_ROUTE }}
ACCOUNTS_ROUTE={{ .Env.ACCOUNTS_ROUTE }}
HOME_ROUTE={{ .Env.HOME_ROUTE }}
HELMCHARTS_ROUTE={{ .Env.HELMCHARTS_ROUTE }}
APIDOCS_ROUTE={{ .Env.APIDOCS_ROUTE }}
IDENTITY_ROUTE={{ .Env.IDENTITY_ROUTE }}
FILE_ROUTE={{ .Env.FILE_ROUTE }}
STATUS_PAGE_ROUTE={{ .Env.STATUS_PAGE_ROUTE }}

View File

@@ -85,23 +85,36 @@ export const RedisHostname: string = process.env['REDIS_HOST'] || '';
export const RedisPassword: string = process.env['REDIS_PASSWORD'] || '';
export const RedisPort: Port = new Port(process.env['REDIS_PORT'] || '');
export const DashboardApiRoute: Route = new Route(
process.env['DASHBOARD_API_ROUTE'] || ''
);
export const DashboardApiRoute: Route = new Route(process.env['DASHBOARD_API_ROUTE'] || '');
export const IdentityRoute: Route = new Route(process.env['IDENTITY_ROUTE'] || '');
export const IdentityRoute: Route = new Route(
process.env['IDENTITY_ROUTE'] || ''
);
export const FileRoute: Route = new Route(process.env['FILE_ROUTE'] || '');
export const StausPageRoute: Route = new Route(process.env['STATUS_PAGE_ROUTE'] || '');
export const StausPageRoute: Route = new Route(
process.env['STATUS_PAGE_ROUTE'] || ''
);
export const DashboardRoute: Route = new Route(process.env['DASHBOARD_ROUTE'] || '');
export const DashboardRoute: Route = new Route(
process.env['DASHBOARD_ROUTE'] || ''
);
export const IntegrationRoute: Route = new Route(process.env['INTEGRATION_ROUTE'] || '');
export const IntegrationRoute: Route = new Route(
process.env['INTEGRATION_ROUTE'] || ''
);
export const HelmRoute: Route = new Route(process.env['HELMCHART_ROUTE'] || '');
export const AccountsRoute: Route = new Route(process.env['ACCOUNTS_ROUTE'] || '');
export const AccountsRoute: Route = new Route(
process.env['ACCOUNTS_ROUTE'] || ''
);
export const ApiDocsRoute: Route = new Route(process.env['APIDOCS_ROUTE'] || '');
export const ApiDocsRoute: Route = new Route(
process.env['APIDOCS_ROUTE'] || ''
);
export const AdminDashboardRoute: Route = new Route(
process.env['ADMINDASHBOARD_ROUTE'] || ''

View File

@@ -34,7 +34,7 @@ export default class ClusterKeyAuthorization {
);
}
const isAuthorized: boolean = clusterKey === ONEUPTIME_SECRET;
const isAuthorized: boolean = clusterKey.toString() === ONEUPTIME_SECRET.toString();
if (!isAuthorized) {
return Response.sendErrorResponse(

View File

@@ -15,6 +15,7 @@ export default class MailService {
): Promise<HTTPResponse<EmptyResponseData>> {
const body: JSONObject = {
...mail,
clusterKey: ClusterKey.toString()
};
if (mailServer) {
@@ -28,15 +29,8 @@ export default class MailService {
}
return await API.post<EmptyResponseData>(
new URL(
HttpProtocol,
MailHostname,
new Route('/email/send')
),
body,
{
clusterkey: ClusterKey.toString(),
}
new URL(HttpProtocol, MailHostname, new Route('/email/send')),
body
);
}
}

View File

@@ -16,7 +16,10 @@ app.use(ExpressStatic(path.join(__dirname, 'public')));
app.use(`/${APP_NAME}`, ExpressStatic(path.join(__dirname, 'public')));
app.use([`/${APP_NAME}/assets`,`/${APP_NAME}/${APP_NAME}/assets`], ExpressStatic(path.join(__dirname, 'dist')));
app.use(
[`/${APP_NAME}/assets`, `/${APP_NAME}/${APP_NAME}/assets`],
ExpressStatic(path.join(__dirname, 'dist'))
);
app.get('/*', (_req: ExpressRequest, res: ExpressResponse) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
@@ -26,7 +29,6 @@ const init: Function = async (): Promise<void> => {
try {
// init the app
await App(APP_NAME);
} catch (err) {
logger.error('App Init Failed:');
logger.error(err);

View File

@@ -24,7 +24,7 @@
"test": "react-app-rewired test",
"eject": "webpack eject",
"compile": "tsc",
"start": "webpack serve --port=3009",
"start": "node --require ts-node/register Index.ts",
"audit": "npm audit --audit-level=low",
"preinstall": "npx npm-force-resolutions || echo 'No package-lock.json file. Skipping force resolutions'",
"dep-check": "depcheck ./ --skip-missing=true'"

View File

@@ -31,6 +31,7 @@ import OneUptimeDate from 'Common/Types/Date';
import PositiveNumber from 'Common/Types/PositiveNumber';
import BaseModel from 'Common/Models/BaseModel';
import Route from 'Common/Types/API/Route';
import logger from 'CommonServer/Utils/Logger';
const router: ExpressRouter = Express.getRouter();
@@ -86,7 +87,7 @@ router.post(
emailVerificationToken &&
user &&
alreadySavedUser?.id?.toString() ===
emailVerificationToken?.userId?.toString()
emailVerificationToken?.userId?.toString()
) {
user.isEmailVerified = true;
}
@@ -123,18 +124,21 @@ router.post(
if (alreadySavedUser) {
// Send Welcome Mail
await MailService.sendMail({
MailService.sendMail({
toEmail: user.email!,
subject: "Welcome to OneUptime.",
subject: 'Welcome to OneUptime.',
templateType: EmailTemplateType.WelomeEmail,
vars: {
name: user.name!.toString(),
dashboardUrl: new URL(
HttpProtocol,
Domain, DashboardRoute
Domain,
DashboardRoute
).toString(),
homeUrl: new URL(HttpProtocol, HomeHostname).toString(),
}
},
}).catch((err: Error) => {
logger.error(err);
});
} else {
// Send EmailVerification Link because this is a new user.
@@ -144,11 +148,18 @@ router.post(
templateType: EmailTemplateType.WelomeEmail,
vars: {
name: user.name!.toString(),
emailVerificationUrl: new URL(HttpProtocol, Domain, new Route(AccountsRoute.toString()).addRoute("/reset-password/")).toString(),
emailVerificationUrl: new URL(
HttpProtocol,
Domain,
new Route(AccountsRoute.toString()).addRoute(
'/reset-password/'
)
).toString(),
homeUrl: new URL(HttpProtocol, HomeHostname).toString(),
}
}
);
},
}).catch((err: Error) => {
logger.error(err);
});
}
if (savedUser) {
@@ -171,7 +182,7 @@ router.post(
);
router.post(
'/request-reset-password',
'/forgot-password',
async (
req: ExpressRequest,
res: ExpressResponse,
@@ -197,29 +208,36 @@ router.post(
});
if (alreadySavedUser) {
const token = ObjectID.generate().toString();
const token: string = ObjectID.generate().toString();
await UserService.updateOneBy({
query: {
_id: user._id!
_id: user._id!,
},
data: {
resetPasswordToken: token,
resetPasswordExpires: OneUptimeDate.getOneDayAfter()
resetPasswordExpires: OneUptimeDate.getOneDayAfter(),
},
props: {
isRoot: true
}
isRoot: true,
},
});
MailService.sendMail({
toEmail: user.email!,
subject: "Password Reset Request for OneUptime",
subject: 'Password Reset Request for OneUptime',
templateType: EmailTemplateType.ForgotPassword,
vars: {
homeURL: new URL(HttpProtocol, Domain).toString(),
tokenVerifyUrl: new URL(HttpProtocol, Domain, new Route(AccountsRoute.toString()).addRoute("/reset-password/" + token)).toString(),
}
tokenVerifyUrl: new URL(
HttpProtocol,
Domain,
new Route(AccountsRoute.toString()).addRoute(
'/reset-password/' + token
)
).toString(),
},
}).catch((err: Error) => {
logger.error(err);
});
return Response.sendEmptyResponse(req, res);
@@ -228,7 +246,6 @@ router.post(
throw new BadDataException(
`No user is registered with ${user.email?.toString()}`
);
} catch (err) {
return next(err);
}

View File

@@ -25,7 +25,7 @@ router.post(
toEmail: new Email(body['to-email'] as string),
subject: body['subject'] as string,
vars: body['vars'] as Dictionary<string>,
body: body['body'] as string || '',
body: (body['body'] as string) || '',
};
let mailServer: EmailServer | undefined = undefined;
@@ -34,16 +34,19 @@ router.post(
mailServer = MailService.getEmailServer(req.body);
}
await MailService.send(
mail, mailServer
);
await MailService.send(mail, mailServer);
return Response.sendEmptyResponse(req, res);
}
);
const hasMailServerSettingsInBody = (body: JSONObject): boolean => {
return body && Object.keys(body).filter((key) => key.startsWith("SMTP_")).length > 0;
}
const hasMailServerSettingsInBody: Function = (body: JSONObject): boolean => {
return (
body &&
Object.keys(body).filter((key: string) => {
return key.startsWith('SMTP_');
}).length > 0
);
};
export default router;

View File

@@ -17,75 +17,81 @@ import { JSONObject } from 'Common/Types/JSON';
import logger from 'CommonServer/Utils/Logger';
export default class MailService {
public static isSMTPConfigValid(obj: JSONObject): boolean {
if (!obj['SMTP_USERNAME']) {
logger.error('SMTP_USERNAME env var not found');
return false;
return false;
}
if (!obj['SMTP_EMAIL']) {
logger.error('SMTP_EMAIL env var not found');
return false;
return false;
}
if (!Email.isValid(obj['SMTP_EMAIL'].toString())) {
logger.error('SMTP_EMAIL env var ' + obj['SMTP_EMAIL'] + ' is not a valid email');
return false;
logger.error(
'SMTP_EMAIL env var ' +
obj['SMTP_EMAIL'] +
' is not a valid email'
);
return false;
}
if (!obj['SMTP_FROM_NAME']) {
logger.error('SMTP_FROM_NAME env var not found');
return false;
return false;
}
if (!obj['SMTP_IS_SECURE']) {
logger.error('SMTP_IS_SECURE env var not found');
return false;
return false;
}
if (!obj['SMTP_PORT']) {
logger.error('SMTP_PORT env var not found');
return false;
return false;
}
if (!Port.isValid(obj['SMTP_PORT'].toString())) {
logger.error('SMTP_PORT ' + obj['SMTP_HOST'] + ' env var not valid');
return false;
logger.error(
'SMTP_PORT ' + obj['SMTP_HOST'] + ' env var not valid'
);
return false;
}
if (!obj['SMTP_HOST']) {
logger.error('SMTP_HOST env var not found');
return false;
return false;
}
if (!Hostname.isValid(obj['SMTP_HOST'].toString())) {
logger.error('SMTP_HOST env var ' + obj['SMTP_HOST'] + ' not valid');
return false;
logger.error(
'SMTP_HOST env var ' + obj['SMTP_HOST'] + ' not valid'
);
return false;
}
if (!obj['SMTP_PASSWORD']) {
logger.error('SMTP_PASSWORD env var not found');
return false;
return false;
}
return true;
return true;
}
public static getEmailServer(obj : JSONObject): EmailServer {
public static getEmailServer(obj: JSONObject): EmailServer {
if (!this.isSMTPConfigValid(obj)) {
throw new BadDataException("SMTP Config is not valid");
throw new BadDataException('SMTP Config is not valid');
}
return {
username: obj['SMTP_USERNAME']?.toString()!,
password: obj['SMTP_PASSWORD']?.toString()!,
host: new Hostname(obj['SMTP_HOST']?.toString()!),
port: new Port(obj['SMTP_PORT']?.toString()!),
fromEmail: new Email(obj['SMTP_EMAIL']?.toString()!),
fromName: obj['SMTP_FROM_NAME']?.toString()!,
secure: obj['SMTP_IS_SECURE'] === "true",
password: obj['SMTP_PASSWORD']?.toString()!,
host: new Hostname(obj['SMTP_HOST']?.toString()!),
port: new Port(obj['SMTP_PORT']?.toString()!),
fromEmail: new Email(obj['SMTP_EMAIL']?.toString()!),
fromName: obj['SMTP_FROM_NAME']?.toString()!,
secure: obj['SMTP_IS_SECURE'] === 'true',
};
}
@@ -93,7 +99,6 @@ export default class MailService {
return this.getEmailServer(process.env);
}
private static async compileEmailBody(
emailTemplateType: EmailTemplateType,
vars: Dictionary<string>
@@ -193,7 +198,9 @@ export default class MailService {
mail.vars['year'] = OneUptimeDate.getCurrentYear().toString();
}
mail.body = mail.templateType ? await this.compileEmailBody(mail.templateType, mail.vars) : this.compileText(mail.body || '', mail.vars);
mail.body = mail.templateType
? await this.compileEmailBody(mail.templateType, mail.vars)
: this.compileText(mail.body || '', mail.vars);
mail.subject = this.compileText(mail.subject, mail.vars);
await this.transportMail(mail, EmailServer);

View File

@@ -1,6 +1,6 @@
// This script merges config.env.tpl to config.env
import fs from 'fs'
import fs from 'fs';
const init: Function = (): void => {
const tempate: string = fs.readFileSync('./config.tpl.env', 'utf8');

View File

@@ -1,7 +1,6 @@
// This script merges config.env.tpl to config.env
import fs from 'fs'
import fs from 'fs';
const init: Function = (): void => {
let env: string = '';

View File

@@ -16,7 +16,10 @@ app.use(ExpressStatic(path.join(__dirname, 'public')));
app.use(`/${APP_NAME}`, ExpressStatic(path.join(__dirname, 'public')));
app.use([`/${APP_NAME}/assets`,`/${APP_NAME}/${APP_NAME}/assets`], ExpressStatic(path.join(__dirname, 'dist')));
app.use(
[`/${APP_NAME}/assets`, `/${APP_NAME}/${APP_NAME}/assets`],
ExpressStatic(path.join(__dirname, 'dist'))
);
app.get('/*', (_req: ExpressRequest, res: ExpressResponse) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
@@ -26,7 +29,6 @@ const init: Function = async (): Promise<void> => {
try {
// init the app
await App(APP_NAME);
} catch (err) {
logger.error('App Init Failed:');
logger.error(err);

View File

@@ -24,7 +24,7 @@
"test": "react-app-rewired test",
"eject": "webpack eject",
"compile": "tsc",
"start": "webpack serve --port=3105",
"start": "node --require ts-node/register Index.ts",
"audit": "npm audit --audit-level=low",
"preinstall": "npx npm-force-resolutions || echo 'No package-lock.json file. Skipping force resolutions'",
"dep-check": "depcheck ./ --skip-missing=true'"

View File

@@ -1,4 +1,4 @@
import React, { FunctionComponent, useState } from 'react';
import React, { FunctionComponent, useState, useEffect } from 'react';
import Route from 'Common/Types/API/Route';
import {
Routes,
@@ -26,7 +26,6 @@ import 'CommonUI/src/Styles/theme.scss';
import Navigation from 'CommonUI/src/Utils/Navigation';
import { JSONFunctions, JSONObject } from 'Common/Types/JSON';
import RouteParams from './Utils/RouteParams';
import { useEffect } from 'react';
const App: FunctionComponent = () => {
Navigation.setNavigateHook(useNavigate());
@@ -35,10 +34,9 @@ const App: FunctionComponent = () => {
const [isPreview, setIsPreview] = useState<boolean>(false);
useEffect(() => {
setIsPreview(isPreviewPage());
}, [])
}, []);
// js.
const [javascript, setJavaScript] = useState<string | null>(null);
@@ -49,7 +47,7 @@ const App: FunctionComponent = () => {
}
};
const isPreviewPage: Function = (): boolean => {
const isPreviewPage: Function = (): boolean => {
const id: string | null = Navigation.getParamByName(
RouteParams.StatusPageId,
RouteMap[PageMap.PREVIEW_OVERVIEW]!
@@ -59,7 +57,7 @@ const App: FunctionComponent = () => {
return true;
}
return false;
return false;
};
return (
@@ -80,7 +78,6 @@ const App: FunctionComponent = () => {
<PageRoute
path={RouteMap[PageMap.OVERVIEW]?.toString()}
element={
<Overview
pageRoute={RouteMap[PageMap.OVERVIEW] as Route}

View File

@@ -129,7 +129,11 @@ const Overview: FunctionComponent<PageComponentProps> = (
footerEventStatus: 'Announced at',
footerDateTime: announcement.showAnnouncementAt,
eventViewRoute: RouteUtil.populateRouteParams(
props.isPreviewPage ? RouteMap[PageMap.PREVIEW_ANNOUNCEMENT_DETAIL] as Route : RouteMap[PageMap.ANNOUNCEMENT_DETAIL] as Route,
props.isPreviewPage
? (RouteMap[
PageMap.PREVIEW_ANNOUNCEMENT_DETAIL
] as Route)
: (RouteMap[PageMap.ANNOUNCEMENT_DETAIL] as Route),
announcement.id!
),
});

View File

@@ -104,7 +104,7 @@ const Overview: FunctionComponent<PageComponentProps> = (
try {
setError(
(err as HTTPErrorResponse).message ||
'Server Error. Please try again'
'Server Error. Please try again'
);
} catch (e) {
setError('Server Error. Please try again');
@@ -177,11 +177,12 @@ const Overview: FunctionComponent<PageComponentProps> = (
eventDescription: incident.description,
eventTimeline: timeline,
eventType: 'Incident',
eventViewRoute: RouteUtil.populateRouteParams(props.isPreviewPage ?
RouteMap[PageMap.PREVIEW_INCIDENT_DETAIL] as Route :
RouteMap[PageMap.INCIDENT_DETAIL] as Route,
incident.id!
),
eventViewRoute: RouteUtil.populateRouteParams(
props.isPreviewPage
? (RouteMap[PageMap.PREVIEW_INCIDENT_DETAIL] as Route)
: (RouteMap[PageMap.INCIDENT_DETAIL] as Route),
incident.id!
),
});
}

View File

@@ -573,11 +573,14 @@ const Overview: FunctionComponent<PageComponentProps> = (
)}
eventType={'Incident'}
eventViewRoute={RouteUtil.populateRouteParams(
props.isPreviewPage ? RouteMap[
PageMap.PREVIEW_INCIDENT_DETAIL
] as Route : RouteMap[
PageMap.INCIDENT_DETAIL
] as Route,
props.isPreviewPage
? (RouteMap[
PageMap
.PREVIEW_INCIDENT_DETAIL
] as Route)
: (RouteMap[
PageMap.INCIDENT_DETAIL
] as Route),
incidentGroup.incident.id!
)}
/>
@@ -616,11 +619,14 @@ const Overview: FunctionComponent<PageComponentProps> = (
}
eventType={'Scheduled Maintenance'}
eventViewRoute={RouteUtil.populateRouteParams(
props.isPreviewPage ? RouteMap[
PageMap.PREVIEW_SCHEDULED_EVENT_DETAIL
] as Route : RouteMap[
PageMap.SCHEDULED_EVENT_DETAIL
] as Route,
props.isPreviewPage
? (RouteMap[
PageMap
.PREVIEW_SCHEDULED_EVENT_DETAIL
] as Route)
: (RouteMap[
PageMap.SCHEDULED_EVENT_DETAIL
] as Route),
scheduledEventGroup.scheduledMaintenance
.id!
)}

View File

@@ -5,5 +5,5 @@ export default interface ComponentProps {
pageRoute: Route;
statusPageId?: ObjectID | null | undefined;
onLoadComplete: () => void;
isPreviewPage?: boolean; // if this status page is not hosted on a domain, then this is true, otherwise false.
isPreviewPage?: boolean; // if this status page is not hosted on a domain, then this is true, otherwise false.
}

View File

@@ -191,7 +191,11 @@ const Overview: FunctionComponent<PageComponentProps> = (
eventTimeline: timeline,
eventType: 'Scheduled Maintenance',
eventViewRoute: RouteUtil.populateRouteParams(
props.isPreviewPage ? RouteMap[PageMap.PREVIEW_SCHEDULED_EVENT_DETAIL] as Route : RouteMap[PageMap.SCHEDULED_EVENT_DETAIL] as Route,
props.isPreviewPage
? (RouteMap[
PageMap.PREVIEW_SCHEDULED_EVENT_DETAIL
] as Route)
: (RouteMap[PageMap.SCHEDULED_EVENT_DETAIL] as Route),
scheduledMaintenance.id!
),
});