Chain filter conditions dynamically - rethinkdb

How to chain multiple conditions in RethinkDB? This is what I got right now and what works if I only pass live or sports as a parameter. As soon as I pass the live and sports parameter, sports obviously always overwrites the filter variable and the live parameter is ignored.
app.get('/bets', function (req, res) {
var live = req.query.live;
var sports = req.query.sports;
var filter = {};
if (live === undefined) {
filter = r.or(r.row('live').eq(0), r.row('live').eq(1));
} else {
filter.live = parseInt(live);
}
if (sports !== undefined) {
var sports = sports.split(',');
filter = function (doc) {
return r.expr(sports).contains(doc("sport"));
}
}
r.table('bets').filter(filter).limit(100).run(connection, function(err, cursor) {
// ...
});
});

You can chain filters with RethinkDB.
Something along the lines of this (warning, untested) :
app.get('/bets', function (req, res) {
var live = req.query.live;
var sports = req.query.sports;
var liveFilter, sportFilter;
if (live === undefined) {
liveFilter = r.or(r.row('live').eq(0), r.row('live').eq(1));
} else {
liveFilter = function (doc) { return true; };
}
if (sports !== undefined) {
sports = sports.split(','); // no need to redefine the variable here
sportFilter = function (doc) {
return r.expr(sports).contains(doc("sport"));
}
} else {
sportFilter = function (doc) { return true; };
}
r.table('bets')
.filter(liveFilter) // apply the first filter
.filter(sportsFilter) // apply the second filter
.limit(100)
.run(connection, function(err, cursor) {
// ...
});
});
Alternatively you could make one filter function that would handle both the live and sport filters (equally untested, this is to get you started) :
app.get('/bets', function (req, res) {
var live = req.query.live;
var sports = req.query.sports.split(',');
var filter = function(doc){
var sportPass, livePass;
if (live === undefined) {
livePass = r.or(r.row('live').eq(0), r.row('live').eq(1))(doc);
} else {
livePass = parseInt(live); // not sure what you meant by filter.live here
}
if (sports !== undefined) {
sportPass = r.expr(sports).contains(doc("sport"));
}
return sportPass && livePass;
};
r.table('bets').filter(filter).limit(100).run(connection, function(err, cursor) {
// ...
});
});

Related

How do I select a range and change font color of specific words in Outlook web add-ins

In Outlook web add-in, I want to select text from email body, keep it as tracked object and then apply styling on it like we do in Word web add-in. In the Word, I do it the following way:
//used to store current selected range
var selection=null;
$scope.getSelectedText = function () {
Word.run(function (context) {
if (selection) {
context.trackedObjects.remove(selection);
}
selection = context.document.getSelection();
context.trackedObjects.add(selection);
context.load(selection, 'text');
return context.sync()
.then(function () {
if (!selection.text) {
systemService.errorHandler("Please select any text from the document");
return false;
}
}).then(context.sync);
})
.catch(systemService.errorHandler);
};
//highlight Words in the selected range or body
$scope.highlightWords = function (item) {
var color = systemService.getColor(item.gradeText);
var filteredWords = JSON.parse(localStorage.getItem("List")) || [];
var promise = new OfficeExtension.Promise(function (resolve, reject) { resolve(null); });
Word.run(function (context) {
var selectedRange = (selection) ? selection : context.document.body;
selectedRange.load('text');
return context.sync().then(function () {
if (selectedRange.text == "") {
systemService.showNotification("Alert:", "No text found in the document!");
return;
}
filteredWords.forEach(function (word) {
promise = promise.then(function () {
return highlightRange(word, color);
})
});
});
}).catch(function (error) {
console.log('Error: ' + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
console.log('Debug info: ' + JSON.stringify(error.debugInfo));
}
});
}
function highlightRange(word, color) {
return Word.run(selection, function (context) {
var range = (selection) ? selection : context.document.body;
var searchResults = null;
searchResults = range.search(word, { ignorePunct: true, matchCase: false, matchWholeWord: true });
searchResults.load('font');
return context.sync().then(function () {
for (var i = 0; i < searchResults.items.length; i++) {
searchResults.items[i].font.color = color;
searchResults.items[i].font.bold = true;
}
}).then(context.sync());
}).catch(function (error) {
console.log('Error: ' + JSON.stringify(error));
if (error instanceof OfficeExtension.Error) {
console.log('Debug info: ' + JSON.stringify(error.debugInfo));
}
});
}
//highlight Words in the selected range or body
I have tried multiple ways to do but there is a problem while keeping track of the selected object. In Word, we can save the range and manipulate it overtime as needed, but in Outlook, the user have to keep the content selected in order to perform operation on it (like changing font color etc.). Also, do we have any font property available for outlook web add-ins like Word?

Vue - DOM is not updating when doing .sort() on array

I am trying to sort some JSON data using Vue. The data gets changed when checking via Vue console debugger, but the actual DOM doesn't get updated.
This is my Vue code:
Array.prototype.unique = function () {
return this.filter(function (value, index, self) {
return self.indexOf(value) === index;
});
};
if (!Array.prototype.last) {
Array.prototype.last = function () {
return this[this.length - 1];
};
};
var vm = new Vue({
el: "#streetleague-news",
data: {
allItems: [],
itemTypes: [],
itemTypesWithHeading: [],
selectedType: "All",
isActive: false,
sortDirection: "newFirst",
paginate: ['sortedItems']
},
created() {
axios.get("/umbraco/api/NewsLibraryApi/getall")
.then(response => {
// JSON responses are automatically parsed.
this.allItems = response.data;
this.itemTypes = this.allItems.filter(function (x) {
return x.Tag != null && x.Tag.length;
}).map(function (x) {
return x.Tag;
}).unique();
});
},
computed: {
isAllActive() {
return this.selectedType === "All";
},
filteredItems: function () {
var _this = this;
return _this.allItems.filter(function (x) {
return _this.selectedType === "All" || x.Tag === _this.selectedType;
});
},
sortedItems: function () {
var _this = this;
var news = _this.filteredItems;
if (_this.sortDirection === 'newFirst') {
news.sort(function (a, b) {
return new Date(b.PostDate) - new Date(a.PostDate);
});
} else {
news.sort(function (a, b) {
return new Date(a.PostDate) - new Date(b.PostDate);
});
}
return news;
}
},
methods: {
onChangePage(sortedItems) {
// update page of items
this.sortedItems = sortedItems;
}
}
});
This is an HTML part:
<paginate class="grid-3 flex" name="sortedItems" :list="sortedItems" :per="12" ref="paginator">
<li class="flex" v-for="item in paginated('sortedItems')">
The bit that seems not to be working is the sortedItems: function () {....
Can anyone see why the DOM is not updating?
The most probable is that sort() method doesn't recognize Date object precedence. Use js timestamp instead:
if (_this.sortDirection === 'newFirst') {
news.sort(function (a, b) {
var dateA = new Date(a.PostDate);
var dateB = new Date(b.PostDate);
return dateB.valueOf() - dateA.valueOf();
});
} else {
news.sort(function (a, b) {
var dateA = new Date(a.PostDate);
var dateB = new Date(b.PostDate);
return dateA.valueOf() - dateB.valueOf();
});
}
Got there eventually - thanks for your help
sortedItems: function () {
var _this = this;
var news = _this.allItems;
if (_this.sortDirection === 'newFirst') {
news.sort(function (a, b) {
var dateA = new Date(a.PostDate);
var dateB = new Date(b.PostDate);
return dateB.valueOf() - dateA.valueOf();
});
} else {
news.sort(function (a, b) {
var dateA = new Date(a.PostDate);
var dateB = new Date(b.PostDate);
return dateA.valueOf() - dateB.valueOf();
})
}
return news.filter(x => {
return _this.selectedType === "All" || x.Tag ===
_this.selectedType;
});
}

nightwatch assert ALL elements, not ANY

I'm trying to test that, when the Submit button is clicked on an empty form, all the "please fill in this field" labels are displayed.
I'm doing so with this:
page.click('#btn_submit');
page.expect.element('#validation_label_required').to.be.visible;
where #validation_label_required is represented by the CSS selector:
input[required] ~ p.error-message-required
However, this test passes if ANY of the validation labels are visible. The test should only pass if they ALL are.
How can I achieve this?
You will need to create a custom assertion for that where you locate all elements by selenium commands and then loop to verify condition. It should look something like this
var util = require('util');
exports.assertion = function (elementSelector, expectedValue, msg) {
this.message = msg || util.format('Testing if elements located by "%s" are visible', elementSelector);
this.expected = expectedValue;
this.pass = function (value) {
return value === this.expected;
};
this.value = function (result) {
return result;
};
this.command = function (callback) {
var that = this.api;
this.api.elements('css selector',elementSelector, function (elements) {
elements.value.forEach(function(element){
that.elementIdDisplayed(element.ELEMENT,function(result){
if(!result.value){
callback(false);
}
});
});
callback(true);
});
return this;
};
};
I've just ended up with another custom assertion that check how many elements are visible by given css selector.
/**
* Check how many elements are visible by given css selector.
*
*/
var util = require('util');
exports.assertion = function(elementSelector, expectedCount, msg) {
this.message = msg || util.format('Asserting %s elements located by css selector "%s" are visible', expectedCount, elementSelector);
this.expected = expectedCount;
this.count = 0;
this.pass = function(value) {
return value === this.expected;
};
this.value = function(result) {
return this.count;
};
this.command = function(callback) {
var me = this, elcount = 0;
this.count = 0;
this.api.elements('css selector', elementSelector, function(elements) {
if(elements.value && elements.value.length > 0){
elcount = elements.value.length;
}else{
return callback(false);
}
elements.value.forEach(function(element) {
me.api.elementIdDisplayed(element.ELEMENT, function(result) {
if (result.value) {
me.count++;
}
elcount--;
if (elcount === 0) {
callback(me.count);
}
});
});
});
};
};

cluster filter geojson mapbox

Im trying to call a my geojson files that were transform to cluster via a filter, but it doesnt work.I apply an alert to the filter "san pedro" and it works but the cluster was set to active.
in
var marcadores = L.mapbox.featureLayer('geojson/todos.geojson').on('ready', function(e) {
var clusterGroup1 = new L.MarkerClusterGroup();
e.target.eachLayer(function(layer1) {
clusterGroup1.addLayer(layer1);
});
mapa.addLayer(clusterGroup1);
});
$('.menu-ui a').on('click', function() {
var filter = $(this).data('filter');
alert(filter);
$(this).addClass('active').siblings().removeClass('active');
marcadores.setFilter(function(f) {
alert(filter === 'sanpedro');
return (filter === 'all') ? true : f.properties[filter] === true;
});
return false;
});
The filter will not update the cluster group layer. You have to update it too.
var marcadores = L.mapbox.featureLayer('geojson/todos.geojson');
var clusterGroup1 = new L.MarkerClusterGroup();
mapa.addLayer(clusterGroup1);
marcadores.on('ready', function(e) {
clusterGroup1.clearLayers();
e.target.eachLayer(function(layer1) {
clusterGroup1.addLayer(layer1);
});
});
$('.menu-ui a').on('click', function() {
var filter = $(this).data('filter');
alert(filter);
$(this).addClass('active').siblings().removeClass('active');
marcadores.setFilter(function(f) {
alert(filter === 'sanpedro');
return (filter === 'all') ? true : f.properties[filter] === true;
});
marcadores.fireEvent('ready');
return false;
});

Cached data returned when making same Web API call consecutively using Breeze.js

I am facing a strange issue while writing a Breeze.js with Durandal SPA (largely based on John Papa's Great SPA Jumpstart (https://github.com/johnpapa/PluralsightSpaJumpStartFinal) training ), the issue when a try to make the same server API call multiple times consecutively the server is hit only once and one the second call it seems I get cached data (call doesn't even hit server), this can be replicated in Jumpstart sample too, below is the modified code to replicate this on Jumpstart
var activate = function () {
for (var i = 0 ; i < 2 ; i++) {
datacontext.getSessionPartials(sessions, true);
}
};
var activate = function () {
for (var i = 0 ; i < 2 ; i++)
{
datacontext.getSpeakerPartials(speakers, true);
}
};
Edit- Updated with the complete code :
Code of my Viewmodel
define(['services/datacontext'], function (datacontext) {
var speakers = ko.observableArray();
var activate = function () {
for (var i = 0 ; i < 2 ; i++)
{
datacontext.getSpeakerPartials(speakers, true);
}
};
var refresh = function () {
return datacontext.getSpeakerPartials(speakers, true);
};
var vm = {
activate: activate,
speakers: speakers,
title: 'Speakers',
refresh: refresh
};
return vm;
});
Below is code of my datacontext/service :
define([
'durandal/system',
'services/model',
'config',
'services/logger',
'services/breeze.partial-entities'],
function (system, model, config, logger, partialMapper) {
var EntityQuery = breeze.EntityQuery;
var manager = configureBreezeManager();
var orderBy = model.orderBy;
var entityNames = model.entityNames;
var getSpeakerPartials = function (speakersObservable, forceRemote) {
if (!forceRemote) {
var p = getLocal('Persons', orderBy.speaker);
if (p.length > 0) {
speakersObservable(p);
return Q.resolve();
}
}
var query = EntityQuery.from('Speakers')
.select('id, firstName, lastName, imageSource')
.orderBy(orderBy.speaker);
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
var list = partialMapper.mapDtosToEntities(
manager, data.results, entityNames.speaker, 'id');
if (speakersObservable) {
speakersObservable(list);
}
log('Retrieved [Speaker] from remote data source',
data, true);
}
};
var getSessionPartials = function (sessionsObservable, forceRemote) {
if (!forceRemote) {
var s = getLocal('Sessions', orderBy.session);
if (s.length > 3) {
// Edge case
// We need this check because we may have 1 entity already.
// If we start on a specific person, this may happen. So we check for > 2, really
sessionsObservable(s);
return Q.resolve();
}
}
var query = EntityQuery.from('Sessions')
.select('id, title, code, speakerId, trackId, timeSlotId, roomId, level, tags')
.orderBy('timeSlotId, level, speaker.firstName');
return manager.executeQuery(query)
.then(querySucceeded)
.fail(queryFailed);
function querySucceeded(data) {
var list = partialMapper.mapDtosToEntities(
manager, data.results, entityNames.session, 'id');
if (sessionsObservable) {
sessionsObservable(list);
}
log('Retrieved [Sessions] from remote data source',
data, true);
}
};
var getSessionById = function(sessionId, sessionObservable) {
// 1st - fetchEntityByKey will look in local cache
// first (because 3rd parm is true)
// if not there then it will go remote
return manager.fetchEntityByKey(
entityNames.session, sessionId, true)
.then(fetchSucceeded)
.fail(queryFailed);
// 2nd - Refresh the entity from remote store (if needed)
function fetchSucceeded(data) {
var s = data.entity;
return s.isPartial() ? refreshSession(s) : sessionObservable(s);
}
function refreshSession(session) {
return EntityQuery.fromEntities(session)
.using(manager).execute()
.then(querySucceeded)
.fail(queryFailed);
}
function querySucceeded(data) {
var s = data.results[0];
s.isPartial(false);
log('Retrieved [Session] from remote data source', s, true);
return sessionObservable(s);
}
};
var cancelChanges = function() {
manager.rejectChanges();
log('Canceled changes', null, true);
};
var saveChanges = function() {
return manager.saveChanges()
.then(saveSucceeded)
.fail(saveFailed);
function saveSucceeded(saveResult) {
log('Saved data successfully', saveResult, true);
}
function saveFailed(error) {
var msg = 'Save failed: ' + getErrorMessages(error);
logError(msg, error);
error.message = msg;
throw error;
}
};
var primeData = function () {
var promise = Q.all([
getLookups(),
getSpeakerPartials(null, true)])
.then(applyValidators);
return promise.then(success);
function success() {
datacontext.lookups = {
rooms: getLocal('Rooms', 'name', true),
tracks: getLocal('Tracks', 'name', true),
timeslots: getLocal('TimeSlots', 'start', true),
speakers: getLocal('Persons', orderBy.speaker, true)
};
log('Primed data', datacontext.lookups);
}
function applyValidators() {
model.applySessionValidators(manager.metadataStore);
}
};
var createSession = function() {
return manager.createEntity(entityNames.session);
};
var hasChanges = ko.observable(false);
manager.hasChangesChanged.subscribe(function(eventArgs) {
hasChanges(eventArgs.hasChanges);
});
var datacontext = {
createSession: createSession,
getSessionPartials: getSessionPartials,
getSpeakerPartials: getSpeakerPartials,
hasChanges: hasChanges,
getSessionById: getSessionById,
primeData: primeData,
cancelChanges: cancelChanges,
saveChanges: saveChanges
};
return datacontext;
//#region Internal methods
function getLocal(resource, ordering, includeNullos) {
var query = EntityQuery.from(resource)
.orderBy(ordering);
if (!includeNullos) {
query = query.where('id', '!=', 0);
}
return manager.executeQueryLocally(query);
}
function getErrorMessages(error) {
var msg = error.message;
if (msg.match(/validation error/i)) {
return getValidationMessages(error);
}
return msg;
}
function getValidationMessages(error) {
try {
//foreach entity with a validation error
return error.entitiesWithErrors.map(function(entity) {
// get each validation error
return entity.entityAspect.getValidationErrors().map(function(valError) {
// return the error message from the validation
return valError.errorMessage;
}).join('; <br/>');
}).join('; <br/>');
}
catch (e) { }
return 'validation error';
}
function queryFailed(error) {
var msg = 'Error retreiving data. ' + error.message;
logError(msg, error);
throw error;
}
function configureBreezeManager() {
breeze.NamingConvention.camelCase.setAsDefault();
var mgr = new breeze.EntityManager(config.remoteServiceName);
model.configureMetadataStore(mgr.metadataStore);
return mgr;
}
function getLookups() {
return EntityQuery.from('Lookups')
.using(manager).execute()
.then(processLookups)
.fail(queryFailed);
}
function processLookups() {
model.createNullos(manager);
}
function log(msg, data, showToast) {
logger.log(msg, data, system.getModuleId(datacontext), showToast);
}
function logError(msg, error) {
logger.logError(msg, error, system.getModuleId(datacontext), true);
}
//#endregion
});
Below is the code for BreezeController/WebApi
namespace CodeCamper.Controllers
{
[BreezeController]
public class BreezeController : ApiController
{
readonly EFContextProvider<CodeCamperDbContext> _contextProvider =
new EFContextProvider<CodeCamperDbContext>();
[HttpGet]
public string Metadata()
{
return _contextProvider.Metadata();
}
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _contextProvider.SaveChanges(saveBundle);
}
[HttpGet]
public object Lookups()
{
var rooms = _contextProvider.Context.Rooms;
var tracks = _contextProvider.Context.Tracks;
var timeslots = _contextProvider.Context.TimeSlots;
return new {rooms, tracks, timeslots};
}
[HttpGet]
public IQueryable<Session> Sessions()
{
return _contextProvider.Context.Sessions;
}
[HttpGet]
public IQueryable<Person> Persons()
{
return _contextProvider.Context.Persons;
}
[HttpGet]
public IQueryable<Person> Speakers()
{
return _contextProvider.Context.Persons
.Where(p => p.SpeakerSessions.Any());
}
}
}
Please help/advise.

Resources