astro-integration-pocketbase
Version:
An Astro integration to support developers working with astro-loader-pocketbase.
254 lines (237 loc) • 7.1 kB
JavaScript
import { defineToolbarApp } from "astro/toolbar";
import { closeOnOutsideClick, createWindowElement, synchronizePlacementOnUpdate } from "astro/runtime/client/dev-toolbar/apps/utils/window.js";
//#region src/toolbar/dom/create-entity.ts
/**
* Creates cards for the entities.
*/
function createEntities(data, baseUrl) {
const groupedData = Object.groupBy(data, (data) => data.collectionName);
return `
<style>
.collectionName {
text-transform: capitalize;
}
.entity {
position: relative;
pre {
margin: 0;
overflow: auto;
}
astro-dev-toolbar-button {
position: absolute;
top: 0;
right: 0;
}
}
</style>
${Object.keys(groupedData).map((collection) => `
<b class=".collectionName">${collection}</b>
${groupedData[collection]?.map((entity) => createEntity(entity, baseUrl)).join("")}
`).join("")}
`;
}
/**
* Creates a card for a single entity
*/
function createEntity(data, baseUrl) {
return `
<astro-dev-toolbar-card>
<div class="entity">
<pre>${JSON.stringify(data, void 0, 2).replaceAll("<", "<")}</pre>
${baseUrl ? `
<astro-dev-toolbar-button
size="small"
button-style="purple"
title="View in PocketBase"
onclick="window.open('${baseUrl}/_/#/collections?collection=${data.collectionId}&record=${data.id}', '_blank')"
>
View in PocketBase
</astro-dev-toolbar-button>
` : ""}
</div>
</astro-dev-toolbar-card>
`;
}
//#endregion
//#region package.json
var version = "4.0.0";
//#endregion
//#region src/toolbar/dom/create-header.ts
/**
* Creates the header for the PocketBase toolbar.
*/
function createHeader(windowElement, server, { hasContentLoader, realtime }) {
const header = windowElement.querySelector("header");
if (!header) throw new Error("The header element is missing");
header.innerHTML = `
<style>
header {
display: grid;
grid-template-columns: auto auto 1fr;
gap: 0.5rem;
}
h1 {
display: flex;
align-items: center;
gap: 8px;
font-weight: 600;
color: #fff;
margin: 0;
font-size: 22px;
}
.actions {
display: flex;
align-items: start;
justify-content: flex-end;
gap: 0.25rem;
.toggle-container {
display: flex;
align-items: center;
label {
font-size: 0.8rem;
}
}
}
</style>
<h1>PocketBase</h1>
<astro-dev-toolbar-badge badge-style="yellow">
${version}
</astro-dev-toolbar-badge>
<div class="actions">
${realtime ? `
<div class="toggle-container">
<label
for="real-time"
title="Enable or disable real-time updates temporarily"
>
Real-time updates
</label>
<!-- real-time-toggle -->
</div>
` : ""}
${hasContentLoader ? `
<astro-dev-toolbar-button
id="refresh-content"
size="small"
button-style="green"
title="Right click to force refresh every collection"
>
Refresh content
</astro-dev-toolbar-button>
` : ""}
</div>
`;
if (realtime) {
const realTimeToggle = document.createElement("astro-dev-toolbar-toggle");
realTimeToggle.input.id = "real-time-toggle";
realTimeToggle.input.title = "Enable or disable real-time updates temporarily";
realTimeToggle.input.checked = !(localStorage.getItem("astro-integration-pocketbase:real-time") === "false");
realTimeToggle.input.addEventListener("change", () => {
localStorage.setItem("astro-integration-pocketbase:real-time", realTimeToggle.input.checked.toString());
server.send("astro-integration-pocketbase:real-time", realTimeToggle.input.checked);
});
server.send("astro-integration-pocketbase:real-time", realTimeToggle.input.checked);
windowElement.querySelector(".toggle-container")?.append(realTimeToggle);
}
if (hasContentLoader) {
const refresh = windowElement.querySelector("#refresh-content");
if (!refresh) throw new Error("The refresh button is missing");
refresh.addEventListener("click", () => {
server.send("astro-integration-pocketbase:refresh", { force: false });
});
refresh.addEventListener("contextmenu", (event) => {
event.preventDefault();
server.send("astro-integration-pocketbase:refresh", { force: true });
});
server.on("astro-integration-pocketbase:refresh", ({ loading }) => {
if (loading) {
refresh.textContent = "Refreshing content...";
refresh.buttonStyle = "gray";
refresh.style.pointerEvents = "none";
} else {
refresh.textContent = "Refresh content";
refresh.buttonStyle = "green";
refresh.style.pointerEvents = "unset";
}
});
}
}
//#endregion
//#region src/toolbar/dom/create-placeholder.ts
/**
* Creates a placeholder card.
*/
function createPlaceholder() {
return `
<style>
#placeholder div {
display: flex;
align-items: center;
justify-content: center;
}
</style>
<astro-dev-toolbar-card id="placeholder">
<div>
<span> Here you will see the raw content of an entity </span>
</div>
</astro-dev-toolbar-card>
`;
}
//#endregion
//#region src/toolbar/init-toolbar.ts
/**
* Initializes the PocketBase toolbar.
*/
function initToolbar(canvas, app, server) {
let options = {
realtime: false,
hasContentLoader: false,
baseUrl: ""
};
server.on("astro-integration-pocketbase:settings", (updatedOptions) => {
options = updatedOptions;
createPocketBaseWindow();
});
createPocketBaseWindow();
document.addEventListener("astro:after-swap", createPocketBaseWindow);
closeOnOutsideClick(app);
synchronizePlacementOnUpdate(app, canvas);
function createPocketBaseWindow() {
canvas.innerHTML = "";
const entities = window.__astro_entities__ || [];
const windowElement = createWindowElement(`
<style>
:host astro-dev-toolbar-window {
max-height: 480px;
}
main {
display: flex;
flex-direction: column;
gap: 1rem;
overflow-y: auto;
}
</style>
<header></header>
<hr />
<main>
${entities.length > 0 ? createEntities(entities, options.baseUrl) : createPlaceholder()}
</main>
`);
createHeader(windowElement, server, options);
canvas.append(windowElement);
if (entities.length > 0) app.toggleNotification({
state: true,
level: "info"
});
else {
app.toggleNotification({ state: false });
app.toggleState({ state: false });
}
}
}
//#endregion
//#region src/toolbar/index.ts
var toolbar_default = defineToolbarApp({ init: initToolbar });
//#endregion
export { toolbar_default as default };
//# sourceMappingURL=toolbar.mjs.map