Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f627a3b
refactor: update Tailwind CSS configuration and styles
Aloento Feb 4, 2026
81f0a1a
feat: add @telekom-ods/react-ui-kit dependency and update .gitignore
Aloento Feb 4, 2026
01ef793
feat: move @telekom-ods/react-ui-kit to optionalDependencies in packa…
Aloento Feb 4, 2026
31fdd96
refactor: remove optionalDependencies for @telekom-ods/react-ui-kit a…
Aloento Feb 4, 2026
b6aa94f
feat: add @telekom-ods/react-ui-kit dependency to package.json and pn…
Aloento Feb 4, 2026
8e10ba0
feat: update branding references and improve metadata across multiple…
Aloento Feb 4, 2026
f63fdcf
feat: add Reviews page and mock data for reviews history
Aloento Feb 4, 2026
f9b1afe
feat: update reviews history mock data with correct region values
Aloento Feb 4, 2026
f3c3f31
feat: update reviews history mock data with additional entries for Lo…
Aloento Feb 4, 2026
b7a7ae8
Merge branch 'main' into role
Aloento Feb 5, 2026
fbaff61
fix: update ScaleTable class for proper overflow handling
Aloento Feb 5, 2026
9dde440
refactor: simplify titles in Availability, History, and Home components
Aloento Feb 5, 2026
d57d5f8
Merge branch 'main' into role
Aloento Feb 5, 2026
2ac02cf
Merge branch 'main' into role
Aloento Feb 6, 2026
6534d05
Merge branch 'main' into role
Aloento Feb 6, 2026
d2abd3a
feat: add contact email functionality to event management
Aloento Feb 12, 2026
6cd9d68
feat: refactor ProfileMenu component structure and enhance notificati…
Aloento Feb 12, 2026
6486e1a
feat: add contact email field for maintenance events and update valid…
Aloento Feb 13, 2026
d849c5c
feat: add informational notification for maintenance events in Home c…
Aloento Feb 13, 2026
8595098
feat: refactor Reviews component to use ScaleDataGrid and improve pag…
Aloento Feb 25, 2026
6c76d75
feat: add new service URLs for T Cloud and MyWorkplace in serviceSlugMap
Aloento Feb 25, 2026
0fc0031
feat: update footer content to reflect T-Systems International GmbH a…
Aloento Feb 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Components/Auth/With.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useAuth } from "react-oidc-context";
export function Authorized({ children }: { children: ReactNode }): ReactNode {
const auth = useAuth();

if (auth.isAuthenticated) {
if (auth.isAuthenticated || process.env.NODE_ENV === "development") {
return children;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Components/Auth/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ function AuthHandler() {

useMount(() => {
if (Paths.at(0) === "signin-oidc") {
return userMgr.signinCallback();
userMgr.signinCallback();
return
}

if (Paths.at(0) === "signout-callback-oidc") {
Expand Down
16 changes: 16 additions & 0 deletions src/Components/Event/EventCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ export function EventCard({ Event }: { Event: Models.IEvent }) {
<label className="text-xl font-medium text-slate-600">
Description:
</label>}

<Authorized>
{Event.ContactEmail &&
<label className="text-xl font-medium text-slate-600">
Contact Email:
</label>}
</Authorized>
</div>

<div className="flex flex-col gap-y-2">
Expand All @@ -95,6 +102,15 @@ export function EventCard({ Event }: { Event: Models.IEvent }) {
<label className="text-xl font-medium text-slate-700 break-all">
{Event.Description}
</label>}

<Authorized>
{Event.ContactEmail &&
<label className="text-xl font-medium text-slate-700 break-all">
<a href={`mailto:${Event.ContactEmail}`} className="text-blue-600 hover:text-blue-800 underline">
{Event.ContactEmail}
</a>
</label>}
</Authorized>
</div>
</div>

Expand Down
14 changes: 13 additions & 1 deletion src/Components/Event/EventEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { useEditForm } from "./useEditForm";
*
* @author Aloento
* @since 1.0.0
* @version 0.3.0
* @version 0.4.0
*/
export function EventEditor({ Event }: { Event: Models.IEvent }) {
const { State, Actions, Validation, OnSubmit, Loading } = useEditForm(Event);
Expand Down Expand Up @@ -125,6 +125,18 @@ export function EventEditor({ Event }: { Event: Models.IEvent }) {
helperText={Validation.description}
/>

{State.type === EventType.Maintenance && (
<ScaleTextField
placeholder="e.g. DL-TSI_OTC_Storage_Squad@t-systems.com"
label="Contact Email"
type="email"
value={State.contactEmail || ""}
onScale-input={(e) => Actions.setContactEmail(e.target.value as string)}
invalid={!!Validation.contactEmail}
helperText={Validation.contactEmail}
/>
)}

<ScaleTextarea
label="Update Message"
resize="vertical"
Expand Down
38 changes: 36 additions & 2 deletions src/Components/Event/useEditForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { EventStatus, EventType, GetEventImpact, GetStatusString, IsIncident, Is
*
* @author Aloento
* @since 1.0.0
* @version 0.3.0
* @version 0.4.0
*/
export function useEditForm(event: Models.IEvent) {
const [title, _setTitle] = useState(event.Title);
Expand Down Expand Up @@ -107,6 +107,32 @@ export function useEditForm(event: Models.IEvent) {
return !err;
}

const [contactEmail, _setContactEmail] = useState(event.ContactEmail || "");
const [valContactEmail, setValContactEmail] = useState<string>();
function setContactEmail(value = contactEmail) {
let err: boolean = false;

if (type === EventType.Maintenance && !value) {
setValContactEmail("Contact Email is required for maintenance.");
err = true;
}

if (value && !value.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) {
setValContactEmail("Please enter a valid email address.");
err = true;
}

if (value && value.length > 100) {
setValContactEmail("Email must be less than 100 characters.");
err = true;
}

_setContactEmail(value);
!err && setValContactEmail(undefined);

return !err;
}

const [status, _setStatus] = useState<EventStatus | undefined>();
const [valStatus, setValStatus] = useState<string>();
function setStatus(value = status) {
Expand Down Expand Up @@ -188,7 +214,7 @@ export function useEditForm(event: Models.IEvent) {
const { DB, Update } = useStatus();

const { runAsync, loading } = useRequest(async () => {
if (![setTitle(), setType(), setUpdate(), setDescription(), setStatus(), setStart(), setEnd(), setUpdateAt()].every(Boolean)) {
if (![setTitle(), setType(), setUpdate(), setDescription(), setContactEmail(), setStatus(), setStart(), setEnd(), setUpdateAt()].every(Boolean)) {
throw new Error("Validation failed.");
}
const url = process.env.SD_BACKEND_URL!;
Expand All @@ -202,6 +228,10 @@ export function useEditForm(event: Models.IEvent) {
description,
};

if (type === EventType.Maintenance && contactEmail) {
body.contact_email = contactEmail;
};

if (event.Type !== type) {
body.status = StatusEnum.ImpactChanged;
}
Expand Down Expand Up @@ -246,6 +276,7 @@ export function useEditForm(event: Models.IEvent) {
updatedEvent.Start = start;
updatedEvent.End = end;
updatedEvent.Description = description;
updatedEvent.ContactEmail = contactEmail;

const newHistory: Models.IHistory = {
Id: Math.max(...Array.from(updatedEvent.Histories).map(h => h.Id), 0) + 1,
Expand Down Expand Up @@ -273,6 +304,7 @@ export function useEditForm(event: Models.IEvent) {
type,
update,
description,
contactEmail,
status,
start,
end,
Expand All @@ -283,6 +315,7 @@ export function useEditForm(event: Models.IEvent) {
setType,
setUpdate,
setDescription,
setContactEmail,
setStatus,
setStart,
setEnd,
Expand All @@ -293,6 +326,7 @@ export function useEditForm(event: Models.IEvent) {
type: valType,
update: valUpdate,
description: valDescription,
contactEmail: valContactEmail,
status: valStatus,
start: valStart,
end: valEnd,
Expand Down
4 changes: 4 additions & 0 deletions src/Components/Home/serviceSlugMap.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
"Open Telekom Cloud": "https://www.open-telekom-cloud.com/",
"Open Telekom Cloud Community": "https://community.open-telekom-cloud.com/",
"Open Telekom Cloud Console": "https://console.otc.t-systems.com/",
"T Cloud Public Homepage": "https://public.t-cloud.com/",
"T Cloud Public Community": "https://community.open-telekom-cloud.com/",
"T Cloud Public Console": "https://console.otc.t-systems.com/",
"MyWorkplace": "https://myworkplace.t-systems.com/MyWorkplace/Login.aspx",
"Financial Dashboard": "",
"Invoicing": ""
}
10 changes: 5 additions & 5 deletions src/Components/Layout/PageFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ export function PageFooter() {
return (
<ScaleTelekomFooter slot="footer" type="minimal" class="mt-auto pt-8" data-mode="dark">
<ScaleTelekomFooterContent>
<span slot="notice"> © Deutsche Telekom AG </span>
<span slot="notice"> © T-Systems International GmbH </span>
<ul slot="navigation">
<li>
<a href="https://open-telekom-cloud.com/en/imprint">Imprint</a>
<a href="https://public.t-cloud.com/en/imprint">Imprint</a>
</li>
<li>
<a href="https://open-telekom-cloud.com/en/data-protection">Data privacy</a>
<a href="https://public.t-cloud.com/en/data-privacy">Data privacy</a>
</li>
<li>
<a href="https://open-telekom-cloud.com/en/disclaimer-of-liability">Disclaimer of liability</a>
<a href="https://public.t-cloud.com/en/disclaimer-of-liability">Disclaimer of liability</a>
</li>
<li>
<a href="https://open-telekom-cloud.com/en/contact">Contact</a>
<a href="https://public.t-cloud.com/en/contact">Contact</a>
</li>
</ul>
</ScaleTelekomFooterContent>
Expand Down
28 changes: 24 additions & 4 deletions src/Components/Layout/ProfileMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { ODSBadgeNumber } from "@telekom-ods/react-ui-kit";
import { ScaleButton, ScaleIconUserFileUser, ScaleMenuFlyout, ScaleMenuFlyoutItem, ScaleMenuFlyoutList, ScaleTelekomNavItem } from "@telekom/scale-components-react";
import { useAuth } from "react-oidc-context";
import { Authorized } from "../Auth/With";

/**
* @author Aloento
Expand All @@ -13,21 +15,39 @@ export function ProfileMenu() {
<ScaleTelekomNavItem hideOnMobile>
<ScaleMenuFlyout>

<ScaleButton slot="trigger" variant="secondary" iconOnly>
<ScaleIconUserFileUser accessibility-title="Menu" />
</ScaleButton>
<div slot="trigger" className="relative">
<ScaleButton variant="secondary" iconOnly>
<ScaleIconUserFileUser accessibility-title="Menu" />
</ScaleButton>

<Authorized>
<div className="absolute -top-1 -right-1">
<ODSBadgeNumber
notificationNumber={6}
size="standard"
variant="notification"
/>
</div>
</Authorized>
</div>

<ScaleMenuFlyoutList>
<ScaleMenuFlyoutItem>
Hi, {auth.user?.profile.name}
</ScaleMenuFlyoutItem>

<ScaleMenuFlyoutItem>
<a className="text-black no-underline" href="/NewEvent">
<a href="/NewEvent">
New Event
</a>
</ScaleMenuFlyoutItem>

<ScaleMenuFlyoutItem>
<a href="/Reviews">
Reviews
</a>
</ScaleMenuFlyoutItem>

<ScaleMenuFlyoutItem onScale-select={() => auth.signoutSilent()}>
Logout
</ScaleMenuFlyoutItem>
Expand Down
15 changes: 14 additions & 1 deletion src/Components/New/NewForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { useNewForm } from "./useNewForm";
*
* @author Aloento
* @since 1.0.0
* @version 0.1.0
* @version 0.3.0
*/
export function NewForm() {
const { DB } = useStatus();
Expand Down Expand Up @@ -147,6 +147,19 @@ export function NewForm() {
/>
)}

{State.type === EventType.Maintenance && (
<ScaleTextField
placeholder="e.g. DL-TSI_OTC_Storage_Squad@t-systems.com"
label="Contact Email"
type="email"
required
value={State.contactEmail || ""}
onScale-input={(e) => Actions.setContactEmail(e.target.value as string)}
invalid={!!Validation.contactEmail}
helperText={Validation.contactEmail}
/>
)}

<ScaleButton
class="self-end"
size="small"
Expand Down
43 changes: 38 additions & 5 deletions src/Components/New/useNewForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useRouter } from "../Router";
*
* @author Aloento
* @since 1.0.0
* @version 0.2.0
* @version 0.3.0
*/
export function useNewForm() {
const { DB, Update } = useStatus();
Expand Down Expand Up @@ -128,6 +128,32 @@ export function useNewForm() {
setEnd();
}, [start, end]);

const [contactEmail, _setContactEmail] = useState("");
const [valContactEmail, setValContactEmail] = useState<string>();
function setContactEmail(value = contactEmail) {
let err: boolean = false;

if (type === EventType.Maintenance && !value) {
setValContactEmail("Contact Email is required for maintenance.");
err = true;
}

if (value && !value.match(/^[^\s@]+@[^\s@]+\.[^\s@]+$/)) {
setValContactEmail("Please enter a valid email address.");
err = true;
}

if (value && value.length > 100) {
setValContactEmail("Email must be less than 100 characters.");
err = true;
}

_setContactEmail(value);
!err && setValContactEmail(undefined);

return !err;
}

const [services, _setServices] = useState<Models.IRegionService[]>([]);
const [valServices, setValServices] = useState<string>();
function setServices(action: (curr: Models.IRegionService[]) => Models.IRegionService[] = (s) => s) {
Expand All @@ -150,7 +176,7 @@ export function useNewForm() {
const getToken = useAccessToken();

const { runAsync, loading } = useRequest(async () => {
if (![setTitle(), setType(), setDescription(), setStart(), setEnd(), setServices()].every(Boolean)) {
if (![setTitle(), setType(), setDescription(), setStart(), setEnd(), setServices(), setContactEmail()].every(Boolean)) {
return;
}

Expand Down Expand Up @@ -180,6 +206,10 @@ export function useNewForm() {
start_date: start.toISOString()
}

if (type === EventType.Maintenance && contactEmail) {
body.contact_email = contactEmail;
}

if (!IsIncident(type) && end) {
body.end_date = end
}
Expand Down Expand Up @@ -215,23 +245,26 @@ export function useNewForm() {
description,
start,
end,
services
services,
contactEmail
},
Actions: {
setTitle,
setType,
setDescription,
setStart,
setEnd,
setServices
setServices,
setContactEmail
},
Validation: {
title: valTitle,
type: valType,
description: valDescription,
start: valStart,
end: valEnd,
services: valServices
services: valServices,
contactEmail: valContactEmail
},
OnSubmit: runAsync,
Loading: loading
Expand Down
6 changes: 6 additions & 0 deletions src/Pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ export function Home() {
<title>{Dic.Name} {Dic.Prod}</title>
</Helmet>

<ScaleNotification
heading="You have 6 maintenance events for the review."
opened
variant="informational"
/>

<ScaleNotification
heading={heading}
opened
Expand Down
Loading