refactor: Update import statements for TimezoneUtil in multiple files

This commit is contained in:
Simon Larsen
2024-06-18 10:38:45 +01:00
parent 5243ae6b8d
commit 401fbb58e3
15 changed files with 178 additions and 34 deletions

View File

@@ -11,7 +11,6 @@ import UserUtil from "CommonUI/src/Utils/User";
import User from "Model/Models/User";
import React, { useState } from "react";
import ProjectSSO from "Model/Models/ProjectSSO";
import ErrorMessage from "CommonUI/src/Components/ErrorMessage/ErrorMessage";
import PageLoader from "CommonUI/src/Components/Loader/PageLoader";
import API from "CommonUI/src/Utils/API/API";
import BasicForm from "CommonUI/src/Components/Forms/BasicForm";
@@ -44,25 +43,29 @@ const LoginPage: () => JSX.Element = () => {
}
if (!listResult.data || (listResult.data as JSONArray).length === 0) {
return setError("No SSO configuration found for the email: " + email.toString());
setError("No SSO configuration found for the email: " + email.toString());
} else {
setProjectSsoConfigList(ProjectSSO.fromJSONArray(listResult['data'], ProjectSSO));
}
setProjectSsoConfigList(ProjectSSO.fromJSONArray(listResult['data'], ProjectSSO));
} catch (error) {
setError(API.getFriendlyErrorMessage(error as Error));
}
setIsLoading(false);
} else {
setError("Email is required to perform this action");
}
setIsLoading(false);
};
const getSsoConfigModelList = (configs: Array<ProjectSSO>) => {
return (<StaticModelList<ProjectSSO>
return (
<StaticModelList<ProjectSSO>
list={configs}
titleField="name"
selectedItems={[]}
@@ -81,25 +84,21 @@ const LoginPage: () => JSX.Element = () => {
/>);
}
if (error) {
return <ErrorMessage error={error} />;
}
if (isLoading) {
return <PageLoader isVisible={true} />;
}
const getProjectName = (projectId: string): string => {
const projectNames = projectSsoConfigList.filter((config: ProjectSSO) => config.projectId?.toString() === projectId.toString()).map((config: ProjectSSO) => config.project?.name);
const projectNames = projectSsoConfigList.filter((config: ProjectSSO) => config.projectId?.toString() === projectId.toString()).map((config: ProjectSSO) => config.project?.name);
return projectNames[0] || 'Project';
}
if (projectSsoConfigList.length > 0) {
if (projectSsoConfigList.length > 0 && !error && !isLoading) {
const projectIds: Array<string> = projectSsoConfigList.map((config: ProjectSSO) => config.projectId?.toString() as string);
return (
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="">
<img
@@ -107,7 +106,7 @@ const LoginPage: () => JSX.Element = () => {
src={OneUptimeLogo}
alt="OneUptime"
/>
<h2 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
<h2 className="mt-10 text-center text-xl tracking-tight text-gray-900">
Select Project
</h2>
<p className="mt-2 text-center text-sm text-gray-600">
@@ -118,14 +117,15 @@ const LoginPage: () => JSX.Element = () => {
{projectIds.map((projectId: string) => {
return (
<div key={projectId}>
<h3 className="mt-6 text-center text-2xl tracking-tight text-gray-900">
Project: {getProjectName(projectId)}
<h3 className="mt-6 font-medium tracking-tight">
{getProjectName(projectId)}
</h3>
{getSsoConfigModelList(projectSsoConfigList.filter((config: ProjectSSO) => config.projectId?.toString() === projectId.toString()))}
</div>
)
})}
</div>
</div>
);
}
@@ -154,6 +154,7 @@ const LoginPage: () => JSX.Element = () => {
<BasicForm
modelType={User}
id="login-form"
error={error}
name="Login"
fields={[
{

View File

@@ -387,11 +387,7 @@ const BaseAPIFeatureSet: FeatureSet = {
const APP_NAME: string = "api";
//attach api's
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<User, UserServiceType>(User, UserService).getRouter(),
);
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
@@ -1211,6 +1207,13 @@ const BaseAPIFeatureSet: FeatureSet = {
);
app.use(`/${APP_NAME.toLocaleLowerCase()}`, NotificationAPI);
//attach api's
app.use(
`/${APP_NAME.toLocaleLowerCase()}`,
new BaseAPI<User, UserServiceType>(User, UserService).getRouter(),
);
},
};

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@@ -11,7 +11,7 @@
<img class="h-6 mt-2" src="/img/viewsonic.svg" alt="ViewSonic">
</div>
<div class="mt-4 ml-8 flex justify-center flex-shrink-0 flex-grow lg:ml-4 lg:flex-grow-0">
<img class="h-9 mt-1" src="/img/Siemens-logo.svg" alt="Siemens">
<img class="h-9 mt-1" src="/img/skillable-logo.svg" alt="Skillable">
</div>
<div class="mt-4 ml-8 flex justify-center flex-shrink-0 flex-grow lg:ml-4 lg:flex-grow-0">
<img class="h-11 -mt-2" src="/img/sodexo.svg" alt="Sodexo">

View File

@@ -1,11 +0,0 @@
import UserService, {
Service as UserServiceType,
} from "../Services/UserService";
import BaseAPI from "./BaseAPI";
import User from "Model/Models/User";
export default class UserAPI extends BaseAPI<User, UserServiceType> {
public constructor() {
super(User, UserService);
}
}

View File

@@ -27,6 +27,7 @@
"Common": "file:../Common",
"formik": "^2.4.6",
"history": "^5.3.0",
"jwt-decode": "^4.0.0",
"lodash": "^4.17.21",
"Model": "file:../Model",
"moment-timezone": "^0.5.45",
@@ -14543,6 +14544,14 @@
"node": ">=6"
}
},
"node_modules/jwt-decode": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
"engines": {
"node": ">=18"
}
},
"node_modules/kleur": {
"version": "3.0.3",
"dev": true,

View File

@@ -32,6 +32,7 @@
"Common": "file:../Common",
"formik": "^2.4.6",
"history": "^5.3.0",
"jwt-decode": "^4.0.0",
"lodash": "^4.17.21",
"Model": "file:../Model",
"moment-timezone": "^0.5.45",

View File

@@ -121,6 +121,7 @@ const BasicForm: ForwardRefExoticComponent<any> = forwardRef(
null,
);
useEffect(() => {
if (formSteps && formSteps.length > 0 && formSteps[0]) {
setCurrentFormStepId(formSteps[0].id);

View File

@@ -97,4 +97,5 @@ export default interface Field<TEntity> {
// set this to true if you want to show this field in the form even when the form is in edit mode.
doNotShowWhenEditing?: boolean | undefined;
doNotShowWhenCreating?: boolean | undefined;
}

View File

@@ -0,0 +1,9 @@
import { JSONObject } from "Common/Types/JSON";
import { jwtDecode } from "jwt-decode";
export default class JWTToken {
public static decodeToken(token: string): JSONObject {
return jwtDecode(token);
}
}

View File

@@ -9,6 +9,7 @@ import Name from "Common/Types/Name";
import ObjectID from "Common/Types/ObjectID";
import Timezone from "Common/Types/Timezone";
import API from "Common/Utils/API";
import JWTToken from "./JWT";
export default class User {
public static setProfilePicId(id: ObjectID | null): void {
@@ -62,6 +63,31 @@ export default class User {
LocalStorage.setItem("user_name", name.toString());
}
public static refreshUserDataFromToken(token: string): void {
const decodedToken: JSONObject = JWTToken.decodeToken(token);
if(decodedToken["userId"]) {
this.setUserId(new ObjectID(decodedToken["userId"] as string));
}
if(decodedToken["email"]) {
this.setEmail(new Email(decodedToken["email"] as string));
}
if(decodedToken["name"]) {
this.setName(new Name(decodedToken["name"] as string));
}
if(decodedToken["isMasterAdmin"]) {
this.setIsMasterAdmin(decodedToken["isMasterAdmin"] as boolean);
}
if(decodedToken["timezone"]) {
this.setSavedUserTimezone(decodedToken["timezone"] as Timezone);
}
}
public static getEmail(): Email | null {
if (!LocalStorage.getItem("user_email")) {
return null;

View File

@@ -54,6 +54,9 @@ import {
useParams,
} from "react-router-dom";
import useAsyncEffect from "use-async-effect";
import User from "CommonUI/src/Utils/User";
import Cookie from "CommonUI/src/Utils/Cookie";
import { JSONValue } from "Common/Types/JSON";
const App: () => JSX.Element = () => {
Navigation.setNavigateHook(useNavigate());
@@ -75,6 +78,18 @@ const App: () => JSX.Element = () => {
const [hasPaymentMethod, setHasPaymentMethod] = useState<boolean>(false);
useEffect(() => {
const token: JSONValue = Cookie.getItem("user_token");
if(!token) {
return;
}
User.refreshUserDataFromToken(token.toString());
}, []);
useAsyncEffect(async () => {
try {
if (selectedProject && selectedProject._id) {

View File

@@ -47,7 +47,7 @@ const MonitorCriteriaIncidentForm: FunctionComponent<ComponentProps> = (
},
title: "Incident Description",
stepId: "incident-details",
fieldType: FormFieldSchemaType.LongText,
fieldType: FormFieldSchemaType.Markdown,
required: true,
placeholder: "Description",
},
@@ -88,6 +88,17 @@ const MonitorCriteriaIncidentForm: FunctionComponent<ComponentProps> = (
fieldType: FormFieldSchemaType.Toggle,
required: false,
},
{
field: {
remediationNotes: true,
},
title: "Remediation Notes",
stepId: "incident-details",
description:
"Notes to help the on-call engineer resolve this incident.",
fieldType: FormFieldSchemaType.Markdown,
required: false,
},
]}
/>

View File

@@ -589,6 +589,46 @@ const IncidentView: FunctionComponent<
modelId: modelId,
}}
/>
<CardModelDetail
name="Remediation Notes"
cardProps={{
title: "Remediation Notes",
description:
"What steps were taken to resolve this incident? Here are the remediation notes.",
}}
editButtonText="Edit Remediation Notes"
isEditable={true}
formFields={[
{
field: {
remediationNotes: true,
},
title: "Remediation Notes",
fieldType: FormFieldSchemaType.Markdown,
required: true,
placeholder: "Remediation Notes",
},
]}
modelDetailProps={{
showDetailsInNumberOfColumns: 1,
modelType: Incident,
id: "model-detail-incident-remediation-notes",
fields: [
{
field: {
remediationNotes: true,
},
title: "Remediation Notes",
placeholder: "No remediation notes added for this incident.",
fieldType: FieldType.Markdown,
},
],
modelId: modelId,
}}
/>
</Fragment>
);
};

View File

@@ -1015,4 +1015,41 @@ export default class Incident extends BaseModel {
default: false,
})
public isCreatedAutomatically?: boolean = undefined;
@ColumnAccessControl({
create: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.CreateProjectIncident,
],
read: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.ReadProjectIncident,
],
update: [
Permission.ProjectOwner,
Permission.ProjectAdmin,
Permission.ProjectMember,
Permission.EditProjectIncident,
],
})
@TableColumn({
required: false,
type: TableColumnType.Markdown,
title: "Remediation Notes",
description:
"Notes on how to remediate this incident. This is in markdown.",
})
@Column({
nullable: true,
type: ColumnType.Markdown,
})
public remediationNotes?: string = undefined;
}