Added autoFocus on Sds and MissionLog
This commit is contained in:
@@ -14,32 +14,5 @@ export const handleConnectDesktop = (socket: Socket, io: Server) => () => {
|
|||||||
|
|
||||||
socket.on("ptt", async (data: PTTData) => {
|
socket.on("ptt", async (data: PTTData) => {
|
||||||
socket.to(`user:${user.id}`).emit("ptt", data);
|
socket.to(`user:${user.id}`).emit("ptt", data);
|
||||||
const connectedAircraft = await prisma.connectedAircraft.findFirst({
|
|
||||||
where: {
|
|
||||||
userId: user.id,
|
|
||||||
logoutTime: null,
|
|
||||||
},
|
|
||||||
include: {
|
|
||||||
Station: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const connectedDispatcher = await prisma.connectedDispatcher.findFirst({
|
|
||||||
where: {
|
|
||||||
userId: user.id,
|
|
||||||
logoutTime: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const otherPttData = {
|
|
||||||
publicUser: getPublicUser(user),
|
|
||||||
source:
|
|
||||||
connectedAircraft?.Station.bosCallsignShort || connectedDispatcher
|
|
||||||
? "Leitstelle"
|
|
||||||
: user.publicId,
|
|
||||||
};
|
|
||||||
if (data.shouldTransmit) {
|
|
||||||
socket.to("dispatchers").emit("other-ptt", otherPttData);
|
|
||||||
socket.to("pilots").emit("other-ptt", otherPttData);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -112,22 +112,6 @@ export const handleConnectPilot =
|
|||||||
connectedAircraftEntry,
|
connectedAircraftEntry,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add a listener for station-specific events
|
|
||||||
socket.on("ptt", async ({ shouldTransmit, channel }) => {
|
|
||||||
if (shouldTransmit) {
|
|
||||||
io.to("dispatchers").emit("other-ptt", {
|
|
||||||
publicUser: getPublicUser(user),
|
|
||||||
channel,
|
|
||||||
source: Station?.bosCallsignShort,
|
|
||||||
});
|
|
||||||
io.to("piots").emit("other-ptt", {
|
|
||||||
publicUser: getPublicUser(user),
|
|
||||||
channel,
|
|
||||||
source: Station?.bosCallsignShort,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("disconnect", async () => {
|
socket.on("disconnect", async () => {
|
||||||
await prisma.connectedAircraft
|
await prisma.connectedAircraft
|
||||||
.update({
|
.update({
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
|
|||||||
|
|
||||||
export const SituationBoard = () => {
|
export const SituationBoard = () => {
|
||||||
const { setSituationTabOpen, situationTabOpen } = useLeftMenuStore();
|
const { setSituationTabOpen, situationTabOpen } = useLeftMenuStore();
|
||||||
const dispatcherConnected = useDispatchConnectionStore((state) => state.status === "connected");
|
const { status, setHideDraftMissions, hideDraftMissions } = useDispatchConnectionStore(
|
||||||
|
(state) => state,
|
||||||
|
);
|
||||||
|
const dispatcherConnected = status === "connected";
|
||||||
|
|
||||||
const { data: missions } = useQuery({
|
const { data: missions } = useQuery({
|
||||||
queryKey: ["missions", "missions-on-stations"],
|
queryKey: ["missions", "missions-on-stations"],
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
@@ -34,6 +38,11 @@ export const SituationBoard = () => {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const filteredMissions = missions?.filter(
|
||||||
|
(mission) => !hideDraftMissions || mission.state !== "draft",
|
||||||
|
);
|
||||||
|
|
||||||
const { data: connectedAircrafts } = useQuery({
|
const { data: connectedAircrafts } = useQuery({
|
||||||
queryKey: ["aircrafts"],
|
queryKey: ["aircrafts"],
|
||||||
queryFn: () => getConnectedAircraftsAPI(),
|
queryFn: () => getConnectedAircraftsAPI(),
|
||||||
@@ -60,8 +69,21 @@ export const SituationBoard = () => {
|
|||||||
<div className="card-body flex flex-row gap-4">
|
<div className="card-body flex flex-row gap-4">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h2 className="inline-flex items-center gap-2 text-lg font-bold mb-2">
|
<h2 className="inline-flex items-center gap-2 text-lg font-bold mb-2">
|
||||||
<ListCollapse /> Einsatzliste
|
<ListCollapse /> Einsatzliste{" "}
|
||||||
</h2>
|
</h2>
|
||||||
|
<div>
|
||||||
|
<div className="form-control mb-2">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="checkbox checkbox-sm"
|
||||||
|
checked={hideDraftMissions}
|
||||||
|
onChange={() => setHideDraftMissions(!hideDraftMissions)}
|
||||||
|
/>
|
||||||
|
<span className="label-text text-sm">vorgeplante Einsätze verbergen</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="overflow-x-auto">
|
<div className="overflow-x-auto">
|
||||||
<table className="table table-xs">
|
<table className="table table-xs">
|
||||||
{/* head */}
|
{/* head */}
|
||||||
@@ -74,8 +96,7 @@ export const SituationBoard = () => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{/* row 1 */}
|
{filteredMissions?.map(
|
||||||
{missions?.map(
|
|
||||||
(mission) =>
|
(mission) =>
|
||||||
(dispatcherConnected || mission.state !== "draft") && (
|
(dispatcherConnected || mission.state !== "draft") && (
|
||||||
<tr
|
<tr
|
||||||
|
|||||||
@@ -365,7 +365,9 @@ const MissionMarker = ({ mission }: { mission: Mission }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const MissionLayer = () => {
|
export const MissionLayer = () => {
|
||||||
const dispatcherConnected = useDispatchConnectionStore((s) => s.status) === "connected";
|
const dispatchState = useDispatchConnectionStore((s) => s);
|
||||||
|
const dispatcherConnected = dispatchState.status === "connected";
|
||||||
|
|
||||||
const { data: missions = [] } = useQuery({
|
const { data: missions = [] } = useQuery({
|
||||||
queryKey: ["missions"],
|
queryKey: ["missions"],
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
@@ -377,10 +379,15 @@ export const MissionLayer = () => {
|
|||||||
|
|
||||||
const filteredMissions = useMemo(() => {
|
const filteredMissions = useMemo(() => {
|
||||||
if (!dispatcherConnected) {
|
if (!dispatcherConnected) {
|
||||||
return missions.filter((m: Mission) => m.state === "running");
|
return missions.filter((m: Mission) => {
|
||||||
|
m.state === "running";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (dispatchState.hideDraftMissions) {
|
||||||
|
return missions.filter((m: Mission) => m.state !== "draft");
|
||||||
}
|
}
|
||||||
return missions;
|
return missions;
|
||||||
}, [missions, dispatcherConnected]);
|
}, [missions, dispatcherConnected, dispatchState.hideDraftMissions]);
|
||||||
|
|
||||||
// IDEA: Add Marker to Map Layer / LayerGroup
|
// IDEA: Add Marker to Map Layer / LayerGroup
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -334,6 +334,7 @@ const SDSTab = ({
|
|||||||
const [isChatOpen, setIsChatOpen] = useState(false);
|
const [isChatOpen, setIsChatOpen] = useState(false);
|
||||||
const [note, setNote] = useState("");
|
const [note, setNote] = useState("");
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
const textInputRef = React.useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const dispatcherConnected = useDispatchConnectionStore((s) => s.status) === "connected";
|
const dispatcherConnected = useDispatchConnectionStore((s) => s.status) === "connected";
|
||||||
|
|
||||||
@@ -352,13 +353,23 @@ const SDSTab = ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const log =
|
const log = useMemo(
|
||||||
(mission?.missionLog as unknown as MissionLog[])
|
() =>
|
||||||
?.slice()
|
(mission?.missionLog as unknown as MissionLog[])
|
||||||
.reverse()
|
?.slice()
|
||||||
.filter(
|
.reverse()
|
||||||
(entry) => entry.type === "sds-log" && entry.data.stationId === aircraft.Station.id,
|
.filter(
|
||||||
) || [];
|
(entry) => entry.type === "sds-log" && entry.data.stationId === aircraft.Station.id,
|
||||||
|
) || [],
|
||||||
|
[mission?.missionLog, aircraft.Station.id],
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
textInputRef.current?.focus();
|
||||||
|
}, 100);
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
@@ -377,11 +388,13 @@ const SDSTab = ({
|
|||||||
) : (
|
) : (
|
||||||
<div className="flex items-center gap-2 w-full">
|
<div className="flex items-center gap-2 w-full">
|
||||||
<input
|
<input
|
||||||
|
autoFocus
|
||||||
type="text"
|
type="text"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
className="input input-sm text-base-content flex-1"
|
className="input input-sm text-base-content flex-1"
|
||||||
value={note}
|
value={note}
|
||||||
onChange={(e) => setNote(e.target.value)}
|
onChange={(e) => setNote(e.target.value)}
|
||||||
|
ref={textInputRef}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-primary btn-outline"
|
className="btn btn-sm btn-primary btn-outline"
|
||||||
|
|||||||
@@ -591,6 +591,7 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => {
|
|||||||
const [isAddingNote, setIsAddingNote] = useState(false);
|
const [isAddingNote, setIsAddingNote] = useState(false);
|
||||||
const [note, setNote] = useState("");
|
const [note, setNote] = useState("");
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
const textInputRef = React.useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const dispatcherConnected = useDispatchConnectionStore((s) => s.status) === "connected";
|
const dispatcherConnected = useDispatchConnectionStore((s) => s.status) === "connected";
|
||||||
|
|
||||||
@@ -603,6 +604,13 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
textInputRef.current?.focus();
|
||||||
|
}, 100);
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
});
|
||||||
|
|
||||||
if (!session.data?.user) return null;
|
if (!session.data?.user) return null;
|
||||||
return (
|
return (
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
@@ -626,6 +634,7 @@ const FMSStatusHistory = ({ mission }: { mission: Mission }) => {
|
|||||||
className="input input-sm text-base-content flex-1"
|
className="input input-sm text-base-content flex-1"
|
||||||
value={note}
|
value={note}
|
||||||
onChange={(e) => setNote(e.target.value)}
|
onChange={(e) => setNote(e.target.value)}
|
||||||
|
ref={textInputRef}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-primary btn-outline"
|
className="btn btn-sm btn-primary btn-outline"
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import { ConnectedDispatcher } from "@repo/db";
|
|||||||
|
|
||||||
interface ConnectionStore {
|
interface ConnectionStore {
|
||||||
status: "connected" | "disconnected" | "connecting" | "error";
|
status: "connected" | "disconnected" | "connecting" | "error";
|
||||||
|
hideDraftMissions: boolean;
|
||||||
|
setHideDraftMissions: (hide: boolean) => void;
|
||||||
connectedDispatcher: ConnectedDispatcher | null;
|
connectedDispatcher: ConnectedDispatcher | null;
|
||||||
message: string;
|
message: string;
|
||||||
selectedZone: string;
|
selectedZone: string;
|
||||||
@@ -15,6 +17,8 @@ interface ConnectionStore {
|
|||||||
|
|
||||||
export const useDispatchConnectionStore = create<ConnectionStore>((set) => ({
|
export const useDispatchConnectionStore = create<ConnectionStore>((set) => ({
|
||||||
status: "disconnected",
|
status: "disconnected",
|
||||||
|
hideDraftMissions: false,
|
||||||
|
setHideDraftMissions: (hide) => set({ hideDraftMissions: hide }),
|
||||||
connectedDispatcher: null,
|
connectedDispatcher: null,
|
||||||
message: "",
|
message: "",
|
||||||
selectedZone: "LST_01",
|
selectedZone: "LST_01",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { useAudioStore } from "_store/audioStore";
|
|||||||
interface ConnectionStore {
|
interface ConnectionStore {
|
||||||
status: "connected" | "disconnected" | "connecting" | "error";
|
status: "connected" | "disconnected" | "connecting" | "error";
|
||||||
message: string;
|
message: string;
|
||||||
|
|
||||||
logoffTime: string;
|
logoffTime: string;
|
||||||
selectedStation: Station | null;
|
selectedStation: Station | null;
|
||||||
connectedAircraft: ConnectedAircraft | null;
|
connectedAircraft: ConnectedAircraft | null;
|
||||||
@@ -34,6 +35,7 @@ export const usePilotConnectionStore = create<ConnectionStore>((set) => ({
|
|||||||
selectedStation: null,
|
selectedStation: null,
|
||||||
connectedAircraft: null,
|
connectedAircraft: null,
|
||||||
activeMission: null,
|
activeMission: null,
|
||||||
|
|
||||||
connect: async (uid, stationId, logoffTime, station, user) =>
|
connect: async (uid, stationId, logoffTime, station, user) =>
|
||||||
new Promise((resolve) => {
|
new Promise((resolve) => {
|
||||||
set({
|
set({
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { BADGES, PublicUser } from "@repo/db";
|
import { asPublicUser, BADGES, PublicUser } from "@repo/db";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { Badge } from "_components/Badge/Badge";
|
import { Badge } from "_components/Badge/Badge";
|
||||||
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
|
import { getConnectedAircraftsAPI } from "_querys/aircrafts";
|
||||||
@@ -70,7 +70,7 @@ export const ConnectedDispatcher = () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div>{(d.publicUser as unknown as PublicUser)?.firstname}</div>
|
<div>{asPublicUser(d.publicUser).fullName}</div>
|
||||||
<div className="text-xs uppercase font-semibold opacity-60">{d.zone}</div>
|
<div className="text-xs uppercase font-semibold opacity-60">{d.zone}</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Reference in New Issue
Block a user