diff --git a/.idea/costcalc.iml b/.idea/costcalc.iml index 24643cc..76fdc1a 100644 --- a/.idea/costcalc.iml +++ b/.idea/costcalc.iml @@ -1,12 +1,15 @@ + + + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..b717786 --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index f06d3d1..e0afe6c 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,668 +1,725 @@ + - - - + + - + - + - - + + + + - + - - + + - + + + + + + + + + + - - + + + + - - + + + + + + - - - - - + + + + + + + + + + - - + + + + + + + + - console tip tooltip url icon props.data. data ButtonInput TxtInput numeric here if UserCost > upd + rawexport + randomint + console Url Icon Data UserCostSelect &gt; true true true true DEFINITION_ORDER - Amount : {value} {this.props.unit} ); } } class SelectorInput extends React.Component { constructor(props) { super(props); // this.state={listoptions:this.makelist(props.options)}; this.handleChange = this.handleChange.bind(this); } rate(i){ return i; } makelist(data){ var listoptions=[]; for (var i = 0; i < data.length; i++) { listoptions.push(); } return listoptions; } handleChange(select) { this.props.onChange(select.target.value); } makerate(){ if (this.props.rate!=null){ return( Rate : {this.props.rate} {this.props.unit} );} } maketitle(title){ const maxstr=20 if (title.length>maxstr){ title=title.substr(0,maxstr)+"..."; } return title; } render() { return (
{this.makerate()}
) } } class MakeknowmoreInput extends React.Component { constructor(props) { super(props); this.state={btnsize:20} } render() { const data = this.props.data; if (((data.Url !== '') )) { // if (data.Url.length==1){ // return( // } url={data.Url[0].Url} // id="btn-plugin-knowmore" // class="btn-primary btn-sm" tips={"Know more about " + data.Name}/> // ); // }else { return (} options={data.Url} id="btn-plugin-knowmore" class="btn-primary btn-sm" tips={"Know more about " + data.Name}/>); //} } else{ return null } } } class CheckboxInput extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state={checked:this.props.defaults}; } handleChange() { this.setState({checked: !this.state.checked}); this.props.onChange(!this.state.checked); } render() { return (
); } } class ButtonHrefInput extends React.Component { constructor(props) { super(props); } render() { return ( {this.props.name} ); } } class ButtonInputWpop extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state={target:"Modal"+this.props.idp}; } handleChange() { const out={n:this.props.n,target:this.state.target}; this.props.onClick(out); } render() { return ( ); } } class ButtonInput extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); } handleChange() { this.props.onClick(this.props.n); } render() { return ( ); } } class MenuInput extends React.Component { constructor(props) { super(props); this.state={listoptions:this.makelist(props.options)}; } makelist(data){ var listoptions=[]; for (var i = 0; i < data.length; i++) { listoptions.push({data[i].Name}); } return listoptions; } render() { return (
{this.state.listoptions}
); } } class TxtInput extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); } handleChange(e) { this.props.onChange(e.target.value); } render() { return (
{this.props.Prepend}
{this.props.InvalidMessage}
); } } // Outputs definition // --------------------- // --------------------- class CostOutput extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); } handleChange() { this.props.onCostChange(this.props.display); } render() { return (
); } } function Textoutput(props){ return(
{props.text}
); } // Plugins definition // --------------------- // --------------------- class AmountRatesCost extends React.Component { constructor(props) { super(props); this.handleAmountChange = this.handleAmountChange.bind(this); this.handleRateChange = this.handleRateChange.bind(this); this.state={ Amount : 1, SelectRate : 0 , Rate : this.props.data.Rates[Object.keys(this.props.data.Rates)[0]] }; this.make_export(); } handleAmountChange(amount) { this.setState({Amount: amount}); } handleRateChange(select) { this.setState({SelectRate: select}); this.setState({Rate: this.props.data.Rates[Object.keys(this.props.data.Rates)[select]]}); } make_export(){ this.export=[ {Name:"Amount",Value:this.state.Amount+" "+this.props.data.AmountUnit}, {Name:this.props.data.RateName,Value:Object.keys(this.props.data.Rates)[this.state.SelectRate]} ]; + this.props.export(this.export); } componentDidUpdate(){ this.makecost(this.state.Amount,this.state.Rate); this.make_export(); } render() { return (
); } makecost(amount,rate) { if (amount<=this.props.data.AmountFree){ amount=0; } var total=amount*rate; total=tomoney(total); this.props.onCostChange(this.props.n,total); return total; } } class CategoryAmountRatesCost extends React.Component { constructor(props) { super(props); this.handleCatChange = this.handleCatChange.bind(this); this.handleAmountChange = this.handleAmountChange.bind(this); this.handleRateChange = this.handleRateChange.bind(this); this.state={ SelectCat : 0, Cat : this.props.data.Cat[Object.keys(this.props.data.Cat)[0]], Amount : 1, SelectRate : 0 , Rate : this.props.data.Rates[Object.keys(this.props.data.Rates)[0]] }; this.make_export(); } handleAmountChange(amount) { this.setState({Amount: amount}); } handleRateChange(select) { this.setState({SelectRate: select}); this.setState({Rate: this.props.data.Rates[Object.keys(this.props.data.Rates)[select]]}); } handleCatChange(select) { this.setState({SelectCat: select}); this.setState({Cat: this.props.data.Cat[Object.keys(this.props.data.Cat)[select]]}); } make_export(){ this.export=[ {Name:this.props.data.CatName,Value:Object.keys(this.props.data.Cat)[this.state.SelectCat]}, {Name:"Amount",Value:this.state.Amount+" "+this.props.data.AmountUnit}, {Name:this.props.data.RateName,Value:Object.keys(this.props.data.Rates)[this.state.SelectRate]} ]; + this.props.export(this.export); } componentDidUpdate(){ this.makecost(this.state.Cat,this.state.Amount,this.state.Rate); this.make_export(); } render() { return (
); } makecost(cat,amount,rate) { if (amount<=this.props.data.AmountFree){ amount=0; } var total=cat+amount*rate; total=tomoney(total); this.props.onCostChange(this.props.n,total); return total; } } class CategoryCost extends React.Component { constructor(props) { super(props); this.handleCatChange = this.handleCatChange.bind(this); this.state={SelectCat : 0, Cat : this.props.data.Cat[Object.keys(this.props.data.Cat)[0]] }; this.make_export(); } handleCatChange(select) { this.setState({SelectCat: select}); this.setState({Cat: this.props.data.Cat[Object.keys(this.props.data.Cat)[select]]}); } make_export(){ this.export=[ {Name:this.props.data.CatName,Value:Object.keys(this.props.data.Cat)[this.state.SelectCat]}, ]; + this.props.export(this.export); } componentDidUpdate(){ this.makecost(this.state.Cat); this.make_export(); } render() { return (
); } makecost(cat) { var total=cat; total=tomoney(total); this.props.onCostChange(this.props.n,total); return total; } } class NoneSelect extends React.Component { constructor(props) { super(props); this.export=[] } render() { const Cost=tomoney(0); this.props.onCostChange(this.props.n,Cost); + this.props.export(this.export); return (
Please select a provider in the list.
); } } class UserCost extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.handleProviderChange = this.handleProviderChange.bind(this); this.handleServiceChange = this.handleServiceChange.bind(this); this.state={total:0, CostError:false, ProviderError:true, ServiceError:true, }; this.export=[] } handleChange(value){ if (isNaN(value)||value===''){ - console.log("Nan Detected"); this.setState({CostError: true}); value=0; }else{ this.setState({CostError: false}); } this.setState({total:value}); this.props.onCostChange(this.props.n,tomoney(value)); } handleProviderChange(txt){ this.props.handleProviderChange(txt); if(txt ===''){ this.setState({ProviderError: true}); } else { this.setState({ProviderError: false}); } } handleServiceChange(txt){ this.props.handleServiceChange(txt); if(txt ===''){ this.setState({ServiceError: true}); } else { this.setState({ServiceError: false}); } } classtxt(error){ if(error){ return "is-invalid"; } else { return "is-valid"; } } render() { - // this.handleChange(this.state.total); + this.props.export(this.export); return (
); } } // Combine plugins // --------------------- // --------------------- class ProviderPluginsSelector extends React.Component { constructor(props) { super(props); this.handleCostChange = this.handleCostChange.bind(this); this.handleProviderChange = this.handleProviderChange.bind(this); this.handleCommentChange = this.handleCommentChange.bind(this); this.handleAddPlugin = this.handleAddPlugin.bind(this); this.handleRmvPlugin = this.handleRmvPlugin.bind(this); this.handleProviderChangetxt = this.handleProviderChangetxt.bind(this); this.handleServiceChangetxt = this.handleServiceChangetxt.bind(this); - - this.refcmp = React.createRef(); - + this.make_exportcmp = this.make_exportcmp.bind(this); + this.make_export = this.make_export.bind(this); this.state={ selected:0, keys:this.ProvidersName(props.data), n:1, cost:0, - prevcost:0, comments:"", Provider:"", - exportcmp:"", - Name:"", manualname:false, show_plus:false, + exportcmp:"", }; } handleCostChange(n,e) { - if (this.state.prevcost !== e ) { + if (this.state.cost !== e ) { this.setState({cost: e}); - this.setState({prevcost: e}); - - this.props.handleCostChange(n,e);} + this.props.handleCostChange(n,e); + } } handleProviderChange(select){ this.setState({selected:select}); if (select>0){ this.setState({show_plus:true}); }else { this.setState({show_plus:false}); } this.state.Provider=this.props.data.Data[select].Provider; this.state.Name=this.props.data.Data[select].Name; this.props.handleCostChange(this.props.n,this.state.cost); } componentDidUpdate(){ - this.state.exportcmp=this.refcmp.current.export; - this.props.handleCostChange(this.props.n,this.state.cost);//provoke export update on the parent + this.props.handleCostChange(this.props.n,this.state.cost); + this.make_export(); } + make_exportcmp(data){ + this.state.exportcmp=data + } + make_export(){ + const out={ + Category:this.props.data.Name, + Provider:this.state.Provider, + Name:this.state.Name, + Comments:this.state.comments, + ExportCmp:this.state.exportcmp, + Cost:this.state.cost, + }; + + this.props.export(out,this.props.n) + } handleCommentChange(com){ this.setState({comments:com}); } handleAddPlugin(n){ this.props.handleAddPlugin(n); } handleRmvPlugin(n){ this.props.handleRmvPlugin(n); } handleProviderChangetxt(txt){ this.setState({Provider:txt}); // this.props.handleCostChange(this.props.n,this.state.cost);//provoke export update on the parent } handleServiceChangetxt(txt){ this.setState({Name:txt}); // this.props.handleCostChange(this.props.n,this.state.cost);//provoke export update on the parent } render() { - // console.log("n= "+this.props.n) const selected=this.state.selected; this.state.manualname=false; this.state.keys=this.ProvidersName(this.props.data); const Cmp=this.cmp2string(this.cmpdata(selected).Style); const Cdata=this.cmpdata(selected); const id=this.props.data.Name.replace(/\s/g,'')+this.props.n; return(
+ export={this.make_exportcmp}/>
); } cmpdata(select){ let out=this.props.data.Data[select]; if (this.state.manualname){ out.Name=this.state.Name; if ( this.state.Provider ==='') { this.state.keys[select] = 'Please provide a Provider'; }else { this.state.keys[select]=this.state.Provider; } } return out; } cmp2string(str){ switch (str) { case "AmountRatesCost" : return AmountRatesCost; case "CategoryCost" : return CategoryCost; case "CategoryAmountRatesCost" : return CategoryAmountRatesCost; case "NoneSelect":return NoneSelect; case "UserCost":{this.state.manualname=true; return UserCost;} } } ProvidersName(main){ const data = main.Data; - // console.log(data); var providers=[]; for (var i = 0; i < data.length; i++) { providers.push(data[i].Provider); } return providers; } } -function makeinfo(keys,selected,Cdata){ - let name=Cdata.Name; - if ( name ===''&&keys[selected]===''){ - name='Please provide a Provider'; - return ({name}); - }else if(keys[selected]==='None'){ - return ({name}); - }else{ - return ({keys[selected]} : {name}); - } -} - class ModuleHeader extends React.Component{ constructor(props) { super(props); this.handleAddPlugin = this.handleAddPlugin.bind(this); this.handleRmvPlugin = this.handleRmvPlugin.bind(this); } handleAddPlugin(n){ this.props.handleAddPlugin(n); } handleRmvPlugin(n){ this.props.handleRmvPlugin(n); } render() { let minus=''; let plus=''; if (this.props.show_minus){ minus=} onClick={this.handleRmvPlugin} n={this.props.n} tips={"Remove this line"} idp={this.props.id} info={this.props.data.Name}/>; } if (this.props.show_plus){ plus= } onClick={this.handleAddPlugin} n={this.props.n} tips={"Add a new "+this.props.data.Name}/> } return(
-
+
{plus}
-
+
{minus}
- {makeinfo(this.props.keys,this.props.selected,this.props.Cdata)} + {this.makeinfo(this.props.keys,this.props.selected,this.props.Cdata)}
{this.props.comments}
); } - + makeinfo(keys,selected,Cdata){ + let name=Cdata.Name; + if ( name ===''&&keys[selected]===''){ + name='Please provide a Provider'; + return ({name}); + }else if(keys[selected]==='None'){ + return ({name}); + }else{ + return ({keys[selected]} : {name}); + } + } } class ManagePlugins extends React.Component{ constructor(props) { super(props); this.handleCostChange = this.handleCostChange.bind(this); this.handleAddPlugin = this.handleAddPlugin.bind(this); this.handleRmvPlugin = this.handleRmvPlugin.bind(this); - // this.handletest = this.handletest.bind(this); + this.make_exportplug=this.make_exportplug.bind(this); + this.make_export = this.make_export.bind(this); this.state={ displayed:[], varsum:{}, plugins:[], + export:[], }; - this.state.displayed.push(this.randomint()); - this.export=[]; + this.state.displayed.push(randomint(this.state.displayed)); } handleRmvPlugin(n){ $('#'+n.target).modal('hide'); var tmp=this.state.displayed; tmp.splice(n.n,1); this.setState({displayed:tmp}); this.handleCostChange(n.n,0); } handleAddPlugin(n){ var tmp=this.state.displayed; - tmp.splice(n+1,0,this.randomint()); + tmp.splice(n+1,0,randomint(this.state.displayed)); this.setState({displayed:tmp}); } handleCostChange(n,cost) { this.state.varsum[n]=cost; this.props.handleCostChange(this.props.n,sum(this.state.varsum)); + } + make_exportplug(data,n) { + this.state.export[n] = data; this.make_export() } - make_export() { - // console.log("export asked : "+this.props.n); - var pdata=[]; - var state=[]; - for (var i = 0; i < this.export.length; i++) { - if((this.export[i]!==null)&&(typeof this.export[i].props !== 'undefined')&&(typeof this.export[i].state !== 'undefined')){ - pdata[i]=this.export[i].props.data; - state[i]=this.export[i].state; - }} - rawexport[this.props.n]={data:pdata,state:state}; - // console.log(rawexport); - } - randomint(){ - const tmp=this.state.displayed; - var rnd; - do { - rnd=Math.floor(Math.random() * 100); - var cont=false; - for (let i = 0; i < tmp.length ; i++) { - if (tmp[i]===rnd){ - cont=true; - } - } - } while(cont); - return rnd; + make_export(){ + // var out=[]; + // for (var i = 0; i < this.state.export.length; i++) { + // if((this.state.export[i]!==null)&& + // (typeof this.state.export[i].data !== 'undefined')&&(typeof this.state.export[i].state !== 'undefined')){ + // out.push({data:this.state.export[i].data,state:this.state.export[i].state}); + // }} + // + // this.props.export(out,this.props.n) + if (this.state.export.length === this.give_n()) { + this.props.export(this.state.export, this.props.n) + } } + give_id(index){ return this.state.displayed[index] } give_n(){ const disp=this.state.displayed; return disp.length } componentDidUpdate(){ this.make_export(); } render() { let show_minus = false; if (this.give_n()>1) { show_minus=true; } this.make_export(); return(
- - {(index) => {this.export[index] = input }}/>} - - {/**/} -
- - + + {(index) => } - );} + +
+ );} } class PluginsMain extends React.Component { constructor(props) { super(props); this.handleCostChange = this.handleCostChange.bind(this); - this.state={'varsum':{}}; + this.make_exportplug=this.make_exportplug.bind(this); + this.make_export = this.make_export.bind(this); + + this.state={ + varsum:{}, + export:[] + }; } handleCostChange(name,e) { - // console.log("name"+name); this.state.varsum[name]=e; this.props.TotalCost(sum(this.state.varsum)); } + make_exportplug(data,n) { + this.state.export[n] = data; + this.make_export() + } + + make_export(){ + if (this.state.export.length === this.props.data.length) { + this.props.export(this.state.export); + + } + } render() { return(
+
Line controls
Category
Provider information
Cost
+
{(index) => } + export={this.make_exportplug} n={index} handleCostChange={this.handleCostChange}/>}
+
); } } // MAIN // --------------------- // --------------------- class Main extends React.Component { constructor(props) { super(props); this.handleCostChange = this.handleCostChange.bind(this); - this.state={ - 'total':0, - 'prevtotal':0}; - this.input = React.createRef(); + this.make_exportmain = this.make_exportmain.bind(this); + + this.state= { + total: 0, + export: [], + exportmain:[], + }; + + this.init=true; } handleCostChange(total) { - // console.log("there total : "+total ) - if (this.state.prevtotal !== total){ + if (this.state.total !== total){ + this.setState({total:total}); + } + + } + make_exportmain(idata) { + + const tmp=JSON.parse(JSON.stringify(idata)); + let disp=false; + if(!this.init){ + if(!Object.compare(tmp,this.state.exportmain.data)){ + disp=true; + } + - this.setState({'total':total}); - this.setState({'prevtotal':total}); } + if((this.init)||(disp)){ + this.setState({exportmain: {data: tmp, total: tomoney(this.state.total)}}); + this.init=false; + } } + + render() { return(
{this.page_head()} -
+
- + {this.final_cost()} - + {this.howto()}
{this.page_foot()}
); } howto(){ return(

HOWTO

Categories
This tool is divided by categories (for example Activate storage). Click on the category name, and it will expand.
Providers

Providers can be chosen from the Select a provider box. You can then tune your setting for this provider to fit your needs.

If the provider you want is not registered, you can add it manually with Provide your own provider and then enter your provider/service and cost.

Add or Remove Line

If you want to add a new provider use the } tips={"Add a new category"} onClick={this.fctnull}/> button.

You can also remove a provider with } tips={"Remove this line"} onClick={this.fctnull}/> button.

To know more about
Some extra information about the category or the provider can be obtained with the } tips={"Know more"} onClick={this.fctnull}/> button.
Comments your input
Comments are for your own usage, you can use for remembering what each section is and for a nice export.
Export
You can export your work into different format :
HTML : This format can be used in any wordprocessing software (such as Microsoft Word or Libreoffice).
HTML Source code and Markdown formats are also possible.
Click on the in order to copy your work into your clipboard. A simple Paste will transfer your work into any software.
); } final_cost(){ return(
- + {/**/}

Total Cost

); } page_head(){ return( ); } move2howto(){ $('html,body').animate({ scrollTop: $("#howto").offset().top}, 'slow'); } page_foot(){ return( ); } fctnull(){} } //Main Declaration // --------------------- // --------------------- ReactDOM.render(
,document.getElementById('root')); $(function () { $('[data-toggle="tooltip"]').tooltip() });