import Head from 'next/head' import { useState, useEffect, useRef } from 'react' import { saveAs } from 'file-saver'; import CreatableSelect from 'react-select/creatable'; import Select from 'react-select'; import { useRouter } from 'next/router' import allapps from '../../../public/list.json' export async function getStaticPaths() { let paths = allapps.apps.map(app => ({ params: { app: [btoa(app.name)] } })) paths.push({ params: { app: null } }) return { paths, fallback: false, // can also be true or 'blocking' } } // `getStaticPaths` requires using `getStaticProps` export async function getStaticProps({ params }) { const app = params.app return { // Passed to the page component as props props: { app: app ?? null }, } } export default function AddApp({ app }) { function friendlyUrl(url) { // make the url lowercase var encodedUrl = url.toString().toLowerCase(); // replace & with and encodedUrl = encodedUrl.split(/\&+/).join("-and-") // remove invalid characters encodedUrl = encodedUrl.split(/[^a-z0-9]/).join("-"); // remove duplicates encodedUrl = encodedUrl.split(/-+/).join("-"); // trim leading & trailing characters encodedUrl = encodedUrl.trim('-'); return encodedUrl; } const downloadZip = () => { var JSZip = require("jszip"); const zip = new JSZip() const folder = zip.folder(application.friendly_name) folder.file('app.json', JSON.stringify(application, null, 2)) if (icon) { folder.file(application.image_src, icon.file) } else if (inlineImage) { const promise = fetch(inlineImage).then(response => response.blob()) folder.file(application.image_src, promise) } zip.generateAsync({ type: "blob" }) .then(function (content) { // Force down of the Zip file saveAs(content, friendlyUrl(application.friendly_name) + '.zip'); }); } const name = useRef(null); const friendly_name = useRef(null); const description = useRef(null); const [categories, setCategories] = useState(null) const [architecture, setArchitecture] = useState(null) const [icon, setIcon] = useState(null) const [ext, setExt] = useState('png') const [inlineImage, setInlineImage] = useState(null) const defaultState = { friendly_name: null, image_src: null, description: null, name: null, cores: 1, memory: 1024, gpu_count: 0, cpu_allocation_method: "Inherit", docker_registry: "https://index.docker.io/v1/", categories: [], require_gpu: false, enabled: true, image_type: 'Container', } const [application, setApplication] = useState(defaultState) const router = useRouter() // const { app } = router.query useEffect(() => { console.log(app) if(app === null) { description.current.value = '' name.current.value = '' friendly_name.current.value = '' setCategories(null) setArchitecture(null) setIcon(null) setApplication(defaultState) } else if (app && app[0]) { const appDetails = allapps.apps.find(el => el.name === atob(app[0])) delete appDetails['sha'] description.current.value = appDetails.description name.current.value = appDetails.name friendly_name.current.value = appDetails.friendly_name if (appDetails.categories) { let catMap = [] appDetails.categories.map((e) => catMap.push({ label: e, value: e, })) setCategories(catMap) } if (appDetails.architecture) { let archMap = [] appDetails.architecture.map((e) => archMap.push({ label: e, value: e, })) setArchitecture(archMap) } setInlineImage('../../icons/' + appDetails.image_src) setApplication({ ...application, ...appDetails }) } }, [app]) const displayApplication = () => { return { ...application, // categories: JSON.stringify(application.categories) } } const customStyles = { control: (base, state) => ({ ...base, background: "#f1f5f9", borderRadius: '0.5rem', borderColor: "#94a3b8" }), multiValue: (styles, { data }) => { return { ...styles, backgroundColor: '#dde6f1', }; } } useEffect(() => { if (application && application.friendly_name) { const updateapp = { ...application } updateapp.image_src = friendlyUrl(updateapp.friendly_name) + '.' + ext setApplication(updateapp) } }, [ext]) const updateCategories = (items) => { const updateapp = { ...application } updateapp.categories = items.map(cat => cat.value) setApplication(updateapp) let catMap = [] updateapp.categories.map((e) => catMap.push({ label: e, value: e, })) setCategories(catMap) } const updateArchitecture = (items) => { const updateapp = { ...application } updateapp.architecture = items.map(arch => arch.value) setApplication(updateapp) let archMap = [] updateapp.architecture.map((e) => archMap.push({ label: e, value: e, })) setArchitecture(archMap) } const handleChange = (event) => { const updateapp = { ...application } updateapp[event.target.name] = event.target.value if (event.target.name === 'icon') { delete updateapp.icon setIcon({ value: event.target.value, file: event.target.files[0] }) setExt(event.target.value.substr(event.target.value.lastIndexOf('.') + 1)) setInlineImage(null) // return } if (updateapp.friendly_name) { updateapp.image_src = friendlyUrl(updateapp.friendly_name) + '.' + ext } setApplication(updateapp) } const options = [ { value: 'Browser', label: 'Browser' }, { value: 'Communication', label: 'Communication' }, { value: 'Desktop', label: 'Desktop' }, { value: 'Development', label: 'Development' }, { value: 'Games', label: 'Games' }, { value: 'Multimedia', label: 'Multimedia' }, { value: 'Office', label: 'Office' }, { value: 'Privacy', label: 'Privacy' }, { value: 'Productivity', label: 'Productivity' }, { value: 'Remote Access', label: 'Remote Access' } ] return (
Kasm Apps

Add Application

This will help you generate the JSON file you need to upload to the App directory.

Select the image to use, image will be renamed when it's downloaded.

This is the name that will show for users

You can select from the available option or create new ones.

A short description about the application

The docker image to use, i.e. kasmweb/filezilla:develop