Credits estimate finished

pull/580/head
Piero Toffanin 2019-01-02 11:57:19 -05:00
rodzic bd2fff98ad
commit 66b0c4f6ee
6 zmienionych plików z 152 dodań i 19 usunięć

Wyświetl plik

@ -180,6 +180,7 @@ footer,
/* Highlight */
.task-list-item:nth-child(odd),
.table-striped>tbody>tr:nth-of-type(odd),
select.form-control option[disabled],
.theme-background-highlight{
background-color: theme("highlight");
}

Wyświetl plik

@ -76,6 +76,10 @@ class NewTaskPanel extends React.Component {
setResizeMode(v){
return e => {
this.setState({resizeMode: v});
setTimeout(() => {
this.handleFormChanged();
}, 0);
}
}
@ -84,6 +88,10 @@ class NewTaskPanel extends React.Component {
let n = parseInt(e.target.value.replace(/[^\d]*/g, ""));
if (isNaN(n)) n = "";
this.setState({resizeSize: n});
setTimeout(() => {
this.handleFormChanged();
}, 0);
}
handleFormTaskLoaded(){
@ -139,6 +147,7 @@ class NewTaskPanel extends React.Component {
{this.state.items.map((Item, i) => <div key={i} className="form-group">
<Item taskInfo={this.state.taskInfo}
getFiles={this.props.getFiles}
filesCount={this.props.filesCount}
/>
</div>)}
</div>

Wyświetl plik

@ -14,6 +14,8 @@ from django.views.decorators.http import require_POST
from nodeodm.models import ProcessingNode
from app.api.processingnodes import ProcessingNodeSerializer
ds = GlobalDataStore('lightning')
def JsonResponse(dict):
return HttpResponse(json.dumps(dict), content_type='application/json')
@ -30,11 +32,11 @@ class Plugin(PluginBase):
def app_mount_points(self):
@login_required
def main(request):
ds = UserDataStore('lightning', request.user)
uds = UserDataStore('lightning', request.user)
return render(request, self.template_path("index.html"), {
'title': 'Lightning Network',
'api_key': ds.get_string("api_key")
'api_key': uds.get_string("api_key")
})
@login_required
@ -44,16 +46,14 @@ class Plugin(PluginBase):
if api_key is None:
return JsonResponse({'error': 'api_key is required'})
ds = UserDataStore('lightning', request.user)
ds.set_string('api_key', api_key)
uds = UserDataStore('lightning', request.user)
uds.set_string('api_key', api_key)
return JsonResponse({'success': True})
@login_required
@require_POST
def sync_processing_node(request):
ds = GlobalDataStore('lightning')
hostname = request.POST.get('hostname')
port = int(request.POST.get('port'))
token = request.POST.get('token')
@ -83,8 +83,6 @@ class Plugin(PluginBase):
@login_required
def get_processing_nodes(request):
ds = GlobalDataStore('lightning')
nodes = get_objects_for_user(request.user, 'view_processingnode', ProcessingNode,
accept_global_perms=False)
lightning_node_ids = ds.get_json("nodes", [])
@ -94,19 +92,23 @@ class Plugin(PluginBase):
return JsonResponse(serializer.data)
@login_required
def is_lightning_node(request):
lightning_node_ids = ds.get_json("nodes", [])
return JsonResponse({'result': int(request.GET.get('id')) in lightning_node_ids})
return [
MountPoint('$', main),
MountPoint('save_api_key$', save_api_key),
MountPoint('sync_processing_node$', sync_processing_node),
MountPoint('get_processing_nodes$', get_processing_nodes),
MountPoint('is_lightning_node$', is_lightning_node),
]
@receiver(signals.processing_node_removed, dispatch_uid="lightning_on_processing_node_removed")
def lightning_on_processing_node_removed(sender, processing_node_id, **kwargs):
ds = GlobalDataStore('lightning')
node_ids = ds.get_json('nodes', [])
try:
node_ids.remove(processing_node_id)

Wyświetl plik

@ -1,5 +1,6 @@
import React from 'react';
import './CostEstimateItem.scss';
import ResizeModes from 'webodm/classes/ResizeModes';
import PropTypes from 'prop-types';
import $ from 'jquery';
@ -7,21 +8,140 @@ export default class CostEstimateItem extends React.Component {
static defaultProps = {
};
static propTypes = {
taskInfo: PropTypes.object.isRequired,
getFiles: PropTypes.func.isRequired,
filesCount: PropTypes.number.isRequired
}
constructor(props){
super(props);
this.state = {
loading: false,
show: false,
credits: ""
}
this.imageWidth = null;
this.imageHeight = null;
}
componentDidUpdate(prevProps){
if (prevProps.taskInfo.selectedNode &&
this.props.taskInfo.selectedNode &&
prevProps.taskInfo.selectedNode.key !== this.props.taskInfo.selectedNode.key){
if (this.props.taskInfo.selectedNode.key !== "auto"){
$.get(`/plugins/lightning/is_lightning_node?id=${this.props.taskInfo.selectedNode.key}`)
.done(json => {
if (json.result !== undefined){
this.setState({show: json.result});
if (json.result) this.estimateCredits();
}
});
}
}
if (this.state.show){
if (prevProps.taskInfo.resizeMode !== this.props.taskInfo.resizeMode ||
prevProps.taskInfo.resizeSize !== this.props.taskInfo.resizeSize){
this.estimateCredits();
}
}
}
extractImageDimensions = (file, cb) => {
const reader = new FileReader();
reader.onload = (entry => {
var image = new Image();
image.src = entry.target.result;
image.onload = function() {
cb({
width: this.width,
height: this.height
})
};
});
reader.readAsDataURL(file);
}
estimateCredits = () => {
this.setState({loading: true});
const getEstimate = () => {
const { taskInfo } = this.props;
let width = this.imageWidth;
let height = this.imageHeight;
if (taskInfo.resizeMode === ResizeModes.YES ||
taskInfo.resizeMode === ResizeModes.YESINBROWSER){
let largestSide = Math.max(width, height);
let multiplier = taskInfo.resizeSize / largestSide;
width = Math.ceil(width * multiplier);
height = Math.ceil(height * multiplier);
if (width <= 0) width = 1;
if (height <= 0) height = 1;
}
if (this.estimateRequest){
this.estimateRequest.abort();
this.estimateRequest = null;
}
this.estimateRequest = $.get("https://webodm.net/r/tasks/estimateCost", {
images: this.props.filesCount,
width,
height
}).done(json => {
if (json.credits_estimate !== undefined){
if (json.credits_estimate === 0) json.credits_estimate += " (Free)";
this.setState({credits: json.credits_estimate})
}else{
this.setState({credits: "Cannot retrieve estimate. Try again later."});
}
}).fail(e => {
this.setState({credits: `Cannot retrieve estimate. Check parameters or try again later.`});
}).always(() => {
this.setState({loading: false});
this.estimateRequest = null;
});
}
if (this.props.filesCount > 0){
if (this.imageWidth === null && this.imageHeight === null){
const files = this.props.getFiles();
const imageFile = Array.prototype.find.call(files, f => f.type.startsWith("image/"));
if (imageFile){
this.extractImageDimensions(files[0], dims => {
this.imageWidth = dims.width;
this.imageHeight = dims.height;
getEstimate();
});
}else{
this.setState({show: false});
}
}else{
getEstimate();
}
}else{
this.setState({show: false});
}
}
render(){
const { show, loading, credits } = this.state;
return (
<div className="lightning-cost-estimate-item">
<label className="col-sm-2 control-label">Credits Required</label>
<div className={"lightning-cost-estimate-item " + (show ? "" : "hide")}>
<label className="col-sm-2 control-label">Credits Estimate</label>
<div className="col-sm-10 num-credits">
{this.props.taskInfo.name}
{loading ?
<i className="fa fa-circle-o-notch fa-spin"></i> :
<div>
{ credits }
</div>}
</div>
</div>
);

Wyświetl plik

@ -26,7 +26,7 @@ export default class Dashboard extends React.Component {
}
apiUrl = url => {
return `http://192.168.2.253:5000${url}?api_key=${this.props.apiKey}`;
return `https://webodm.net${url}?api_key=${this.props.apiKey}`;
};
componentDidMount = () => {
@ -121,10 +121,11 @@ export default class Dashboard extends React.Component {
</div> }
</div>
<div className="estimator">
<h5>Cost Calculator</h5>
Drag &amp; drop some images below to estimate the number of credits required to process them with lightning.
</div>
{nodes.length > 0 ?
<div>
<hr/>
<i className="fa fa-thumbs-o-up"></i> You are all set! When creating a new task from the <a href="/dashboard">Dashboard</a>, select <strong>{nodes[0].hostname}:{nodes[0].port}</strong> from the <strong>Processing Node</strong> drop-down instead of Auto.
</div> : ""}
<div className="buttons text-right">
<hr/>

Wyświetl plik

@ -33,7 +33,7 @@ export default class Login extends React.Component {
handleLogin = () => {
this.setState({loggingIn: true});
$.post("http://192.168.2.253:5000/r/auth/login",//"https://webodm.net/r/auth/login",
$.post("https://webodm.net/r/auth/login",
{
username: this.state.email,
password: this.state.password