Skip to content

Commit

Permalink
Add publishing and draft states to static elements
Browse files Browse the repository at this point in the history
  • Loading branch information
cr0wst committed Feb 3, 2025
1 parent 352a645 commit ce7d876
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 12 deletions.
2 changes: 2 additions & 0 deletions src/lib/components/map/AirspaceMap.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
id: string;
name: string;
icon: MdiIconName;
isPublished: boolean;
components: {
id: string;
name: string;
Expand Down Expand Up @@ -699,6 +700,7 @@
icon: s.icon,
active: showStaticElements[s.id],
tooltip: `Toggle ${s.name}`,
isAdminOnly: !s.isPublished,
onClick: () => {
showStaticElements[s.id] = !showStaticElements[s.id];
}
Expand Down
9 changes: 7 additions & 2 deletions src/lib/components/map/MapMenu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
dividerBefore?: boolean;
dividerAfter?: boolean;
group?: string;
isAdminOnly?: boolean;
};
let { actions = [] } = $props<{ actions: MenuAction[] }>();
Expand All @@ -34,7 +35,9 @@
<button
type="button"
class={{
'flex items-center justify-center rounded-lg border border-accent px-4 py-2 text-sm font-medium transition duration-300 focus:outline-none': true,
'flex items-center justify-center rounded-lg px-4 py-2 text-sm font-medium transition duration-300 focus:outline-none': true,
'border border-accent': !action.isAdminOnly,
'border border-dashed border-accent/70': action.isAdminOnly,
'bg-accent text-white hover:bg-accent/90': action.active,
'bg-surface text-accent hover:bg-accent/10': !action.active,
'dark:bg-accent dark:text-white': action.active,
Expand All @@ -55,7 +58,9 @@
<button
type="button"
class={{
'flex items-center justify-center rounded-lg border border-accent px-4 py-2 text-sm font-medium transition duration-300 focus:outline-none': true,
'flex items-center justify-center rounded-lg px-4 py-2 text-sm font-medium transition duration-300 focus:outline-none': true,
'border border-accent': !action.isAdminOnly,
'border border-dashed border-accent/70': action.isAdminOnly,
'bg-accent text-white hover:bg-accent/90': action.active,
'bg-surface text-accent hover:bg-accent/10': !action.active,
'dark:bg-accent dark:text-white': action.active,
Expand Down
3 changes: 2 additions & 1 deletion src/lib/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ export type Restriction = InferSelectModel<typeof restrictionsTable> & {
export const airspaceStaticElementGroupsTable = pgTable('airspace_static_element_groups', {
id: uuid('id').primaryKey().defaultRandom(),
name: text('name'),
icon: text('icon')
icon: text('icon'),
isPublished: boolean('is_published').notNull().default(false)
});

export const airspaceStaticElementComponentsTable = pgTable('airspace_static_element_components', {
Expand Down
37 changes: 32 additions & 5 deletions src/routes/(protected)/admin/airspace/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import { db } from '$lib/server/db';
import { redirect } from '@sveltejs/kit';
import { eq } from 'drizzle-orm';
import { object, optional, string, nonempty, any, array, number } from 'superstruct';
import { object, optional, string, nonempty, any, array, number, boolean } from 'superstruct';
import { fail, message, superValidate } from 'sveltekit-superforms';
import { superstruct } from 'sveltekit-superforms/adapters';

Expand All @@ -29,14 +29,16 @@ const staticElementGroupSchema = object({
id: optional(string()),
name: nonempty(string()),
icon: nonempty(string()),
components: array(staticElementComponentSchema)
components: array(staticElementComponentSchema),
isPublished: optional(boolean())
});

const defaults = {
id: '',
name: '',
icon: '',
components: []
components: [],
isPublished: false
};

const defaultSettings = {
Expand Down Expand Up @@ -96,6 +98,29 @@ export const actions = {
.where(eq(airspaceStaticElementGroupsTable.id, id));
return { success: true };
},

togglePublish: async ({ request }) => {
const formData = await request.formData();
const id = formData.get('id') as string;
const publish = formData.get('publish') === 'true';

if (!id) {
return fail(400, { error: 'Static Element Group ID is required' });
}

try {
await db
.update(airspaceStaticElementGroupsTable)
.set({ isPublished: publish })
.where(eq(airspaceStaticElementGroupsTable.id, id));

return { success: true };
} catch (e) {
console.error('Error updating static element group publish status:', e);
return fail(500, { error: 'Failed to update static element group publish status' });
}
},

addUpdateStaticElements: async ({ request }) => {
const formData = await request.formData();
const form = await superValidate(formData, superstruct(staticElementGroupSchema, { defaults }));
Expand All @@ -113,7 +138,8 @@ export const actions = {
.update(airspaceStaticElementGroupsTable)
.set({
name: form.data.name,
icon: form.data.icon
icon: form.data.icon,
isPublished: form.data.isPublished
})
.where(eq(airspaceStaticElementGroupsTable.id, form.data.id!));
// Delete all components and re-add them instead of trying to merge
Expand All @@ -137,7 +163,8 @@ export const actions = {
.insert(airspaceStaticElementGroupsTable)
.values({
name: form.data.name,
icon: form.data.icon
icon: form.data.icon,
isPublished: form.data.isPublished
})
.returning();

Expand Down
36 changes: 33 additions & 3 deletions src/routes/(protected)/admin/airspace/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@
// Search query for filtering elements
let searchQuery = $state('');
type StaticElementComponent = {
id: string;
name: string;
color: string;
geojson: any;
settings: {
weight?: number;
opacity?: number;
lineCap?: string;
lineJoin?: string;
radius?: number;
fillOpacity?: number;
};
};
// Filtered elements derived from the search query
let filteredElements = $derived.by(() => {
return data.staticElements.filter((element) => {
Expand Down Expand Up @@ -89,7 +104,7 @@
Components ({element.components.length})
</div>
<div class="flex flex-wrap gap-2">
{#each element.components.filter((c): c is NonNullable<typeof c> => c !== null) as component}
{#each element.components.filter((c: StaticElementComponent | null): c is StaticElementComponent => c !== null) as component}
<div
class="inline-flex items-center rounded-md border border-surface-tertiary px-2 py-1 text-sm"
>
Expand All @@ -99,9 +114,9 @@
</div>
</div>

<!-- Footer with icon -->
<!-- Footer with icon and publish status -->
<div
class="flex items-center gap-2 border-t border-surface-tertiary p-4 dark:border-surface-dark-tertiary"
class="flex items-center justify-between gap-2 border-t border-surface-tertiary p-4 dark:border-surface-dark-tertiary"
>
<span
class="inline-flex items-center gap-2 rounded-md bg-surface-secondary px-3 py-1.5 text-sm font-medium text-content-secondary dark:bg-surface-dark-secondary dark:text-content-dark-secondary"
Expand All @@ -111,6 +126,21 @@
{/if}
{element.icon ?? 'No Icon'}
</span>

<form method="POST" action="?/togglePublish" class="flex-1 text-right">
<input type="hidden" name="id" value={element.id} />
<input type="hidden" name="publish" value={(!element.isPublished).toString()} />
<button
type="submit"
class={`rounded-md px-3 py-1.5 text-sm font-medium transition-all hover:shadow-sm focus:outline-none focus:ring-2 ${
element.isPublished
? 'bg-accent bg-opacity-10 text-accent hover:bg-opacity-20'
: 'bg-surface-secondary text-content-secondary hover:bg-surface-tertiary dark:bg-surface-dark-secondary dark:text-content-dark-secondary dark:hover:bg-surface-dark-tertiary'
}`}
>
{element.isPublished ? 'Published' : 'Draft'}
</button>
</form>
</div>
</div>
{/each}
Expand Down
8 changes: 7 additions & 1 deletion src/routes/airspace/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
airspaceStaticElementGroupsTable,
splitsTable
} from '$lib/db/schema';
import { eq, or } from 'drizzle-orm';
import { eq, or, and } from 'drizzle-orm';

type StaticElementGroup = {
id: string;
Expand All @@ -28,6 +28,12 @@ export async function load({ locals }) {
.leftJoin(
airspaceStaticElementComponentsTable,
eq(airspaceStaticElementGroupsTable.id, airspaceStaticElementComponentsTable.groupId)
)
.where(
or(
eq(airspaceStaticElementGroupsTable.isPublished, true),
locals.user && locals.user?.isAdmin === true
)
);

// Group results by static element groups and their components
Expand Down

0 comments on commit ce7d876

Please sign in to comment.