const up = async () => { logger.info('Moving existing shared dashboards into new array format.'); const dashboards = await Dashboard.find({}).lean().exec(); const updatePromises = map(dashboards, async (dashboard) => { if (!dashboard.shareable) { dashboard.shareable = []; } const shareable = dashboard.shareable; shareable.unshift({ title: '~ Shareable', filter: dashboard.filter, visibility: dashboard.visibility, validDomains: dashboard.validDomains, createdAt: new Date(), }); return OldDashboardModel.updateOne( { _id: objectId(dashboard._id) }, { shareable, }, { safe: false, strict: false } ); }); await Promise.all(updatePromises); };
const down = async () => { logger.info('Moving first shared link in dashboards back into old format.'); const dashboards = await OldDashboardModel.find({}).exec(); const updatePromises = map(dashboards, (dashboard) => { if (!dashboard.shareable || dashboard.shareable.length < 1) { return Promise.resolve(); } const shareable = dashboard.shareable.shift(); return OldDashboardModel.updateOne( { _id: objectId(dashboard._id) }, { filter: shareable.filter, visibility: shareable.visibility, validDomains: shareable.validDomains, shareable: dashboard.shareable, }, { safe: false, strict: false } ); }); await Promise.all(updatePromises); };
export default function (lrsId, options) { const since = options.since && moment(new Date(options.since)) || false; const query = lrsId ? { lrs_id: lrsId } : {}; if (since && since.isValid()) { // apply a constraint on stored query.stored = { $gte: since.toDate() }; } logger.info('query: ', query); logger.info('Looking for statements...'); const statementStream = highland(Statement.find(query).select({ _id: 1, completedQueues: 1, processingQueues: 1 }).cursor()); statementStream.on('error', (err) => { logger.error(err); process.exit(); }); const batchSize = 100; const queueAddStream = statementStream .batch(batchSize) .flatMap((statements) => { const promises = map(statements, statement => // do something with the mongoose document new Promise((resolve, reject) => { addStatementToPendingQueues(statement, undefined, (err) => { if (err) return reject(err); return resolve(); }); })); return highland(Promise.all(promises)); }); queueAddStream.reduce(0, (val) => { const newValue = val + batchSize; logger.info(`Batch of ${batchSize} complete. Added ${newValue}`); return newValue; }).flatten().apply((totalCount) => { logger.info(`Added ${totalCount} statements back to the queue.`); process.exit(); }); }
export default function () { logger.info('Updating statement client ids...'); Client.find({}).lean() .then(docs => Promise.mapSeries(docs, doc => migrateDoc(doc)) ) .then(logSuccess, logError) .then(() => process.exit()); }
const clearPrefix = (prefix, callback) => { const redisClient = redis.createClient(); logger.info(`Clearing cache keys starting with "${prefix}"`); redisClient.keys(`${prefix}*`, (err, rows) => { async.each(rows, (row, callbackDelete) => { redisClient.del(row, callbackDelete); }, callback.bind(null, { total: rows.length })); }); };
.then(() => { totalHandled += statements.length; logger.info(`Finished batch of ${statements.length} (${totalHandled})`); return Statement.updateMany( { _id: { $in: updateIDs } }, { $addToSet: { completedQueues: jobType }, $pull: { processingQueues: jobType } }) .exec(); })
it('should create logger', function () { sinon.spy(window.console, 'info'); var information = 'Hello Firefox!'; logger = new Logger(); logger.info(information); assert.equal(window.console.info.args[0][0], information); assert.isNotNull(window.console.info.thisValues[0]); window.console.info.restore(); });
it('should create logger with window', function () { var mockWindow = new WindowMock(); var information = 'Hello Firefox!'; sinon.spy(mockWindow.console, 'info'); logger = new Logger(mockWindow); logger.info(information); assert.equal(mockWindow.console.info.args[0][0], information); assert.isNotNull(mockWindow.console.info.thisValues[0]); mockWindow.console.info.restore(); });
export default function () { logger.info('Updating download URLs to be CSVs...'); Download.find({}).lean() .then(docs => Promise.all(docs.map((doc) => { const shouldMigrate = doc.url.indexOf('.csv') !== (doc.url.length - 4); if (shouldMigrate) return migrateDoc(doc); logger.debug(`Not migrating ${doc.name}`); return Promise.resolve(); })) ) .then(logSuccess, logError) .then(() => process.exit()); }
export default function () { logger.info('Updating download paths...'); const cursor = Download.find({}).cursor(); const downloadStream = highland(cursor); downloadStream.on('error', (err) => { logger.error(err); process.exit(); }); downloadStream .map(updateDownload) .parallel(10) .reduce(0, count) .apply(logAndExit); }
function StyleFindBackground(/*string*/name) { // Finds the requested image, form factor and orientation add suffixes as appropriate. var isTablet = (screenSizeInInches > 6); var isLandscape = Ti.Gesture.orientation == Ti.UI.LANDSCAPE_LEFT || Ti.Gesture.orientation == Ti.UI.LANDSCAPE_RIGHT; name = name.split('.'); var ext = name.pop(); name.push(isLandscape ? 'Landscape' : 'Portrait'); if (osname == 'iphone' || osname == 'ipad') { name.push(isTablet ? 'Tablet' : 'Phone'); } name = name.join('-') + (isShort ? '-Short' : '') + '.' + ext; log.info('Find background in /images/' + name); return '/images/' + name; }
export default function () { logger.info('Migrating all/read to xapi/read scope...'); const prevScope = 'all/read'; const nextScope = 'xapi/read'; const filter = { scopes: prevScope }; const options = {}; const pushUpdate = { $push: { scopes: nextScope } }; const pullUpdate = { $pull: { scopes: prevScope } }; Client.updateMany(filter, pushUpdate, options) .then((result) => { if (result.nModified === 0) return result; return Client.updateMany(filter, pullUpdate, options); }) .then(logSuccess, logError) .then(() => process.exit()); }
export default function () { logger.info('Updating clients authorities...'); Client.find({}).lean() .then(docs => Promise.all(docs.map((doc) => { const hasConstructor = doc.authority !== undefined && doc.authority !== null; const shouldMigrate = hasConstructor && doc.authority.constructor === Object; // Because the Client model currently parses the authority and returns an Object. // It will always migrate. So keep calm and carry on migrating. if (shouldMigrate) return migrateDoc(doc); logger.debug(`Not migrating ${doc.title}`); return Promise.resolve(); })) ) .then(logSuccess, logError) .then(() => process.exit()); }
export default async function () { logger.info('Adding new cache paths...'); const cursor = querybuildercache.find().lean().cursor(); const cacheStream = highland(cursor); cacheStream.on('error', (err) => { logger.error(err); process.exit(); }); cacheStream .map(createSubPaths) .reject(isNull) .uniqBy(checkUnique) .batch(500) .map(saveBatch) .parallel(10) .reduce(0, count) .apply(logAndExit); };
.catch((error) => { logger.info( 'Duplicate keys detected. May indicate that thsis migration has already been run.', error.message ); });
.then((res) => { logger.info(`Completed batch of ${queryBuilderCaches.length}.`); return res; })
const logSuccess = results => logger.info(`${results.length} models updated`);
}).flatten().apply((totalCount) => { logger.info(`Added ${totalCount} statements back to the queue.`); process.exit(); });
assert.doesNotThrow(function () { logger.info('Hello Firefox!'); });
export default function (query, jobType, batchSize = 1000) { let jobHandler; switch (jobType) { default: logger.info(`No handler found for ${jobType}`); process.exit(); break; case STATEMENT_QUERYBUILDERCACHE_QUEUE: jobHandler = queryBuilderCacheStatementHandler; break; case STATEMENT_EXTRACT_PERSONAS_QUEUE: jobHandler = extractPersonasStatementHandler(getService()); break; } if (!query) { query = {}; } query.completedQueues = { $nin: [jobType] }; logger.info('Counting total statements...'); logger.debug('Query...', query); const handleJob = Promise.promisify(jobHandler); let totalHandled = 0; logger.info(`Batching in groups of ${batchSize}`); const statementStream = highland(Statement.find(query).batchSize(batchSize).cursor()); const handler = statementStream.batch(Number(batchSize)).flatMap((statements) => { const updateIDs = map(statements, statement => statement._id); const promise = handleJob(statements).catch((err) => { logger.error(err); return err; }); const allJobsDone = promise .then(() => { totalHandled += statements.length; logger.info(`Finished batch of ${statements.length} (${totalHandled})`); return Statement.updateMany( { _id: { $in: updateIDs } }, { $addToSet: { completedQueues: jobType }, $pull: { processingQueues: jobType } }) .exec(); }) .catch((err) => { logger.error(err); }); return highland(allJobsDone); }); handler.apply(() => { logger.info(`Ran handler on ${totalHandled} statements.`); process.exit(); }); }
const logSuccess = result => logger.info(`${result.nModified} clients updated`);
queueAddStream.reduce(0, (val) => { const newValue = val + batchSize; logger.info(`Batch of ${batchSize} complete. Added ${newValue}`); return newValue; }).flatten().apply((totalCount) => {
import statementWorker from 'worker/handlers/statement'; import importPersonasWorker from 'worker/handlers/importPersonas'; import logger from 'lib/logger'; import expirationNotification from 'worker/handlers/expirationNotification'; import orgUsageTracker from 'worker/handlers/orgUsageTracker'; import batchStatementDeletion from 'worker/handlers/batchStatementDeletion'; statementWorker({}); expirationNotification(); importPersonasWorker({}); orgUsageTracker(); batchStatementDeletion(); logger.info('STARTED WORKER'); if (process.send) process.send('ready');
const logAndExit = (totalCount) => { logger.info(`Updated ${totalCount} downloads.`); process.exit(); };
const down = async () => { logger.info('This migration created indexes that may be useful, please remove them manually.'); };
const logAndExit = (totalCount) => { logger.info(`Inserted ${totalCount} batches.`); process.exit(); };
handler.apply(() => { logger.info(`Ran handler on ${totalHandled} statements.`); process.exit(); });
function mainButtonGridClick(e) { var theButton = e.source; var dlg; log.info(theButton.id + ' button pressed (' + e + ')'); Ti.Analytics.featureEvent('com.noblecall.toolset.' + theButton.id); switch (theButton.id) { case 'armor': case 'great': case 'character': case 'conciliatory': case 'connecting': case 'collaborating': case 'test': showWebView(navController, mainButtons[theButton.id].text, mainButtons[theButton.id].url); break; case 'courageous': // We want a maximum of three buttons across the narrowest aspect of the device. var bg = new ButtonGrid({ viewWidth: Math.min(Ti.Platform.displayCaps.platformWidth, Ti.Platform.displayCaps.platformHeight), buttons: courageousButtons, buttonWidth: style.buttonGrid.width, buttonHeight: style.buttonGrid.height, click: courageousButtonClick }); var win = Ti.UI.createWindow({// Need a window to host the grid. anchorPoint: { x: 0, y: 0 }, barColor : style.win.barColor, title : L('courageous_conversation') }); win.add(bg.scrollview); navController.open(win); // Handle orientation and close events function relayoutCourageousWindow(e) { bg.relayout(Ti.Platform.displayCaps.platformWidth); } win.addEventListener('close', function courageousWindowClose(e) { Ti.Gesture.removeEventListener('orientationchange', relayoutCourageousWindow); }); Ti.Gesture.addEventListener('orientationchange', relayoutCourageousWindow); setTimeout(relayoutCourageousWindow, 1000); break; case 'identity': // There are 2 paths through identity. We need to ask the user whether they are a man or a woman. dlg = Ti.UI.createOptionDialog({ title : L('question_man'), options : [L('button_man'), L('button_woman'), L('button_cancel')], cancel : 2 }); dlg.addEventListener('click', function(e) { if(e.index != 2) { showWebView(navController, mainButtons[theButton.id].text, mainButtons[theButton.id].url[e.index]); } }); dlg.show(); break; default: dlg = Ti.UI.createAlertDialog({ title : 'Alert', message : "Button " + theButton.id + " is not implemented!", buttonNames : ['Ok'] }); dlg.show(); break; } }
const logSuccess = results => logger.info(`${results.length} clients updated`);
var _ = require('lib/underscore'); var log = require('lib/logger'); log.info('*** Device Attributes'); log.info('density: ' + Ti.Platform.displayCaps.density); log.info('dpi: ' + Ti.Platform.displayCaps.dpi); log.info('platformHeight: ' + Ti.Platform.displayCaps.platformHeight); log.info('platformWidth: ' + Ti.Platform.displayCaps.platformWidth); var osname = Ti.Platform.osname; if (osname === 'android') { log.info('xdpi: ' + Ti.Platform.displayCaps.xdpi); log.info('ydpi: ' + Ti.Platform.displayCaps.ydpi); log.info('logicalDensityFactor: ' + Ti.Platform.displayCaps.logicalDensityFactor); } // Calculate whether we're dealing with a "short" device on Android. var screenRatio = Ti.Platform.displayCaps.platformHeight / Ti.Platform.displayCaps.platformWidth; var isShort = (screenRatio == 3/4 || screenRatio == 4/3); // Calculate the scaling factor var scaleFactor = 1; // Based on density var scales = { 'xhigh' : 2, 'high': 1.5, 'medium' : 1, 'low' : 0.75 } if (osname == 'android') scaleFactor = scales[Ti.Platform.displayCaps.density];