Sticky headers fix, added Heliports
This commit is contained in:
@@ -9,6 +9,7 @@ export default function Page() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PaginatedTable
|
<PaginatedTable
|
||||||
|
stickyHeaders
|
||||||
prismaModel="event"
|
prismaModel="event"
|
||||||
columns={
|
columns={
|
||||||
[
|
[
|
||||||
|
|||||||
13
apps/hub/app/(app)/admin/heliport/[id]/page.tsx
Normal file
13
apps/hub/app/(app)/admin/heliport/[id]/page.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { prisma } from "@repo/db";
|
||||||
|
import { HeliportForm } from "../_components/Form";
|
||||||
|
|
||||||
|
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
|
||||||
|
const { id } = await params;
|
||||||
|
const heliport = await prisma.heliport.findUnique({
|
||||||
|
where: {
|
||||||
|
id: parseInt(id),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!heliport) return <div>Heliport not found</div>;
|
||||||
|
return <HeliportForm heliport={heliport} />;
|
||||||
|
}
|
||||||
151
apps/hub/app/(app)/admin/heliport/_components/Form.tsx
Normal file
151
apps/hub/app/(app)/admin/heliport/_components/Form.tsx
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
"use client";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import { HeliportOptionalDefaultsSchema } from "@repo/db/zod";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { Heliport, HeliportType } from "@repo/db";
|
||||||
|
import { FileText, LocateIcon } from "lucide-react";
|
||||||
|
import { Input } from "../../../../_components/ui/Input";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { deleteHeliport, upsertHeliport } from "../action";
|
||||||
|
import { Button } from "../../../../_components/ui/Button";
|
||||||
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
|
export const HeliportForm = ({ heliport }: { heliport?: Heliport }) => {
|
||||||
|
const form = useForm({
|
||||||
|
resolver: zodResolver(HeliportOptionalDefaultsSchema),
|
||||||
|
defaultValues: heliport,
|
||||||
|
});
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [deleteLoading, setDeleteLoading] = useState(false);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<form
|
||||||
|
onSubmit={form.handleSubmit(async (values) => {
|
||||||
|
setLoading(true);
|
||||||
|
await upsertHeliport(values, heliport?.id);
|
||||||
|
setLoading(false);
|
||||||
|
if (!heliport) redirect(`/admin/Heliport`);
|
||||||
|
})}
|
||||||
|
className="flex flex-wrap gap-3"
|
||||||
|
>
|
||||||
|
<div className="card bg-base-200 shadow-xl flex-1 basis-[300px]">
|
||||||
|
<div className="card-body">
|
||||||
|
<h2 className="card-title">
|
||||||
|
<FileText className="w-5 h-5" /> Allgemeines
|
||||||
|
</h2>
|
||||||
|
<label className="form-control w-full">
|
||||||
|
<select
|
||||||
|
className="input-sm select select-bordered select-sm w-full"
|
||||||
|
{...form.register("type")}
|
||||||
|
>
|
||||||
|
{Object.keys(HeliportType).map((use) => (
|
||||||
|
<option key={use} value={use}>
|
||||||
|
{use}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<Input form={form} label="Designator" name="designator" className="input-sm" />
|
||||||
|
<Input
|
||||||
|
form={form}
|
||||||
|
label="Designator (6 Zeichen)"
|
||||||
|
name="designatorSub6"
|
||||||
|
className="input-sm"
|
||||||
|
/>
|
||||||
|
<Input form={form} label="FIR" name="fir" className="input-sm" />
|
||||||
|
<Input form={form} label="Name" name="siteName" className="input-sm" />
|
||||||
|
<Input
|
||||||
|
form={form}
|
||||||
|
label="Name (21 Zeichen)"
|
||||||
|
name="siteNameSub21"
|
||||||
|
className="input-sm"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
form={form}
|
||||||
|
label="Name (26 Zeichen)"
|
||||||
|
name="siteNameSub26"
|
||||||
|
className="input-sm"
|
||||||
|
/>
|
||||||
|
<textarea
|
||||||
|
className="textarea textarea-bordered textarea-sm w-full"
|
||||||
|
{...form.register("info")}
|
||||||
|
placeholder="Info"
|
||||||
|
/>
|
||||||
|
<Input form={form} label="Krankenhaus" name="hospital" className="input-sm" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="card bg-base-200 shadow-xl flex-1 basis-[300px]">
|
||||||
|
<div className="card-body">
|
||||||
|
<h2 className="card-title">
|
||||||
|
<LocateIcon className="w-5 h-5" /> Standort
|
||||||
|
</h2>
|
||||||
|
<Input form={form} label="Bundesland (voller Name)" name="state" className="input-sm" />
|
||||||
|
<Input
|
||||||
|
form={form}
|
||||||
|
label="Bundesland (2 Zeichen)"
|
||||||
|
name="stateShort"
|
||||||
|
className="input-sm"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
form={form}
|
||||||
|
formOptions={{
|
||||||
|
valueAsNumber: true,
|
||||||
|
value: null,
|
||||||
|
}}
|
||||||
|
label="Elevation"
|
||||||
|
name="siteElevation"
|
||||||
|
className="input-sm"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
form={form}
|
||||||
|
label="Elevation Einheit"
|
||||||
|
name="siteElevationUnit"
|
||||||
|
className="input-sm"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
form={form}
|
||||||
|
formOptions={{
|
||||||
|
valueAsNumber: true,
|
||||||
|
}}
|
||||||
|
label="Latitude"
|
||||||
|
name="lat"
|
||||||
|
className="input-sm"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
form={form}
|
||||||
|
formOptions={{
|
||||||
|
valueAsNumber: true,
|
||||||
|
}}
|
||||||
|
label="Longitude"
|
||||||
|
name="lng"
|
||||||
|
className="input-sm"
|
||||||
|
/>
|
||||||
|
<Input form={form} label="Land (2 Zeichen)" name="country" className="input-sm" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="card bg-base-200 shadow-xl flex-[100%]">
|
||||||
|
<div className="card-body ">
|
||||||
|
<div className="flex w-full gap-4">
|
||||||
|
<Button isLoading={loading} type="submit" className="btn btn-primary flex-1">
|
||||||
|
Speichern
|
||||||
|
</Button>
|
||||||
|
{heliport && (
|
||||||
|
<Button
|
||||||
|
isLoading={deleteLoading}
|
||||||
|
onClick={async () => {
|
||||||
|
setDeleteLoading(true);
|
||||||
|
await deleteHeliport(heliport.id);
|
||||||
|
redirect("/admin/Heliport");
|
||||||
|
}}
|
||||||
|
className="btn btn-error"
|
||||||
|
>
|
||||||
|
Löschen
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
17
apps/hub/app/(app)/admin/heliport/action.ts
Normal file
17
apps/hub/app/(app)/admin/heliport/action.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import { prisma, Prisma, Heliport } from "@repo/db";
|
||||||
|
|
||||||
|
export const upsertHeliport = async (heliport: Prisma.HeliportCreateInput, id?: Heliport["id"]) => {
|
||||||
|
const newHeliport = id
|
||||||
|
? await prisma.heliport.update({
|
||||||
|
where: { id: id },
|
||||||
|
data: heliport,
|
||||||
|
})
|
||||||
|
: await prisma.heliport.create({ data: heliport });
|
||||||
|
return newHeliport;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteHeliport = async (id: Heliport["id"]) => {
|
||||||
|
await prisma.heliport.delete({ where: { id: id } });
|
||||||
|
};
|
||||||
19
apps/hub/app/(app)/admin/heliport/layout.tsx
Normal file
19
apps/hub/app/(app)/admin/heliport/layout.tsx
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { Error } from "_components/Error";
|
||||||
|
import { getServerSession } from "api/auth/[...nextauth]/auth";
|
||||||
|
|
||||||
|
const AdminStationLayout = async ({ children }: { children: React.ReactNode }) => {
|
||||||
|
const session = await getServerSession();
|
||||||
|
|
||||||
|
if (!session) return <Error title="Nicht eingeloggt" statusCode={401} />;
|
||||||
|
|
||||||
|
const user = session.user;
|
||||||
|
|
||||||
|
if (!user?.permissions.includes("ADMIN_HELIPORT"))
|
||||||
|
return <Error title="Keine Berechtigung" statusCode={403} />;
|
||||||
|
|
||||||
|
return <>{children}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
AdminStationLayout.displayName = "AdminStationLayout";
|
||||||
|
|
||||||
|
export default AdminStationLayout;
|
||||||
5
apps/hub/app/(app)/admin/heliport/new/page.tsx
Normal file
5
apps/hub/app/(app)/admin/heliport/new/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { HeliportForm } from "../_components/Form";
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return <HeliportForm />;
|
||||||
|
};
|
||||||
63
apps/hub/app/(app)/admin/heliport/page.tsx
Normal file
63
apps/hub/app/(app)/admin/heliport/page.tsx
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
"use client";
|
||||||
|
import { DatabaseBackupIcon } from "lucide-react";
|
||||||
|
import { PaginatedTable } from "../../../_components/PaginatedTable";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { ColumnDef } from "@tanstack/react-table";
|
||||||
|
import { Heliport } from "@repo/db";
|
||||||
|
|
||||||
|
const page = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PaginatedTable
|
||||||
|
stickyHeaders
|
||||||
|
prismaModel="heliport"
|
||||||
|
searchFields={["siteName", "info", "hospital"]}
|
||||||
|
columns={
|
||||||
|
[
|
||||||
|
{
|
||||||
|
header: "Typ",
|
||||||
|
accessorKey: "type",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "designator",
|
||||||
|
header: "Designator",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: "Name",
|
||||||
|
accessorKey: "siteName",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
header: "Name (21 zeichen)",
|
||||||
|
accessorKey: "siteNameSub21",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
header: "Aktionen",
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<Link href={`/admin/heliport/${row.original.id}`}>
|
||||||
|
<button className="btn btn-sm">Edit</button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
] as ColumnDef<Heliport>[]
|
||||||
|
}
|
||||||
|
leftOfSearch={
|
||||||
|
<span className="flex items-center gap-2">
|
||||||
|
<DatabaseBackupIcon className="w-5 h-5" /> Heliports
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
rightOfSearch={
|
||||||
|
<p className="text-2xl font-semibold text-left flex items-center gap-2 justify-between">
|
||||||
|
<Link href={"/admin/heliport/new"}>
|
||||||
|
<button className="btn btn-sm btn-outline btn-primary">Erstellen</button>
|
||||||
|
</Link>
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default page;
|
||||||
@@ -9,6 +9,7 @@ export default () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PaginatedTable
|
<PaginatedTable
|
||||||
|
stickyHeaders
|
||||||
initialOrderBy={[{ id: "category", desc: true }]}
|
initialOrderBy={[{ id: "category", desc: true }]}
|
||||||
prismaModel="keyword"
|
prismaModel="keyword"
|
||||||
searchFields={["name", "abreviation", "description"]}
|
searchFields={["name", "abreviation", "description"]}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export default function ReportPage() {
|
|||||||
return (
|
return (
|
||||||
<PaginatedTable
|
<PaginatedTable
|
||||||
prismaModel="penalty"
|
prismaModel="penalty"
|
||||||
|
stickyHeaders
|
||||||
include={{
|
include={{
|
||||||
CreatedUser: true,
|
CreatedUser: true,
|
||||||
Report: true,
|
Report: true,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export default function ReportPage() {
|
|||||||
<PaginatedTable
|
<PaginatedTable
|
||||||
initialOrderBy={[{ id: "timestamp", desc: true }]}
|
initialOrderBy={[{ id: "timestamp", desc: true }]}
|
||||||
prismaModel="report"
|
prismaModel="report"
|
||||||
|
stickyHeaders
|
||||||
include={{
|
include={{
|
||||||
Sender: true,
|
Sender: true,
|
||||||
Reported: true,
|
Reported: true,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const page = () => {
|
|||||||
<PaginatedTable
|
<PaginatedTable
|
||||||
prismaModel="station"
|
prismaModel="station"
|
||||||
searchFields={["bosCallsign", "operator"]}
|
searchFields={["bosCallsign", "operator"]}
|
||||||
|
stickyHeaders
|
||||||
columns={
|
columns={
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -176,7 +176,14 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({ user }: ProfileFormPro
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
form.setValue(
|
form.setValue(
|
||||||
"permissions",
|
"permissions",
|
||||||
["LOGIN_NEXTCLOUD", "PILOT", "DISPO", "AUDIO", "ADMIN_EVENT"],
|
[
|
||||||
|
"LOGIN_NEXTCLOUD",
|
||||||
|
"PILOT",
|
||||||
|
"DISPO",
|
||||||
|
"AUDIO",
|
||||||
|
"ADMIN_EVENT",
|
||||||
|
"ADMIN_HELIPORT",
|
||||||
|
],
|
||||||
{
|
{
|
||||||
shouldDirty: true,
|
shouldDirty: true,
|
||||||
},
|
},
|
||||||
@@ -191,7 +198,15 @@ export const ProfileForm: React.FC<ProfileFormProps> = ({ user }: ProfileFormPro
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
form.setValue(
|
form.setValue(
|
||||||
"permissions",
|
"permissions",
|
||||||
["LOGIN_NEXTCLOUD", "PILOT", "DISPO", "AUDIO", "ADMIN_KICK", "ADMIN_USER"],
|
[
|
||||||
|
"LOGIN_NEXTCLOUD",
|
||||||
|
"PILOT",
|
||||||
|
"DISPO",
|
||||||
|
"AUDIO",
|
||||||
|
"ADMIN_KICK",
|
||||||
|
"ADMIN_USER",
|
||||||
|
"ADMIN_HELIPORT",
|
||||||
|
],
|
||||||
{
|
{
|
||||||
shouldDirty: true,
|
shouldDirty: true,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ export default async function Page({ params }: { params: Promise<{ id: string }>
|
|||||||
total60Days: totalReports60Days,
|
total60Days: totalReports60Days,
|
||||||
};
|
};
|
||||||
if (!user) return <Error statusCode={404} title="User not found" />;
|
if (!user) return <Error statusCode={404} title="User not found" />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-6 gap-4">
|
<div className="grid grid-cols-6 gap-4">
|
||||||
<div className="col-span-full flex justify-between items-center">
|
<div className="col-span-full flex justify-between items-center">
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const AdminUserPage = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PaginatedTable
|
<PaginatedTable
|
||||||
|
stickyHeaders
|
||||||
prismaModel="user"
|
prismaModel="user"
|
||||||
searchFields={["publicId", "firstname", "lastname", "email"]}
|
searchFields={["publicId", "firstname", "lastname", "email"]}
|
||||||
initialOrderBy={[
|
initialOrderBy={[
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ export const VerticalNav = async () => {
|
|||||||
<Link href="/admin/keyword">Stichworte</Link>
|
<Link href="/admin/keyword">Stichworte</Link>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
|
{session.user.permissions.includes("ADMIN_HELIPORT") && (
|
||||||
|
<li>
|
||||||
|
<Link href="/admin/heliport">Heliports</Link>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
{session.user.permissions.includes("ADMIN_EVENT") && (
|
{session.user.permissions.includes("ADMIN_EVENT") && (
|
||||||
<li>
|
<li>
|
||||||
<Link href="/admin/event">Events</Link>
|
<Link href="/admin/event">Events</Link>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useState, Ref, useImperativeHandle, useEffect, useCallback } from "reac
|
|||||||
import SortableTable, { Pagination, RowsPerPage, SortableTableProps } from "./Table";
|
import SortableTable, { Pagination, RowsPerPage, SortableTableProps } from "./Table";
|
||||||
import { PrismaClient } from "@repo/db";
|
import { PrismaClient } from "@repo/db";
|
||||||
import { getData } from "./pagiantedTableActions";
|
import { getData } from "./pagiantedTableActions";
|
||||||
import { useDebounce } from "@repo/shared-components";
|
import { cn, useDebounce } from "@repo/shared-components";
|
||||||
|
|
||||||
export interface PaginatedTableRef {
|
export interface PaginatedTableRef {
|
||||||
refresh: () => void;
|
refresh: () => void;
|
||||||
@@ -11,6 +11,7 @@ export interface PaginatedTableRef {
|
|||||||
|
|
||||||
interface PaginatedTableProps<TData> extends Omit<SortableTableProps<TData>, "data"> {
|
interface PaginatedTableProps<TData> extends Omit<SortableTableProps<TData>, "data"> {
|
||||||
prismaModel: keyof PrismaClient;
|
prismaModel: keyof PrismaClient;
|
||||||
|
stickyHeaders?: boolean;
|
||||||
filter?: Record<string, unknown>;
|
filter?: Record<string, unknown>;
|
||||||
initialRowsPerPage?: number;
|
initialRowsPerPage?: number;
|
||||||
searchFields?: string[];
|
searchFields?: string[];
|
||||||
@@ -31,6 +32,7 @@ export function PaginatedTable<TData>({
|
|||||||
include,
|
include,
|
||||||
ref,
|
ref,
|
||||||
strictQuery = false,
|
strictQuery = false,
|
||||||
|
stickyHeaders = false,
|
||||||
leftOfSearch,
|
leftOfSearch,
|
||||||
rightOfSearch,
|
rightOfSearch,
|
||||||
leftOfPagination,
|
leftOfPagination,
|
||||||
@@ -110,7 +112,7 @@ export function PaginatedTable<TData>({
|
|||||||
// useEffect to show loading spinner
|
// useEffect to show loading spinner
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
}, [searchTerm, page, rowsPerPage, orderBy, filter, setLoading, refreshTableData]);
|
}, [searchTerm, page, rowsPerPage, orderBy, filter, setLoading]);
|
||||||
|
|
||||||
useDebounce(
|
useDebounce(
|
||||||
() => {
|
() => {
|
||||||
@@ -122,7 +124,13 @@ export function PaginatedTable<TData>({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4 m-4">
|
<div className="space-y-4 m-4">
|
||||||
<div className="flex items-center gap-2">
|
{(rightOfSearch || leftOfSearch || searchFields.length > 0) && (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"flex items-center gap-2 sticky py-2 z-20",
|
||||||
|
stickyHeaders && "sticky top-0 bg-base-100/80 backdrop-blur border-b",
|
||||||
|
)}
|
||||||
|
>
|
||||||
<div className="flex-1 flex gap-2">
|
<div className="flex-1 flex gap-2">
|
||||||
<div>{leftOfSearch}</div>
|
<div>{leftOfSearch}</div>
|
||||||
<div>{loading && <span className="loading loading-dots loading-md" />}</div>
|
<div>{loading && <span className="loading loading-dots loading-md" />}</div>
|
||||||
@@ -141,6 +149,7 @@ export function PaginatedTable<TData>({
|
|||||||
)}
|
)}
|
||||||
<div className="flex justify-center">{rightOfSearch}</div>
|
<div className="flex justify-center">{rightOfSearch}</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
{!hide && (
|
{!hide && (
|
||||||
<SortableTable
|
<SortableTable
|
||||||
data={data}
|
data={data}
|
||||||
|
|||||||
25
packages/database/prisma/schema/heliports.prisma
Normal file
25
packages/database/prisma/schema/heliports.prisma
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
enum HeliportType {
|
||||||
|
HELIPAD
|
||||||
|
POI
|
||||||
|
MOUNTAIN
|
||||||
|
}
|
||||||
|
|
||||||
|
model Heliport {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
type HeliportType
|
||||||
|
designator String
|
||||||
|
designatorSub6 String
|
||||||
|
fir String
|
||||||
|
state String
|
||||||
|
stateShort String
|
||||||
|
siteName String
|
||||||
|
siteNameSub26 String
|
||||||
|
siteNameSub21 String
|
||||||
|
siteElevation Float?
|
||||||
|
siteElevationUnit String?
|
||||||
|
info String?
|
||||||
|
lat Float
|
||||||
|
lng Float
|
||||||
|
country Country
|
||||||
|
hospital String?
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "Heliport" (
|
||||||
|
"id" SERIAL NOT NULL,
|
||||||
|
"state" TEXT NOT NULL,
|
||||||
|
"stateShort" TEXT NOT NULL,
|
||||||
|
"siteName" TEXT NOT NULL,
|
||||||
|
"siteNameSub26" TEXT NOT NULL,
|
||||||
|
"siteNameSub21" TEXT NOT NULL,
|
||||||
|
"siteElevation" DOUBLE PRECISION NOT NULL,
|
||||||
|
"siteElevationUnit" TEXT NOT NULL,
|
||||||
|
"info" TEXT NOT NULL,
|
||||||
|
"lat" DOUBLE PRECISION NOT NULL,
|
||||||
|
"lng" DOUBLE PRECISION NOT NULL,
|
||||||
|
"country" TEXT NOT NULL,
|
||||||
|
"hospital" TEXT NOT NULL,
|
||||||
|
|
||||||
|
CONSTRAINT "Heliport_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- AlterEnum
|
||||||
|
ALTER TYPE "PERMISSION" ADD VALUE 'ADMIN_HELIPORT';
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- Added the required column `type` to the `Heliport` table without a default value. This is not possible if the table is not empty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "HeliportType" AS ENUM ('HELIPORT', 'POI');
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Heliport" ADD COLUMN "type" "HeliportType" NOT NULL;
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- Added the required column `designator` to the `Heliport` table without a default value. This is not possible if the table is not empty.
|
||||||
|
- Added the required column `designator_sub6` to the `Heliport` table without a default value. This is not possible if the table is not empty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Heliport" ADD COLUMN "designator" TEXT NOT NULL,
|
||||||
|
ADD COLUMN "designator_sub6" TEXT NOT NULL;
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the column `designator_sub6` on the `Heliport` table. All the data in the column will be lost.
|
||||||
|
- Added the required column `designatorSub6` to the `Heliport` table without a default value. This is not possible if the table is not empty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Heliport" DROP COLUMN "designator_sub6",
|
||||||
|
ADD COLUMN "designatorSub6" TEXT NOT NULL;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- Added the required column `fir` to the `Heliport` table without a default value. This is not possible if the table is not empty.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Heliport" ADD COLUMN "fir" TEXT NOT NULL;
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- The values [HELIPORT] on the enum `HeliportType` will be removed. If these variants are still used in the database, this will fail.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterEnum
|
||||||
|
BEGIN;
|
||||||
|
CREATE TYPE "HeliportType_new" AS ENUM ('HELIPAD', 'POI');
|
||||||
|
ALTER TABLE "Heliport" ALTER COLUMN "type" TYPE "HeliportType_new" USING ("type"::text::"HeliportType_new");
|
||||||
|
ALTER TYPE "HeliportType" RENAME TO "HeliportType_old";
|
||||||
|
ALTER TYPE "HeliportType_new" RENAME TO "HeliportType";
|
||||||
|
DROP TYPE "HeliportType_old";
|
||||||
|
COMMIT;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Heliport" ALTER COLUMN "siteElevation" DROP NOT NULL,
|
||||||
|
ALTER COLUMN "siteElevationUnit" DROP NOT NULL,
|
||||||
|
ALTER COLUMN "info" DROP NOT NULL,
|
||||||
|
ALTER COLUMN "hospital" DROP NOT NULL;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- AlterEnum
|
||||||
|
ALTER TYPE "HeliportType" ADD VALUE 'MOUNTAIN';
|
||||||
@@ -17,6 +17,7 @@ enum PERMISSION {
|
|||||||
ADMIN_KEYWORD
|
ADMIN_KEYWORD
|
||||||
ADMIN_MESSAGE
|
ADMIN_MESSAGE
|
||||||
ADMIN_KICK
|
ADMIN_KICK
|
||||||
|
ADMIN_HELIPORT
|
||||||
AUDIO
|
AUDIO
|
||||||
PILOT
|
PILOT
|
||||||
DISPO
|
DISPO
|
||||||
|
|||||||
Reference in New Issue
Block a user