mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
refactor: Update import statements for TimezoneUtil in multiple files
This commit is contained in:
@@ -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={[
|
||||
{
|
||||
|
||||
@@ -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(),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
1
App/FeatureSet/Home/Static/img/skillable-logo.svg
Normal file
1
App/FeatureSet/Home/Static/img/skillable-logo.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 6.8 KiB |
@@ -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">
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
9
CommonUI/package-lock.json
generated
9
CommonUI/package-lock.json
generated
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -121,6 +121,7 @@ const BasicForm: ForwardRefExoticComponent<any> = forwardRef(
|
||||
null,
|
||||
);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (formSteps && formSteps.length > 0 && formSteps[0]) {
|
||||
setCurrentFormStepId(formSteps[0].id);
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
9
CommonUI/src/Utils/JWT.ts
Normal file
9
CommonUI/src/Utils/JWT.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user