Skip to content

Commit 9093dde

Browse files
authored
[feat] Add Product Information Feature and Enhance Event Handling Logic (#173)
1 parent fa73d78 commit 9093dde

15 files changed

Lines changed: 1105 additions & 1045 deletions

package.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "statusdashboard",
3-
"version": "1.0.0",
3+
"version": "1.1.0",
44
"type": "module",
55
"scripts": {
66
"dev": "farm start",
@@ -11,15 +11,15 @@
1111
"test": "vitest"
1212
},
1313
"dependencies": {
14-
"@fluentui/react-components": "^9.64.1",
14+
"@fluentui/react-components": "^9.66.1",
1515
"@telekom/scale-components": "3.0.0-beta.155",
1616
"@telekom/scale-components-react": "3.0.0-beta.155",
1717
"ahooks": "^3.8.5",
1818
"dayjs": "^1.11.13",
1919
"idb": "^8.0.3",
2020
"jwt-decode": "^4.0.0",
2121
"lodash": "^4.17.21",
22-
"oidc-client-ts": "^3.2.1",
22+
"oidc-client-ts": "^3.3.0",
2323
"react": "^19.1.0",
2424
"react-dom": "^19.1.0",
2525
"react-helmet": "^6.1.0",
@@ -31,22 +31,22 @@
3131
"@farmfe/core": "^1.7.5",
3232
"@farmfe/js-plugin-postcss": "^1.12.0",
3333
"@farmfe/plugin-react": "^1.2.6",
34-
"@tailwindcss/postcss": "^4.1.8",
34+
"@tailwindcss/postcss": "^4.1.10",
3535
"@testing-library/react": "^16.3.0",
3636
"@types/lodash": "^4.17.17",
37-
"@types/node": "^22.15.30",
38-
"@types/react": "^19.1.6",
37+
"@types/node": "^22.15.32",
38+
"@types/react": "^19.1.8",
3939
"@types/react-dom": "^19.1.6",
4040
"@types/react-helmet": "^6.1.11",
4141
"autoprefixer": "^10.4.21",
42-
"core-js": "^3.42.0",
43-
"eslint": "^9.28.0",
42+
"core-js": "^3.43.0",
43+
"eslint": "^9.29.0",
4444
"globals": "^16.2.0",
45-
"postcss": "^8.5.4",
45+
"postcss": "^8.5.6",
4646
"react-refresh": "^0.17.0",
4747
"tailwindcss": "3.4.17",
4848
"tailwindcss-scoped-preflight": "^3.4.12",
49-
"typescript-eslint": "^8.33.1"
49+
"typescript-eslint": "^8.34.1"
5050
},
5151
"packageManager": "pnpm@10.11.1"
5252
}

pnpm-lock.yaml

Lines changed: 1020 additions & 979 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Components/Event/Enums.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,14 @@ export function GetEventType(impact: number): EventType {
4141
*/
4242
export function GetEventImpact(type: EventType): number {
4343
switch (type) {
44-
case EventType.Maintenance:
45-
return 0;
4644
case EventType.Minor:
4745
return 1;
4846
case EventType.Major:
4947
return 2;
5048
case EventType.Outage:
5149
return 3;
5250
default:
53-
return 4;
51+
return 0;
5452
}
5553
}
5654

@@ -76,10 +74,11 @@ export enum EventStatus {
7674

7775
Planned = "Planned",
7876
Modified = "Modified",
79-
InProgress = "InProgress",
77+
InProgress = "In Progress",
8078
Completed = "Completed",
8179
Cancelled = "Cancelled",
8280

81+
Active = "Active",
8382
Reopened = "Reopened",
8483
Changed = "Changed",
8584
}
@@ -94,7 +93,7 @@ export function GetStatusList(type: EventType): EventStatus[] {
9493
case EventType.Maintenance:
9594
return Object.values(EventStatus).slice(4, 9);
9695
case EventType.Information:
97-
return [EventStatus.Planned, EventStatus.Completed, EventStatus.Cancelled];
96+
return [EventStatus.Planned, EventStatus.Active, EventStatus.Completed, EventStatus.Cancelled];
9897
default:
9998
return Object.values(EventStatus).slice(0, 4);
10099
}
@@ -138,5 +137,7 @@ export function GetStatusString(status: EventStatus): string {
138137
return StatusEnum.Planned;
139138
case EventStatus.Cancelled:
140139
return StatusEnum.Cancelled;
140+
case EventStatus.Active:
141+
return StatusEnum.Active;
141142
}
142143
}

src/Components/Event/EventCard.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Dic } from "~/Helpers/Entities";
33
import { Models } from "~/Services/Status.Models";
44
import { Authorized } from "../Auth/With";
55
import { Indicator } from "../Home/Indicator";
6-
import { EventStatus, EventType } from "./Enums";
6+
import { EventStatus, IsIncident } from "./Enums";
77
import { EventAffected } from "./EventAffected";
88
import { EventEditor } from "./EventEditor";
99
import { EventExtract } from "./EventExtract";
@@ -23,7 +23,7 @@ import { EventExtract } from "./EventExtract";
2323
*
2424
* @author Aloento
2525
* @since 1.0.0
26-
* @version 0.1.0
26+
* @version 0.2.0
2727
*/
2828
export function EventCard({ Event }: { Event: Models.IEvent }) {
2929
return (
@@ -63,12 +63,12 @@ export function EventCard({ Event }: { Event: Models.IEvent }) {
6363
</label>
6464

6565
<label className="text-xl font-medium text-slate-600 whitespace-nowrap">
66-
{Event.Type === EventType.Maintenance &&
66+
{!IsIncident(Event.Type) &&
6767
Event.Status !== EventStatus.Completed &&
6868
"(Plan)"} End At:
6969
</label>
7070

71-
{Event.Type === EventType.Maintenance && Event.Description &&
71+
{!IsIncident(Event.Type) && Event.Description &&
7272
<label className="text-xl font-medium text-slate-600">
7373
Description:
7474
</label>}
@@ -91,7 +91,7 @@ export function EventCard({ Event }: { Event: Models.IEvent }) {
9191
{Event.End ? dayjs(Event.End).tz(Dic.TZ).format(Dic.TimeTZ) : "Still Ongoing"}
9292
</label>
9393

94-
{Event.Type === EventType.Maintenance && Event.Description &&
94+
{!IsIncident(Event.Type) && Event.Description &&
9595
<label className="text-xl font-medium text-slate-700 break-all">
9696
{Event.Description}
9797
</label>}

src/Components/Event/EventEditor.tsx

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useBoolean } from "ahooks";
33
import dayjs from "dayjs";
44
import { Dic } from "~/Helpers/Entities";
55
import { Models } from "~/Services/Status.Models";
6-
import { EventStatus, EventType, IsOpenStatus } from "./Enums";
6+
import { EventStatus, EventType, GetStatusList, IsIncident, IsOpenStatus } from "./Enums";
77
import { useEditForm } from "./useEditForm";
88

99
/**
@@ -20,7 +20,7 @@ import { useEditForm } from "./useEditForm";
2020
*
2121
* @author Aloento
2222
* @since 1.0.0
23-
* @version 0.1.0
23+
* @version 0.2.0
2424
*/
2525
export function EventEditor({ Event }: { Event: Models.IEvent }) {
2626
const { State, Actions, Validation, OnSubmit, Loading } = useEditForm(Event);
@@ -60,12 +60,12 @@ export function EventEditor({ Event }: { Event: Models.IEvent }) {
6060
<ScaleDropdownSelect
6161
label="Type"
6262
value={State.type}
63-
disabled={Event.Type === EventType.Maintenance}
63+
disabled={!IsIncident(Event.Type)}
6464
onScale-change={(e) => Actions.setType(e.target.value as EventType)}
6565
invalid={!!Validation.type}
6666
helperText={Validation.type}
6767
>
68-
{Object.values(EventType).slice(2).map((type, i) =>
68+
{Object.values(EventType).slice(2, 5).map((type, i) =>
6969
<ScaleDropdownSelectItem value={type} key={i}>
7070
{type}
7171
</ScaleDropdownSelectItem>)}
@@ -78,11 +78,8 @@ export function EventEditor({ Event }: { Event: Models.IEvent }) {
7878
invalid={!!Validation.status}
7979
helperText={Validation.status}
8080
>
81-
{Object.values(EventStatus)
82-
.slice(
83-
State.type === EventType.Maintenance ? 4 : 0,
84-
State.type === EventType.Maintenance ? 9 : 4
85-
).map((status, i) =>
81+
{GetStatusList(State.type)
82+
.map((status, i) =>
8683
<ScaleDropdownSelectItem value={status} key={i}>
8784
{status}
8885
</ScaleDropdownSelectItem>)}
@@ -91,7 +88,7 @@ export function EventEditor({ Event }: { Event: Models.IEvent }) {
9188
<ScaleTextField
9289
type="datetime-local"
9390
label="Start CET"
94-
disabled={State.type !== EventType.Maintenance && IsOpenStatus(Event.Status)}
91+
disabled={IsIncident(State.type) && IsOpenStatus(Event.Status)}
9592
value={dayjs(State.start).format(Dic.Picker)}
9693
onScale-input={(e) => Actions.setStart(new Date(e.target.value as string))}
9794
invalid={!!Validation.start}
@@ -101,7 +98,7 @@ export function EventEditor({ Event }: { Event: Models.IEvent }) {
10198
<ScaleTextField
10299
type="datetime-local"
103100
label="(Plan) End CET"
104-
disabled={!(State.type === EventType.Maintenance || !IsOpenStatus(State.status))}
101+
disabled={!(!IsIncident(State.type) || !IsOpenStatus(State.status))}
105102
value={State.end ? dayjs(State.end).format(Dic.Picker) : null}
106103
onScale-input={(e) => Actions.setEnd(new Date(e.target.value as string))}
107104
invalid={!!Validation.end}

src/Components/Event/useEditForm.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useStatus } from "~/Services/Status";
44
import { StatusEnum } from "~/Services/Status.Entities";
55
import { Models } from "~/Services/Status.Models";
66
import { useAccessToken } from "../Auth/useAccessToken";
7-
import { EventStatus, EventType, GetEventImpact, GetStatusString, IsOpenStatus } from "./Enums";
7+
import { EventStatus, EventType, GetEventImpact, GetStatusString, IsIncident, IsOpenStatus } from "./Enums";
88

99
/**
1010
* Custom hook for managing the edit form state and validation for an event.
@@ -23,7 +23,7 @@ import { EventStatus, EventType, GetEventImpact, GetStatusString, IsOpenStatus }
2323
*
2424
* @author Aloento
2525
* @since 1.0.0
26-
* @version 0.1.0
26+
* @version 0.2.0
2727
*/
2828
export function useEditForm(event: Models.IEvent) {
2929
const [title, _setTitle] = useState(event.Title);
@@ -60,12 +60,12 @@ export function useEditForm(event: Models.IEvent) {
6060
return false;
6161
}
6262

63-
if (type === EventType.Maintenance && value !== EventType.Maintenance) {
63+
if (!IsIncident(type) && IsIncident(value)) {
6464
_setStatus(EventStatus.Analysing);
6565
}
6666

67-
if (type !== EventType.Maintenance && value === EventType.Maintenance) {
68-
_setStatus(EventStatus.Modified);
67+
if (IsIncident(type) && !IsIncident(value)) {
68+
_setStatus(EventStatus.Planned);
6969
}
7070

7171
_setType(value);
@@ -124,7 +124,7 @@ export function useEditForm(event: Models.IEvent) {
124124
setValStart("Start Date cannot be later than End Date.");
125125
err = true;
126126
}
127-
if (value > now && type !== EventType.Maintenance) {
127+
if (value > now && IsIncident(type)) {
128128
setValStart("Start Date cannot be in the future.");
129129
err = true;
130130
}
@@ -194,15 +194,15 @@ export function useEditForm(event: Models.IEvent) {
194194
body.status = StatusEnum.ImpactChanged;
195195
}
196196

197-
if (event.Type === EventType.Maintenance) {
197+
if (!IsIncident(event.Type)) {
198198
body.start_date = start.toISOString();
199199
}
200200

201201
if (end && !isNaN(end.getTime())) {
202202
body.end_date = end.toISOString();
203203
}
204204

205-
if (!IsOpenStatus(event.Status) && event.Type !== EventType.Maintenance) {
205+
if (!IsOpenStatus(event.Status) && IsIncident(event.Type)) {
206206
if (event.Status !== status) {
207207
body.end_date = undefined;
208208
body.status = StatusEnum.Reopened;

src/Components/History/EventItem.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ interface IEventItem {
1515
/**
1616
* @author Aloento
1717
* @since 1.0.0
18-
* @version 0.1.0
18+
* @version 0.2.0
1919
*/
2020
export function EventItem({ Prev, Curr }: IEventItem) {
2121
const isBegin = useMemo(() => {
@@ -68,11 +68,25 @@ export function EventItem({ Prev, Curr }: IEventItem) {
6868

6969
switch (Curr.Status) {
7070
case EventStatus.Analysing:
71+
color = "red";
72+
break;
73+
7174
case EventStatus.Fixing:
75+
color = "orange";
76+
break;
77+
7278
case EventStatus.Observing:
7379
color = "yellow";
7480
break;
7581

82+
case EventStatus.Planned:
83+
color = "cyan";
84+
break;
85+
86+
case EventStatus.Active:
87+
color = "teal";
88+
break;
89+
7690
case EventStatus.Modified:
7791
case EventStatus.InProgress:
7892
color = "violet";

src/Components/Home/EventGrid.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import { chain } from "lodash";
55
import { useEffect, useRef } from "react";
66
import { Dic } from "~/Helpers/Entities";
77
import { useStatus } from "~/Services/Status";
8-
import { EventType, IsOpenStatus } from "../Event/Enums";
8+
import { EventType, IsIncident, IsOpenStatus } from "../Event/Enums";
99

1010
/**
1111
* @author Aloento
1212
* @since 1.0.0
13-
* @version 0.1.0
13+
* @version 0.2.0
1414
*/
1515
export function EventGrid() {
1616
const { DB } = useStatus();
@@ -87,7 +87,7 @@ export function EventGrid() {
8787
}
8888
})
8989
.filter(x => {
90-
if (x.Type !== EventType.Maintenance && x.End) {
90+
if (IsIncident(x.Type) && x.End) {
9191
return false;
9292
}
9393

@@ -107,9 +107,11 @@ export function EventGrid() {
107107
case EventType.Outage:
108108
tag = { content: EventType.Outage, color: "red" };
109109
break;
110-
default:
110+
case EventType.Maintenance:
111111
tag = { content: EventType.Maintenance, color: "cyan" };
112112
break;
113+
default:
114+
tag = { content: EventType.Information, color: "standard" };
113115
}
114116

115117
return [

src/Components/Home/Indicator.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface IIndicator {
1010
/**
1111
* @author Aloento
1212
* @since 1.0.0
13-
* @version 0.1.0
13+
* @version 0.2.0
1414
*/
1515
export function Indicator({ Type, Size, Class }: IIndicator) {
1616
const scaleIcon = "scale-icon-";
@@ -28,6 +28,8 @@ export function Indicator({ Type, Size, Class }: IIndicator) {
2828
return "alert-warning";
2929
case EventType.Outage:
3030
return "action-circle-close";
31+
case EventType.Information:
32+
return "alert-information";
3133
default:
3234
return "action-success";
3335
}
@@ -43,6 +45,8 @@ export function Indicator({ Type, Size, Class }: IIndicator) {
4345
return `${text}warning)`;
4446
case EventType.Outage:
4547
return `${text}danger)`;
48+
case EventType.Information:
49+
return `${text}disabled)`;
4650
default:
4751
return `${text}success)`;
4852
}

src/Components/Home/ServiceItem.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { chain } from "lodash";
44
import { useEffect, useState } from "react";
55
import { useStatus } from "~/Services/Status";
66
import { Models } from "~/Services/Status.Models";
7-
import { EventType, IsOpenStatus } from "../Event/Enums";
7+
import { EventType, IsIncident, IsOpenStatus } from "../Event/Enums";
88
import { Indicator } from "./Indicator";
99
import "./ServiceItem.css";
1010

@@ -15,7 +15,7 @@ interface IServiceItem {
1515
/**
1616
* @author Aloento
1717
* @since 1.0.0
18-
* @version 0.1.0
18+
* @version 0.2.0
1919
*/
2020
export function ServiceItem({ RegionService }: IServiceItem) {
2121
const { DB } = useStatus();
@@ -27,7 +27,7 @@ export function ServiceItem({ RegionService }: IServiceItem) {
2727
useEffect(() => {
2828
const res = chain([...RegionService.Events])
2929
.filter(x => {
30-
if (x.Type !== EventType.Maintenance && x.End) {
30+
if (IsIncident(x.Type) && x.End) {
3131
return false;
3232
}
3333

0 commit comments

Comments
 (0)