How to update a widget when modifying model data in Odoo - odoo-13

I'm showing the reported hours of a User on the Odoo navbar but I have to F5 if I want to update the data.
It's possible to update the reported hours when someone modifies the model data that contain this information?
My javascript code
odoo.define('L6Odoo13_systray_reported_hours.systray_reported_hours', function (require) {
"use strict";
var Widget = require('web.Widget');
var SystrayMenu = require('web.SystrayMenu');
var field_utils = require('web.field_utils');
var core = require('web.core');
var session = require('web.session');
var ReportedHours = Widget.extend({
template: 'ReportedHours',
init: function() {
this.reported_hours = 0
this._super.apply(this, arguments);
},
events: {
'onchange account.analytic.line': 'willStart',
},
willStart: function(){
var self = this;
var def = this._rpc({
model: 'account.analytic.line',
method: 'search_read',
args: [[['user_id', '=', this.getSession().uid]], ['name', 'unit_amount', 'date']],
})
.then(function (res) {
var today = new Date();
var hoy = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate()
if (res.length) {
var total = 0.0
res.forEach(function(elem){
if (elem.date === hoy){
total += elem.unit_amount
}
})
self.reported_hours = field_utils.format.float_time(total);
}
});
return Promise.all([def, this._super.apply(this, arguments)]);
},
})
ReportedHours.prototype.sequence = 90;
SystrayMenu.Items.push(ReportedHours);
return {
ReportedHours: ReportedHours,
};
});
My xml code
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-name="ReportedHours">
<li class="o_mail_systray_item" style="margin-top: 13px;">
<div>
<span t-esc="widget.reported_hours"/>
</div>
</li>
</t>
</templates>
Of course I know that the code in 'events:' is incorrect, but is what I'm looking for.
I want to update the 'self.reported_hours' when someone modifies the 'account.analytic.line' data.

Related

Why do I need to refresh the page to get the newly-updated data?

I was making an application including a comment function with "likes" and "dislikes" just like Facebook. But I find when users click the button of "like" or "dislike", everything goes well --- the database has been updated and the new data has been rendered back to previous webpage, except users need to refresh the page manually to get the new webpage with newly-updated data. Here are my files (I just take the codes of "like" function as example, the codes of "dislike" function is the same):
JS codes:
$("#scrollit").on("click", ".fa-thumbs-up", function(){
var numberOfLikes = Number($(this).next().html());
var numberOfDislikes = Number($(this).next().next().next().html());
numberOfLikes = numberOfLikes + 1;
var Text = $(this).next().next().next().next().next().html();
console.log(Text);
$.ajax({
method: "POST",
url: "/searchresult/comments/likes",
data: {text:Text, likes: numberOfLikes, dislikes: numberOfDislikes}
});
});
Node.js codes:
app.post("/searchresult/comments/likes", function(req, res) {
var likes = req.body.likes;
var Text = req.body.text;
new Promise(function(resolve, reject) {
comments.update({text: Text}, {$set: {likes: likes}}, function(err){
if (err) {
console.log(err);
} else {
console.log("Likes update successfully!");
resolve(comments);
}
});
}).then(function(r){
console.log("DONE!");
res.redirect("/searchresult");
});
});
app.get("/searchresult", function(req, res){
var EnglishofWord = EnglishofWords[EnglishofWords.length - 1];
grewords.findOne({English: EnglishofWord}).populate("Comments").exec(function(err, allgrewords){
if (err) {
console.log(err);
} else {
console.log(allgrewords);
if (allgrewords == null || allgrewords.length < 1 || allgrewords == undefined ) {
console.log("We don't have this word in dictionary!");
res.render("errorpage");
} else {
res.render("searchresult", {greword:allgrewords});
}
}
});
});
ejs codes:
<% greword.Comments.forEach(function(comment){ %>
<strong><p class="author"><%= comment.author %></p></strong>
<i class="far fa-thumbs-up"></i><span class="likes"><%= comment.likes %></span>
<i class="far fa-thumbs-down"></i><span class="dislikes"><%= comment.dislikes%></span>
<span class="pull-right">10 days ago</span>
<p><%= comment.text %></p>
<% }) %>
Could anybody help me to figure it out? ---- Why doesn't the webpage refresh itself automatically? Thanks so much! :P
//************************************************ Update! ***************************************************//
Thanks a lot to t3__rry, his/her suggestion was enlightening! Now I have made it work properly.

HTML5 audio not playing with Handlebars templated src attribute

I'm trying to play mp3's that I am streaming out of a Mongo GridFSBucket. The root of my issue is that I set the src attribute of my audio tag with my handlebars template to the URL that my stream should be headed to but the player is unresponsive.
If I don't feed this URL to my the audio tag and I remove the handlebars code, my browser (Chrome) creates a video tag that blacks out the window and superimposes HTML media player controls in the center and plays the track without issue.
How should I specify to the player that whatever it is streaming to the video tag it is creating should instead go to the audio player?
list.handlebars
<script src="../index.js" ></script>
<title>CRATE</title>
</head>
<body>
<div>tracks displayed below</div>
<div>{{userNameId}}'s Tracks</div>
{{#each tracks}}
<div class="row">
<div class="col-md-12">
<form id="trackSelection" method="GET" action="/play">
<input type="hidden" name="bytes" value="{{length}}">
<button class="playButton" type="submit" name="id" value=" .
{{_id}}">{{filename}}</button>
</form>
</div>
</div>
{{/each}}
<audio id="playback" src="{{sourceUrl}}" type="audio/mpeg" controls>
</audio>
</body>
</html>
index.js
app.get('/play', urlEditor, function(req, res, next) {
var db = req.db // => Db object
var size = sanitizer.escape(req.query.bytes);
var sanitizedTrackId = sanitizer.escape(req.query.id);
var username = 'ross';
var protocol = req.protocol;
var originalUrl = req.originalUrl;
// var sourceUrl = protocol + '://' + hosted + originalUrl;
var sourceUrl = protocol + '://' + req.get('host') + originalUrl;
console.log("sourceUrl", sourceUrl)
console.log("type", typeof sourceUrl)
if (username) {
const collection = db.collection(username + ".files");
var userNameId = collection.s.name;
console.log(userNameId);
const tracks = new Promise(function(resolve, reject) {
resolve(collection.find({}).toArray(function(err, tracks) {
assert.equal(err, null);
// return tracks;
finishPage(tracks);
}))
})
} else {
console.log('waiting')
}
function finishPage(tracks) {
try {
console.log("SID", sanitizedTrackId);
var trackID = new ObjectID(sanitizedTrackId);
} catch (err) {
return res.status(400).json({ message: "Invalid trackID in URL parameter. Must be a single String of 12 bytes or a string of 24 hex characters" });
}
let playEngine = new mongo.GridFSBucket(db, {
bucketName: username
});
var downloadStream = playEngine.openDownloadStream(trackID);
downloadStream.pipe(res);
console.log('success');
console.log("___________________");
var head = {
'Accept-Ranges': 'bytes',
'Content-Length': size,
'Content-Type': 'audio/mp3',
}
// res.render("list");
// res.set({ 'content-type': 'audio/mp3', 'accept-ranges': 'bytes', 'content-length': size }).render("list", { tracks: tracks, userNameId: userNameId, sourceUrl: sourceUrl });
res.status(206, head).render("list", { tracks: tracks, userNameId: userNameId, sourceUrl: sourceUrl });
}

How to record desktop screen video using recordRTC node module of selected screen area?

I am working on desktop application using NW.js wherein required to record selected area of desktop screen. currently using RecordRTC node module for recording video. but this gives me full screen video recording. please assist if there any other package to achieve this across platforms (win/linux/mac).
Please check this demo (name as "Record Cropped Screen using RecordRTC"):
https://www.webrtc-experiment.com/RecordRTC/simple-demos/record-cropped-screen.html
Here is complete HTML code (try on any HTTPs page or localhost or node-webkit):
<button id="btn-start-recording">Start Recording</button>
<button id="btn-stop-recording" style="display: none;">Stop Recording</button>
<br><hr>
<div id="edit-panel" style="border-bottom: 1px solid;">
<div>
<label for="x">X</label>
<input type="number" name="x" id="x" value="0" />
</div>
<div>
<label for="y">Y</label>
<input type="number" name="y" id="y" value="0" />
</div>
<div>
<label for="w">Width (-1 = Full size)</label>
<input type="number" name="w" id="w" value="-1" />
</div>
<div>
<label for="h">Height (-1 = Full size)</label>
<input type="number" name="h" id="h" value="-1" />
</div>
<button id="update" style="display: none;">Update X-Y Width-Height Coordinates</button>
<canvas></canvas>
</div>
<video id="mediaElement"></video>
<script src="https://cdn.webrtc-experiment.com/RecordRTC.js"></script>
<script src="https://cdn.WebRTC-Experiment.com/getScreenId.js"></script>
<script>
// this script tag is taken from: https://github.com/andersevenrud/webrtc-screenshare-crop-demo
var CROP_X = 10;
var CROP_Y = 20;
var CROP_W = 320; // default width
var CROP_H = 240; // default height
var VIDEO_WIDTH = 0;
var VIDEO_HEIGHT = 0;
var MAX_VIDEO_WIDTH = 1920;
var MAX_VIDEO_HEIGHT = 1080;
var _canvas;
var _context;
var htmlCanvasElement = document.querySelector('canvas');
// Form elements
document.getElementById("x").value = CROP_X;
document.getElementById("y").value = CROP_Y;
document.getElementById("w").value = CROP_W;
document.getElementById("h").value = CROP_H;
document.getElementById("update").onclick = function() {
var x = document.getElementById("x").value << 0;
var y = document.getElementById("y").value << 0;
var w = document.getElementById("w").value << 0;
var h = document.getElementById("h").value << 0;
if (x >= 0) {
CROP_X = x;
}
if (y >= 0) {
CROP_Y = y;
}
CROP_W = w || 0;
CROP_H = h || 0;
};
_context = htmlCanvasElement.getContext('2d');
/**
* Crops a video frame and shows it to the user
*/
function CropFrame(ev, stream, video, callback) {
callback = callback || function() {};
_canvas = htmlCanvasElement;
if (CROP_X < 0) {
CROP_X = 0;
}
if (CROP_Y < 0) {
CROP_Y = 0;
}
if (CROP_W <= 0) {
CROP_W = VIDEO_WIDTH;
}
if (CROP_H <= 0) {
CROP_H = VIDEO_HEIGHT;
}
if (CROP_W > MAX_VIDEO_WIDTH) {
CROP_W = MAX_VIDEO_WIDTH;
}
if (CROP_H > MAX_VIDEO_HEIGHT) {
CROP_W = MAX_VIDEO_HEIGHT;
}
_canvas.width = CROP_W;
_canvas.height = CROP_H;
_context.drawImage(video, CROP_X, CROP_Y, CROP_W, CROP_H, 0, 0, CROP_W, CROP_H);
// We need to scale down the image or else we get HTTP 414 Errors
// Also we scale down because of RTC message length restriction
var scanvas = document.createElement('canvas');
scanvas.width = _canvas.width;
scanvas.height = _canvas.height;
var wRatio = _canvas.width / 320;
var hRatio = _canvas.height / 240;
var maxRatio = Math.max(wRatio, hRatio);
if (maxRatio > 1) {
scanvas.width = _canvas.width / maxRatio;
scanvas.height = _canvas.height / maxRatio;
}
scanvas.getContext('2d').drawImage(_canvas, 0, 0, scanvas.width, scanvas.height);
callback(scanvas.toDataURL("image/jpeg"));
}
var recorder;
function captureScreen(cb) {
getScreenId(function(error, sourceId, screen_constraints) {
navigator.getUserMedia(screen_constraints, cb, function(error) {
console.error('getScreenId error', error);
alert('Failed to capture your screen. Please check Chrome console logs for further information.');
});
});
}
var mediaElement = document.querySelector('#mediaElement');
document.querySelector('#btn-start-recording').onclick = function() {
document.querySelector('#btn-start-recording').style.display = 'none';
navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
captureScreen(function(screen) {
var inited = false;
mediaElement.ontimeupdate = function(ev) {
if (!inited) {
VIDEO_WIDTH = mediaElement.offsetWidth;
VIDEO_HEIGHT = mediaElement.offsetHeight;
mediaElement.style.display = 'none';
document.querySelector('#edit-panel').style.display = 'block';
inited = true;
}
CropFrame(ev, screen, mediaElement);
};
mediaElement.src = URL.createObjectURL(screen);
mediaElement.play();
mediaElement.screen = screen;
addStreamStopListener(screen, function() {
document.querySelector('#btn-stop-recording').onclick();
});
// RecordRTC goes here
var captureStream = htmlCanvasElement.captureStream();
recorder = RecordRTC(captureStream, {
type: 'video'
});
recorder.startRecording();
document.querySelector('#btn-stop-recording').style.display = 'inline';
});
};
document.querySelector('#btn-stop-recording').onclick = function() {
document.querySelector('#btn-stop-recording').style.display = 'none';
recorder.stopRecording(function() {
var blob = recorder.getBlob();
document.querySelector('#edit-panel').style.display = 'none';
mediaElement.style.display = 'block';
mediaElement.src = URL.createObjectURL(blob);
mediaElement.play();
if (mediaElement.screen && mediaElement.screen.getVideoTracks) {
mediaElement.screen.stop();
mediaElement.screen = null;
}
document.querySelector('#btn-start-recording').style.display = 'inline';
});
};
function addStreamStopListener(stream, callback) {
var streamEndedEvent = 'ended';
if ('oninactive' in stream) {
streamEndedEvent = 'inactive';
}
stream.addEventListener(streamEndedEvent, function() {
callback();
callback = function() {};
}, false);
stream.getAudioTracks().forEach(function(track) {
track.addEventListener(streamEndedEvent, function() {
callback();
callback = function() {};
}, false);
});
stream.getVideoTracks().forEach(function(track) {
track.addEventListener(streamEndedEvent, function() {
callback();
callback = function() {};
}, false);
});
}
function querySelectorAll(selector) {
return Array.prototype.slice.call(document.querySelectorAll(selector));
}
querySelectorAll('input').forEach(function(input) {
input.onkeyup = input.oninput = function() {
if (!document.querySelector('#update').onclick) return;
document.querySelector('#update').onclick();
};
});
</script>

I want to display some query mongoose result data using Angular on an html page

I have a little problem, I want to display some mongoose query result data using Angular on on an html page.
I don't know how to send data to the angular $scope.
app.js:
User.find({ Code: doc.Code}, function (err, data){
var users = [];
var userswithsamecode = '';
data.forEach(function(d){
console.log(d.nom + " " + d.prenom);
users.push(d);
userswithsamecode += "<li>" + d.nom +" "+ d.prenom + '</li><br>';
How can I send this result to the angular $scope,
collegues.html
<html data-ng-app="demo">
<div data-ng-controller="simple">
Name:
<br/>
<input type="text" data-ng-model="name" />
<br/>
<ul>
<li data-ng-repeat="collegue in collegues |filter:name">{{}} </li>
</ul>
</div>
<script src="angular.min.js"></script>
<script>
var demo=angular.module('demo', []);
function simple($scope){
$scope.collegues=
];}
demo.controller('simple', simple);
</script>'
Thanks for your help!
First you need to create a model for mongo. An example
var Example = mongoose.model('ExampleCollection'{
name:String,
description: String
});
//posting to a mongodb
var example = new Example (
app.post("/add-something-to-mongo", function(req, res) {
name: req.body.name,
description: req.body.description
});
listing.save(function(err) {
if(err) {
console.log("Error! ", err);
}else
{
console.log("Saved!"
};
});
});
});
The angular code would look something like this.
var app = this;
var url = "heroku_url or localhost url";
app.save = function(Example) {
// create a new object
var newExample = {
"name": $scope.name
"description": $scope.description
};
$http.post(url + "/routefromserver", newExample).success(function() {
console.log("posting");
})
};
And lastly the HTML
<input id="name" type="text" ng-model="name" />
<input id="city" type="text" ng-model="description"/>
<button ng-click="app.save()">Save Me</button>

display messages on page refresh using nowjs

from the nowjs.org example, i have this code:
var server = require('http').createServer(function(req, res){
res.end(html);
});
server.listen(9080);
console.log("This server's process pid is: " + process.pid);
var nowjs = require("now");
var everyone = nowjs.initialize(server);
var MESSAGE_BACKLOG = 200,
SESSION_TIMEOUT = 60 * 1000;
function updateRSS () {
var bytes = parseInt(rss);
if (bytes) {
var megabytes = bytes / (1024*1024);
megabytes = Math.round(megabytes*10)/10;
$("#rss").text(megabytes.toString());
}
}
var mem = process.memoryUsage();
var rss;
setInterval(function () {
mem = process.memoryUsage();
}, 10*1000);
var messages = [];
var rss = updateRSS();
everyone.now.distributeMessage = function(message){
var messagetime = (new Date()).getTime();
// var mem = process.memoryUsage();
console.log(mem);
console.log(rss);
console.log('User '+this.now.name+' added message ' +message + messagetime + ' ' + mem + ' mem: ' + rss);
everyone.now.receiveMessage(this.now.name, message, messagetime);
messages.push([this.now.name, message, messagetime]);
console.log(messages);
};
i am pushing the messages into the messages = [], as per line:
messages.push([this.now.name, message, messagetime]);
here is the html file, i am using:
<script type="text/javascript" src="http://127.0.0.1:9080/nowjs/now.js"></script>
<script type="text/javascript">
$(function(){
//submit new messages when the user hits enter if the message isnt blank
now.receiveMessage = function(name, message, messagetime){
$("#messages").append('<br />' + '' + name + '' + ': ' + message +messagetime);
}
$("#text-input").keypress(function (e) {
if (e.keyCode != 13 /* Return */) return;
now.distributeMessage($("#text-input").val());
$("#text-input").attr("value", ""); // clear the entry field.
});
$("#send-button").click(function(){
now.distributeMessage($("#text-input").val());
$("#text-input").val("");
});
now.name = "${user}";
});
</script>
<div id="chat">
<div id="log"></div>
<div id="messages"></div>
<input type="text" id="text-input" />
<input type="button" value="Send" id="send-button" />
</div>
<ul id="status">
<li><a id="usersLink" href="#">5 users</a></li>
<li>uptime: <span id="uptime">?</span></li>
<li>memory: <span id="rss">?</span>mb RSS</li>
</ul>
but i dont see how to redisplay the already posted messages back, when the user refreshes the page?
any advice much appreciated.

Resources