Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
NebulaServices
GitHub Repository: NebulaServices/Nebula
Path: blob/main/src/components/catalog/InstalledPlugins.astro
976 views
<div id="parent" class="flex flex-row flex-wrap gap-4 items-center font-roboto justify-center"> 
</div>
<div class="w-0 h-0 visibility-none hidden"> <asset-loader1 /> </div>
<script>
    import { Elements } from "@utils/index";
    import { Marketplace } from "@utils/marketplace";
    import { SettingsVals } from "@utils/values";

    type Item = {
        description: string,
        image: string,
        package_name: string,
        payload: string,
        tags: [],
        background_video: string,
        background_image: string,
        title: string,
        type: string,
        version: string
    }

    const getItem = async (item: any) => {
        try {
            const res = await fetch(new URL(`/api/packages/${item.name}`, window.location.origin));
            const data = await res.json();
            return { ...data, package_name: item.name }
        }
        catch (err: any) {
            console.log(`Err in themes: ${err}`);
            return null;
        }
    }

    const constructElements = async (item: Item, parent: HTMLDivElement, marketplace: Marketplace) => {
        const main = document.createElement("div");
        main.classList.add("rounded-3xl", "bg-navbar-color", "w-64", "flex", "flex-col", "cursor-pointer", "border-text-color");
        main.dataset.name = item.package_name

        const click = document.createElement("div");
        click.classList.add("w-full"); 

        const img = document.createElement("img");
        img.classList.add("aspect-[16/9]", "rounded-t-3xl");
        img.src = `/packages/${item.package_name}/${item.image}`;
        img.alt = `${item.type}-${item.package_name}`;
        img.loading = "lazy";

        const info = document.createElement("div");
        info.classList.add("h-2/6", "text-center", "content-center", "p-3", "font-semibold", "items-center", "flex", "flex-col");

        const infoTitle = document.createElement("p");
        infoTitle.classList.add("text-2xl");
        infoTitle.innerHTML = item.title;

        const infoInner = document.createElement("div");
        infoInner.classList.add("flex", "flex-row");

        const infoInnerDelete = document.createElement("div");
        infoInnerDelete.classList.add("h-8", "w-8", "cursor-pointer");
        // This is cursed yes. SVG's SUUUCK
        infoInnerDelete.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 256 256"><path fill="currentColor" d="M216 48h-40v-8a24 24 0 0 0-24-24h-48a24 24 0 0 0-24 24v8H40a8 8 0 0 0 0 16h8v144a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16V64h8a8 8 0 0 0 0-16M112 168a8 8 0 0 1-16 0v-64a8 8 0 0 1 16 0Zm48 0a8 8 0 0 1-16 0v-64a8 8 0 0 1 16 0Zm0-120H96v-8a8 8 0 0 1 8-8h48a8 8 0 0 1 8 8Z" /></svg>`; 

        const infoInnerOpen = document.createElement("a");
        infoInnerOpen.classList.add("h-8", "w-8", "cursor-pointer");
        infoInnerOpen.href = `../catalog/package/${item.package_name}`;
        infoInnerOpen.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 256 256"><path fill="currentColor" d="M192 136v72a16 16 0 0 1-16 16H48a16 16 0 0 1-16-16V80a16 16 0 0 1 16-16h72a8 8 0 0 1 0 16H48v128h128v-72a8 8 0 0 1 16 0m32-96a8 8 0 0 0-8-8h-64a8 8 0 0 0-5.66 13.66L172.69 72l-42.35 42.34a8 8 0 0 0 11.32 11.32L184 83.31l26.34 26.35A8 8 0 0 0 224 104Z" /></svg>`;

        click.appendChild(img);
        infoInner.appendChild(infoInnerDelete);
        infoInner.appendChild(infoInnerOpen);
        info.appendChild(infoTitle);
        info.appendChild(infoInner);
        main.appendChild(click);
        main.appendChild(info);
        parent.appendChild(main);
        

        Elements.attachEvent(infoInnerDelete, "click", async () => {
            await marketplace.uninstallPlugin({ name: item.package_name, type: item.type as "page" | "serviceWorker" })
            parent.removeChild(main);
        });
    }

    const init = async () => {
        await Marketplace.ready();
        const mp = Marketplace.getInstances().next().value!;
        const els = Elements.select([
            { type: 'id', val: 'parent' }
        ]);
        const itemsJSON = JSON.parse(await mp.getValueFromStore(SettingsVals.marketPlace.plugins)) || [];
        const filteredItems = itemsJSON.filter((dat: any) => dat.remove !== true);
        const itemPromises = filteredItems.map(getItem);
        const itemsArray = await Promise.all(itemPromises);
        return {
            items: itemsArray.filter((data) => data !== null),
            elements: els,
            marketplace: mp
        }
    }

    Elements.createCustomElement("asset-loader1", async () => {
        const { items, elements, marketplace } = await init();
        const parentElem = Elements.exists<HTMLDivElement>(await elements.next());
        const promises = items.map(item => constructElements(item, parentElem, marketplace));
        await Promise.all(promises);
    });
</script>