Ionic 5 : Webrtc remote video not displaying - ionic-framework

import { Component, OnInit, ElementRef, ViewChild } from '#angular/core';
import { Socket } from 'ngx-socket-io';
import { ToastController } from '#ionic/angular';
import { AppointmentService } from 'src/app/services/appointment.service';
#Component({
selector: 'app-videocall',
templateUrl: './videocall.page.html',
styleUrls: ['./videocall.page.scss'],
})
export class VideocallPage implements OnInit {
#ViewChild('localVideo', { static: true }) localVideo: ElementRef;
#ViewChild('remoteVideo', { static: true }) remoteVideo: ElementRef;
consultationRoomId: any;
callBtn: any;
muteBtn: any;
localStream: MediaStream;
remoteStream: MediaStream;
rtcPeerConnection: RTCPeerConnection;
constructor(public socket: Socket, private toastCtrl: ToastController, private appoint: AppointmentService,
private elRef: ElementRef) { }
ngOnInit() {
this.callBtn = document.getElementById("call");
this.muteBtn = document.getElementById("mute");
var endBtn = document.getElementById("end");
var divConsultingRoom = document.getElementById("consultingRoom");
var iceServers = {
'iceServers': [
{ urls: 'stun:stun.services.mozilla.com' },
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:stun01.sipphone.com' },
{ urls: 'stun:stun.ekiga.net' },
{ urls: 'stun:stun.fwdnet.net' },
{ urls: 'stun:stun.ideasip.com' },
{ urls: 'stun:stun.iptel.org' },
{ urls: 'stun:stun.rixtelecom.se' },
{ urls: 'stun:stun.schlund.de' },
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'stun:stun1.l.google.com:19302' },
{ urls: 'stun:stun2.l.google.com:19302' },
{ urls: 'stun:stun3.l.google.com:19302' },
{ urls: 'stun:stun4.l.google.com:19302' },
{ urls: 'stun:stunserver.org' },
{ urls: 'stun:stun.softjoys.com' },
{ urls: 'stun:stun.voiparound.com' },
{ urls: 'stun:stun.voipbuster.com' },
{ urls: 'stun:stun.voipstunt.com' },
{ urls: 'stun:stun.voxgratia.org' },
{ urls: 'stun:stun.xten.com' },
{
urls: 'turn:192.158.29.39:3478?transport=udp',
credential: 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
username: '28224511:1379330808'
},
{
urls: 'turn:192.158.29.39:3478?transport=tcp',
credential: 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
username: '28224511:1379330808'
}
]
}
var streamConstraints = { audio: true, video: true };
var isCaller;
//this.consultationRoomId = this.appoint.getConsultationId();
this.consultationRoomId = '1234';
this.socket.connect();
this.socket.on('created', (room) => {
//debugger;
alert('Starting consultation');
navigator.mediaDevices.getUserMedia(streamConstraints).then((stream) => {
this.localStream = stream;
this.localVideo.nativeElement.srcObject = stream;
isCaller = true;
}).catch(function (err) {
console.log('An error ocurred when accessing media devices', err);
});
});
this.socket.on('joined', (room) => {
alert('Joining consultation');
navigator.mediaDevices.getUserMedia(streamConstraints).then((stream) => {
this.localStream = stream;
this.localVideo.nativeElement.srcObject = stream;
this.socket.emit('ready', this.consultationRoomId);
}).catch(function (err) {
console.log('An error ocurred when accessing media devices', err);
});
});
this.socket.on('disconnect', (room) => {
console.log('Doctor has ended the consultation>>>' + room);
});
this.socket.on('candidate', (event) => {
var candidate = new RTCIceCandidate({
sdpMLineIndex: event.label,
candidate: event.candidate
});
this.rtcPeerConnection.addIceCandidate(candidate);
});
this.socket.on('ready', () => {
if (isCaller) {
this.rtcPeerConnection = new RTCPeerConnection(iceServers);
this.rtcPeerConnection.onicecandidate = this.onIceCandidate;
this.rtcPeerConnection.ontrack = this.onAddStream;
this.rtcPeerConnection.addTrack(this.localStream.getTracks()[0], this.localStream);
this.rtcPeerConnection.addTrack(this.localStream.getTracks()[1], this.localStream);
this.rtcPeerConnection.createOffer()
.then(sessionDescription => {
this.rtcPeerConnection.setLocalDescription(sessionDescription);
this.socket.emit('offer', {
type: 'offer',
sdp: sessionDescription,
room: this.consultationRoomId
});
})
.catch(error => {
console.log(error)
})
}
});
this.socket.on('offer', (event) => {
if (!isCaller) {
this.rtcPeerConnection = new RTCPeerConnection(iceServers);
this.rtcPeerConnection.onicecandidate = this.onIceCandidate;
this.rtcPeerConnection.ontrack = this.onAddStream;
this.rtcPeerConnection.addTrack(this.localStream.getTracks()[0], this.localStream);
this.rtcPeerConnection.addTrack(this.localStream.getTracks()[1], this.localStream);
this.rtcPeerConnection.setRemoteDescription(new RTCSessionDescription(event));
this.rtcPeerConnection.createAnswer()
.then(sessionDescription => {
this.rtcPeerConnection.setLocalDescription(sessionDescription);
this.socket.emit('answer', {
type: 'answer',
sdp: sessionDescription,
room: this.consultationRoomId
});
})
.catch(error => {
console.log(error)
})
}
});
this.socket.on('answer', (event) => {
console.log("on answer>>>>" + event);
this.rtcPeerConnection.setRemoteDescription(new RTCSessionDescription(event));
})
}
call() {
//this.divConsultingRoom.style = "display: block;";
this.socket.emit('create or join', this.consultationRoomId);
}
mute() {
if (this.muteBtn.innerHTML == "Mute") {
this.localStream.getAudioTracks()[0].enabled = false;
this.muteBtn.innerHTML = "Unmute";
}
else {
this.localStream.getAudioTracks()[0].enabled = true;
this.muteBtn.innerHTML = "Mute";
}
}
end() {
this.socket.emit('disconnect', this.consultationRoomId);
}
onIceCandidate = (event) => {
if (event.candidate) {
console.log('sending ice candidate');
this.socket.emit('candidate', {
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate,
room: this.consultationRoomId
})
}
}
onAddStream = (event) => {
this.remoteVideo.nativeElement.srcObject = event.streams[0];
this.remoteStream = event.streams[0];
}
}
Below is the HTML page as well
<ion-content>
<div id="consultingRoom">
<video id="localVideo" #localVideo inline autoplay></video>
<video id="remoteVideo" #remoteVideo inline autoplay></video>
</div>
<ion-button id="call" color="primary" (click)="call()">Call</ion-button>
<ion-button id="mute" color="secondary" (click)="mute()">Mute</ion-button>
<ion-button id="end" color="tertiary" (click)="end()">End</ion-button>
</ion-content>
The event.streams[0] object in addStreamMethod shows the remote MediaStream with receiver's id but the remoteVideo element on front end is still blank.
The signalling server is a node socket server running on AWS EC2 instance.
Below is the debug for remote Media Stream
RemoteMediaStream console debug
Below is the webrtc internals logs from Chrome
9/3/2020, 4:39:00 PM
transceiverAdded
9/3/2020, 4:39:00 PM
transceiverAdded
9/3/2020, 4:39:00 PM
createOffer
options: {offerToReceiveVideo: -1, offerToReceiveAudio: -1, voiceActivityDetection: true, iceRestart: false}
9/3/2020, 4:39:00 PM negotiationneeded
9/3/2020, 4:39:00 PM
createOfferOnSuccess
9/3/2020, 4:39:00 PM
setLocalDescription
9/3/2020, 4:39:00 PM
transceiverModified
9/3/2020, 4:39:00 PM
transceiverModified
9/3/2020, 4:39:00 PM
signalingstatechange
9/3/2020, 4:39:00 PM setLocalDescriptionOnSuccess
9/3/2020, 4:39:00 PM
icegatheringstatechange
9/3/2020, 4:39:00 PM
icecandidate (host)
9/3/2020, 4:39:00 PM
icecandidate (host)
9/3/2020, 4:39:00 PM
icecandidate (host)
9/3/2020, 4:39:00 PM
icecandidate (host)
9/3/2020, 4:39:00 PM
icecandidate (host)
9/3/2020, 4:39:00 PM
icecandidate (host)
9/3/2020, 4:39:00 PM
icecandidate (host)
9/3/2020, 4:39:00 PM
icecandidate (host)
9/3/2020, 4:39:00 PM
icecandidateerror
9/3/2020, 4:39:00 PM
icecandidateerror
9/3/2020, 4:39:00 PM
icecandidateerror
9/3/2020, 4:39:00 PM
icecandidateerror
9/3/2020, 4:39:00 PM
icecandidate (srflx)
9/3/2020, 4:39:00 PM
icecandidate (srflx)
9/3/2020, 4:39:00 PM
setRemoteDescription
9/3/2020, 4:39:00 PM
icecandidate (srflx)
9/3/2020, 4:39:00 PM
transceiverModified
9/3/2020, 4:39:00 PM
transceiverModified
9/3/2020, 4:41:38 PM
signalingstatechange
9/3/2020, 4:41:38 PM setRemoteDescriptionOnSuccess
9/3/2020, 4:41:39 PM
icecandidate (srflx)
9/3/2020, 4:41:39 PM
icecandidate (srflx)
9/3/2020, 4:41:39 PM
icecandidate (srflx)
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidate (srflx)
9/3/2020, 4:41:39 PM
icecandidate (srflx)
9/3/2020, 4:41:39 PM
icecandidate (srflx)
9/3/2020, 4:41:39 PM
icecandidate (srflx)
9/3/2020, 4:41:39 PM
icecandidate (srflx)
9/3/2020, 4:41:39 PM
icecandidate (srflx)
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icecandidateerror
9/3/2020, 4:41:39 PM
icegatheringstatechange
complete
9/3/2020, 4:41:39 PM
addIceCandidate (host)
9/3/2020, 4:41:39 PM
addIceCandidate (host)
9/3/2020, 4:41:39 PM
iceconnectionstatechange
checking
9/3/2020, 4:41:39 PM
addIceCandidate (host)
9/3/2020, 4:41:39 PM
iceconnectionstatechange (legacy)
checking
9/3/2020, 4:41:39 PM
connectionstatechange
connecting
9/3/2020, 4:41:39 PM
addIceCandidate (host)
9/3/2020, 4:41:39 PM
addIceCandidate (host)
9/3/2020, 4:41:39 PM
addIceCandidate (host)
9/3/2020, 4:41:39 PM
addIceCandidate (srflx)
9/3/2020, 4:41:39 PM
addIceCandidate (srflx)
9/3/2020, 4:41:54 PM
iceconnectionstatechange
disconnected
9/3/2020, 4:41:54 PM
iceconnectionstatechange (legacy)
failed
9/3/2020, 4:41:54 PM
connectionstatechange
failed
Currently I am only testing on browser, have not tested on Android and IOS yet
Please let me know what am I missing?

Related

How to add points on leaflet map from local geojson file?

I'm trying to display points from a local geojson file (created with overpass turbo) on a leaflet map, but since I'm a total newbie I can't get it right
Here's what I have now:
var mymap = L.map('mapid').setView([57.1497, -2.0943], 13);
var Esri_WorldGrayCanvas = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}',
{attribution: 'Tiles © Esri — Esri, DeLorme, NAVTEQ', maxZoom: 16 });
Esri_WorldGrayCanvas.addTo(mymap);
var CartoDB_Voyager = L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', {
attribution: '© OpenStreetMap contributors © CARTO',
subdomains: 'abcd',
maxZoom: 19
});
CartoDB_Voyager.addTo(mymap);
L.geoJSON(geojsonFeature).addTo(mymap);
$.ajax({
dataType: "json",
url: "AllAberdeen.geojson",
success: function(data) {
$(data.features).each(function(key, data) {
console.log(result)
result.features.forEach(function(point) {
var lon = point.geometry.coodrinates.lon;
var lat = point.geometry.coodrinates.lat;
var circle = L.circle( [lon, lat], {
color: 'red',
opacity: 0,
fillColor: 'red',
fillOpacity: 0.8
})
circle.addTo(mymap)
});
});
}
}).error(function() {});
I will be grateful for any help
Try to create a geoJson layergroup:
$.ajax({
dataType: "json",
url: "AllAberdeen.geojson",
success: function(data) {
console.log(data);
L.geoJSON(data).addTo(mymap);
}
}).error(function(error) {
console.log(error);
});

file-transfer incidence in IOS IONIC 3

I commented that I am developing an application in IONIC 3 and I am working with the native file transfer library.
At the moment of wanting to download a file in IOS it does not execute it, not so when it is installed or debugged in android.
According to the ionic documentation I am implementing it correctly and I do not understand why or what is missing so that IOS can execute the transfer.download which is the instruction that is not executed
and I get the following error in the console:
console.warn: 'Native: tried accessing the FileTransfer plugin but it's not installed.
Below I leave my code:
import { FileTransfer, FileTransferObject } from '#ionic-native/file-transfer';
import { File } from '#ionic-native/file';
import { LoadingController } from 'ionic-angular';
declare var cordova: any;
#IonicPage()
#Component({
selector: 'page-liquidaciones',
templateUrl: 'liquidaciones.html',
})
export class LiquidacionesPage {
formLiquidaciones: FormGroup;
public txtCorreoLiquidacion;
rutUsuario: any;
resultado: any;
liquidaciones: any;
liquidacionesSeleccionadas:any={};
loading: any;
storageDirectory: string = '';
//private fileTransfer: FileTransferObject;
//private localPath = '';
constructor(public navCtrl: NavController,
public navParams: NavParams,
private alertCtrl: AlertController,
public formBuilder: FormBuilder,
public kiberKiberpro: KibernumKiberproProvider,
public databaseService: DatabaseServiceProvider,
private transfer: FileTransfer,
private file: File,
private androidPermissions: AndroidPermissions,
public loadingController: LoadingController,
public platform: Platform
){
this.formLiquidaciones = this.formBuilder.group({
txtCorreoLiquidacion: ['', Validators.required]
});
this.platform.ready().then(() => {
if(!this.platform.is('cordova')) {
return false;
}
if (this.platform.is('ios')) {
//this.storageDirectory = this.file.dataDirectory;
this.storageDirectory = cordova.file.dataDirectory;
}
else if(this.platform.is('android')) {
this.storageDirectory = cordova.file.externalRootDirectory + '/Download/';
this.androidPermissions.checkPermission(this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE).then(
result => {
if (result.hasPermission) {
// code
} else {
this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE).then(result => {
if (result.hasPermission) {
// code
}
});
}
},
err => this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE)
);
}
else {
return false;
}
});
this.databaseService.getSesion(2).then(result => {
this.rutUsuario = result.valor;
})
.catch( error => {
});
}
DescargarLiquidaciones(){
this.loading = this.loadingController.create({ content: "Descargando Liquidacion(es)..." });
const fileTransfer: FileTransferObject = this.transfer.create();
var enviarLiquidaciones = [];
for(var i in this.liquidacionesSeleccionadas) {
if(this.liquidacionesSeleccionadas[i]) {
enviarLiquidaciones.push(i);
}
}
if(enviarLiquidaciones.length == 0)
{
this.alerta("Debe seleccionar por lo menos una liquidación para que sea descargada.");
}
else
{
this.loading.present();
this.txtCorreoLiquidacion = '';
this.kiberKiberpro.DescargarEnviarLiquidaciones(this.rutUsuario,enviarLiquidaciones, this.txtCorreoLiquidacion).then((res) => {
this.resultado = res;
var respuesta = JSON.parse(this.resultado.data);
let datos: string = JWT(this.resultado.data);
if(respuesta.status == "200") {
let autorizacion = this.resultado.headers;
let nombreArchivo = datos.split("tmp/");
let urlFinal = datos;
fileTransfer.download(urlFinal , this.storageDirectory + nombreArchivo[1]).then((entry) => {
console.log("LLEGA ACA");
this.alerta("Se ha descargado el archivo de manera satisfactoria.");
console.log("LLEGA ACA 2");
this.loading.dismissAll();
console.log("LLEGA ACA 3");
this.databaseService.GuardaSQLlite(1, autorizacion.authorization);
this.navCtrl.setRoot(HomePage);
}, (error) => {
this.alerta("Hubo un error al momento de descargar el archivo. Si el problema persiste favor contactarse al 816 35 12 o 816 35 09.");
this.loading.dismissAll();
});
}
else if (respuesta.status == "201"){
this.alerta("Hubo un problema con el envío de la(s) liquidacion(es) al correo ingresado. Si el problema persiste favor contactarse al 816 35 12 o 816 35 09");
this.loading.dismissAll();
let autorizacion = this.resultado.headers;
this.databaseService.GuardaSQLlite(1, autorizacion.authorization);
}
else if (respuesta.status == "401"){
this.alerta("Token no válido.");
this.loading.dismissAll();
}
else{
this.alerta("Hubo un problema inesperado, Favor intente nuevamente. Si el problema persiste favor contactarse al 816 35 12 o 816 35 09");
this.loading.dismissAll();
}
}, (err) => {
this.alerta("Ha ocurrido un problema, intente nuevamente por favor. Si el error persiste pongase en contacto con el area de soporte.");
this.loading.dismissAll();
});
}
}
I remain attentive to your answers and I thank you in advance for your help and opinions
I forgot to put the information of my ionic which is the following:
Ionic:
ionic (Ionic CLI) : 4.1.2 (/usr/local/lib/node_modules/ionic)
Ionic Framework : ionic-angular 3.9.2
#ionic/app-scripts : 3.1.10
Cordova:
cordova (Cordova CLI) : 8.1.1 (cordova-lib#8.1.0)
Cordova Platforms : ios 4.5.4
Cordova Plugins : cordova-plugin-ionic-keyboard 2.1.3, cordova-plugin-ionic-webview 1.2.1, (and 6 other plugins)
System:
ios-deploy : 2.0.0
NodeJS : v8.12.0 (/usr/local/bin/node)
npm : 6.4.1
OS : macOS
Xcode : Xcode 9.4 Build version 9F1027a
It looks to me like your file transfer logic is not wrapped in a this.platform.ready() call. Could it be that there are times when this is called before platform ready (and thus, before the plugin is ready to be used)?

Test Report is not generating using 'protractor-angular-screenshot-reporter'

I am using POM concepts and all the instructions given :
https://npm.runkit.com/protractor-angular-screenshot-reporter
https://github.com/bcole/protractor-angular-screenshot-reporter/blob/master/README.md
but still no reports is generating. Is that anything I am lacking. Earlier I have used 'protractor-jasmine2-html-reporter' and it was working fine.
Console output I am getting is correct on running protractor conf.js using cmd:
4 specs, 3 failures
Finished in 32.847 seconds
[11:32:40] I/local - Shutting down selenium standalone server.
[11:32:40] I/launcher - 0 instance(s) of WebDriver still running
[11:32:40] I/launcher - chrome #01 failed 3 test(s)
[11:32:40] I/launcher - overall: 3 failed spec(s)
[11:32:40] E/launcher - Process exited with error code 1
Project Structure:
Project Structure
pages/AllevaHome.js
var AllevaHomePage = function() {
var logoutBtn = element(by.className('logoutbtn'));
this.isLogoutDisplays = function(){
var flag = logoutBtn.isDisplayed();
return flag
};
this.logout = function(){
logoutBtn.click();
};
};
module.exports = new AllevaHomePage();
pages/AllevaLogin.js
var AllevaLoginPage = function() {
var username = element(by.model('LoginViewModel.UserName'));<br>
var password = element(by.model('LoginViewModel.Password'));<br>
var loginBtn = element(by.className('orange-btn login_btn'));<br>
var securityAns = element(by.model('twoFactorModel.answer'));<br>
var proceedBtn = element(by.css('[value="Proceed"]'));<br>
this.get = function() {
browser.get('some url');
browser.manage().window().maximize();
};
function setUsername(user){
username.sendKeys(user);
};
function setPassword(pass){
password.sendKeys(pass);
};
function setAnswer(ans){
securityAns.sendKeys(ans);
};
this.login = function(user, pass, ans){
setUsername(user);
setPassword(pass);
loginBtn.click();
setAnswer(ans);
proceedBtn.click();
};
/* this.getGreetingText = function() {
return greeting.getText();
};*/
};
module.exports = new AllevaLoginPage();
testdata/LoginData.js
'use strict';
module.exports = {
LoginData: {
'Valid Username/Password': {username: 'someuser', password: 'somepass',
answer: 'someans'},
'Invalid Username/Correct Password': {username: 'testuser', password:
'Test#12345', answer: 'kusum'},
'Invalid Username/Invalid Password': {username: 'testuser', password:
'Test#1234', answer: 'kusum'},
'Valid Username/Invalid Password': {username: 'rohitnegi', password:
'Test#1234', answer: 'kusum'}
}
}
tests/AllevaLoginTest.js
var AllevaLoginObj = require('../pages/AllevaLogin.js');
var AllevaHomeObj = require('../pages/AllevaHome.js');
var LoginData = require('../testdata/LoginData.js');
var using = require('jasmine-data-provider');
describe('Checking Alleva Login Functionality', function() {
using(LoginData.LoginData, function(data, description) {
it('Login with: '+description, function() {
AllevaLoginObj.get();
AllevaLoginObj.login(data.username, data.password, data.answer);
expect(AllevaHomeObj.isLogoutDisplays());
})
});
afterEach(function() {
AllevaHomeObj.logout();
})
});
Conf.js:
var HtmlReporter = require('protractor-angular-screenshot-reporter');
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: [
'./tests/AllevaLoginTest.js'
],
capabilities: {
'browserName': 'chrome'
},
onPrepare: function() {
jasmine.getEnv().addReporter(new HtmlReporter({
baseDirectory: '/tmp/screenshots'
}).getJasmine2Reporter());
},
jasmineNodeOpts: {
onComplete: null,
isVerbose: true,
showColors: true,
includeStackTrace: true,
defaultTimeoutInterval: 2500000
}
};
Please let me know if you need anything else.

Mongodb remove objects

I have the following code:
Log.ts
import * as mongoose from "mongoose";
import ILog = require("./ILog");
interface ILogModel extends ILog, mongoose.Document { }
var logSchema = new mongoose.Schema({
title: String,
description: String,
date: Date,
});
var log = mongoose.model<ILogModel>("Log", logSchema);
export = log;
ILog.ts
interface ILog {
title: string;
description: string;
date: Date;
};
export = ILog;
In my app I generate Logs with the following code:
var log = {
title: "tag",
description: "test",
date: Date.now()
};
Log.create(log, function (err: any, remote: any) {
});
But when I do Log.remove( { }) nothing happens.
In ROBO 3T if I do db.getCollection('logs').remove({})
the log is cleared, but I don't understand how to do it in the app
Please help.
Log.remove({}, function (err: any) {
if (err) return console.log("err", err);
});
did the trick

Breezejs date always Dec 31, 1969

I am trying to bind to a date using breeze and knockout. The data returned from the BreezeController is as expected. But I see this in the debugger:
TripDate: function dependentObservable() {
__ko_proto__: function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
_latestValue: Wed Dec 31 1969 19:00:00 GMT-0500 (Eastern Standard Time)
__proto__: Invalid Date
The json data coming in back from the database server is:
TripDate: "2013-07-21T00:00:00.000"
Any idea why the date is "Invalid"?
use this in view model
ko.bindingHandlers.datepicker = {
init: function(element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
$(element).datepicker(options);
//handle the field changing
ko.utils.registerEventHandler(element, "change", function () {
var observable = valueAccessor();
observable($(element).datepicker("getDate"));
});
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).datepicker("destroy");
});
},
//update the control when the view model changes
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
$(element).datepicker("setDate", value);
}
};
then in html
data-bind="datepicker:tripDate"
Now you will get what u need ....also you can save the updated date
check it if you just want to display
ko.bindingHandlers.dateString = {
update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
var value = valueAccessor(),
allBindings = allBindingsAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
var pattern = allBindings.datePattern || 'MM/dd/yyyy';
$(element).text(valueUnwrapped.toString(pattern));
}
}
in html replace 'datepicker' with 'dateString'