Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 app/.devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ services:
command: sleep infinity

db:
image: postgres:15.6-alpine3.19
image: postgres:18.2-alpine3.23
restart: no
environment:
POSTGRES_PASSWORD: admin
Expand Down
27 changes: 26 additions & 1 deletion app/src/app/app/changelog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import image20250906NewLayout from "@/modules/changelog/assets/2025-09-06-new-layout.png";
import image20251007sincome from "@/modules/changelog/assets/2025-10-07-sincome.png";
import image20251013rolesHistory from "@/modules/changelog/assets/2025-10-13-roles-history.png";
import image20260214RoleTooltip from "@/modules/changelog/assets/2026-02-14-role-tooltip.png";
import { Link } from "@/modules/common/components/Link";
import { SmallBadge } from "@/modules/common/components/SmallBadge";
import { random } from "lodash";
Expand All @@ -44,6 +45,30 @@

return (
<div className="flex flex-col gap-4">
<Day heading="14. Februar 2026">
<DayItem heading="Tooltip für Rollen" badges={["Neu", "Citizen"]}>
<p>
Rollen haben nun ein Tooltip in welchem alle Details zu der
jeweiligen Rolle angezeigt werden. Auch kann direkt hier die
jeweilige Rolle von einem Citizen entfernt werden.
</p>

<p>
Zukünftig wird hier das aktuelle Level von levelbaren Rollen
gezeigt. Auch kann direkt hier das Level angepasst werden.
</p>

<Link href={image20260214RoleTooltip.src}>

Check failure on line 61 in app/src/app/app/changelog/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Unsafe member access .src on an `error` typed value

Check failure on line 61 in app/src/app/app/changelog/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Unsafe assignment of an error typed value
<Image
quality={100}
src={image20260214RoleTooltip}

Check failure on line 64 in app/src/app/app/changelog/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Unsafe assignment of an error typed value
alt=""
loading="eager"
/>
</Link>
</DayItem>
</Day>

<Day heading="6. Februar 2026">
<DayItem heading="Projekte" badges={["Neu", "Apps"]}>
<p>
Expand Down Expand Up @@ -362,12 +387,12 @@
Verlauf aller Änderungen an den Rollen dieses Citizen.
</p>

<Link href={image20251013rolesHistory.src}>

Check failure on line 390 in app/src/app/app/changelog/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Unsafe member access .src on an `error` typed value

Check failure on line 390 in app/src/app/app/changelog/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Unsafe assignment of an error typed value
<Image
quality={100}
src={image20251013rolesHistory}

Check failure on line 393 in app/src/app/app/changelog/page.tsx

View workflow job for this annotation

GitHub Actions / lint

Unsafe assignment of an error typed value
alt=""
loading="eager"
loading="lazy"
/>
</Link>
</DayItem>
Expand Down
64 changes: 35 additions & 29 deletions app/src/app/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { ServiceWorkerLoader } from "@/modules/common/components/ServiceWorkerLo
import { getUnleashFlag } from "@/modules/common/utils/getUnleashFlag";
import { UNLEASH_FLAG } from "@/modules/common/utils/UNLEASH_FLAG";
import { ChannelsProvider } from "@/modules/pusher/components/ChannelsContext";
import { RolesContextProvider } from "@/modules/roles/components/RolesContext";
import { getVisibleRoles } from "@/modules/roles/utils/getRoles";
import { CmdKProvider } from "@/modules/shell/components/CmdK/CmdKContext";
import { MobileActionBarLoader } from "@/modules/shell/components/Sidebar/MobileActionBarLoader";
import { TopBar } from "@/modules/shell/components/TopBar";
Expand All @@ -21,11 +23,13 @@ import { NuqsAdapter } from "nuqs/adapters/next/app";
import { Suspense } from "react";

export default async function AppLayout({ children }: LayoutProps<"/app">) {
const [authentication, disableAlgolia, apps] = await Promise.all([
requireAuthenticationPage(),
getUnleashFlag(UNLEASH_FLAG.DisableAlgolia),
getAppLinks(),
]);
const [authentication, disableAlgolia, apps, visibleRoles] =
await Promise.all([
requireAuthenticationPage(),
getUnleashFlag(UNLEASH_FLAG.DisableAlgolia),
getAppLinks(),
getVisibleRoles(),
]);

return (
<>
Expand All @@ -35,34 +39,36 @@ export default async function AppLayout({ children }: LayoutProps<"/app">) {
<TRPCReactProvider>
<ChannelsProvider userId={authentication.session.user.id}>
<NextIntlClientProvider>
<div className="min-h-dvh background-primary">
<AppsContextProvider apps={apps}>
<CreateContextProvider>
<CmdKProvider disableAlgolia={disableAlgolia}>
<TopBar />
<MobileActionBarLoader />
</CmdKProvider>
<RolesContextProvider roles={visibleRoles}>
<div className="min-h-dvh background-primary">
<AppsContextProvider apps={apps}>
<CreateContextProvider>
<CmdKProvider disableAlgolia={disableAlgolia}>
<TopBar />
<MobileActionBarLoader />
</CmdKProvider>

<div className="pt-12 lg:pt-[104px] pb-[64px] lg:pb-0 min-h-dvh">
{children}
</div>
</CreateContextProvider>
</AppsContextProvider>
</div>
<div className="pt-12 lg:pt-[104px] pb-[64px] lg:pb-0 min-h-dvh">
{children}
</div>
</CreateContextProvider>
</AppsContextProvider>
</div>

<Suspense>
<ImpersonationBannerContainer />
</Suspense>
<Suspense>
<ImpersonationBannerContainer />
</Suspense>

{authentication.session.user.role === "admin" && (
<AdminEnabler
enabled={
(await cookies()).get("enable_admin")?.value === "1"
}
/>
)}
{authentication.session.user.role === "admin" && (
<AdminEnabler
enabled={
(await cookies()).get("enable_admin")?.value === "1"
}
/>
)}

<NewReleaseToast />
<NewReleaseToast />
</RolesContextProvider>
</NextIntlClientProvider>
</ChannelsProvider>
</TRPCReactProvider>
Expand Down
4 changes: 2 additions & 2 deletions app/src/app/app/leaderboards/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ export default async function Page() {
{citizen.rank}
</td>

<td className="h-14 flex items-center px-2 overflow-hidden text-ellipsis whitespace-nowrap">
<td className="h-14 flex items-center px-2 truncate">
{/* <Link
href={`/app/spynet/citizen/${}`}
prefetch={false}
className="flex items-center gap-2 text-brand-red-500 hover:bg-neutral-800 px-2 rounded-secondary h-full overflow-hidden text-ellipsis whitespace-nowrap"
className="flex items-center gap-2 text-brand-red-500 hover:bg-neutral-800 px-2 rounded-secondary h-full truncate"
> */}
{citizen.displayname}
{/* </Link> */}
Expand Down
5 changes: 3 additions & 2 deletions app/src/app/app/roles/[id]/inheritance/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { requireAuthenticationPage } from "@/modules/auth/server";
import { InheritanceForm } from "@/modules/roles/components/InheritanceForm";
import { SingleRole } from "@/modules/roles/components/SingleRole";
import { SingleRoleBadge } from "@/modules/roles/components/SingleRoleBadge";
import { getRoleById, getRoles } from "@/modules/roles/queries";
import type { Metadata } from "next";
import { notFound } from "next/navigation";
Expand Down Expand Up @@ -30,7 +30,8 @@ export default async function Page({
<section className="rounded-primary bg-neutral-800/50 p-4">
<h2 className="text-xl font-bold mb-2">Vererbungen</h2>
<p className="max-w-prose">
Die Rolle <SingleRole role={role} className="inline-flex align-sub" />{" "}
Die Rolle{" "}
<SingleRoleBadge roleId={roleId} className="inline-flex align-sub" />{" "}
erhält alle Berechtigungen von den folgenden ausgewählten Rollen. Im
Karrieresystem gelten die folgenden Rollen ebenfalls als freigeschaltet.
Verschachtelte Vererbungen werden nicht berücksichtigt.
Expand Down
4 changes: 1 addition & 3 deletions app/src/app/app/spynet/citizen/[id]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,7 @@ export default async function Layout({

<span className="text-neutral-500">/</span>

<h1 className="overflow-hidden text-ellipsis whitespace-nowrap">
{citizen.handle || citizen.id}
</h1>
<h1 className="truncate">{citizen.handle || citizen.id}</h1>
</div>

<CitizenNavigation citizenId={citizen.id} className="mt-2 mb-4" />
Expand Down
4 changes: 1 addition & 3 deletions app/src/app/app/spynet/organization/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,7 @@ export default async function Page(props: Props) {

<span className="text-neutral-500">/</span>

<h1 className="overflow-hidden text-ellipsis whitespace-nowrap">
{organization.name}
</h1>
<h1 className="truncate">{organization.name}</h1>

{/* {authentication.authorize("organization", "delete") && <DeleteEntity entity={organization} />} */}
</div>
Expand Down
6 changes: 3 additions & 3 deletions app/src/modules/career/nodes/RoleCitizens/client/Node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { Handles } from "@/modules/career/components/Handles";
import { CitizenLink } from "@/modules/common/components/CitizenLink";
import { SingleRole } from "@/modules/roles/components/SingleRole";
import { SingleRoleBadge } from "@/modules/roles/components/SingleRoleBadge";
import {
FlowNodeRoleCitizensAlignment,
FlowNodeType,
Expand Down Expand Up @@ -231,8 +231,8 @@ export const Node: ComponentType<NodeProps<RoleNode>> = (props) => {
})}
>
{!props.data.roleCitizensHideRole && (
<SingleRole
role={props.data.role}
<SingleRoleBadge
roleId={props.data.role.id}
className="text-white flex-none"
/>
)}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 68 additions & 0 deletions app/src/modules/citizen/actions/deleteRoleAssignment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"use server";

import { prisma } from "@/db";
import { createAuthenticatedAction } from "@/modules/actions/utils/createAction";
import { RoleAssignmentChangeType } from "@prisma/client";
import { refresh } from "next/cache";
import { z } from "zod";

const schema = z.object({
citizenId: z.string(),
roleId: z.string(),
});

export const deleteRoleAssignment = createAuthenticatedAction(
"deleteRoleAssignment",
schema,
async (formData, authentication, data, t) => {
/**
* Authorize the request
*/
if (!authentication.session.entity)
return {
error: t("Common.forbidden"),
requestPayload: formData,
};
if (
!(await authentication.authorize("otherRole", "dismiss", [
{
key: "roleId",
value: data.roleId,
},
]))
)
return {
error: t("Common.forbidden"),
requestPayload: formData,
};

/**
*
*/
await prisma.$transaction([
prisma.roleAssignment.delete({
where: {
citizenId_roleId: {
citizenId: data.citizenId,
roleId: data.roleId,
},
},
}),

prisma.roleAssignmentChange.create({
data: {
citizenId: data.citizenId,
roleId: data.roleId,
type: RoleAssignmentChangeType.REMOVE,
createdById: authentication.session.entity.id,
},
}),
]);

refresh();

return {
success: t("Common.successfullySaved"),
};
},
);
6 changes: 0 additions & 6 deletions app/src/modules/citizen/actions/updateRoleAssignment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { createAuthenticatedAction } from "@/modules/actions/utils/createAction"
import { triggerNotifications } from "@/modules/notifications/utils/triggerNotification";
import { getRoles } from "@/modules/roles/queries";
import { RoleAssignmentChangeType } from "@prisma/client";
import { revalidatePath } from "next/cache";
import { z } from "zod";

export interface Change {
Expand Down Expand Up @@ -155,11 +154,6 @@ export const updateRoleAssignments = createAuthenticatedAction(
})),
);

/**
* Revalidate cache(s)
*/
revalidatePath("/app/account/notifications");

return {
success: t("Common.successfullySaved"),
};
Expand Down
6 changes: 3 additions & 3 deletions app/src/modules/citizen/components/CitizenInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import Button from "@/modules/common/components/Button";
import { CitizenLink } from "@/modules/common/components/CitizenLink";
import { underlineCharacters } from "@/modules/common/utils/underlineCharacters";
import { SingleRole } from "@/modules/roles/components/SingleRole";
import { SingleRoleBadge } from "@/modules/roles/components/SingleRoleBadge";
import { api } from "@/trpc/react";
import {
Combobox,
Expand Down Expand Up @@ -283,8 +283,8 @@ const Multiple = ({
onClick={() => handleSelectRole(role.id)}
className="group"
>
<SingleRole
role={role}
<SingleRoleBadge
roleId={role.id}
showPlaceholder
className="bg-transparent group-hover:bg-neutral-700/50 group-focus-visible:bg-neutral-700/50"
/>
Expand Down
2 changes: 1 addition & 1 deletion app/src/modules/citizen/components/NotesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export const NotesTable = ({ rows, searchParams }: Props) => {
</td>

<td
className="overflow-hidden text-ellipsis whitespace-nowrap"
className="truncate"
title={row.entityLog.content || undefined}
>
{row.entityLog.content}
Expand Down
4 changes: 2 additions & 2 deletions app/src/modules/citizen/components/OtherTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,14 @@ export const OtherTable = ({ rows, searchParams }: Props) => {
</td>

<td
className="overflow-hidden text-ellipsis whitespace-nowrap"
className="truncate"
title={entityLogTypeTranslations[row.entityLog.type]}
>
{entityLogTypeTranslations[row.entityLog.type]}
</td>

<td
className="overflow-hidden text-ellipsis whitespace-nowrap"
className="truncate"
title={row.entityLog.content || undefined}
>
{row.entityLog.content}
Expand Down
8 changes: 6 additions & 2 deletions app/src/modules/citizen/components/ProfileTile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { requireAuthentication } from "@/modules/auth/server";
import Avatar from "@/modules/common/components/Avatar";
import { Link } from "@/modules/common/components/Link";
import { getPenaltyEntriesOfCurrentUser } from "@/modules/penalty-points/queries";
import { SingleRole } from "@/modules/roles/components/SingleRole";
import { SingleRoleBadge } from "@/modules/roles/components/SingleRoleBadge";
import { getMyAssignedRoles } from "@/modules/roles/utils/getRoles";
import {
getMonthlySalaryOfCurrentCitizen,
Expand Down Expand Up @@ -61,7 +61,11 @@ export const ProfileTile = async ({ className }: Props) => {
{roles.length > 0 && (
<div className="flex gap-1 flex-wrap justify-center">
{roles.map((role) => (
<SingleRole key={role.id} role={role} />
<SingleRoleBadge
key={role.id}
roleId={role.id}
citizenId={authentication.session.entity?.id}
/>
))}
</div>
)}
Expand Down
8 changes: 6 additions & 2 deletions app/src/modules/citizen/components/RolesCell.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { requireAuthentication } from "@/modules/auth/server";
import { AddRoles } from "@/modules/citizen/components/roles/AddRoles";
import { SingleRole } from "@/modules/roles/components/SingleRole";
import { SingleRoleBadge } from "@/modules/roles/components/SingleRoleBadge";
import { getAssignedRoles } from "@/modules/roles/utils/getRoles";
import {
type Entity,
Expand Down Expand Up @@ -48,7 +48,11 @@ export const RolesCell = async ({
{roles.length > 0 ? (
<div className={clsx("flex gap-1", className)}>
{roles.map((role) => (
<SingleRole key={role.id} role={role} />
<SingleRoleBadge
key={role.id}
roleId={role.id}
citizenId={entity.id}
/>
))}
</div>
) : (
Expand Down
Loading
Loading