mirror of
https://github.com/mickael-kerjean/filestash.git
synced 2025-11-03 13:11:46 +08:00
feature (form): form pages
This commit is contained in:
@ -2,7 +2,7 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { Input, Textarea, Select, Enabler } from './';
|
import { Input, Textarea, Select, Enabler } from './';
|
||||||
import { FormObjToJSON, bcrypt_password, format } from '../helpers/';
|
import { FormObjToJSON, bcrypt_password, format, autocomplete } from '../helpers/';
|
||||||
|
|
||||||
import "./formbuilder.scss";
|
import "./formbuilder.scss";
|
||||||
|
|
||||||
@ -122,7 +122,34 @@ const FormElement = (props) => {
|
|||||||
}
|
}
|
||||||
props.onChange(value);
|
props.onChange(value);
|
||||||
};
|
};
|
||||||
$input = ( <Input onChange={(e) => onTextChange(e.target.value)} {...id} name={struct.label} type="text" value={struct.value || ""} placeholder={struct.placeholder} readOnly={struct.readonly}/> );
|
|
||||||
|
const list_id = struct.datalist ? "list_"+Math.random() : null;
|
||||||
|
$input = ( <Input list={list_id} onChange={(e) => onTextChange(e.target.value)} {...id} name={struct.label} type="text" value={struct.value || ""} placeholder={struct.placeholder} readOnly={struct.readonly}/> );
|
||||||
|
if(list_id != null){
|
||||||
|
const filtered = function(multi, datalist, currentValue){
|
||||||
|
if(multi !== true || currentValue == null) return datalist;
|
||||||
|
|
||||||
|
return autocomplete(
|
||||||
|
currentValue
|
||||||
|
.split(",")
|
||||||
|
.map((t) => t.trim())
|
||||||
|
.filter((t) => t),
|
||||||
|
datalist
|
||||||
|
);
|
||||||
|
};
|
||||||
|
$input = (
|
||||||
|
<span>
|
||||||
|
{ $input }
|
||||||
|
<datalist id={list_id}>
|
||||||
|
{
|
||||||
|
filtered(struct.multi, struct.datalist, struct.value).map((item,i) => {
|
||||||
|
return ( <option key={i} value={item} /> );
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</datalist>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "number":
|
case "number":
|
||||||
const onNumberChange = (value) => {
|
const onNumberChange = (value) => {
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
opacity: 0.25;
|
opacity: 0.25;
|
||||||
font-size: 0.95em;
|
font-size: 0.95em;
|
||||||
|
line-height: 0.95em;
|
||||||
}
|
}
|
||||||
|
|
||||||
input::placeholder, textarea::placeholder{
|
input::placeholder, textarea::placeholder{
|
||||||
|
|||||||
@ -15,3 +15,13 @@ export function copyToClipboard (str){
|
|||||||
document.execCommand("copy");
|
document.execCommand("copy");
|
||||||
$input.remove();
|
$input.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function format(str = ""){
|
||||||
|
if(str.length === 0) return str;
|
||||||
|
return str.split("_")
|
||||||
|
.map((word, index) => {
|
||||||
|
if(index != 0) return word;
|
||||||
|
return word[0].toUpperCase() + word.substring(1);
|
||||||
|
})
|
||||||
|
.join(" ");
|
||||||
|
}
|
||||||
|
|||||||
@ -52,3 +52,48 @@ export function createFormBackend(backend_available, backend_data){
|
|||||||
obj[backend_data.type] = template;
|
obj[backend_data.type] = template;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* return a new list of autocompletion candidates considering the current input
|
||||||
|
*/
|
||||||
|
export function autocomplete(values, list) {
|
||||||
|
if(values.length === 0) return list;
|
||||||
|
let candidates_input = [],
|
||||||
|
candidates_output = [];
|
||||||
|
|
||||||
|
for(let i=0; i<list.length; i++){
|
||||||
|
const last_value = values[values.length - 1];
|
||||||
|
|
||||||
|
if(list[i].indexOf(last_value) === 0){
|
||||||
|
let tmp = JSON.parse(JSON.stringify(values))
|
||||||
|
tmp[values.length - 1] = list[i];
|
||||||
|
if(list[i] === last_value){
|
||||||
|
candidates_input = [tmp];
|
||||||
|
} else {
|
||||||
|
candidates_input.push(tmp)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if(values.indexOf(list[i]) === -1){
|
||||||
|
candidates_output.push(list[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(candidates_input.length === 0){
|
||||||
|
candidates_input = [values]
|
||||||
|
}
|
||||||
|
candidates_output = [""].concat(candidates_output);
|
||||||
|
|
||||||
|
if(candidates_input.length > 1) {
|
||||||
|
return candidates_input.map((candidate) => {
|
||||||
|
return candidate.join(", ");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return candidates_output.map((candidate, idx) => {
|
||||||
|
return candidates_input[0]
|
||||||
|
.concat(candidate)
|
||||||
|
.join(", ")
|
||||||
|
.replace(/\,\s?$/, "");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -11,8 +11,7 @@ export { invalidate, http_get, http_post, http_delete, http_options } from './aj
|
|||||||
export { prompt, alert, confirm } from './popup';
|
export { prompt, alert, confirm } from './popup';
|
||||||
export { notify } from './notify';
|
export { notify } from './notify';
|
||||||
export { gid, randomString } from './random';
|
export { gid, randomString } from './random';
|
||||||
export { leftPad, copyToClipboard } from './common';
|
export { leftPad, format, copyToClipboard } from './common';
|
||||||
export { getMimeType } from './mimetype';
|
export { getMimeType } from './mimetype';
|
||||||
export { settings_get, settings_put } from './settings';
|
export { settings_get, settings_put } from './settings';
|
||||||
export { FormObjToJSON, createFormBackend } from './form';
|
export { FormObjToJSON, createFormBackend, autocomplete } from './form';
|
||||||
export { format } from './text';
|
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
export function format(str = ""){
|
|
||||||
if(str.length === 0) return str;
|
|
||||||
return str.split("_")
|
|
||||||
.map((word, index) => {
|
|
||||||
|
|
||||||
if(index != 0) return word;
|
|
||||||
return word[0].toUpperCase() + word.substring(1);
|
|
||||||
})
|
|
||||||
.join(" ");
|
|
||||||
}
|
|
||||||
@ -341,6 +341,7 @@ const DateTime = (props) => {
|
|||||||
|
|
||||||
const FileSize = (props) => {
|
const FileSize = (props) => {
|
||||||
function displaySize(bytes){
|
function displaySize(bytes){
|
||||||
|
if(bytes === -1) return "";
|
||||||
if(Number.isNaN(bytes) || bytes === undefined){
|
if(Number.isNaN(bytes) || bytes === undefined){
|
||||||
return "";
|
return "";
|
||||||
}else if(bytes < 1024){
|
}else if(bytes < 1024){
|
||||||
|
|||||||
@ -7,10 +7,7 @@ export class FormViewer extends React.Component {
|
|||||||
constructor(props){
|
constructor(props){
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
form: {
|
form: {}
|
||||||
"test": {label: "test", type: "text", "value": null, default: "polo", placeholder: "test"},
|
|
||||||
"something": {label: "test", type: "text", "value": null, default: "polo", placeholder: "test"}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,13 +20,12 @@ export class FormViewer extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
console.log(this.state.form);
|
|
||||||
return (
|
return (
|
||||||
<div className="component_formviewer">
|
<div className="component_formviewer">
|
||||||
<MenuBar title={this.props.filename} download={this.props.data} />
|
<MenuBar title={this.props.filename} download={this.props.data} />
|
||||||
<div className="formviewer_container">
|
<div className="formviewer_container">
|
||||||
<Container>
|
<Container>
|
||||||
<form className="sticky">
|
<form className="sticky box">
|
||||||
<FormBuilder form={this.state.form} onChange={this.onChange.bind(this)} render={ ($input, props, struct, onChange) => {
|
<FormBuilder form={this.state.form} onChange={this.onChange.bind(this)} render={ ($input, props, struct, onChange) => {
|
||||||
return (
|
return (
|
||||||
<label className={"no-select"}>
|
<label className={"no-select"}>
|
||||||
@ -41,6 +37,12 @@ export class FormViewer extends React.Component {
|
|||||||
{ $input }
|
{ $input }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<span className="nothing"></span>
|
||||||
|
<div style={{width: '100%'}}>
|
||||||
|
{ struct.description ? (<div className="description">{struct.description}</div>) : null }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
}}/>
|
}}/>
|
||||||
|
|||||||
@ -13,18 +13,43 @@
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.formbuilder{
|
.box{
|
||||||
label.no-select > div {
|
padding: 25px 20px;
|
||||||
display: flex;
|
border-radius: 2px;
|
||||||
line-height: 30px;
|
|
||||||
|
|
||||||
> span {
|
|
||||||
display: inline-block;
|
.formbuilder{
|
||||||
width: 150px;
|
> div {
|
||||||
max-width: 150px;
|
margin-bottom: 10px;
|
||||||
text-align: right;
|
@media screen and (max-width: 470px) { margin-bottom: 20px; }
|
||||||
padding-right: 15px;
|
|
||||||
color: var(--emphasis);
|
|
||||||
|
label.no-select > div {
|
||||||
|
display: flex;
|
||||||
|
line-height: 30px;
|
||||||
|
@media screen and (max-width: 470px) {
|
||||||
|
display: block;
|
||||||
|
line-height: inherit;
|
||||||
|
span.nothing{ position: absolute; }
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
display: inline-block;
|
||||||
|
width: 160px;
|
||||||
|
max-width: 160px;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 15px;
|
||||||
|
color: var(--emphasis);
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
@media screen and (max-width: 470px) {
|
||||||
|
text-align: left;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,9 @@ type FormElement struct {
|
|||||||
ReadOnly bool `json:"readonly"`
|
ReadOnly bool `json:"readonly"`
|
||||||
Default interface{} `json:"default"`
|
Default interface{} `json:"default"`
|
||||||
Value interface{} `json:"value"`
|
Value interface{} `json:"value"`
|
||||||
|
MultiValue bool `json:"multi,omitempty"`
|
||||||
|
Datalist []string `json:"datalist,omitempty"`
|
||||||
|
Order int `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
Reference in New Issue
Block a user