Commit 63ade4dc authored by Mihkel Putrinš's avatar Mihkel Putrinš
Browse files

render resource stats

parent 3a0b5c98
var msToTime = require('./msToTime.js')
var msToDate = require('./msToDate.js')
var metrics
var CB = {}
var progress = function progress() {
var initMetrics = function initMetrics() {
metrics = {
total: 0,
current: 0,
left: 0,
start_time_ms: undefined, // timestamp
advance_time_ms: undefined, // timestamp of last advance
elapsed_ms: 0, // advance_time_ms - start_time_ms
eta_ms: 0, // ms, estimated time left
eta_time: '', // humanize(eta_ms)
eta_date: '',
counter: 0,
percentage: 0,
last_path: 'N/A',
registered: false,
started: false,
loading: false,
uploading: false,
last_refresh_ms: 0, // timestamp of last refresh
last_amount: 0, // amount of data between last two refreshes
last_interval_ms: 0, // interval between last two refreshes
mov_ave_pool_ms: 100000, // length of moving average calculation pool
mov_ave_pool_bytes: 0, // moving average of bytes transferred in last mov_ave_pool_ms
mov_ave_speed: 0, // bytes/ms, mov_ave_pool_bytes / min(elapsed_ms, mov_ave_pool_ms)
done: false
}
}
initMetrics()
var refresh_interval_target = 1000
var refresh_interval = refresh_interval_target
var refresh = function refresh() {
if (!metrics.started)
return
// console.log(metrics)
var d = new Date()
var now_ms = d.getTime()
if (metrics.last_refresh_ms === 0)
metrics.last_refresh_ms = now_ms
metrics.last_interval_ms = now_ms - metrics.last_refresh_ms
if (metrics.last_interval_ms > refresh_interval_target) {
refresh_interval--
} else if (metrics.last_interval_ms < refresh_interval_target) {
refresh_interval++
}
if (metrics.elapsed_ms > metrics.mov_ave_pool_ms) {
metrics.mov_ave_pool_bytes -= Math.round(metrics.mov_ave_pool_bytes * metrics.last_interval_ms / metrics.mov_ave_pool_ms)
}
metrics.mov_ave_pool_bytes += metrics.last_amount
metrics.mov_ave_speed = Math.round( metrics.mov_ave_pool_bytes / Math.min(metrics.elapsed_ms, metrics.mov_ave_pool_ms) )
metrics.eta_ms = metrics.left / metrics.mov_ave_speed
metrics.eta_time = msToTime(metrics.eta_ms)
metrics.eta_date = msToDate(metrics.advance_time_ms + metrics.eta_ms)
metrics.percentage = metrics.current / metrics.total * 100
if (metrics.left <= 0) {
metrics.done = true
}
if (metrics.left < 0) {
// console.log('Metrics inconsistent', metrics)
}
metrics.last_amount = 0
metrics.last_refresh_ms = now_ms
}
return {
metrics: metrics,
register_callbacks: function(started_cb, increased_cb, decreased_cb, advanced_cb, output_cb, done_cb) {
CB['started_cb'] = started_cb
CB['increased_cb'] = increased_cb
CB['decreased_cb'] = decreased_cb
CB['advanced_cb'] = advanced_cb
CB['output_cb'] = output_cb
CB['done_cb'] = done_cb
metrics.registered = true
CB.output_cb(metrics)
return metrics
},
start: function() {
if (!metrics.registered) throw "Callbacks not registered!"
if (metrics.started) throw "Allready started!"
var d = new Date()
metrics.start_time_ms = metrics.advance_time_ms = d.getTime()
metrics.started = true
CB.started_cb(metrics)
var output_rec = function output_rec () {
if (!metrics.done) {
refresh()
CB.output_cb(metrics)
// console.log(metrics + ' | Next output in ' + refresh_interval + ' ms.')
setTimeout(function() {output_rec()}, refresh_interval)
}
}
// var output_rec = function output_rec () {
// if (!metrics.done) {
// if (metrics.started) {
// CB.output_cb(metrics)
// } else {
// metrics.started = true
// CB.started_cb(metrics)
// }
// }
// }
output_rec()
},
restart: function() {
if (!metrics.registered) throw "Callbacks not registered!"
initMetrics()
var d = new Date()
metrics.start_time_ms = metrics.advance_time_ms = d.getTime()
metrics.started = true
CB.started_cb(metrics)
},
increase: function(amount) {
if (!metrics.registered) throw "Callbacks not registered!"
metrics.loading = true
// console.log(metrics, amount)
amount = Number(amount)
metrics.total += amount
// console.log(metrics, amount)
metrics.left += amount
CB.increased_cb(metrics)
},
decrease: function(amount) {
if (!metrics.registered) throw "Callbacks not registered!"
amount = Number(amount)
metrics.total -= amount
metrics.left -= amount
// if (isNaN(metrics.left))
// console.log(metrics.last_amount, metrics)
CB.decreased_cb(metrics)
},
advance: function(amount) {
if (!metrics.registered) throw "Callbacks not registered!"
metrics.loading = false
metrics.uploading = true
var d = new Date()
if (!metrics.started) {
this.start()
}
if (amount === undefined) {
amount = 0
}
metrics.current += amount
metrics.left -= amount
metrics.advance_time_ms = d.getTime()
metrics.elapsed_ms = metrics.advance_time_ms - metrics.start_time_ms
metrics.last_amount += Number(amount)
CB.advanced_cb(metrics)
if (metrics.done)
CB.done_cb(metrics)
},
setLastPath: function(path) {
metrics.last_path = path
}
}
}
module.exports = progress()
\ No newline at end of file
// 1. core modules
var gui = require('nw.gui')
var util = require('util')
var fs = require('fs')
var https = require('https')
var events = require('events')
var path = require('path')
// 2. public modules from npm
// var os = require('os-utils')
// 3. Own modules
var stringifier = require('./stringifier.js')
var bytesToSize = require('./bytesToSize.js')
var msToTime = require('./msToTime.js')
var loadDirs = require('./loadDirs.js')
var uploader = require('./uploader.js')
var progress = require('./progress.js')
var translate = require('./translations/estonian.js')
var entu_user_email = ''
var progressStartedCB = function progressStartedCB(metrics) {
// console.log('progress started', metrics)
$('#waitspinner').show()
$('#upload_back').width('100%')
}
var progressIncreasedCB = function progressIncreasedCB(metrics) {
// console.log('total increased', metrics)
// $('[progress]').text(bytesToSize(metrics.total))
}
var progressDecreasedCB = function progressDecreasedCB(metrics) {
// console.log('total decreased', metrics)
// $('[progress]').text(bytesToSize(metrics.total))
}
var progressAdvancedCB = function progressAdvancedCB(metrics) {
// console.log('progressAdvancedCB', metrics)
}
var progressOutputCB = function progressOutputCB(metrics) {
var output_txt = ''
if (metrics.loading) {
output_txt = bytesToSize(metrics.total)
+ '; ' + metrics.last_path
+ '; ' + metrics.node_count
} else if (metrics.uploading) {
output_txt = bytesToSize(metrics.total)
+ ' - ' + bytesToSize(metrics.current)
+ ' = ' + bytesToSize(metrics.left)
+ '; ' + metrics.eta_time
+ '; ' + metrics.eta_date
// console.log(metrics)
} else {
output_txt = bytesToSize(metrics.total)
}
// console.log(output_txt)
$('[progress]').text(output_txt)
$('#upload_front').width(metrics.percentage + '%')
}
var progressDoneCB = function progressDoneCB(metrics) {
// $('#upload_progress').children().empty()
$('#upload_back').width('0%')
$('#upload_front').width('0%')
// console.log('progress done', metrics)
}
progress.register_callbacks(
progressStartedCB,
progressIncreasedCB,
progressDecreasedCB,
progressAdvancedCB,
progressOutputCB,
progressDoneCB
)
// 4. And configuration
var configuration = require('./configuration.json')
// Add os-specific shortcuts and menu
require('./decorate.js').decorate()
global.$ = $
__VERSION = gui.App.manifest.version
ENTU_DNS = 'entu.keeleressursid.ee'
ENTU_URI = 'https://' + ENTU_DNS + '/'
ENTU_API = ENTU_URI + 'api2/'
ENTU_API_ENTITY = ENTU_API + 'entity-'
ENTU_API_EMAIL = ENTU_API + 'email'
ENTU_API_POST_FILE = ENTU_API + 'file'
ENTU_PING = ENTU_API + 'ping/'
ENTU_API_AUTH = ENTU_API + 'user/auth'
ENTU_API_USER = ENTU_API + 'user'
// console.log ( '= ' + gui.App.manifest.name + ' v.' + __VERSION + ' ==================================')
gui.Window.get().focus()
gui.Window.get().on('focus', function() {
})
gui.Window.get()
.on('resize', function(width, height) {
$('#card_contents').height($(window).height() - 100)
})
$( document ).ready(function() {
// puudub internetiühendus
require('dns').resolve('www.google.com', function(err) {
if (err) {
window.alert ('Netti pole')
// console.log(err)
process.exit(1)
}
})
// repositoorium ei vasta
require('dns').resolve(ENTU_DNS, function(err) {
if (err)
{
// console.log(err)
window.alert ('Entu pole saadaval')
process.exit(1)
}
})
$('#overquota_files, #overquota_total').hide()
$('[translate]')
.each(function() {
$(this).html(translate($(this).attr('translate')))
})
// Remove tabstop from links in helptexts
.find('a').attr('tabindex', '-1')
$('#resource_name')
.keyup(function(event) {
loadDirs.root_node().entuname = $('#resource_name').val()
})
$('#chdir_button')
.text('Vali kaust')
.click(function() {
// progress.start()
$('#chdir_input').click()
})
$('#chdir_input')
.change(function(event) {
$('#waitspinner').show()
$('#chdir_button').hide()
// console.log('foo')
// Now give a tick-or-two for spinner to load
// because he's too shy to start animation while CPU is intensely engaged
setTimeout(function() {
var now_ms = (new Date()).getTime()
var full_path = $('#chdir_input').val()
// In nwjs v12 behaviour of directory selecting input form is broken and instead of selected folder it
// returns recursive list of all files in that folder.
if (full_path !== full_path.split(';')[0]) {
full_path = full_path.split(';')[0]
full_path = path.dirname(full_path)
}
loadDirs.load(full_path, function finalCallback() {
$('#chdir_button').show()
$('#waitspinner').hide('slow')
$('#resource_name').val(path.basename(full_path))
if (Object.keys(loadDirs.nodes()).length > 0) {
// console.log(Object.keys(loadDirs.nodes()).length, loadDirs.nodes())
var status_message = Object.keys(loadDirs.nodes()).length
+ ' faili ja kataloogi lugemiseks kulus '
+ msToTime((new Date()).getTime() - now_ms) + '.'
$('[progress]').text(status_message)
// console.log(status_message)
advanceToNextCard()
loadDirs.displayNodes((new Date()).getTime() - now_ms)
}
})
}, 2)
})
$('#back_button')
.text('Tagasi')
.click(function() {
advanceToPrevCard()
loadDirs.reset()
})
$('#login_button')
.text('Logi sisse')
.click(function() {
checkAuth(function(data) {
ENTU_USER_ID = data.result.id
ENTU_SESSION_KEY = data.result.session_key
advanceToNextCard()
// console.log(data)
$("a:contains('__USER_EMAIL')").text(data.result.email).prop('href', 'mailto:' + data.result.email)
$('[progress]').text("Tere, " + data.result.name)
if (data.result.email === 'mihkel.putrinsh@gmail.com') {
require('nw.gui').Window.get().showDevTools()
}
// sendFinalEmail([{'Name':'test','Uri':'https://entu.keeleressursid.ee'}])
})
})
$('#upload_button')
.text('Lae valitud ressursid')
.click(function() {
$('#back_button').hide()
$('#upload_button').hide()
uploader.createResources(configuration.__ROOT_EID, function uploadCallback(data) {
// console.log('Uploaded OK') // , data)
advanceToNextCard()
$('[progress]').text('Valmis.')
$('#waitspinner').hide('slow')
sendFinalEmail(data)
})
})
var meta_path = path.resolve(homePath(), gui.App.manifest.name)
if (!inoExistsSync(meta_path)) {
fs.mkdir(meta_path)
}
loadCard('hello')
})
var login_frame = $('<IFRAME/>')
.attr('id', 'login_frame')
.attr('name', 'login_frame')
.attr('src', ENTU_API_AUTH)
var auth_in_progress = false
var checkAuth = function checkAuth(successCallback) {
if (auth_in_progress)
return
auth_in_progress = true
// console.log('Check user from Entu.')
$.get( ENTU_API_USER )
.done(function userOk( data ) {
auth_in_progress = false
entu_user_email = data.result.email
window.sessionStorage.setItem('ENTU_USER_ID', data.result.id)
window.sessionStorage.setItem('ENTU_SESSION_KEY', data.result.session_key)
successCallback(data)
})
.fail(function userFail( data ) {
if ($('#login_frame').length === 0) {
$('body').append(login_frame)
$('#login_frame').fadeIn(500)
$('#login_frame').load( function() {
$.get( ENTU_API_USER )
.done(function userOk( data ) {
auth_in_progress = false
$('#login_frame').detach()
entu_user_email = data.result.email
window.sessionStorage.setItem('ENTU_USER_ID', data.result.id)
window.sessionStorage.setItem('ENTU_SESSION_KEY', data.result.session_key)
successCallback(data)
})
})
}
})
}
var homePath = function homePath() {
var home_path = ''
if (process.env.HOME !== undefined) {
home_path = process.env.HOME
} else if (process.env.HOMEPATH !== undefined) {
home_path = process.env.HOMEDRIVE + process.env.HOMEPATH
}
return path.normalize(home_path)
}
var execPath = function execPath() {
var exec_path = ''
if (process.PWD !== undefined) {
exec_path = process.PWD
} else if (process.execPath !== undefined) {
exec_path = process.execPath
}
return path.dirname(exec_path)
}
var sendFinalEmail = function sendFinalEmail(data) {
// console.log('Send email notification to submitter.')
var message_body = []
data.forEach(function iterateUploadedResources(resource) {
message_body.push('<li><a href="' + resource.Uri + '">' + resource.Name + '</a></li>')
})
message_body = '<ul>' + message_body.join('<br/>') + '</ul>'
message_body = '<h1>Teie poolt upitatud ressursid</h1>\n\n' + message_body
var post_data = {
'to': entu_user_email,
'subject': 'Panustajaga upitatud ressursid',
'message': message_body,
'campaign': 'panustaja'
}
$.post(ENTU_API_EMAIL, post_data, function(returned_data) {
// console.log(returned_data)
})
}
var advanceToNextCard = function advanceToNextCard() {
$('card').removeClass('current')
$('.card_title.current').removeClass('current').addClass('complete').next().addClass('current')
$('#' + $('.card_title.current').attr('translate') ).addClass('current')
}
var advanceToPrevCard = function advanceToPrevCard() {
$('card').removeClass('current')
$('.card_title.current').removeClass('current').prev().removeClass('complete').addClass('current')
$('#' + $('.card_title.current').attr('translate') ).addClass('current')
}
var loadCard = function loadCard(card_name) {
$('card').removeClass('current')
$('.card_title.current').removeClass('current')
var card_id = card_name + '_card'
var card_label_id = card_name + '_card_label'
$('#' + card_label_id).addClass('current')
$('#' + card_id).addClass('current')
}
// fs.existsSync got deprecated and replaced with fs.accessSync in node 1.0.0
var inoExistsSync = function inoExistsSync(path) {
// console.log('Node version ' + process.versions.node)
if (process.versions.node.substr(0,2) === '1.') {
try {
fs.accessSync(path)
return true
} catch(err) {
return false
}
} else {
return fs.existsSync(path)
}
}
// catch all kinds of uncatched errors
window.addEventListener('error', function(errEvent){
var m
console && console.error(errEvent)
m = 'uncaughtException: ' +
errEvent.message + '\nfilename:"' +
(errEvent.filename ? errEvent.filename : 'app_front.js') +
'", line:' + errEvent.lineno
// show any errors early
document.write('<pre><h2>' +
m + '</h2><div style="color:white;background-color:red">' +
errEvent.error.stack + '</div></pre>'
)
// window.alert(m)
})
process.on('uncaughtException', function(err){
// console.error('uncaughtException:', err)
// console.error(err.stack)
// window.alert('uncaughtException ' + err)
})
var stringifier = function stringifier(o) {
var cache = [];
return JSON.stringify(o, function(key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Circular reference found, replace key
return 'Circular reference to: ' + key
}
// Store value in our collection
cache.push(value)
}
return value
}, '\t')
}
module.exports = stringifier
* {
-webkit-user-select: none;
}
#cards {
position: fixed;
border-spacing: 1em;
cursor: default;
right: 0em;
top: 0;
}
#card_contents {
overflow: auto;
height: 800px;
}
card {
display: none;
width: 100%;
/*margin: 5em 1em 1em 1em;*/
}
card.current {
display: inline;
}
.card_title {
width: 25%;
border: black 1px solid;
color: gray;
background-color: lightgray;
padding: 0.7em;
}
.card_title.current {
color: darkblue;