Skip to content

Commit

Permalink
allow to upload/create new html file in UserAppDialog
Browse files Browse the repository at this point in the history
  • Loading branch information
andreas committed Dec 11, 2024
1 parent e2854ed commit e65d427
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 26 deletions.
4 changes: 3 additions & 1 deletion viewer/components/IconDialog.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import GuiHelpers from "../util/GuiHelpers";
import Helper from "../util/helper";
import UploadHandler from "./UploadHandler";
import Toast from "./Toast";
import globalStore from "../util/globalstore";
import keys from "../util/keys";

const IMAGES_FLAG=1;
const SOURCES=[
Expand Down Expand Up @@ -138,7 +140,7 @@ export const IconDialog=(props)=>{
label:'New',
onClick:()=>setUploadSequence(uploadSequence+1),
close:false,
visible: (props.allowUpload === undefined|| props.allowUpload),
visible: (props.allowUpload === undefined|| props.allowUpload) && globalStore.getData(keys.gui.capabilities.uploadImages),
disabled: ! (sources & IMAGES_FLAG)
},
DBCancel()
Expand Down
10 changes: 9 additions & 1 deletion viewer/components/UploadHandler.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,15 @@ class UploadHandler extends React.Component{
resolve({name: name});
});
}
return this.props.checkNameCallback(name);
let rt=this.props.checkNameCallback(name);
if (rt instanceof Promise) return rt;
return new Promise((resolve,reject)=>{
if (typeof(rt) === 'object') {
if (!rt.error) resolve(rt);
else reject(rt.error);
}
else reject(rt);
})
}
upload(file){
let self=this;
Expand Down
127 changes: 103 additions & 24 deletions viewer/components/UserAppDialog.jsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,119 @@
import React, {useEffect, useState} from 'react';
import PropTypes from 'prop-types';
import OverlayDialog, {useDialogContext} from './OverlayDialog.jsx';
import OverlayDialog, {SelectList, showPromiseDialog, useDialogContext} from './OverlayDialog.jsx';
import Toast from './Toast.jsx';
import {Checkbox,Input,InputReadOnly,InputSelect} from './Inputs.jsx';
import {Checkbox,Input,InputReadOnly} from './Inputs.jsx';
import Addons from './Addons.js';
import Helper from '../util/helper.js';
import Requests from '../util/requests.js';
import GuiHelpers from '../util/GuiHelpers.js';
import UploadHandler from "./UploadHandler";
import {DBCancel, DBOk, DialogButtons, DialogFrame} from "./OverlayDialog";
import {IconDialog} from "./IconDialog";
import globalStore from "../util/globalstore";
import keys from "../util/keys";

const contains = (list, url, opt_key) => {
if (opt_key === undefined) opt_key = "url";
for (let k = 0; k < list.length; k++) {
if (list[k][opt_key] === url) return true;
}
return false;
}
const UserAppDialog = (props) => {
const [currentAddon, setCurrentAddon] = useState({...props.addon, ...props.fixed});
const dialogContext = useDialogContext();
const [userFiles, setUserFiles] = useState([]);
const initiallyLoaded = (props.fixed || {}).url === undefined || props.addon !== undefined;
const [loaded, setLoaded] = useState(initiallyLoaded);
const [internal, setInternal] = useState(!(initiallyLoaded && (props.addon || {}).keepUrl));

const fillLists = () => {
const SelectHtmlDialog=({allowUpload,resolveFunction,current})=>{
const dialogContext=useDialogContext();
const [uploadSequence,setUploadSequence]=useState(0);
const [userFiles,setUserFiles]=useState([]);
const listFiles=(name)=>{
Requests.getJson("?request=list&type=user")
.then((data) => {
let nuserFiles = [];
if (data.items) {
data.items.forEach((el) => {
if (Helper.getExt(el.name) === 'html') {
el.label = el.url;
el.label = el.name;
el.value = el.url;
if (el.url === current) el.selected=true;
nuserFiles.push(el);
if (name && el.name === name) {
resolveFunction(el.url);
dialogContext.closeDialog();
}
}
});
setUserFiles(nuserFiles)
}
}).catch((error) => {
});
}
useEffect(() => {
listFiles();
}, []);
const checkName=(name)=>{
for (let i=0;i<userFiles.length;i++) {
if (userFiles[i].name ===name) return "file "+name+" already exists";
}
}
return <DialogFrame title={"Select HTML file"}>
<UploadHandler
uploadSequence={uploadSequence}
type={'user'}
checkNameCallback={(name)=>{
if (name && name.substring(name.length-4).toUpperCase() === 'HTML') {
let err=checkName(name);
if (err) return err;
return {name: name}
}
return "only files of type html allowed";
}}
doneCallback={(v)=>listFiles(v.param.name)}
errorCallback={(err)=>Toast(err)}
/>
<SelectList
list={userFiles}
onClick={(el)=>{
dialogContext.closeDialog();
resolveFunction(el.url);
}}
/>
<DialogButtons buttonList={[
{
name: 'upload',
label: 'Upload',
onClick: ()=>{ setUploadSequence((old)=>old+1)},
visible: (allowUpload === undefined|| allowUpload) && globalStore.getData(keys.gui.capabilities.uploadUser),
close: false
},
{
name: 'new',
label: 'New',
onClick:()=>{
showPromiseDialog(dialogContext,OverlayDialog.createValueDialog("enter html filename"),"")
.then((name)=>{
if (! name) throw Error("empty name");
if (!Helper.getExt(name) === 'html') name+=".html";
const err=checkName(name);
if (err) throw Error(err);
const data="<html>\n<head>\n</head>\n<body>\n<!--- your text here --->\n</body>\n</html>";
Requests.postPlain({
request:'upload',
type: 'user',
name: name
}, data)
.then(()=>{
listFiles();
})
})
.catch((err)=>Toast(err+""));
},
visible: (allowUpload === undefined|| allowUpload) && globalStore.getData(keys.gui.capabilities.uploadUser),
close: false
},
DBCancel()

]}/>
</DialogFrame>
}

const UserAppDialog = (props) => {
const [currentAddon, setCurrentAddon] = useState({...props.addon, ...props.fixed});
const dialogContext = useDialogContext();
const initiallyLoaded = (props.fixed || {}).url === undefined || props.addon !== undefined;
const [loaded, setLoaded] = useState(initiallyLoaded);
const [internal, setInternal] = useState(!(initiallyLoaded && (props.addon || {}).keepUrl));
const fillLists = () => {
if (!loaded) Addons.readAddOns()
.then((addons) => {
let current = Addons.findAddonByUrl(addons, props.fixed.url)
Expand Down Expand Up @@ -90,14 +162,21 @@ const UserAppDialog = (props) => {
mandatory={(v) => !v}
onChange={(val) => setCurrentAddon({...currentAddon, url: val})}/>
:
<InputSelect
<InputReadOnly
dialogRow={true}
label="internal url"
value={currentAddon.url}
mandatory={(v) => !v}
list={userFiles}
showDialogFunction={dialogContext.showDialog}
onChange={(selected) => setCurrentAddon({...currentAddon, url: selected.url})}/>
onClick={()=>{
dialogContext.showDialog(()=>{
return <SelectHtmlDialog
resolveFunction={(url)=>
setCurrentAddon({...currentAddon,url:url})
}
current={currentAddon.url}
/>
})
}}/>
}
</React.Fragment>
}
Expand Down

0 comments on commit e65d427

Please sign in to comment.