Socket
Socket
Sign inDemoInstall

liveblog-client

Package Overview
Dependencies
26
Maintainers
4
Versions
8
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.3.7 to 3.4.0

.eslintignore

133

.eslintrc.json
{
"plugins": [
"angular"
"angular",
"jasmine",
"react",
],

@@ -26,4 +28,3 @@

"protractor": false,
"requirejs": false,
"__SUPERDESK_CONFIG__": true
"requirejs": false
},

@@ -43,4 +44,9 @@

"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:jasmine/recommended",
],
"rules": {
"angular/di-unused": 2,
"angular/empty-controller": 2,

@@ -50,37 +56,19 @@ "angular/no-cookiestore": 2,

"no-cond-assign": 2,
"no-console": [2, {"allow": ["warn", "error", "info"]}],
"no-constant-condition": 2,
"no-debugger": 2,
"no-dupe-args": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-empty": 2,
"no-ex-assign": 2,
"no-extra-boolean-cast": 2,
"no-extra-parens": 1,
"no-extra-semi": 1,
"no-func-assign": 2,
"no-inner-declarations": 2,
"no-irregular-whitespace": 2,
"no-obj-calls": 2,
"no-unexpected-multiline": 2,
"no-unreachable": 2,
"no-unsafe-negation": 2,
"use-isnan": 2,
"valid-typeof": 2,
"accessor-pairs": 2,
"react/no-did-update-set-state": 2,
"react/no-direct-mutation-state": 2,
"react/no-multi-comp": 2,
"react/self-closing-comp": 2,
"react/prefer-es6-class": 2,
// deprecated apis
"react/no-find-dom-node": 1,
"react/no-string-refs": 1,
"array-callback-return": 2,
"block-scoped-var": 1,
"complexity": [1, 15],
"curly": 1,
"dot-location": [2, "property"],
"dot-notation": 2,
"eqeqeq": 2,
"no-alert": 1,
"block-scoped-var": 2,
"complexity": [1, 10],
"no-alert": 2,
"no-caller": 2,
"no-case-declarations": 2,
"no-else-return": 2,
"no-console": ["error", {"allow": ["info", "warn", "error"]}],
"no-empty-function": 2,
"no-empty-pattern": 2,
"no-eval": 2,

@@ -90,3 +78,2 @@ "no-extend-native": 2,

"no-floating-decimal": 2,
"no-global-assign": 2,
"no-implied-eval": 2,

@@ -100,9 +87,5 @@ "no-iterator": 2,

"no-new-wrappers": 2,
"no-octal": 2,
"no-param-reassign": 1,
"no-param-reassign": 2,
"no-proto": 2,
"no-redeclare": 2,
"no-return-assign": 2,
"no-script-url": 2,
"no-self-assign": 2,
"no-self-compare": 2,

@@ -112,6 +95,7 @@ "no-unmodified-loop-condition": 2,

"no-useless-concat": 2,
"no-useless-return": 1,
"no-useless-escape": 1,
"no-useless-return": 2,
"no-void": 2,
"no-with": 2,
"radix": 1,
"radix": 2,
"yoda": 2,

@@ -122,17 +106,20 @@

"no-shadow-restricted-names": 2,
"no-unused-vars": [1, {"vars": "all", "args": "none"}],
"no-undef": 2,
"no-unused-vars": [2, {"vars": "all", "args": "none"}],
"no-undef-init": 2,
"no-use-before-define": 0,
"array-bracket-spacing": [1, "never"],
"block-spacing": 1,
"brace-style": [1, "1tbs"],
"camelcase": [1, {"properties": "never"}],
"comma-spacing": 1,
"comma-style": 1,
// jasmine
"jasmine/new-line-before-expect": 0,
"jasmine/new-line-between-declarations": 0,
// style
"array-bracket-spacing": [2, "never"],
"block-spacing": 2,
"brace-style": [2, "1tbs"],
"camelcase": [2, {"properties": "never"}],
"comma-spacing": 2,
"comma-style": 2,
"computed-property-spacing": 2,
"consistent-this": [1, "self"],
"consistent-this": [2, "self"],
"func-call-spacing": 2,
"indent": [1, 4],
"indent": [2, 4],
"jsx-quotes": 2,

@@ -142,28 +129,27 @@ "key-spacing": 2,

"linebreak-style": [2, "unix"],
"max-depth": [2, 5],
"max-depth": [2, 3],
"max-len": [2, 120, 4],
"new-parens": 2,
"newline-after-var": 1,
"newline-after-var": 2,
"newline-per-chained-call": [2, {"ignoreChainWithDepth": 2}],
"no-lonely-if": 2,
"no-mixed-spaces-and-tabs": 2,
"no-multiple-empty-lines": 2,
"no-nested-ternary": 2,
"no-trailing-spaces": 1,
"no-trailing-spaces": 2,
"no-underscore-dangle": 0,
"no-unneeded-ternary": 2,
"no-whitespace-before-property": 2,
"object-curly-spacing": [1, "never"],
"padded-blocks": [1, "never"],
"quote-props": [1, "as-needed"],
"quotes": [1, "single"],
"object-curly-spacing": [2, "never"],
"padded-blocks": [2, "never"],
"quote-props": [2, "as-needed"],
"quotes": [2, "single"],
"require-jsdoc": 0,
"semi-spacing": 2,
"semi": [1, "always"],
"space-before-blocks": 1,
"space-before-function-paren": [1, "never"],
"space-in-parens": [1, "never"],
"space-infix-ops": 1,
"space-unary-ops": 1,
"spaced-comment": 1,
"semi": [2, "always"],
"space-before-blocks": 2,
"space-before-function-paren": [2, "never"],
"space-in-parens": [2, "never"],
"space-infix-ops": 2,
"space-unary-ops": 2,
"spaced-comment": 2,

@@ -173,5 +159,2 @@ "arrow-body-style": [2, "as-needed"],

"arrow-spacing": 2,
"constructor-super": 2,
"no-class-assign": 2,
"no-const-assign": 2,
"no-useless-computed-key": 2,

@@ -182,4 +165,4 @@ "no-useless-constructor": 2,

"object-shorthand": [2, "consistent"],
"prefer-arrow-callback": [1, {"allowNamedFunctions": true}],
"prefer-spread": 1,
"prefer-arrow-callback": [2, {"allowNamedFunctions": true}],
"prefer-spread": 2,
"rest-spread-spacing": 2,

@@ -186,0 +169,0 @@ "template-curly-spacing": 2,

@@ -6,6 +6,6 @@ // This file allows you to change the config value

window.superdeskConfig = {
//subscriptionLevel: 'solo', // SUBSCRIPTION_LEVEL
//syndication: true, // SYNDICATION
//marketplace: true, // MARKETPLACE
//maxContentLength: 8 * 1024 * 1024 // MAX_CONTENT_LENGTH
// subscriptionLevel: 'solo', // SUBSCRIPTION_LEVEL
syndication: true, // SYNDICATION
marketplace: true, // MARKETPLACE
// maxContentLength: 8 * 1024 * 1024 // MAX_CONTENT_LENGTH
};
export default angular.module('liveblog.flux', [])
.factory('Dispatcher', function() {
return {
dispatch: function(action) {
document.dispatchEvent(
new CustomEvent('dispatch', { detail: action })
);
}
}
})
.factory('Store', function() {
var Store = function(reducers, initialState) {
.factory('Dispatcher', () => ({
dispatch: function(action) {
document.dispatchEvent(
new CustomEvent('dispatch', {detail: action})
);
},
}))
.factory('Store', () => {
const Store = function(reducers, initialState) {
this.dispatch = this.dispatch.bind(this);

@@ -29,5 +27,5 @@ this.destroy = this.destroy.bind(this);

this.state = this.reducers(this.state, e.detail);
var state = this.state;
const state = this.state;
this.listeners.forEach(function(listener) {
this.listeners.forEach((listener) => {
listener(state);

@@ -39,5 +37,5 @@ });

document.removeEventListener('dispatch', this.dispatch);
}
};
return Store;
});

@@ -1,3 +0,2 @@

define([], function() {
define([], () => {
/**

@@ -4,0 +3,0 @@ * Noop for registering string for translation in js files.

@@ -10,3 +10,2 @@ import 'lb-bootstrap.scss';

import 'angular-moment';
import 'angular-bootstrap-npm';
import 'angular-resource';

@@ -29,2 +28,3 @@ import 'angular-route';

import 'lr-infinite-scroll';
import 'superdesk-ui-framework';

@@ -80,3 +80,3 @@ import _ from 'lodash';

import 'superdesk-core/scripts/apps/legal-archive';
// import 'superdesk-core/scripts/apps/stream';
import 'superdesk-core/scripts/apps/stream';
import 'superdesk-core/scripts/apps/packaging';

@@ -106,2 +106,3 @@ import 'superdesk-core/scripts/apps/highlights';

// eslint-disable-next-line
const config = __SUPERDESK_CONFIG__;

@@ -116,3 +117,3 @@

// what is required to run liveblog
let sdCore = angular.module('superdesk.core', [
const sdCore = angular.module('superdesk.core', [
'ngRoute',

@@ -122,3 +123,3 @@ 'ngResource',

'ui.bootstrap',
'superdesk-ui',

@@ -144,3 +145,3 @@ 'superdesk.core.activity',

'superdesk.core.directives'
'superdesk.core.directives',
]);

@@ -170,7 +171,7 @@

// 'superdesk.apps.searchProviders',
// 'superdesk.apps.stream',
'superdesk.apps.stream',
'superdesk.apps.publish', // Can't remove
'superdesk.apps.templates',
'superdesk.apps.monitoring',
'superdesk.apps.profiling'
'superdesk.apps.profiling',
]);

@@ -180,3 +181,3 @@

let liveblogModules = [
const liveblogModules = [
'liveblog.analytics',

@@ -190,3 +191,3 @@ 'liveblog.bloglist',

'liveblog.advertising',
'ngMessages'
'ngMessages',
];

@@ -202,3 +203,3 @@

let liveblog = angular.module('liveblog', liveblogModules);
const liveblog = angular.module('liveblog', liveblogModules);

@@ -217,4 +218,4 @@ sdCore.constant('lodash', _);

liveblog.run(['$rootScope', '$timeout', 'notify', 'gettext', 'session',
function($rootScope, $timeout, notify, gettext, session) {
liveblog.run(['$rootScope', '$timeout', 'notify', 'gettext', 'session', '$templateCache',
function($rootScope, $timeout, notify, gettext, session, $templateCache) {
var alertTimeout;

@@ -241,5 +242,102 @@

});
$templateCache.put(
'scripts/core/menu/notifications/views/notifications.html',
/**
* @TODO: from template loacated `template/core/menu/notifications/views/notifications.html`
* wepack `ngtemplate` isn't loading the content.
*
*/
`
<div class="notification-pane" ng-class="{show: flags.notifications}">
<div class="header" ng-if="flags.notifications">
<figure class="avatar medium">
<img sd-user-avatar data-user="currentUser">
</figure>
<div class="user-info">
<span class="name">{{currentUser.display_name }}</span>
<span class="displayname">{{currentUser.username }}</span>
</div>
<div class="actions">
<a href="#/profile/" ng-click="flags.notifications = false" translate>Profile</a>
<button ng-click="logout()" translate>SIGN OUT</button>
</div>
</div>
<div class="content" ng-if="flags.notifications">
<section class="module">
<header class="title" translate>Notifications</header>
<div class="notification-list">
<ul>
<li ng-repeat="notification in notifications._items track by notification._id"
ng-class="{unread: notification._unread}" sd-mark-as-read>
<figure class="avatar">
<img sd-user-avatar data-user="notification.user">
</figure>
<div class="content" ng-if="notification.name == 'notify'">
<time sd-datetime data-date="notification._created"></time>
<p class="text"><b>{{:: notification.user_name }}</b>
<span translate>commented on</span>
<i><a
ng-href="#/authoring/{{ notification.item }}?_id={{ notification.item }}&comments={{ notification.data.comment_id }}"
title="{{ notification.item_slugline }}">
{{ :: notification.item_slugline }}
</a></i>
:<br>{{:: notification.data.comment }}</p>
</div>
<div class="content" ng-if="notification.name == 'user:mention'">
<time sd-datetime data-date="notification._created"></time>
<p class="text">
<b>{{:: notification.user_name }}</b>
<span translate>mentioned you</span> <i>
<a title="{{ notification.item_slugline }}" ng-click="openArticle(notification)">
{{:: notification.item_slugline}}
</a></i>:<br>{{:: notification.data.comment }}</p>
</div>
<div class="content" ng-if="notification.name == 'liveblog:request'">
<time sd-datetime data-date="notification._created"></time>
<p class="text">
<b>{{:: notification.user_name }}</b>
<span translate>request access to </span>
<i>
<a ng-href="#/liveblog/edit/{{ notification.item }}?panel=editor" title="{{:: notification.data.item_slugline }}">
{{:: notification.data.item_slugline }}
</a>
</i>
</p>
</div>
<div class="content" ng-if="notification.name == 'liveblog:add'">
<time sd-datetime data-date="notification._created"></time>
<p class="text">
<b>{{:: notification.user_name }}</b>
<span translate>added you as a member to </span>
<i>
<a ng-href="#/liveblog/edit/{{ notification.item }}?panel=editor" title="{{:: notification.data.item_slugline }}">
{{:: notification.data.item_slugline }}
</a>
</i>
</p>
</div>
<div class="content"
ng-if="notification.name != 'notify' &&
notification.name != 'user:mention' &&
notification.name.indexOf('liveblog') == -1"
ng-click="onNotificationClick(notification)">
<time sd-datetime data-date="notification._created"></time>
<p class="text">
<b>{{:: notification.user_name || "System" }}</b>:
<span sd-activity-message data-activity="notification"></span></p>
</div>
</li>
<div class="info" ng-show="notifications._items.length === 0" translate>All good so far.</div>
<div class="info" ng-show="notifications._items == null" translate>Loading...</div>
</ul>
</div>
</section>
</div>
</div>
`
);
}]);
let body = angular.element('body');
const body = angular.element('body');

@@ -257,3 +355,3 @@ body.ready(() => {

'superdesk.apps',
'liveblog'
'liveblog',
], {strictDi: true});

@@ -260,0 +358,0 @@

@@ -1,2 +0,2 @@

import adManagTemplate from 'scripts/liveblog-advertising/views/main.html';
import adManagTemplate from 'scripts/liveblog-advertising/views/main.ng1';
import advertisingController from './controllers/advertising.js';

@@ -6,3 +6,3 @@ activities.$inject = ['superdeskProvider'];

export default function activities(superdesk) {
superdesk
superdesk
.activity('/advertising/', {

@@ -14,5 +14,5 @@ label: gettext('Advertising manager'),

adminTools: true,
privileges: {'global_preferences': 1},
templateUrl: adManagTemplate
privileges: {global_preferences: 1},
templateUrl: adManagTemplate,
});
}

@@ -1,10 +0,9 @@

import angular from 'angular';
export default function adsUtil() {
return {
uniqueNameInItems: uniqueNameInItems
}
return {
uniqueNameInItems: uniqueNameInItems,
};
function uniqueNameInItems (item, existingItems) {
var invalid = false;
function uniqueNameInItems(item, existingItems) {
let invalid = false;
if (!item || !item.name) {

@@ -14,4 +13,5 @@ invalid = gettext('required');

if (!invalid) {
let found = existingItems.find((existingItem) => (item.name === existingItem.name &&
(!item._id || item._id !== existingItem._id)))
const found = existingItems.find((existingItem) => item.name === existingItem.name &&
(!item._id || item._id !== existingItem._id));
if (found) {

@@ -18,0 +18,0 @@ invalid = gettext('must be unique');

@@ -1,14 +0,13 @@

import adsLocalTpl from 'scripts/liveblog-edit/views/ads-local.html';
import adsRemoteTpl from 'scripts/liveblog-edit/views/ads-remote.html';
import advertModalTpl from 'scripts/liveblog-advertising/views/advert-modal.html';
import collectionModalTpl from 'scripts/liveblog-advertising/views/collection-modal.html';
import _ from 'lodash';
import adsLocalTpl from 'scripts/liveblog-edit/views/ads-local.ng1';
import adsRemoteTpl from 'scripts/liveblog-edit/views/ads-remote.ng1';
import advertModalTpl from 'scripts/liveblog-advertising/views/advert-modal.ng1';
import collectionModalTpl from 'scripts/liveblog-advertising/views/collection-modal.ng1';
import adblockDetect from 'adblock-detect';
LiveblogAdvertisingController.$inject = ['$scope', 'api', 'notify', 'gettext',
'upload','$templateCache', 'freetypeService', 'modal', 'adsUtilSevice'];
'upload', '$templateCache', 'freetypeService', 'modal', 'adsUtilSevice'];
export default function LiveblogAdvertisingController($scope, api, notify, gettext,
upload, $templateCache, freetypeService, modal, adsUtilSevice) {
adblockDetect(function(adblockDetected) {
upload, $templateCache, freetypeService, modal, adsUtilSevice) {
adblockDetect((adblockDetected) => {
$scope.adblockDetected = adblockDetected;

@@ -33,9 +32,9 @@ });

name: 'Advertisement Local',
template: $templateCache.get(adsLocalTpl)
template: $templateCache.get(adsLocalTpl),
},
{
name: 'Advertisement Remote',
template: $templateCache.get(adsRemoteTpl)
}
]
template: $templateCache.get(adsRemoteTpl),
},
];

@@ -45,9 +44,9 @@ $scope.changeState = function(state) {

switch (state) {
case 'collections':
loadCollections();
break;
default:
loadAdverts();
case 'collections':
loadCollections();
break;
default:
loadAdverts();
}
}
};

@@ -58,3 +57,3 @@ $scope.openAdvertDialog = function(ad) {

$scope.advert = angular.copy(ad);
angular.forEach($scope.adTypes, function(adType) {
angular.forEach($scope.adTypes, (adType) => {
if (adType.name === ad.type) {

@@ -70,22 +69,21 @@ $scope.advertType = adType;

$scope.advertModalActive = true;
}
};
$scope.cancelAdvertCreate = function() {
$scope.freetypeControl.reset();
$scope.advertModalActive = false;
}
};
function loadAdverts(silent) {
silent = silent || false;
function loadAdverts(silent = false) {
$scope.advertsLoading = !silent;
return api('advertisements').query({where: {deleted: false}})
.then(function(data) {
$scope.adverts = data._items;
if (!silent) {
notify.info('Adverts loaded');
}
$scope.advertsLoading = false;
}, function(data) {
$scope.advertsLoading = false;
notify.error(gettext('There was an error getting the adverts'));
})
.then((data) => {
$scope.adverts = data._items;
if (!silent) {
notify.info('Adverts loaded');
}
$scope.advertsLoading = false;
}, (data) => {
$scope.advertsLoading = false;
notify.error(gettext('There was an error getting the adverts'));
});
}

@@ -102,34 +100,34 @@

function handleAdvertSaveError() {
notify.error(gettext('Something went wrong, please try again later!'), 5000)
notify.error(gettext('Something went wrong, please try again later!'), 5000);
}
$scope.removeAdvert = function (advert, $index) {
modal.confirm(gettext('Are you sure you want to remove this advert?')).then(function() {
$scope.removeAdvert = function(advert, $index) {
modal.confirm(gettext('Are you sure you want to remove this advert?')).then(() => {
api('advertisements').save(advert, {deleted: true})
.then(function(data) {
$scope.adverts.splice($index, 1);
}, function(data) {
notify.error(gettext('Can\'t remove advert'));
});
.then((data) => {
$scope.adverts.splice($index, 1);
}, (data) => {
notify.error(gettext('Can\'t remove advert'));
});
});
}
};
$scope.saveAdvert = function() {
var newAd = {
const newAd = {
name: $scope.advert.name,
type: $scope.advertType.name,
text: freetypeService.htmlContent($scope.advertType.template, $scope.freetypesData),
meta: {data: $scope.freetypesData}
}
meta: {data: $scope.freetypesData},
};
$scope.dialogAdvertLoading = true;
api('advertisements').save($scope.advert, newAd)
.then(handleAdvertSaveSuccess, handleAdvertSaveError);
}
.then(handleAdvertSaveSuccess, handleAdvertSaveError);
};
loadAdverts();
//COLLECTIONS
function loadCollections(silent) {
silent = silent || false;
// COLLECTIONS
function loadCollections(silent = false) {
if (!silent) {

@@ -139,13 +137,13 @@ $scope.collectionsLoading = true;

return api('collections').query({where: {deleted: false}})
.then(function(data) {
$scope.collections = data._items;
if (!silent) {
notify.info(gettext('Collections loaded'));
}
$scope.collectionsLoading = false;
})
.catch(function(data) {
$scope.collectionsLoading = false;
notify.error(gettext('There was an error getting the adverts'));
})
.then((data) => {
$scope.collections = data._items;
if (!silent) {
notify.info(gettext('Collections loaded'));
}
$scope.collectionsLoading = false;
})
.catch((data) => {
$scope.collectionsLoading = false;
notify.error(gettext('There was an error getting the adverts'));
});
}

@@ -162,9 +160,8 @@

function handleCollectionSaveError() {
notify.error(gettext('Something went wrong, please try again later!'), 5000)
notify.error(gettext('Something went wrong, please try again later!'), 5000);
}
$scope.openCollectionDialog = function(collection) {
collection = collection || false;
$scope.openCollectionDialog = function(collection = false) {
// load all available adverts without showing any messages
loadAdverts(true).then(function() {
loadAdverts(true).then(() => {
if (collection) {

@@ -174,4 +171,4 @@ // editing collection

$scope.collection.checkAdverts = {};
//console.log('$scope.collection ', $scope.collection);
angular.forEach($scope.adverts, function(advert) {
// console.log('$scope.collection ', $scope.collection);
angular.forEach($scope.adverts, (advert) => {
if ($scope.collectionHasAdvert($scope.collection, advert)) {

@@ -187,3 +184,3 @@ $scope.collection.checkAdverts[advert._id] = true;

$scope.collection.checkAdverts = {};
angular.forEach($scope.adverts, function(advert) {
angular.forEach($scope.adverts, (advert) => {
$scope.collection.checkAdverts[advert._id] = false;

@@ -194,34 +191,35 @@ });

});
}
};
$scope.saveCollection = function() {
// create the saveable advertisement array for the collection
const advertisements = [];
//create the saveable advertisement array for the collection
var advertisements = [];
angular.forEach($scope.collection.checkAdverts, function(checked, ad_id) {
angular.forEach($scope.collection.checkAdverts, (checked, adId) => {
if (checked) {
advertisements.push({'advertisement_id': ad_id});
advertisements.push({advertisement_id: adId});
}
})
var newCollection = {
'name': $scope.collection.name,
'advertisements': advertisements
}
});
const newCollection = {
name: $scope.collection.name,
advertisements: advertisements,
};
$scope.dialogCollectionLoading = true;
api('collections').save($scope.collection, newCollection)
.then(handleCollectionSaveSuccess, handleCollectionSaveError);
}
.then(handleCollectionSaveSuccess, handleCollectionSaveError);
};
$scope.removeCollection = function (collection, $index) {
$scope.removeCollection = function(collection, $index) {
modal.confirm(gettext('Are you sure you want to remove this collection?'))
.then(function() {
api('collections').save(collection, {deleted: true})
.then(function(data) {
$scope.collections.splice($index, 1);
}, function(data) {
notify.error(gettext('Can\'t remove collection'));
.then(() => {
api('collections').save(collection, {deleted: true})
.then((data) => {
$scope.collections.splice($index, 1);
}, (data) => {
notify.error(gettext('Can\'t remove collection'));
});
});
});
}
};

@@ -231,7 +229,7 @@ $scope.cancelCollectionCreate = function() {

$scope.collectionModalActive = false;
}
};
$scope.collectionHasAdvert = function (collection, advert) {
$scope.collectionHasAdvert = function(collection, advert) {
return !!collection.advertisements.find((ad) => ad.advertisement_id === advert._id);
}
};

@@ -242,3 +240,3 @@ $scope.notValidName = adsUtilSevice.uniqueNameInItems;

return !Object.keys($scope.validation).find((key) => !$scope.validation[key]);
}
};
}

@@ -5,4 +5,4 @@ import './styles/advertising.scss';

var liveblogAdvertisingModule = angular.module('liveblog.advertising', ['liveblog.edit'])
.config(activities)
.service('adsUtilSevice' , adsUtil);
angular.module('liveblog.advertising', ['liveblog.edit'])
.config(activities)
.service('adsUtilSevice', adsUtil);

@@ -1,65 +0,75 @@

liveblogAnalyticsController.$inject = ['$scope','$location', 'api', 'analytics', 'blog', 'notify'];
liveblogAnalyticsController.$inject = ['$scope', '$location', 'api', 'analytics', 'blog', 'notify'];
function liveblogAnalyticsController($scope, $location, api, analytics, blog, notify) {
var vm = this;
const self = this;
var close = function() { // Return to blog list page
$location.path('/liveblog/edit/' + blog._id);
};
const close = function() { // Return to blog list page
$location.path('/liveblog/edit/' + blog._id);
};
var loadAnalytics = function(page) {
var q = { page: page || 1, max_results: 200 };
api('blogs/<regex("[a-f0-9]{24}"):blog_id>/bloganalytics', {_id: blog._id})
.query(q)
.then(function(data) {
if (q.page === 1) $scope.analytics_data = data;
else $scope.analytics_data._items.concat(data._items);
if (data._links.next) loadAnalytics(q.page + 1)
})
};
const loadAnalytics = function(page = 1) {
const q = {page: page, max_results: 200};
var downloadCSV = function() { // Convert relevant item fields to CSV
var fileContent = "", filename = "liveblog_analytics_" + blog._id;
api('blogs/<regex("[a-f0-9]{24}"):blog_id>/bloganalytics', {_id: blog._id})
.query(q)
.then((data) => {
if (q.page === 1) {
$scope.analytics_data = data;
} else {
$scope.analytics_data._items.concat(data._items);
}
if (data._links.next) {
loadAnalytics(q.page + 1);
}
});
};
$scope.analytics_data._items.forEach(function(arr, index) {
var item = $scope.analytics_data._items[index]
, filtered = [item.blog_id, item.context_url, item.hits];
fileContent += filtered.join(",") + "\n"
});
const downloadCSV = function() { // Convert relevant item fields to CSV
let fileContent = '';
const filename = `liveblog_analytics_${blog._id}`;
var blob = new Blob([fileContent], {
type: 'text/csv;charset=utf-8;'
});
$scope.analytics_data._items.forEach((arr, index) => {
const item = $scope.analytics_data._items[index];
const filtered = [item.blog_id, item.context_url, item.hits];
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename);
return // early exit
}
fileContent += filtered.join(',') + '\n';
});
var link = document.createElement("a");
if (link.download === undefined) return; // detect HTML5 download attribute
const blob = new Blob([fileContent], {
type: 'text/csv;charset=utf-8;',
});
var url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
};
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, filename);
return; // early exit
}
loadAnalytics(); // load all, calls aren't expensive
angular.extend(vm, {
blog: blog,
close: close,
tab: "embeds",
downloadCSV: downloadCSV,
changeTab: function(tab) {
vm.tab = tab;
if (!vm.tab) return;
},
})
const link = document.createElement('a');
};
if (link.download === undefined) {
return;
} // detect HTML5 download attribute
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
};
loadAnalytics(); // load all, calls aren't expensive
angular.extend(self, {
blog: blog,
close: close,
tab: 'embeds',
downloadCSV: downloadCSV,
changeTab: function(tab) {
self.tab = tab;
},
});
}
export default liveblogAnalyticsController;
lbAnalyticsListCtrl.$inject = ['$scope', '$element'];
export default function lbAnalyticsListCtrl($scope, $element) {
$scope.predicate = '';
$scope.predicate = '';
$scope.order = function(predicate) {
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
$scope.predicate = predicate;
};
$scope.order = function(predicate) {
$scope.reverse = $scope.predicate === predicate ? !$scope.reverse : false;
$scope.predicate = predicate;
};
$scope.isReversePredicate = function(predicate) {
return $scope.reverse && $scope.predicate === predicate;
};
$scope.isReversePredicate = function(predicate) {
return $scope.reverse && $scope.predicate === predicate;
};
$scope.setPage = function($index) {
$scope.currentPage = $index;
}
$scope.setPage = function($index) {
$scope.currentPage = $index;
};
$scope.pageSize = 10;
$scope.currentPage = 0;
$scope.pages = new Array(Math.ceil($scope.analytics._items.length / $scope.pageSize));
$scope.pageSize = 10;
$scope.currentPage = 0;
$scope.pages = new Array(Math.ceil($scope.analytics._items.length / $scope.pageSize));
return null;
return null;
}
import './styles/analytics.scss';
import analiticsListTpl from 'scripts/liveblog-analytics/views/view-list.html';
import analiticsListTpl from 'scripts/liveblog-analytics/views/view-list.ng1';

@@ -9,6 +9,6 @@ import liveblogAnalyticsController from './controllers/controller-analytics';

export default angular
.module('liveblog.analytics', ['liveblog.security'])
.config(['apiProvider', function(apiProvider) {
apiProvider
/*
.module('liveblog.analytics', ['liveblog.security'])
.config(['apiProvider', function(apiProvider) {
apiProvider
/*
* 'analytics' being one of the resources that we discovered

@@ -21,26 +21,21 @@ * earlier by requesting http://localhost:5000/api -- endpoints are described with href, title pairs.

.api('analytics', {
type: 'http',
backend: {rel: 'analytics'}
})
}])
.controller('LiveblogAnalyticsController', liveblogAnalyticsController)
.api('analytics', {
type: 'http',
backend: {rel: 'analytics'},
});
}])
.controller('LiveblogAnalyticsController', liveblogAnalyticsController)
.directive('lbAnalyticsList', function() {
return {
restrict: 'E',
scope: {
analytics: '='
},
templateUrl: analiticsListTpl,
controllerAs: 'analyticsList',
controller: lbAnalyticsListCtrl
};
})
.directive('lbAnalyticsList', () => ({
restrict: 'E',
scope: {
analytics: '=',
},
templateUrl: analiticsListTpl,
controllerAs: 'analyticsList',
controller: lbAnalyticsListCtrl,
}))
.filter('startFrom', function() {
return function(input, start) {
start = parseInt(start); // Parse to int
return input.slice(start);
}
});
.filter('startFrom', () => function(input, start) {
return input.slice(parseInt(start, 10));
});

@@ -14,3 +14,5 @@ BlogListController.$inject = [

'urls',
'moment'
'moment',
'modal',
'blogService',
];

@@ -31,3 +33,5 @@

urls,
moment
moment,
modal,
blogService
) {

@@ -37,3 +41,3 @@ $scope.maxResults = 25;

{name: 'active', code: 'open', text: gettext('Active blogs')},
{name: 'archived', code: 'closed', text: gettext('Archived blogs')}
{name: 'archived', code: 'closed', text: gettext('Archived blogs')},
];

@@ -50,2 +54,3 @@ $scope.activeState = isArchivedFilterSelected ? $scope.states[1] : $scope.states[0];

$scope.modalActive = false;
$scope.bulkActions = 0;

@@ -62,3 +67,3 @@ $scope.mailto = 'mailto:upgrade@liveblog.pro?subject=' +

title: '',
description: ''
description: '',
};

@@ -75,8 +80,8 @@ $scope.newBlogError = '';

function fetchBloglistEmbed() {
var criteria = {source: {
query: {filtered: {filter: {term: {key: 'blogslist'}}}}
const criteria = {source: {
query: {filtered: {filter: {term: {key: 'blogslist'}}}},
}};
api.blogslist.query(criteria, false).then((embed) => {
var url;
let url;

@@ -94,2 +99,28 @@ if (embed._items.length) {

}
function bulkDelete(blog) {
api.blogs.remove(angular.copy(blog)).then((message) => {
notify.pop();
notify.info(gettext('Blog removed'));
}, () => {
notify.pop();
notify.error(gettext('Something went wrong'));
});
}
$scope.askRemoveBlog = function() {
modal.confirm(gettext('Are you sure you want to delete the blog(s)?'))
.then(() => {
var selectedBlogs = [];
angular.forEach($scope.blogs._items, (blog) => {
if (blog.selected) {
bulkDelete(blog);
}
});
$scope.blogs._items = $scope.blogs._items.filter((el) => selectedBlogs.indexOf(el) < 0);
});
};
$scope.cancelEmbed = function() {

@@ -103,2 +134,58 @@ $scope.embedModal = false;

$scope.blogSelect = function($event, isSelected) {
$event.stopPropagation();
if (isSelected) {
$scope.bulkActions += 1;
} else {
$scope.bulkActions -= 1;
}
};
$scope.bulkActionCancel = () => {
angular.forEach($scope.blogs._items, (blog) => {
blog.selected = false;
});
$scope.bulkActions = 0;
};
$scope.bulkAction = function(activeState) {
let selectedBlogs = [];
angular.forEach($scope.blogs._items, (blog) => {
if (blog.selected) {
selectedBlogs.push(blog);
const deferred = $q.defer();
const changedBlog = {
blog_status: activeState.name == 'active' ? 'closed' : 'open',
};
let newBlog = angular.copy(blog);
angular.extend(newBlog, changedBlog);
delete newBlog._latest_version;
delete newBlog._current_version;
delete newBlog._version;
delete newBlog.marked_for_not_publication;
delete newBlog._type;
delete newBlog.selected;
delete newBlog.firstcreated;
newBlog.original_creator = blog.original_creator._id;
blogService.update(blog, newBlog).then((blog) => {
notify.pop();
if (blog.blog_status == 'closed') {
notify.info(gettext('Blog(s) moved to archived'));
} else {
notify.info(gettext('Blog(s) is actived now'));
}
deferred.resolve();
$scope.bulkActions = 0;
});
return deferred.promise;
}
});
$scope.blogs._items = $scope.blogs._items.filter((el) => selectedBlogs.indexOf(el) < 0);
};
$scope.cancelCreate = function() {

@@ -130,6 +217,6 @@ clearCreateBlogForm();

var members = _.map($scope.blogMembers, (obj) => ({user: obj._id}));
const members = _.map($scope.blogMembers, (obj) => ({user: obj._id}));
// Upload image only if we have a valid one chosen
var promise = $scope.preview.url ? $scope.upload($scope.preview) : $q.when();
const promise = $scope.preview.url ? $scope.upload($scope.preview) : $q.when();

@@ -143,3 +230,3 @@ return promise.then(() => api.blogs

picture_renditions: $scope.newBlog.picture_renditions,
members: members
members: members,
})

@@ -157,3 +244,3 @@ .then((blog) => {

$scope.upload = function(config) {
var form = {};
const form = {};

@@ -171,20 +258,20 @@ if (config.img) {

url: uploadUrl,
data: form
data: form,
})
.then((response) => {
if (response.data._status === 'ERR') {
return;
}
var pictureUrl = response.data.renditions.viewImage.href;
.then((response) => {
if (response.data._status === 'ERR') {
return;
}
var pictureUrl = response.data.renditions.viewImage.href;
$scope.newBlog.picture_url = pictureUrl;
$scope.newBlog.picture = response.data._id;
$scope.newBlog.picture_renditions = response.data.renditions;
}, (error) => {
notify.error(
error.statusText !== '' ? error.statusText : gettext('There was a problem with your upload')
);
}, (progress) => {
$scope.progress.width = Math.round(progress.loaded / progress.total * 100.0);
}));
$scope.newBlog.picture_url = pictureUrl;
$scope.newBlog.picture = response.data._id;
$scope.newBlog.picture_renditions = response.data.renditions;
}, (error) => {
notify.error(
error.statusText !== '' ? error.statusText : gettext('There was a problem with your upload')
);
}, (progress) => {
$scope.progress.width = Math.round(progress.loaded / progress.total * 100.0);
}));
}

@@ -221,3 +308,3 @@ };

var theoricalMembers = [];
const theoricalMembers = [];

@@ -236,22 +323,22 @@ if (blog.members) {

headers: {
'Content-Type': 'application/json;charset=utf-8'
}
'Content-Type': 'application/json;charset=utf-8',
},
})
.then((response) => {
if (response.data._items.length > 0) {
response.data._items.forEach((item) => {
if (theoricalMembers.indexOf(item._id) === -1) {
theoricalMembers.push(item._id);
}
});
}
.then((response) => {
if (response.data._items.length > 0) {
response.data._items.forEach((item) => {
if (theoricalMembers.indexOf(item._id) === -1) {
theoricalMembers.push(item._id);
}
});
}
if (theoricalMembers.length < config.assignableUsers[config.subscriptionLevel]) {
$scope.allowAccessRequest = true;
}
});
if (theoricalMembers.length < config.assignableUsers[config.subscriptionLevel]) {
$scope.allowAccessRequest = true;
}
});
};
$scope.requestAccess = function(blog) {
var showRequestDialog = true;
let showRequestDialog = true;

@@ -278,3 +365,3 @@ // Check to see if the current user hasn't been accepted during this session (before refreshing)

notify.pop();
var message = gettext('Something went wrong, plase try again later!');
let message = gettext('Something went wrong, plase try again later!');

@@ -321,2 +408,9 @@ if (data.data._message === 'A request has already been sent') {

$scope.removeImage = function() {
modal.confirm(gettext('Are you sure you want to remove the blog image?')).then(() => {
$scope.preview.url = '';
$scope.progress.width = 0;
});
};
$scope.hasReachedMembersLimit = function() {

@@ -345,11 +439,11 @@ if (!config.assignableUsers.hasOwnProperty(config.subscriptionLevel)) {

function getCriteria() {
var params = $location.search(),
criteria = {
max_results: $scope.maxResults,
embedded: {original_creator: 1},
sort: '[("versioncreated", -1)]',
source: {
query: {filtered: {filter: {term: {blog_status: $scope.activeState.code}}}}
}
};
const params = $location.search();
const criteria = {
max_results: $scope.maxResults,
embedded: {original_creator: 1},
sort: '[("versioncreated", -1)]',
source: {
query: {filtered: {filter: {term: {blog_status: $scope.activeState.code}}}},
},
};

@@ -360,4 +454,4 @@ if (params.q) {

query: '*' + params.q + '*',
fields: ['title', 'description']
}
fields: ['title', 'description'],
},
};

@@ -364,0 +458,0 @@ }

@@ -5,14 +5,14 @@ export default function ifBackgroundImage() {

scope: {
ifBackgroundImage: '@'
ifBackgroundImage: '@',
},
link: function(scope, element, attrs) {
var url = scope.ifBackgroundImage;
const url = scope.ifBackgroundImage;
if (url) {
element.css({
'background-image': 'url(' + url + ')'
'background-image': 'url(' + url + ')',
});
}
}
},
};
}

@@ -14,3 +14,3 @@ sdPlainImage.$inject = ['gettext', 'notify', 'config'];

msgErrorMax: '@',
msgErrorMin: '@'
msgErrorMin: '@',
},

@@ -21,3 +21,3 @@ link: function(scope, elem) {

if (src) {
var img = new Image();
const img = new Image();

@@ -37,6 +37,6 @@ if (scope.file.size > config.maxContentLength) {

var minWidth = scope.minWidth || 320,
minHeight = scope.minHeight || 240,
maxWidth = scope.maxWidth || 3840,
maxHeight = scope.maxHeight || 2160;
const minWidth = scope.minWidth || 320;
const minHeight = scope.minHeight || 240;
const maxWidth = scope.maxWidth || 3840;
const maxHeight = scope.maxHeight || 2160;

@@ -78,4 +78,4 @@ if (this.width < minWidth || this.height < minHeight) {

});
}
},
};
}

@@ -7,7 +7,10 @@ lbUserSelectList.$inject = ['api'];

members: '=',
onchoose: '&'
user: '=',
onchoose: '&',
},
templateUrl: 'scripts/apps/desks/views/user-select.html',
link: function(scope, elem, attrs) {
var ARROW_UP = 38, ARROW_DOWN = 40, ENTER = 13;
const ARROW_UP = 38;
const ARROW_DOWN = 40;
const ENTER = 13;

@@ -18,3 +21,3 @@ scope.selected = null;

var _refresh = function() {
const _refresh = function() {
scope.users = {};

@@ -26,21 +29,28 @@ return api('users').query({where: JSON.stringify({

{last_name: {$regex: scope.search, $options: '-i'}},
{email: {$regex: scope.search, $options: '-i'}}
]
{email: {$regex: scope.search, $options: '-i'}},
],
})})
.then((result) => {
scope.users = result;
scope.users._items = _.filter(scope.users._items, (item) => {
var found = false;
.then((result) => {
for (var i = 0; i < result._items.length; i++) {
var obj = result._items[i];
_.each(scope.members, (member) => {
if (member._id === item._id) {
found = true;
if (scope.user && obj._id === scope.user._id || obj._id === scope.$root.identity._id) {
result._items.splice(i, 1);
}
}
scope.users = result;
scope.users._items = _.filter(scope.users._items, (item) => {
var found = false;
_.each(scope.members, (member) => {
if (member._id === item._id) {
found = true;
}
});
return !found;
});
return !found;
scope.selected = null;
});
scope.selected = null;
});
};
var refresh = _.debounce(_refresh, 1000);
const refresh = _.debounce(_refresh, 1000);

@@ -55,3 +65,3 @@ scope.$watch('search', () => {

if (scope.selected) {
var selectedIndex = -1;
let selectedIndex = -1;

@@ -70,4 +80,4 @@ _.each(scope.users._items, (item, index) => {

function previous() {
var selectedIndex = getSelectedIndex(),
previousIndex = _.max([0, selectedIndex - 1]);
const selectedIndex = getSelectedIndex();
const previousIndex = _.max([0, selectedIndex - 1]);

@@ -80,4 +90,4 @@ if (selectedIndex > 0) {

function next() {
var selectedIndex = getSelectedIndex(),
nextIndex = _.min([scope.users._items.length - 1, selectedIndex + 1]);
const selectedIndex = getSelectedIndex();
const nextIndex = _.min([scope.users._items.length - 1, selectedIndex + 1]);

@@ -110,2 +120,7 @@ scope.select(scope.users._items[nextIndex]);

scope.onchoose({user: user});
var exists = scope.members.some((el) => el._id === user._id);
if (!exists) {
scope.members.push(user);
}
scope.search = null;

@@ -119,4 +134,4 @@ };

scope.getUserDisplay = (user) => user.display_name;
}
},
};
}
}
import './styles/liveblog-bloglist.scss';
import './styles/liveblog-upload.scss';
import mainTemplate from 'scripts/liveblog-bloglist/views/main.html';
import mainTemplate from 'scripts/liveblog-bloglist/views/main.ng1';

@@ -16,11 +16,11 @@ import blogListController from './controllers/blog-list';

type: 'http',
backend: {rel: 'blogslist'}
backend: {rel: 'blogslist'},
});
apiProvider.api('blogs', {
type: 'http',
backend: {rel: 'blogs'}
backend: {rel: 'blogs'},
});
apiProvider.api('archive', {
type: 'http',
backend: {rel: 'archive'}
backend: {rel: 'archive'},
});

@@ -36,5 +36,7 @@ }])

adminTools: false,
resolve: {isArchivedFilterSelected: function() {
return false;
}}
resolve: {
isArchivedFilterSelected: function() {
return false;
},
},
})

@@ -45,5 +47,7 @@ .activity('/liveblog/active', {

templateUrl: mainTemplate,
resolve: {isArchivedFilterSelected: function() {
return false;
}}
resolve: {
isArchivedFilterSelected: function() {
return false;
},
},
})

@@ -54,5 +58,7 @@ .activity('/liveblog/archived', {

templateUrl: mainTemplate,
resolve: {isArchivedFilterSelected: function() {
return true;
}}
resolve: {
isArchivedFilterSelected: function() {
return true;
},
},
});

@@ -62,3 +68,3 @@ }])

// Replace paragraph and list item with an empty space
var retValue = text ? String(text).replace(/<(p|li)>/g, ' ') : '';
let retValue = text ? String(text).replace(/<(p|li)>/g, ' ') : '';

@@ -65,0 +71,0 @@ retValue = retValue.replace(/<[^>]+>/gm, '');

@@ -11,4 +11,2 @@ /**

import angular from 'angular';
blogService.$inject = ['api', '$q', '$rootScope', 'config'];

@@ -37,12 +35,13 @@

function getPublicUrl(blog) {
var deferred = $q.defer();
const deferred = $q.defer();
// for debug purpose
if (!blog.public_url && config.debug) {
deferred.resolve('http://localhost:5000/embed/' + blog._id);
deferred.resolve(config.server.url.replace('/api', `/embed/${blog._id}`));
} else if (blog.public_url) {
// if the blog contains the url, returns it
deferred.resolve(blog.public_url.replace('http://', 'https://'));
deferred.resolve(config.debug ? blog.public_url : blog.public_url.replace('http://', 'https://'));
} else {
// otherwise, listen for websocket notifications regarding publication
var notif_listener = $rootScope.$on('blog', function updateBlogAndResolve(e, data) {
const notifListener = $rootScope.$on('blog', function updateBlogAndResolve(e, data) {
if (data.blog_id === blog._id && data.published === 1) {

@@ -52,6 +51,6 @@ // update the blog property

// unbind the listener
notif_listener();
notifListener();
// return the url
// fix https issue
deferred.resolve(blog.public_url.replace('http://', 'https://'));
deferred.resolve(config.debug ? blog.public_url : blog.public_url.replace('http://', 'https://'));
}

@@ -67,4 +66,4 @@ });

save: save,
getPublicUrl: getPublicUrl
getPublicUrl: getPublicUrl,
};
}

@@ -14,5 +14,5 @@ /**

import scorecardsTpl from 'scripts/liveblog-edit/views/scorecards.html';
import adsLocalTpl from 'scripts/liveblog-edit/views/ads-local.html';
import adsRemoteTpl from 'scripts/liveblog-edit/views/ads-remote.html';
import scorecardsTpl from 'scripts/liveblog-edit/views/scorecards.ng1';
import adsLocalTpl from 'scripts/liveblog-edit/views/ads-local.ng1';
import adsRemoteTpl from 'scripts/liveblog-edit/views/ads-remote.ng1';

@@ -48,3 +48,3 @@ import './../../ng-sir-trevor';

'$rootScope',
'$location'
'$location',
];

@@ -85,2 +85,3 @@

$scope.freetypesData = {}; $scope.freetypeControl = {}; $scope.validation = {};
$scope.freetypesOriginal = {};
$scope.validation.imageUploaded = true;

@@ -95,3 +96,3 @@

const emptyDivRegex = /<div><br\/?><\/div>/g;
const targetIconRegex = /target\s*=\s*"\<\/?i\>blank\"/g;
const targetIconRegex = /target\s*=\s*"<\/?i>blank"/g;
// start listening for unread posts.

@@ -104,11 +105,19 @@

// go with the 'classic' editor items
return _.map(self.editor.get(), (block) => ({
group_type: 'default',
text: block.text
.replace(emptyPRegex, '<br/>')
.replace(emptyDivRegex, '<br/>')
.replace(targetIconRegex, 'target="_blank"'),
meta: block.meta,
item_type: block.type
}));
return _.map(self.editor.get(), (block) => {
const syndicatedCreator = block.meta && block.meta.syndicated_creator;
if (syndicatedCreator) {
delete block.meta.syndicated_creator;
}
return {
group_type: 'default',
text: block.text
.replace(emptyPRegex, '<br/>')
.replace(emptyDivRegex, '<br/>')
.replace(targetIconRegex, 'target="_blank"'),
meta: block.meta,
syndicated_creator: syndicatedCreator,
item_type: block.type,
};
});
}

@@ -122,4 +131,5 @@

text: freetypeService.htmlContent($scope.selectedPostType.template, $scope.freetypesData),
meta: {data: $scope.freetypesData}
}
meta: {data: $scope.freetypesData},
syndicated_creator: $scope.freetypesOriginal.syndicated_creator,
},
];

@@ -256,16 +266,16 @@ }

var scorecards = {
const scorecards = {
name: 'Scorecard',
template: $templateCache.get(scorecardsTpl),
separator: true
separator: true,
};
var adLocal = {
const adLocal = {
name: 'Advertisement Local',
template: $templateCache.get(adsLocalTpl)
template: $templateCache.get(adsLocalTpl),
};
var adRemote = {
const adRemote = {
name: 'Advertisement Remote',
template: $templateCache.get(adsRemoteTpl)
template: $templateCache.get(adsRemoteTpl),
};

@@ -291,2 +301,3 @@

$scope.freetypesData = angular.copy(item.meta.data);
$scope.freetypesOriginal = item;
}

@@ -354,3 +365,3 @@ });

var input = el.text().trim();
const input = el.text().trim();

@@ -365,3 +376,3 @@ $scope.$apply(() => {

return $scope.freetypeControl.isValid()
&& ($scope.currentPost.post_status === 'draft'
&& ($scope.currentPost.post_status === 'draft'
|| $scope.currentPost.post_status === 'submitted');

@@ -393,3 +404,3 @@ }

cleanEditor(false);
var delay = 0;
let delay = 0;

@@ -416,3 +427,3 @@ $scope.currentPost = angular.copy(post);

} else {
var data = _.extend(itm, itm.meta);
const data = _.extend({}, itm, itm.meta);

@@ -423,2 +434,4 @@ self.editor.createBlock(itm.item_type, data);

});
$scope.actionDisabled = false;
}, delay);

@@ -526,2 +539,3 @@ }

},
isEditorClean: isEditorClean,
setPending: function(value) {

@@ -535,3 +549,3 @@ $scope.actionPending = value;

$scope.actionPending = true;
var handleError = function(response) {
const handleError = function(response) {
// call the uploader callback with the error message as parameter

@@ -547,3 +561,3 @@ errorCallback(response.data ? response.data._message : undefined);

url: url,
data: {media: file}
data: {media: file},
})

@@ -560,3 +574,3 @@ .then((response) => {

_url: response.data.renditions.thumbnail.href,
renditions: response.data.renditions
renditions: response.data.renditions,
};

@@ -575,7 +589,7 @@ // media will be added latter in the `meta` if this item in this callback

image_url: imgURL,
mimetype: 'image/jpeg'
mimetype: 'image/jpeg',
},
headers: {
'Content-Type': 'application/json;charset=utf-8'
}
'Content-Type': 'application/json;charset=utf-8',
},
})

@@ -590,6 +604,6 @@ .then((response) => {

_url: response.data.renditions.thumbnail.href,
renditions: response.data.renditions
renditions: response.data.renditions,
}};
});
}
},
},

@@ -636,3 +650,3 @@ fetchNewContributionPage: function() {

$scope.preview = !$scope.preview;
}
},
});

@@ -654,5 +668,5 @@ // initalize the view with the editor panel

if ($scope.panelState !== 'ingest'
&& data.hasOwnProperty('posts')
&& data.hasOwnProperty('created')) {
let syndPosts = data.posts
&& data.hasOwnProperty('posts')
&& data.hasOwnProperty('created')) {
const syndPosts = data.posts
.filter((post) => post.hasOwnProperty('syndication_in'));

@@ -659,0 +673,0 @@

@@ -18,3 +18,3 @@ /**

import outputEmbedCodeTpl from 'scripts/liveblog-edit/views/output-embed-code-modal.html'
import outputEmbedCodeTpl from 'scripts/liveblog-edit/views/output-embed-code-modal.ng1';

@@ -38,3 +38,3 @@ BlogSettingsController.$inject = [

'urls',
'$rootScope'
'$rootScope',

@@ -62,7 +62,7 @@ ];

) {
// set view's model
var vm = this;
/* eslint consistent-this: ["error", "vm"]*/
const vm = this;
var notif_listener = $rootScope.$on('blog', (e, data) => {
$rootScope.$on('blog', (e, data) => {
if (data.blog_id === vm.blog._id && data.published === 1) {

@@ -75,3 +75,3 @@ // update the blog property

angular.extend(vm, {
mailto: 'mail:upgrade@liveblog.pro?subject='+
mailto: 'mail:upgrade@liveblog.pro?subject=' +
encodeURIComponent(location.hostname) +

@@ -82,3 +82,3 @@ ' ' +

newBlog: angular.copy(blog),
deactivateTheme: (config.subscriptionLevel === 'solo'),
deactivateTheme: config.subscriptionLevel === 'solo',
blogPreferences: angular.copy(blog.blog_preferences),

@@ -96,10 +96,10 @@ availableLanguages: [],

'Politics',
'Others'
'Others',
],
//used as an aux var to be able to change members and safely cancel the changes
// used as an aux var to be able to change members and safely cancel the changes
blogMembers: [],
//users to remove from the pending queue once the changes are saved
// users to remove from the pending queue once the changes are saved
acceptedMembers: [],
memberRequests: [],
//concat of blogMembers and membership requested members
// concat of blogMembers and membership requested members
posibleMembers: [],

@@ -116,24 +116,26 @@ isSaved: true,

outputEmbedCodeTpl: outputEmbedCodeTpl,
loadOutputs: function(silent) {
silent = silent || false;
loadOutputs: function(silent = false) {
if (!silent) {
vm.outputsLoading = true;
}
var criteria = {where: JSON.stringify({
'$and': [
{deleted: false},
{blog: vm.blog._id}
]
})}
const criteria = {
where: JSON.stringify({
$and: [
{deleted: false},
{blog: vm.blog._id},
],
}),
};
api('outputs').query(criteria)
.then(function(data) {
vm.outputs = data._items;
if (!silent) {
notify.info('Output channels loaded');
}
vm.outputsLoading = false;
}, function(data) {
notify.error(gettext('There was an error getting the output channels'));
vm.outputsLoading = false;
})
.then((data) => {
vm.outputs = data._items;
if (!silent) {
notify.info('Output channels loaded');
}
vm.outputsLoading = false;
}, (data) => {
notify.error(gettext('There was an error getting the output channels'));
vm.outputsLoading = false;
});
},

@@ -143,6 +145,4 @@ showOutputEmbedCode: function(output) {

vm.output = output;
let outputTheme = _.find(vm.availableThemes, function(theme) {
return theme.name === vm.output.theme;
});
const outputTheme = _.find(vm.availableThemes, (theme) => theme.name === vm.output.theme);
if (outputTheme.styles && outputTheme.settings.removeStylesESI) {

@@ -152,4 +152,3 @@ vm.output.styleUrl = outputTheme.public_url + outputTheme.styles[outputTheme.styles.length - 1];

},
openOutputDialog: function(output) {
output = output || {};
openOutputDialog: function(output = {}) {
vm.output = angular.copy(output);

@@ -160,4 +159,4 @@ vm.oldOutput = angular.copy(output);

vm.output.preview = {
url: vm.output.style['background-image']
}
url: vm.output.style['background-image'],
};
} else {

@@ -172,15 +171,15 @@ vm.output.style = {};

},
removeOutput: function (output, $index) {
removeOutput: function(output, $index) {
modal.confirm(gettext('Are you sure you want to remove this output channel?'))
.then(function() {
api('outputs').save(output, {deleted: true})
.then(function(data) {
vm.outputs.splice($index, 1);
}, function(data) {
notify.error(gettext('Can\'t remove output'));
.then(() => {
api('outputs').save(output, {deleted: true})
.then((data) => {
vm.outputs.splice($index, 1);
}, (data) => {
notify.error(gettext('Can\'t remove output'));
});
});
});
},
userNotInMembers: function(user) {
for (var i = 0; i < vm.members.length; i ++) {
for (let i = 0; i < vm.members.length; i++) {
if (user._id === vm.members[i]._id) {

@@ -198,3 +197,3 @@ return false;

let firstPicture = pictures[0];
const firstPicture = pictures[0];

@@ -221,3 +220,3 @@ vm.newBlog.picture_url = firstPicture.renditions.viewImage.href;

}
angular.forEach(vm.forms, function(value, key) {
angular.forEach(vm.forms, (value, key) => {
if (vm.forms[key] && vm.forms[key].$dirty) {

@@ -229,3 +228,3 @@ vm.forms[key].$setPristine();

removeImage: function() {
modal.confirm(gettext('Are you sure you want to remove the blog image?')).then(function() {
modal.confirm(gettext('Are you sure you want to remove the blog image?')).then(() => {
deregisterPreventer();

@@ -237,3 +236,3 @@ vm.newBlog.picture_url = null;

saveAndClose: function() {
vm.save().then(function() {
vm.save().then(() => {
vm.close();

@@ -245,3 +244,3 @@ });

vm.posibleMembers = vm.blogMembers.concat(vm.memberRequests);
//close the change owner dropdown if open
// close the change owner dropdown if open
if (vm.openOwner === true) {

@@ -270,6 +269,7 @@ vm.openOwner = false;

hasReachedMembersLimit: function() {
if (!config.assignableUsers.hasOwnProperty(config.subscriptionLevel))
return false;
if (!config.assignableUsers.hasOwnProperty(config.subscriptionLevel)) {
return false;
}
return vm.blogMembers.length >= config.assignableUsers[config.subscriptionLevel];
return vm.blogMembers.length >= config.assignableUsers[config.subscriptionLevel];
},

@@ -281,27 +281,26 @@ removeMember: function(user) {

// save on backend
var deferred = $q.defer();
var members = _.map(vm.members, function(member) {
return ({user: member._id});
});
const deferred = $q.defer();
const members = _.map(vm.members, (member) => ({user: member._id}));
notify.info(gettext('saving blog settings'));
// Set start_date to _created if date and time are empty
var start_date = null;
if (vm.start_date && vm.start_time)
start_date = datetimeHelper.mergeDateTime(vm.start_date, vm.start_time) +
moment.tz(config.defaultTimezone).format('Z');
let startDate = vm.blog._created;
else
start_date = vm.blog._created;
if (vm.start_date && vm.start_time) {
startDate = datetimeHelper.mergeDateTime(vm.start_date, vm.start_time) +
moment.tz(config.defaultTimezone).format('Z');
}
var changedBlog = {
const changedBlog = {
blog_preferences: vm.blogPreferences,
original_creator: vm.original_creator._id,
blog_status: vm.blog_switch === true? 'open': 'closed',
blog_status: vm.blog_switch === true ? 'open' : 'closed',
syndication_enabled: vm.syndication_enabled,
market_enabled: vm.market_enabled,
category: vm.category,
start_date: start_date,
members: members
start_date: startDate,
members: members,
};
angular.extend(vm.newBlog, changedBlog);

@@ -313,3 +312,3 @@ delete vm.newBlog._latest_version;

delete vm.newBlog._type;
blogService.update(vm.blog, vm.newBlog).then(function(blog) {
blogService.update(vm.blog, vm.newBlog).then((blog) => {
vm.isSaved = true;

@@ -319,11 +318,11 @@ vm.blog = blog;

vm.blogPreferences = angular.copy(blog.blog_preferences);
//remove accepted users from the queue
// remove accepted users from the queue
if (vm.acceptedMembers.length) {
_.each(vm.acceptedMembers, function(member) {
_.each(vm.acceptedMembers, (member) => {
api('request_membership')
.getById(member.request_id)
.then(function(item) {
.then((item) => {
api('request_membership')
.remove(item)
.then(null, function() {
.then(null, () => {
notify.pop();

@@ -345,16 +344,16 @@ notify.error(gettext('Something went wrong'));

modal.confirm(gettext('Are you sure you want to delete the blog?'))
.then(function() {
vm.removeBlog();
});
.then(() => {
vm.removeBlog();
});
},
removeBlog: function() {
api.blogs.remove(angular.copy(vm.blog)).then(function(message) {
api.blogs.remove(angular.copy(vm.blog)).then((message) => {
notify.pop();
notify.info(gettext('Blog removed'));
$location.path('/liveblog');
}, function () {
}, () => {
notify.pop();
notify.error(gettext('Something went wrong'));
$location.path('/liveblog/edit/' + vm.blog._id);
});
});
},

@@ -368,5 +367,5 @@ close: function() {

.getById(userID)
.then(function(data) {
//temp_selected_owner is used handle the selection of users in the change owner autocomplete box
//without automatically changing the owner that is displayed
.then((data) => {
// temp_selected_owner is used handle the selection of users in the change owner autocomplete box
// without automatically changing the owner that is displayed
vm.temp_selected_owner = vm.original_creator = data;

@@ -376,6 +375,6 @@ });

getUsers: function(details, ids) {
_.each(ids, function(user) {
_.each(ids, (user) => {
api('users')
.getById(user.user)
.then(function(data) {
.then((data) => {
if (user.request_id) {

@@ -387,12 +386,13 @@ data.request_id = user.request_id;

});
}
},
});
// retieve the blog's public url
var qPublicUrl = blogService.getPublicUrl(blog).then(function(url) {
const qPublicUrl = blogService.getPublicUrl(blog).then((url) => {
vm.publicUrl = url;
});
// load available languages
api('languages')
.query()
.then(function(data) {
.then((data) => {
vm.availableLanguages = data._items;

@@ -402,15 +402,9 @@ });

// load available themes
var qTheme = api('themes')
const qTheme = api('themes')
.query()
.then(function(data) {
.then((data) => {
// filter theme with label (without label are `generic` from inheritance)
vm.angularTheme = data._items.find(function(theme) {
return theme.name === 'angular'
});
vm.availableThemes = data._items.filter(function(theme) {
return !theme.abstract;
});
vm.selectedTheme = _.find(vm.availableThemes, function(theme) {
return theme.name === vm.blogPreferences.theme;
});
vm.angularTheme = data._items.find((theme) => theme.name === 'angular');
vm.availableThemes = data._items.filter((theme) => !theme.abstract);
vm.selectedTheme = _.find(vm.availableThemes, (theme) => theme.name === vm.blogPreferences.theme);
if (vm.selectedTheme.styles) {

@@ -422,25 +416,28 @@ vm.styleUrl = vm.selectedTheme.public_url + vm.selectedTheme.styles[vm.selectedTheme.styles.length - 1];

// after publicUrl and theme is on `vm` object we can compute embeds code.
$q.all([qPublicUrl, qTheme]).then(function() {
$q.all([qPublicUrl, qTheme]).then(() => {
vm.embedMultiHight = true;
// devel link
var parentIframe = 'http://localhost:5000/themes_assets/angular/';
let parentIframe = 'http://localhost:5000/themes_assets/angular/';
if (vm.angularTheme.public_url) {
// production link
parentIframe = vm.angularTheme.public_url
.replace(/\/[0-9\.]+\/themes_assets\//, '/themes_assets/')
.replace('http://', 'https://');
.replace(/\/[0-9.]+\/themes_assets\//, '/themes_assets/')
.replace('http://', 'https://');
}
// loading mechanism, and load parent-iframe.js with callback.
var loadingScript = '<script type="text/javascript">var liveblog={load:function(e,t){'
+ 'var a=document,l=a.createElement("script"),'
+ 'o=a.getElementsByTagName("script")[0];'
+ 'return l.type="text/javascript",l.onload=t,l.async=!0,l.src=e,o.parentNode.insertBefore(l,o),'
+ 'l}};liveblog.load("' + parentIframe
+ 'parent-iframe.js?"+parseInt(new Date().getTime()/900000,10),function(){"function"==typeof '
+ 'liveblog.loadCallback&&liveblog.loadCallback()});</script>';
var loadingScript = `
<script type="text/javascript">
var liveblog={load:function(e,t){
var a=document,l=a.createElement("script"),
o=a.getElementsByTagName("script")[0];
return l.type="text/javascript",l.onload=t,l.async=!0,l.src=e,o.parentNode.insertBefore(l,o),l}};
liveblog.load("${parentIframe}parent-iframe.js?"+parseInt(new Date().getTime()/900000,10),function(){"function"==typeof
liveblog.loadCallback&&liveblog.loadCallback()});</script>`;
vm.embeds = {
normal: '<iframe id="liveblog-iframe" width="100%" height="715" src="' +
normal: '<iframe id="liveblog-iframe" width="100%" height="715" src="' +
vm.publicUrl + '" frameborder="0" allowfullscreen></iframe>',
resizeing: '<iframe id="liveblog-iframe" width="100%" scrolling="no" src="' +
vm.publicUrl + '" frameborder="0" allowfullscreen></iframe>' + loadingScript
resizeing: '<iframe id="liveblog-iframe" width="100%" scrolling="no" src="' +
vm.publicUrl + '" frameborder="0" allowfullscreen></iframe>' + loadingScript,
};

@@ -451,3 +448,3 @@ });

.getById(blog.original_creator)
.then(function(data) {
.then((data) => {
vm.original_creator = data;

@@ -457,3 +454,3 @@ });

.query()
.then(function(data) {
.then((data) => {
vm.avUsers = data._items;

@@ -463,13 +460,16 @@ });

//get details for the users that have requested blog membership
// get details for the users that have requested blog membership
vm.memberRequests = [];
api('blogs/<regex("[a-f0-9]{24}"):blog_id>/request_membership', {_id: vm.blog._id})
.query()
.then(function(data) {
vm.getUsers(vm.memberRequests, _.map(data._items, function(request) {
return {user: request.original_creator, request_id: request._id};
}));
.then((data) => {
vm.getUsers(vm.memberRequests, _.map(data._items,
(request) => ({
user: request.original_creator,
request_id: request._id,
})
));
});
//get team members details
// get team members details
vm.members = [];

@@ -479,21 +479,22 @@ vm.getUsers(vm.members, blog.members);

//when an output is saved in the modal directive, reload outputs
$scope.$on('output.saved', function() {
// when an output is saved in the modal directive, reload outputs
$scope.$on('output.saved', () => {
// load outputs silently
vm.loadOutputs(true);
})
});
//check if form is dirty before leaving the page
var deregisterPreventer = $scope.$on('$locationChangeStart', routeChange);
function routeChange (event, next, current) {
//check if one of the forms is dirty
var dirty = false;
// check if form is dirty before leaving the page
const deregisterPreventer = $scope.$on('$locationChangeStart', routeChange);
function routeChange(event, next, current) {
// check if one of the forms is dirty
let dirty = false;
if (vm.forms.dirty) {
dirty = true;
} else {
angular.forEach(vm.forms, function(value, key) {
angular.forEach(vm.forms, (value, key) => {
if (vm.forms[key] && vm.forms[key].$dirty) {
dirty = true;
return;
}

@@ -506,3 +507,3 @@ });

.confirm(gettext('You have unsaved settings. Are you sure you want to leave the page?'))
.then(function() {
.then(() => {
deregisterPreventer();

@@ -514,4 +515,4 @@ $location.url($location.url(next).hash());

let splitDate = datetimeHelper.splitDateTime(
vm.newBlog.start_date,
const splitDate = datetimeHelper.splitDateTime(
vm.newBlog.start_date,
config.defaultTimezone

@@ -530,8 +531,7 @@ );

// Deactivate status input, when too many blogs are active
blogSecurityService.showUpgradeModal().then(function(showUpgradeModal) {
blogSecurityService.showUpgradeModal().then((showUpgradeModal) => {
vm.deactivateStatus = vm.blog_switch ? false : showUpgradeModal;
});
}
export default BlogSettingsController;

@@ -12,3 +12,2 @@ /**

import angular from 'angular';
import _ from 'lodash';

@@ -50,3 +49,3 @@ import lbPostsList from './directives/posts-list';

.directive('freetypeText', freetypeText)
.directive('freetypeSelect',freetypeSelect)
.directive('freetypeSelect', freetypeSelect)
.directive('freetypeLink', freetypeLink)

@@ -53,0 +52,0 @@ .directive('freetypeCollectionAdd', freetypeCollectionAdd)

@@ -7,7 +7,7 @@ autofocus.$inject = ['$timeout'];

link: function($scope, $element) {
$timeout(function() {
$timeout(() => {
$element[0].focus();
});
}
},
};
}

@@ -6,13 +6,13 @@ export default function lbBindHtml() {

link: function(scope, elem, attrs) {
attrs.$observe('htmlContent', function() {
attrs.$observe('htmlContent', () => {
if (attrs.htmlLocation) {
//need to inject the html in a specific element
// need to inject the html in a specific element
elem.find('[' + attrs.htmlLocation + ']').html(attrs.htmlContent);
} else {
//inject streaght in the elem
// inject streaght in the elem
elem.html(attrs.htmlContent);
}
});
}
},
};
}

@@ -1,2 +0,2 @@

import filterByMemberTpl from 'scripts/liveblog-edit/views/filter-by-member.html';
import filterByMemberTpl from 'scripts/liveblog-edit/views/filter-by-member.ng1';

@@ -10,9 +10,10 @@ lbFilterByMember.$inject = ['api'];

blogId: '=',
onFilterChange: '='
onFilterChange: '=',
},
templateUrl: filterByMemberTpl,
controllerAs: 'vm',
controllerAs: 'self',
controller: ['$scope', function($scope) {
var vm = this;
angular.extend(vm, {
const self = this;
angular.extend(self, {
members: [],

@@ -22,49 +23,50 @@ openSelector: false,

selectedUsers: [],
findUserInPreselection: function(user_id) {
return _.find(vm.preselectedUsers, function(user) {
return user._id === user_id;
});
findUserInPreselection: function(userId) {
return _.find(self.preselectedUsers, (user) => user._id === userId);
},
toggleUserInPreselection: function(user) {
var old_user = vm.findUserInPreselection(user._id);
if (old_user) {
vm.preselectedUsers.splice(vm.preselectedUsers.indexOf(old_user), 1);
const oldUser = self.findUserInPreselection(user._id);
if (oldUser) {
self.preselectedUsers.splice(self.preselectedUsers.indexOf(oldUser), 1);
} else {
vm.preselectedUsers.push(user);
self.preselectedUsers.push(user);
}
},
isUserInPreselection: function(user) {
return vm.findUserInPreselection(user._id);
return self.findUserInPreselection(user._id);
},
confirmPreselection: function() {
vm.updateFilters(angular.copy(vm.preselectedUsers));
self.updateFilters(angular.copy(self.preselectedUsers));
},
updateFilters: function(fitlers) {
vm.selectedUsers = fitlers;
$scope.onFilterChange(vm.selectedUsers);
self.selectedUsers = fitlers;
$scope.onFilterChange(self.selectedUsers);
},
clearSelection: function() {
vm.updateFilters([]);
self.updateFilters([]);
},
removeUserFromSelection: function(user) {
var filters = angular.copy(vm.selectedUsers);
filters.splice(vm.selectedUsers.indexOf(user), 1);
vm.updateFilters(filters);
const filters = angular.copy(self.selectedUsers);
filters.splice(self.selectedUsers.indexOf(user), 1);
self.updateFilters(filters);
},
toggleSelector: function() {
vm.openSelector = !vm.openSelector;
if (vm.openSelector) {
self.openSelector = !self.openSelector;
if (self.openSelector) {
// clear the search input
vm.search = '';
self.search = '';
// preset the preselection to the current selection
vm.preselectedUsers = angular.copy(vm.selectedUsers);
self.preselectedUsers = angular.copy(self.selectedUsers);
// retrieve blog information to know the owner and the members
api('blogs')
.getById($scope.blogId)
.then(function(blog) {
.then((blog) => {
// add the owner
var ids = [blog.original_creator];
const ids = [blog.original_creator];
// add the members
if (blog.members) {
ids.push.apply(ids, blog.members.map(function(member) {return member.user;}));
ids.push(...blog.members.map((member) => member.user));
}

@@ -74,11 +76,11 @@ // retrieve information about these users and list them in the view

.query({where: {_id: {$in: ids}}})
.then(function(data) {
vm.members = data._items;
.then((data) => {
self.members = data._items;
});
});
}
}
},
});
}]
}],
};
}

@@ -9,4 +9,6 @@ freetypeCollectionAdd.$inject = ['$compile'];

this.add = function() {
var last = _.last($scope.vector), el = {};
for (var key in last) {
const last = _.last($scope.vector);
const el = {};
for (const key in last) {
// if the key starts with $$ it is angular internal so skip it.

@@ -18,9 +20,9 @@ if (last.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {

$scope.vector.push(el);
}
};
}],
controllerAs: 'ftca',
scope: {
vector: '='
}
vector: '=',
},
};
}

@@ -6,5 +6,5 @@ export default function freetypeCollectionRemove() {

controller: ['$scope', function($scope) {
this.remove = function() {
this.remove = () => {
$scope.vector.splice($scope.index, 1);
}
};
}],

@@ -14,5 +14,5 @@ controllerAs: 'ftcr',

vector: '=',
index: '='
}
index: '=',
},
};
}

@@ -8,5 +8,5 @@ freetypeEmbed.$inject = ['$compile'];

scope: {
embed: '='
}
embed: '=',
},
};
}

@@ -1,2 +0,2 @@

import freetypeImageTpl from 'scripts/liveblog-edit/views/freetype-image.html';
import freetypeImageTpl from 'scripts/liveblog-edit/views/freetype-image.ng1';

@@ -28,3 +28,3 @@ freetypeImage.$inject = ['$compile', 'modal', 'api', 'upload', 'superdesk', 'urls', 'notify'];

if ($scope.compulsory !== undefined) {
var sentinel = $scope.$watch('[image,compulsory]', (value) => {
const sentinel = $scope.$watch('[image,compulsory]', (value) => {
$scope.compulsoryFlag = value[0].picture_url === '' && value[1] === '';

@@ -61,3 +61,3 @@ }, true);

url: uploadUrl,
data: form
data: form,
})

@@ -72,2 +72,5 @@ .then((response) => {

$scope.image.picture = response.data._id;
if ($scope.progress.width === 100) {
$scope.validation.imageUploaded = true;
}
}, (error) => {

@@ -79,7 +82,6 @@ notify.error(

$scope.progress.width = Math.round(progress.loaded / progress.total * 100.0);
$scope.validation.imageUploaded = true;
}));
};
this.removeImage = function() {
$scope.removeImage = function() {
modal

@@ -100,5 +102,5 @@ .confirm(gettext('Are you sure you want to remove the image?'))

compulsory: '=',
validation: '='
}
validation: '=',
},
};
}

@@ -1,2 +0,2 @@

import freetypeLinkTpl from 'scripts/liveblog-edit/views/freetype-link.html';
import freetypeLinkTpl from 'scripts/liveblog-edit/views/freetype-link.ng1';

@@ -8,8 +8,10 @@ export default function freetypeLink() {

controller: ['$scope', function($scope) {
var regex = /https?:\/\/[^\s]+\.[^\s\.]+/;
const regex = /https?:\/\/[^\s]+\.[^\s.]+/;
$scope._id = _.uniqueId('link');
var sentinel = $scope.$watch('link', function(value) {
const sentinel = $scope.$watch('link', (value) => {
$scope.valid = !value || regex.test(value);
$scope.validation[$scope._id] = $scope.valid;
});
$scope.$on('$destroy', sentinel);

@@ -19,5 +21,5 @@ }],

link: '=',
validation: '='
}
validation: '=',
},
};
}

@@ -9,4 +9,4 @@ freetypeRender.$inject = ['$compile', 'freetypeService'];

restrict: 'E',
link: function (scope, element, attrs) {
scope.$watch('freetype', function(freetype) {
link: function(scope, element, attrs) {
scope.$watch('freetype', (freetype) => {
element.html(freetypeService.transform(freetype.template, scope));

@@ -17,6 +17,6 @@ $compile(element.contents())(scope);

//methods to control freetype functionality from outside the directive
// methods to control freetype functionality from outside the directive
scope.internalControl = scope.control || {};
//check if !dirty
// check if !dirty
scope.internalControl.isClean = function() {

@@ -26,11 +26,10 @@ return angular.equals(scope.freetypeData, scope.initialData);

scope.internalControl.isValid = function() {
var isInvalid = _.reduce(scope.validation, function(memo, val) {
return memo && val;
}, true);
const isInvalid = _.reduce(scope.validation, (memo, val) => memo && val, true);
return !isInvalid;
}
};
function recursiveClean(obj) {
for (var key in obj) {
for (const key in obj) {
if (angular.isObject(obj[key])) {
//keep only the first item in the array
// keep only the first item in the array
if (angular.isArray(obj[key])) {

@@ -44,3 +43,3 @@ obj[key].splice(1);

}
};
}

@@ -57,6 +56,6 @@ scope.internalControl.reset = function() {

validation: '=',
control: '='
}
control: '=',
},
};
}

@@ -1,2 +0,2 @@

import freetypeSelectTpl from 'scripts/liveblog-edit/views/freetype-select.html';
import freetypeSelectTpl from 'scripts/liveblog-edit/views/freetype-select.ng1';

@@ -7,3 +7,3 @@ export default function freetypeLink() {

templateUrl: freetypeSelectTpl,
controller: ['$scope', function($scope) {
controller: ['$scope', ($scope) => {
$scope.split = $scope.split || ',';

@@ -16,5 +16,5 @@ $scope.renderOptions = $scope.options.split($scope.split);

options: '@',
split: '@'
}
split: '@',
},
};
}

@@ -1,2 +0,2 @@

import freetypeTextTpl from 'scripts/liveblog-edit/views/freetype-text.html';
import freetypeTextTpl from 'scripts/liveblog-edit/views/freetype-text.ng1';

@@ -14,3 +14,4 @@ export default function freetypeText() {

if ($scope.number !== undefined) {
$scope.$on('$destroy', $scope.$watch('text', function(value) {
$scope.$on('$destroy', $scope.$watch('text', (value) => {
if ($scope.value === undefined) return;
$scope.numberFlag = (value !== '') && isNaN(value);

@@ -22,3 +23,3 @@ $scope.validation['number__' + $scope._id] = !$scope.numberFlag;

if ($scope.compulsory !== undefined) {
$scope.$on('$destroy', $scope.$watch('[text,compulsory]', function(value) {
$scope.$on('$destroy', $scope.$watch('[text,compulsory]', (value) => {
$scope.compulsoryFlag = (value[0] === '' && value[1] === '');

@@ -30,3 +31,3 @@ $scope.validation['compulsory__' + $scope._id] = !$scope.compulsoryFlag;

if ($scope.tandem !== undefined) {
$scope.$on('$destroy', $scope.$watch('[text,tandem]', function(value) {
$scope.$on('$destroy', $scope.$watch('[text,tandem]', (value) => {
$scope.tandemFlag = (value[0] === '' && value[1] !== '');

@@ -38,3 +39,3 @@ $scope.validation['tandem__' + $scope._id] = !$scope.tandemFlag;

if ($scope.necessary !== undefined) {
$scope.$on('$destroy', $scope.$watch('text', function(value) {
$scope.$on('$destroy', $scope.$watch('text', (value) => {
$scope.necessaryFlag = (value === '');

@@ -45,4 +46,4 @@ $scope.validation['necessary__' + $scope._id] = !$scope.necessaryFlag;

//listen to event in order to destroy scope and avoid garbage
$rootScope.$on('freetypeScopeDestroy', function () {
// listen to event in order to destroy scope and avoid garbage
$rootScope.$on('freetypeScopeDestroy', () => {
$scope.$destroy();

@@ -64,5 +65,5 @@ });

// pass on the maxlength attribute to the input
maxlength: '@'
}
maxlength: '@',
},
};
}

@@ -9,9 +9,11 @@ fullHeight.$inject = ['$timeout', '$window', 'lodash'];

function setHeight() {
$timeout(function() {
var height = $window.innerHeight - $element.offset().top;
$timeout(() => {
let height = $window.innerHeight - $element.offset().top;
if ($attributes.fullHeightOffsetBottom) {
height -= $attributes.fullHeightOffsetBottom;
}
var css_name = $attributes.fullHeightUseMaxHeight ? 'max-height' : 'height';
$element.css(css_name, height);
const cssName = $attributes.fullHeightUseMaxHeight ? 'max-height' : 'height';
$element.css(cssName, height);
$element[0].focus();

@@ -25,7 +27,5 @@ });

// update when offset changes
$scope.$watch(function() {
return $element.offset().top;
}, _.debounce(setHeight, 500));
}
$scope.$watch(() => $element.offset().top, _.debounce(setHeight, 500));
},
};
}

@@ -1,2 +0,2 @@

import itemTpl from 'scripts/liveblog-edit/views/item.html';
import itemTpl from 'scripts/liveblog-edit/views/item.ng1';

@@ -6,6 +6,6 @@ export default function lbItem() {

scope: {
item: '='
item: '=',
},
templateUrl: itemTpl,
}
};
}

@@ -1,2 +0,2 @@

import outputModalTpl from 'scripts/liveblog-edit/views/output-modal.html';
import outputModalTpl from 'scripts/liveblog-edit/views/output-modal.ng1';

@@ -16,8 +16,8 @@ /**

oldOutput: '=',
blog: '='
blog: '=',
},
templateUrl: outputModalTpl,
controllerAs: 'vm',
controllerAs: 'self',
controller: outputModalController,
bindToController: true
bindToController: true,
};

@@ -29,25 +29,26 @@ }

function outputModalController($rootScope, $q, api, urls, notify, modal, upload, adsUtilSevice) {
var vm = this;
vm.themes = [];
vm.collections = [];
vm.readyToSave = false;
vm.disableSave = false;
vm.imageSaved = false;
vm.cancelModal = cancelModal;
vm.saveOutput = saveOutput;
vm.saveOutputImage = saveOutputImage;
vm.removeOutputImage = removeOutputImage;
vm.removeLogoImage = removeLogoImage;
vm.notValidName = adsUtilSevice.uniqueNameInItems;
vm.ordering = [{'title': 'Ascending', 'value': 1}, {'title': 'Descending', 'value': -1}];
const self = this;
var notif_listener = $rootScope.$on('blog', (e, data) => {
if (data.blog_id === vm.blog._id && data.published === 1) {
self.themes = [];
self.collections = [];
self.readyToSave = false;
self.disableSave = false;
self.imageSaved = false;
self.cancelModal = cancelModal;
self.saveOutput = saveOutput;
self.saveOutputImage = saveOutputImage;
self.removeOutputImage = removeOutputImage;
self.removeLogoImage = removeLogoImage;
self.notValidName = adsUtilSevice.uniqueNameInItems;
self.ordering = [{title: 'Ascending', value: 1}, {title: 'Descending', value: -1}];
$rootScope.$on('blog', (e, data) => {
if (data.blog_id === self.blog._id && data.published === 1) {
// update the blog property
vm.blog.public_urls = data.public_urls;
self.blog.public_urls = data.public_urls;
}
});
initialize().then(function() {
vm.readyToSave = true;
initialize().then(() => {
self.readyToSave = true;
});

@@ -57,4 +58,4 @@ loadThemes();

function cancelModal() {
vm.modalActive = false;
vm.disableSave = false;
self.modalActive = false;
self.disableSave = false;
}

@@ -64,41 +65,43 @@

return api('collections').query({where: {deleted: false}})
.then(function(data) {
vm.collections = data._items;
return data._items;
})
.catch(function(data) {
notify.error(gettext('There was an error getting the collections'));
});
.then((data) => {
self.collections = data._items;
return data._items;
})
.catch((data) => {
notify.error(gettext('There was an error getting the collections'));
});
}
function loadThemes() {
vm.themesLoading = true;
self.themesLoading = true;
return api('themes').query({})
.then(function(data) {
vm.themes = data._items.filter((theme) => !theme.abstract);
vm.themesLoading = false;
}, function(data) {
vm.themesLoading = false;
notify.error(gettext('There was an error getting the themes'));
});
.then((data) => {
self.themes = data._items.filter((theme) => !theme.abstract);
self.themesLoading = false;
}, (data) => {
self.themesLoading = false;
notify.error(gettext('There was an error getting the themes'));
});
}
function saveOutput() {
var promises = [],
newOutput = {
name: vm.output.name,
blog: vm.blog._id,
theme: vm.output.theme,
collection: vm.output.collection,
style: vm.output.style,
settings: vm.output.settings,
logo_url: vm.output.logo_url
};
const promises = [];
const newOutput = {
name: self.output.name,
blog: self.blog._id,
theme: self.output.theme,
collection: self.output.collection,
style: self.output.style,
settings: self.output.settings,
logo_url: self.output.logo_url,
};
// disable save button
vm.disableSave = true;
self.disableSave = true;
// if there is a new background image uploaded
if (vm.output.preview && vm.output.preview.img) {
if (self.output.preview && self.output.preview.img) {
promises.push(saveOutputImage('preview', 'progress')
.then(function(data) {
let pictureUrl = data.renditions.original.href;
.then((data) => {
const pictureUrl = data.renditions.original.href;
newOutput.style['background-image'] = pictureUrl;

@@ -110,6 +113,7 @@ newOutput.picture = data._id;

// if there is a new logo image uploaded
if (vm.output.preview_logo && vm.output.preview_logo.img) {
if (self.output.preview_logo && self.output.preview_logo.img) {
promises.push(saveOutputImage('preview_logo', 'progress_logo')
.then(function(data) {
let logoUrl = data.renditions.original.href;
.then((data) => {
const logoUrl = data.renditions.original.href;
newOutput.logo_url = logoUrl;

@@ -121,19 +125,20 @@ newOutput.logo = data._id;

if (vm.oldOutput && vm.output.theme !== vm.oldOutput.theme) {
var newBlog = {
public_urls: angular.copy(vm.blog.public_urls)
if (self.oldOutput && self.output.theme !== self.oldOutput.theme) {
const newBlog = {
public_urls: angular.copy(self.blog.public_urls),
};
newBlog.public_urls.output[vm.output._id]='';
api('blogs').save(vm.blog, newBlog)
.then(function(){
notify.info(gettext('Blog saved'));
})
newBlog.public_urls.output[self.output._id] = '';
api('blogs').save(self.blog, newBlog)
.then(() => {
notify.info(gettext('Blog saved'));
});
}
$q.all(promises).then(function(){
$q.all(promises).then(() => {
if (newOutput.settings && newOutput.settings.frequency) {
newOutput.settings.frequency = parseInt(newOutput.settings.frequency, 10);
}
return api('outputs').save(vm.output, newOutput)
.then(handleSuccessSave, handleErrorSave);
return api('outputs').save(self.output, newOutput)
.then(handleSuccessSave, handleErrorSave);
});

@@ -144,5 +149,5 @@ }

notify.info(gettext('Output saved successfully'));
vm.output = {};
vm.modalActive = false;
vm.disableSave = false;
self.output = {};
self.modalActive = false;
self.disableSave = false;
$rootScope.$broadcast('output.saved');

@@ -152,9 +157,10 @@ }

function handleErrorSave() {
notify.error(gettext('Something went wrong, please try again later!'), 5000)
notify.error(gettext('Something went wrong, please try again later!'), 5000);
}
function saveOutputImage(preview, progress) {
var deferred = $q.defer(),
form = {},
config = vm.output[preview];
const deferred = $q.defer();
const form = {};
const config = self.output[preview];
if (config.img) {

@@ -167,3 +173,3 @@ form.media = config.img;

}
// return a promise of upload which will call the success/error callback

@@ -173,21 +179,21 @@ urls.resource('archive').then((uploadUrl) => upload.start({

url: uploadUrl,
data: form
data: form,
})
.then((response) => {
if (response.data._status === 'ERR') {
.then((response) => {
if (response.data._status === 'ERR') {
deferred.reject();
return;
}
deferred.resolve(response.data);
self.imageSaved = true;
}, (error) => {
notify.error(
error.statusText !== '' ? error.statusText : gettext('There was a problem with your upload')
);
deferred.reject();
return;
}
deferred.resolve(response.data);
vm.imageSaved = true;
}, (error) => {
notify.error(
error.statusText !== '' ? error.statusText : gettext('There was a problem with your upload')
);
deferred.reject();
}, (progress) => {
vm.output[progress] = {
width: Math.round(progress.loaded / progress.total * 100.0)
}
}));
}, (progress) => {
self.output[progress] = {
width: Math.round(progress.loaded / progress.total * 100.0),
};
}));
return deferred.promise;

@@ -198,8 +204,8 @@ }

modal.confirm(gettext('Are you sure you want to remove the background image?'))
.then(() => {
vm.output.preview = {};
vm.output.progress = {width: 0};
vm.output.style['background-image'] = '';
vm.imageSaved = false;
});
.then(() => {
self.output.preview = {};
self.output.progress = {width: 0};
self.output.style['background-image'] = '';
self.imageSaved = false;
});
}

@@ -209,9 +215,9 @@

modal.confirm(gettext('Are you sure you want to remove the logo image?'))
.then(() => {
vm.output.preview_logo = {};
vm.output.progress_logo = {width: 0};
vm.output.logo_url = '';
vm.imageSaved = false;
});
.then(() => {
self.output.preview_logo = {};
self.output.progress_logo = {width: 0};
self.output.logo_url = '';
self.imageSaved = false;
});
}
}

@@ -1,2 +0,2 @@

import postTpl from 'scripts/liveblog-edit/views/post.html';
import postTpl from 'scripts/liveblog-edit/views/post.ng1';

@@ -12,3 +12,3 @@ lbPost.$inject = [

'instagramService',
'$rootScope'
'$rootScope',
];

@@ -22,16 +22,16 @@

onEditAction: '=',
//the post that is in the process of being reordered
// the post that is in the process of being reordered
reorderPost: '=',
//the order property of the post that was reordered and should stay highlighted a bit more
// the order property of the post that was reordered and should stay highlighted a bit more
keepHighlighted: '=',
//call when the user clicks on the reorder icon
// call when the user clicks on the reorder icon
startReorder: '&',
//call when the user escaped the reorder action
// call when the user escaped the reorder action
clearReorderAction: '=',
//call when the user has chosen a new place for the post
// call when the user has chosen a new place for the post
reorder: '&',
//the index of the post in the list
// the index of the post in the list
index: '=',
// the controller of parent posts list directive
postsListCtrl: '='
postsListCtrl: '=',
},

@@ -47,7 +47,8 @@ restrict: 'E',

}
function changePostStatus(post, status) {
function changePostStatus(postRef, status) {
// don't save the original post coming for the posts list, because it needs
// to conserve its original update date in the posts list directive
// in order to retrieve updates from this date (if latest)
post = angular.copy(post);
const post = angular.copy(postRef);
// save the post with the new status

@@ -61,4 +62,4 @@ return postsService.savePost(post.blog, post, undefined, {post_status: status});

angular.extend(scope, {
functionize: function (obj) {
if (typeof(obj) !== 'function') {
functionize: function(obj) {
if (typeof obj !== 'function') {
return function() {

@@ -79,7 +80,7 @@ return obj;

removePost: function(post) {
postsService.remove(angular.copy(post)).then(function(message) {
postsService.remove(angular.copy(post)).then((message) => {
notify.pop();
notify.info(gettext('Removing post...'));
$rootScope.$broadcast('removing_timeline_post', {post: post});
}, function() {
}, () => {
notify.pop();

@@ -100,10 +101,10 @@ notify.error(gettext('Something went wrong'));

},
changePinStatus: function (post, status) {
changePinStatus: function(post, status) {
return postsService.savePost(post.blog, post, undefined, {sticky: status});
},
togglePinStatus: function(post) {
scope.changePinStatus(post, !post.sticky).then(function(post) {
scope.changePinStatus(post, !post.sticky).then((post) => {
notify.pop();
notify.info(post.sticky ? gettext('Post was pinned') : gettext('Post was unpinned'));
}, function() {
}, () => {
notify.pop();

@@ -120,3 +121,3 @@ notify.error(gettext('Something went wrong. Please try again later'));

modal.confirm(gettext('Are you sure you want to delete the post?'))
.then(function() {
.then(() => {
scope.removePost(post);

@@ -127,6 +128,6 @@ });

scope.clearReorder();
changePostStatus(post, 'submitted').then(function(post) {
changePostStatus(post, 'submitted').then((post) => {
notify.pop();
notify.info(gettext('Post saved as contribution'));
}, function() {
}, () => {
notify.pop();

@@ -137,3 +138,3 @@ notify.error(gettext('Something went wrong. Please try again later'));

highlightPost: function(post) {
changeHighlightStatus(post, !post.lb_highlight).then(function(post) {
changeHighlightStatus(post, !post.lb_highlight).then((post) => {
notify.pop();

@@ -143,5 +144,5 @@ notify.info(

);
}, function() {
notify.pop();
notify.error(gettext('Something went wrong. Please try again later'));
}, () => {
notify.pop();
notify.error(gettext('Something went wrong. Please try again later'));
});

@@ -151,13 +152,13 @@ },

scope.clearReorder();
changePostStatus(post, 'open').then(function(post) {
changePostStatus(post, 'open').then((post) => {
notify.pop();
notify.info(gettext('Post published'));
}, function() {
}, () => {
notify.pop();
notify.error(gettext('Something went wrong. Please try again later'));
});
}
},
});
}
},
};
}

@@ -1,2 +0,2 @@

import postsTpl from 'scripts/liveblog-edit/views/posts.html';
import postsTpl from 'scripts/liveblog-edit/views/posts.ng1';

@@ -10,4 +10,5 @@ lbPostsList.$inject = ['postsService', 'notify', '$q', '$timeout', 'session', 'PagesManager'];

$scope.lbSticky = $scope.lbSticky === 'true';
var vm = this;
angular.extend(vm, {
const self = this;
angular.extend(self, {
isLoading: true,

@@ -30,4 +31,4 @@ blogId: $scope.lbPostsBlogId,

$scope.lbPostsStatus,
//if the list is a list with sticky posts, show them all in the 1st pages
$scope.lbSticky === true? 100: 10,
// if the list is a list with sticky posts, show them all in the 1st pages
$scope.lbSticky === true ? 100 : 10,
$scope.lbPostsOrderBy || 'editorial',

@@ -39,17 +40,17 @@ $scope.lbSticky,

fetchNewPage: function() {
vm.isLoading = true;
return vm.pagesManager.fetchNewPage().then(function() {
vm.isLoading = false;
self.isLoading = true;
return self.pagesManager.fetchNewPage().then(() => {
self.isLoading = false;
});
},
startReorder: function(post) {
vm.reorderPost = post;
self.reorderPost = post;
},
clearReorder: function() {
vm.reorderPost = false;
$timeout(function() {
vm.keepHighlighted = false;
self.reorderPost = false;
$timeout(() => {
self.keepHighlighted = false;
}, 2000);
$timeout(function() {
vm.hideAllPosts = false;
$timeout(() => {
self.hideAllPosts = false;
}, 200);

@@ -69,30 +70,32 @@ },

},
reorder: function(index, location) {
if (vm.allowReordering) {
var position = index;
var order, before, after;
reorder: function(position, location) {
if (self.allowReordering) {
let order;
let before;
let after;
if (position === 0) {
order = vm.getOrder(0) + 1;
order = self.getOrder(0) + 1;
} else if (position === $element.find('.posts').find('li .lb-post').length - 1) {
order = vm.getOrder(position) - 1;
order = self.getOrder(position) - 1;
} else {
if (location === 'above') {
before = vm.getOrder(position - 1);
after = vm.getOrder(position);
before = self.getOrder(position - 1);
after = self.getOrder(position);
} else {
before = vm.getOrder(position);
after = vm.getOrder(position + 1);
before = self.getOrder(position);
after = self.getOrder(position + 1);
}
order = after + (before - after) / 2;
}
vm.updatePostOrder(vm.reorderPost, order);
self.updatePostOrder(self.reorderPost, order);
}
},
updatePostOrder: function(post, order) {
vm.hideAllPosts = true;
postsService.savePost(post.blog, post, undefined, {order: order}).then(function() {
vm.keepHighlighted = order;
vm.clearReorder();
}, function() {
vm.hideAllPosts = false;
self.hideAllPosts = true;
postsService.savePost(post.blog, post, undefined, {order: order}).then(() => {
self.keepHighlighted = order;
self.clearReorder();
}, () => {
self.hideAllPosts = false;
notify.pop();

@@ -103,9 +106,9 @@ notify.error(gettext('Something went wrong. Please reload and try again later'));

removePostFromList: function(post) {
vm.pagesManager.removePost(post);
self.pagesManager.removePost(post);
},
isPostsEmpty: function() {
return vm.pagesManager.count() < 1 && !vm.isLoading && vm.isStickyPostsEmpty();
return self.pagesManager.count() < 1 && !self.isLoading && self.isStickyPostsEmpty();
},
numberOfPosts: function() {
return vm.pagesManager.count();
return self.pagesManager.count();
},

@@ -120,12 +123,12 @@ isStickyPostsEmpty: function() {

isSinglePost: function() {
return vm.pagesManager.count() === 1;
return self.pagesManager.count() === 1;
},
isFilterEnable: function() {
return vm.pagesManager.authors.length > 0;
return self.pagesManager.authors.length > 0;
},
setAuthorFilter: function(users) {
vm.authorFilters = users;
vm.isLoading = true;
return vm.pagesManager.setAuthors(users.map(function(user) {return user._id;})).then(function() {
vm.isLoading = false;
self.authorFilters = users;
self.isLoading = true;
return self.pagesManager.setAuthors(users.map((user) => user._id)).then(() => {
self.isLoading = false;
});

@@ -135,46 +138,50 @@ },

// A syndicated post of type free type is not editable
return !(post.syndication_in && post.groups[1].refs[0].item.group_type === 'freetype');
return !(
post.syndication_in &&
post.groups[1].refs[0].item.group_type === 'freetype' &&
post.groups[1].refs[0].item.item_type.toLowerCase() !== 'scorecard'
);
},
isBlogClosed: $scope.$parent.blog.blog_status === 'closed'
isBlogClosed: $scope.$parent.blog.blog_status === 'closed',
});
$scope.lbPostsInstance = vm;
$scope.lbPostsInstance = self;
// retrieve first page
vm.fetchNewPage()
// retrieve updates when event is recieved
.then(function() {
// This function is responsible for updating the timeline,
// the contribution, the draft and the comment panel on incoming
// new post as well unpublished posts
const onNotification = (e, event_params) => {
if (!$element.hasClass('timeline-posts-list')
&& $scope.lbPostsStatus !== 'comment'
&& event_params.posts
&& event_params.posts[0].hasOwnProperty('syndication_in')) {
return false;
}
self.fetchNewPage()
// retrieve updates when event is recieved
.then(() => {
// This function is responsible for updating the timeline,
// the contribution, the draft and the comment panel on incoming
// new post as well unpublished posts
const onNotification = _.throttle((e, eventParams) => {
if (!$element.hasClass('timeline-posts-list')
&& $scope.lbPostsStatus !== 'comment'
&& eventParams.posts
&& eventParams.posts[0].hasOwnProperty('syndication_in')) {
return false;
}
if (!$element.hasClass('timeline-posts-list')
&& angular.isDefined(event_params.stages)) {
return false;
}
if (!$element.hasClass('timeline-posts-list')
&& angular.isDefined(eventParams.stages)) {
return false;
}
vm.isLoading = true;
vm.pagesManager.retrieveUpdate(true).then(function() {
// Regenerate the embed otherwise the image doesn't appear
if (window.hasOwnProperty('instgrm'))
window.instgrm.Embeds.process();
self.isLoading = true;
self.pagesManager.retrieveUpdate(true).then(() => {
// Regenerate the embed otherwise the image doesn't appear
if (window.hasOwnProperty('instgrm')) {
window.instgrm.Embeds.process();
}
if (event_params.deleted === true) {
notify.pop();
notify.info(gettext('Post removed'));
}
vm.isLoading = false;
});
if (eventParams.deleted === true) {
notify.pop();
notify.info(gettext('Post removed'));
}
self.isLoading = false;
});
}, 100);
};
$scope.$on('posts', onNotification);
$scope.$on('content:update', onNotification);
});
$scope.$on('posts', onNotification);
$scope.$on('content:update', onNotification);
});
}

@@ -196,3 +203,3 @@ return {

lbPostsIsUnreadPost: '=',
lbPostsInstance: '='
lbPostsInstance: '=',
},

@@ -203,5 +210,4 @@ restrict: 'EA',

controllerAs: 'postsList',
controller: LbPostsListCtrl
controller: LbPostsListCtrl,
};
}
export default function selectTextOnClick() {
return {
link: function(scope, elem, attrs) {
elem.bind('click', function() {
elem.bind('click', () => {
elem.focus();
elem.select();
});
}
},
};
}
export default function stopEvent() {
return {
restrict: 'A',
link: function (scope, element, attr) {
element.bind(attr.stopEvent, function (e) {
link: (scope, element, attr) => {
element.bind(attr.stopEvent, (e) => {
e.stopPropagation();
});
}
},
};
}

@@ -14,138 +14,130 @@ /**

'use strict';
/**
'use strict';
/**
* Name of the scope variable where the freetype data will be stored.
*/
const SCOPE_FREETYPEDATA = 'freetypeData';
const SCOPE_FREETYPEDATA = 'freetypeData';
/**
/**
* General regex for catching a $dolar variable
*/
const REGEX_VARIABLE = /\$([\$a-z0-9_.\[\]]+)/gi;
const REGEX_VARIABLE = /\$([$a-z0-9_.[\]]+)/gi;
/**
/**
* Generation of new index.
*/
var index = 0;
function getNewIndex(string) {
index = index + 1;
return string + '__' + index;
}
/**
let index = 0;
function getNewIndex(string) {
index = index + 1;
return string + '__' + index;
}
/**
* Makes the form text input with angular model freetypeData.name.
* also add the attributes from the tag, needed in case of classes or styles.
*/
function makeAngularAttr(name, attr) {
attr = attr || '';
// remove any trailing `/` character from attr.
// the trailing character is composed.
attr = attr.replace(/compulsory\s*=\s*("|')?([^\"\']+)("|')/g, 'compulsory="' + SCOPE_FREETYPEDATA + '.$2"');
attr = attr.replace(/\$\$/g, '');
if (attr.substr(attr.length - 1, 1) === '/') {
attr = attr.substr(0, attr.length - 1);
}
if (name.substr(0, 1) === '$') {
return '"' + name.substr(1).replace('[]', '[0]') + '" ' + attr;
}
function makeAngularAttr(name, attrRef = '') {
// remove any trailing `/` character from attr.
// the trailing character is composed.
let attr = attrRef.replace(/compulsory\s*=\s*("|')?([^"']+)("|')/g, 'compulsory="' + SCOPE_FREETYPEDATA + '.$2"');
return '"' + SCOPE_FREETYPEDATA + '.' + name.replace('[]', '[0]') + '" ' + attr;
attr = attr.replace(/\$\$/g, '');
if (attr.substr(attr.length - 1, 1) === '/') {
attr = attr.substr(0, attr.length - 1);
}
/**
if (name.substr(0, 1) === '$') {
return '"' + name.substr(1).replace('[]', '[0]') + '" ' + attr;
}
return '"' + SCOPE_FREETYPEDATA + '.' + name.replace('[]', '[0]') + '" ' + attr;
}
/**
* Sets and gets the obj from path.
* this is needed to create the vectors in the angular scope.
*/
function path2obj(obj, path, value) {
if (path.substr(0, 1) === '$') {
return;
}
var parts, part, vector;
if (angular.isString(path)) {
parts = path.split(/\./);
for (var i = 0, variable = obj; i< parts.length; i++){
if (parts[i].indexOf('[') !== -1) {
vector = parts[i].match(/([^\]]*)\[([^\]]*)]/);
if (parseInt(vector[2], 10) === vector[2]) {
vector[2] = parseInt(vector[2], 10);
}
part = {};
// if the array is already set, just use that.
if (angular.isArray(variable[vector[1]])){
// is the array is set but not that index, make it.
if (angular.isDefined(variable[vector[1]][vector[2]])) {
variable = variable[vector[1]][vector[2]]
} else {
variable[vector[1]][vector[2]] = part
variable = part;
}
} else {
variable[vector[1]] = [];
variable[vector[1]][vector[2]] = part
variable = part;
}
// if the object is already set, just use that.
} else if (angular.isDefined(variable[parts[i]])) {
variable = variable[parts[i]];
if (i === parts.length - 1) {
return variable;
}
} else if (i === parts.length - 1){
variable[parts[i]] = value || '';
} else {
variable[parts[i]] = {};
variable = variable[parts[i]];
}
}
}
function _recusivePath2obj(obj, path, value) {
const index = path.indexOf('.');
if (index === -1) {
obj[path] = value ? value : obj[path];
return obj[path];
}
/**
const key = path.substring(0, index);
const [next] = path.substring(index + 1).split('.', 1);
if (!obj[key]) {
// integer values sets a vector and string sets an object.
// check if the integer next value is the same with the next value.
obj[key] = +next + '' === next ? [] : {};
}
return _recusivePath2obj(obj[key], path.substring(index + 1), value);
}
function path2obj(obj, path, value) {
// the path should be a string and not a $value variable
if (typeof path !== 'string' || path.substr(0, 1) === '$') {
return;
}
// normalize the path, square brackets to . and [] has a default value 0.
return _recusivePath2obj(obj,
path.replace(/\[\]/g, '[0]')
.replace(/\[/g, '.')
.replace(/]/g, ''),
value);
}
/**
* Create a list of paths from `obj` parameter and return it in the
* `ret` parameter
*/
function obj2path(ret, obj, path) {
ret = ret || {};
var gotopath;
angular.forEach(obj, function(value, key) {
if (angular.isArray(value)) {
for (var i = 0; i< value.length; i++) {
gotopath = path? path + '.' + key + '[' + i + ']' : key + '[' + i + ']';
obj2path(ret, value[i], gotopath);
}
} else if (angular.isObject(value)) {
gotopath = path? path + '.' + key : key;
obj2path(ret, value, gotopath);
} else {
gotopath = path? path + '.' + key : key;
ret[gotopath] = value;
function obj2path(ret = {}, obj, path) {
let gotopath;
angular.forEach(obj, (value, key) => {
if (angular.isArray(value)) {
for (let i = 0; i < value.length; i++) {
gotopath = path ? path + '.' + key + '[' + i + ']' : key + '[' + i + ']';
obj2path(ret, value[i], gotopath);
}
});
}
/**
} else if (angular.isObject(value)) {
gotopath = path ? path + '.' + key : key;
obj2path(ret, value, gotopath);
} else {
gotopath = path ? path + '.' + key : key;
ret[gotopath] = value;
}
});
}
/**
* Inject `class` in the class attributes string.
*/
function injectClass(attr, cls) {
if (attr.indexOf('class') > -1) {
return attr.replace(/class\s*=\s*("|')?([^\"\']+)("|')/, 'class="' + cls + ' $2"');
}
function injectClass(attrParam, cls) {
let attr = attrParam;
attr += 'class="' + cls + '" ';
return attr;
if (attr.indexOf('class') > -1) {
return attr.replace(/class\s*=\s*("|')?([^"']+)("|')/, 'class="' + cls + ' $2"');
}
/**
attr += 'class="' + cls + '" ';
return attr;
}
/**
* check if an angular object has all empty values.
*/
function emptyValues(obj) {
var empty = true;
_.each(obj, function(val, key) {
// ingnore angular key settings
if (key.substr(0, 2) !== '$$') {
empty = empty && (val === '')
}
});
return empty;
}
function emptyValues(obj) {
let empty = true;
angular.module('liveblog.edit')
.factory('freetypeService', function () {
return {
/**
_.each(obj, (val, key) => {
// ingnore angular key settings
if (key.substr(0, 2) !== '$$') {
empty = empty && val === '';
}
});
return empty;
}
angular.module('liveblog.edit')
.factory('freetypeService', () => ({
/**
* transformation method from dollar sign template to angular template

@@ -155,32 +147,36 @@ * also requires `scope` object so that the proper object with the data is set.

*/
transform: function(template, scope) {
template = template || '';
transform: function(templateParam = '', scope) {
let template = templateParam;
if (!angular.isObject(scope[SCOPE_FREETYPEDATA])) {
scope[SCOPE_FREETYPEDATA] = {};
}
// transform collection mechaism for `scorers` or for dinamical lists.
template = template.replace(/<li([^>]*)>((.|\n)*?)<\/li>/g, function(all, attr, repeater) {
var iteratorName = getNewIndex('iterator');
var parts, vector = '', collection;
repeater = repeater.replace(REGEX_VARIABLE, function(all, path) {
path2obj(scope[SCOPE_FREETYPEDATA], path);
parts = path.split(/[\d*]/);
if (parts.length === 2 && parts[1] !== '') {
vector = parts[0].substr(0, parts[0].length - 1);
return '$$' + iteratorName + '.' + parts[1].substr(2);
}
if (!angular.isObject(scope[SCOPE_FREETYPEDATA])) {
scope[SCOPE_FREETYPEDATA] = {};
}
// transform collection mechaism for `scorers` or for dinamical lists.
template = template.replace(/<li([^>]*)>((.|\n)*?)<\/li>/g, (all, attr, repeaterParam) => {
const iteratorName = getNewIndex('iterator');
let parts;
let vector = '';
return all;
});
collection = SCOPE_FREETYPEDATA + '.' + vector;
return '<li ng-repeat="' + iteratorName + ' in ' + collection + '">' +
const repeater = repeaterParam.replace(REGEX_VARIABLE, (all, path) => {
path2obj(scope[SCOPE_FREETYPEDATA], path);
parts = path.split(/[\d*]/);
if (parts.length === 2 && parts[1] !== '') {
vector = parts[0].substr(0, parts[0].length - 1);
return '$$' + iteratorName + '.' + parts[1].substr(2);
}
return all;
});
const collection = SCOPE_FREETYPEDATA + '.' + vector;
return '<li ng-repeat="' + iteratorName + ' in ' + collection + '">' +
repeater + '<freetype-collection-remove index="$index" vector="' + collection + '"/>' +
'</li><li><freetype-collection-add vector="' + collection + '"/></li>';
});
// transform dollar variables in the attributes of `name` or `text` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, function(all, tag, attr) {
var name;
attr = attr.replace(/(checkbox|radio)\s*=\s*("|')?\$([\$a-z0-9_.\[\]]+)("|')?/gi,
function(match, tag, quote, rname) {
});
// transform dollar variables in the attributes of `name` or `text` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, (all, tag, attrParam) => {
let name;
const attr = attrParam.replace(/(checkbox|radio)\s*=\s*("|')?\$([$a-z0-9_.[\]]+)("|')?/gi,
(match, tag, quote, rname) => {
name = rname;

@@ -190,13 +186,15 @@ // remove the dollar variable from the attributes.

});
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<input ng-model=' + makeAngularAttr(name, attr) + '/>';
}
return all;
});
// transform dollar variables in the attributes of `name` or `text` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, function(all, tag, attr) {
var name;
attr = attr.replace(/(name|text)\s*=\s*("|')?\$([\$a-z0-9_.\[\]]+)("|')?/gi,
function(match, tag, quote, rname) {
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<input ng-model=' + makeAngularAttr(name, attr) + '/>';
}
return all;
});
// transform dollar variables in the attributes of `name` or `text` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, (all, tag, attrParam) => {
let name;
const attr = attrParam.replace(/(name|text)\s*=\s*("|')?\$([$a-z0-9_.[\]]+)("|')?/gi,
(match, tag, quote, rname) => {
name = rname;

@@ -206,15 +204,18 @@ // remove the dollar variable from the attributes.

});
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<freetype-text text='
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<freetype-text text='
+ makeAngularAttr(name, attr)
+ ' validation="validation"></freetype-text>';
}
return all;
});
// transform dollar variables in the attributes of `name` or `text` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, function(all, tag, attr) {
var name, options;
attr = attr.replace(/(select|dropdown)\s*=\s*("|')?\$([\$a-z0-9_.\[\]]+)("|')?/gi,
function(match, tag, quote, rname) {
}
return all;
});
// transform dollar variables in the attributes of `name` or `text` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, (all, tag, attrParam) => {
let name;
let options;
let attr = attrParam.replace(/(select|dropdown)\s*=\s*("|')?\$([$a-z0-9_.[\]]+)("|')?/gi,
(match, tag, quote, rname) => {
name = rname;

@@ -224,4 +225,5 @@ // remove the dollar variable from the attributes.

});
attr = attr.replace(/(options)\s*=\s*("|')?([^"']+)("|')?/gi,
function(match, tag, quote, roptions) {
attr = attr.replace(/(options)\s*=\s*("|')?([^"']+)("|')?/gi,
(match, tag, quote, roptions) => {
options = roptions;

@@ -231,239 +233,251 @@ // remove the dollar variable from the attributes.

});
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<freetype-select options="' + options + '" select='
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<freetype-select options="' + options + '" select='
+ makeAngularAttr(name, attr)
+ ' validation="validation"></freetype-select>';
}
return all;
});
// transform dollar variables in content of any start to end tag.
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>(.*?)<\/\1>?/gi,
(all, tag, attr, content) => {
let name;
const parts = content.replace(/^\s+|\s+$/g, '')
.match(/^\$([$a-z0-9]+)/gi);
// content should be only the variable name
if (parts && parts[0].length === content.length) {
name = content.substr(1);
}
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<input ng-model=' + makeAngularAttr(name, attr) + '/>';
}
return all;
});
// transform dollar variables in content of any start to end tag.
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>(.*?)<\/\1>?/gi,
function(all, tag, attr, content) {
var name, parts;
content = content.replace(/^\s+|\s+$/g, '');
parts = content.match(/^\$([\$a-z0-9]+)/gi);
// content should be only the variable name
if (parts && parts[0].length === content.length) {
name = content.substr(1);
}
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<input ng-model=' + makeAngularAttr(name, attr) + '/>';
}
return all;
// transform dollar variables in the attributes of `image` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, (all, tag, attrParam) => {
let name;
const attr = attrParam.replace(/(image|graphic|rendition)\s*=\s*("|')?\$([$a-z0-9_.[\]]+)("|')?/gi,
(match, tag, quote, rname) => {
name = rname;
// remove the dollar variable from the attributes.
return '';
});
// transform dollar variables in the attributes of `image` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, function(all, tag, attr) {
var name;
attr = attr.replace(/(image|graphic|rendition)\s*=\s*("|')?\$([\$a-z0-9_.\[\]]+)("|')?/gi,
function(match, tag, quote, rname) {
name = rname;
// remove the dollar variable from the attributes.
return '';
});
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name + '.picture_url');
return '<freetype-image image='
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name + '.picture_url');
return '<freetype-image image='
+ makeAngularAttr(name, attr)
+ ' validation="validation"></freetype-image>';
}
return all;
});
// transform dollar variables in the attributes of `link` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, function(all, tag, attr) {
var name;
attr = attr.replace(/(link|url)\s*=\s*("|')?\$([\$a-z0-9_.\[\]]+)("|')?/gi,
function(match, tag, quote, rname) {
name = rname;
// remove the dollar variable from the attributes.
return '';
});
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<freetype-link link='
}
return all;
});
// transform dollar variables in the attributes of `link` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, (all, tag, attrParam) => {
let name;
const attr = attrParam.replace(/(link|url)\s*=\s*("|')?\$([$a-z0-9_.[\]]+)("|')?/gi,
(match, tag, quote, rname) => {
name = rname;
// remove the dollar variable from the attributes.
return '';
});
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<freetype-link link='
+ makeAngularAttr(name, attr)
+ ' validation="validation"></freetype-link>';
}
}
return all;
});
// transform dollar variables in the attributes of `embed` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, (all, tag, attrParam) => {
let name;
const attr = attrParam.replace(/(embed|html)\s*=\s*("|')?\$([$a-z0-9_.[\]]+)("|')?/gi,
(match, tag, quote, rname) => {
name = rname;
// remove the dollar variable from the avem o problema, attributes.
return '';
});
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<freetype-embed embed=' + makeAngularAttr(name, attr) + '></freetype-embed>';
}
return all;
});
// replace if not empty string variables.
template = template.replace(/@([a-z0-9_.[\]-]+)\?\s*([a-z0-9_.[\]]+)/gi, (all, str, name) => {
if (str.indexOf('media') !== -1) {
return all;
});
// transform dollar variables in the attributes of `embed` in any standalone tag .
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, function(all, tag, attr) {
var name;
attr = attr.replace(/(embed|html)\s*=\s*("|')?\$([\$a-z0-9_.\[\]]+)("|')?/gi,
function(match, tag, quote, rname) {
name = rname;
// remove the dollar variable from the avem o problema, attributes.
return '';
});
if (name) {
path2obj(scope[SCOPE_FREETYPEDATA], name);
return '<freetype-embed embed=' + makeAngularAttr(name, attr) + '></freetype-embed>';
}
}
return '';
});
// replace conditional string variables.
template = template.replace(/@([a-z0-9_.[\]-]+):\s*([a-z0-9_.[\]]+)/gi, (all, str, name) => {
if (str.indexOf('media') !== -1) {
return all;
});
}
return '';
});
// replace variables
template = template.replace(/@([a-z0-9_.[\]-]+)/gi, (all, name) => {
if (all.indexOf('media') !== -1) {
return all;
}
return '{{' + SCOPE_FREETYPEDATA + '.' + name + '}}';
});
return template;
},
// create the html template that will be shown in the timeline and the live feed
htmlContent: function(templateParam, data) {
const paths = {};
let wrapBefore = '';
let wrapAfter = '';
// replace if not empty string variables.
template = template.replace(/@([a-z0-9_.\[\]\-]+)\?\s*([a-z0-9_.\[\]]+)/gi, function(all, str, name) {
if (str.indexOf('media') !== -1) {
obj2path(paths, data);
let template = templateParam.replace(/<li([^>]*)>((.|\n)*?)<\/li>/g, (all, attr, repeaterParam) => {
let vector;
let vectorPath;
let parts;
let templ = '';
const emptyIndex = [];
let i;
const repeater = repeaterParam.replace(REGEX_VARIABLE, (all, path) => {
parts = path.split(/[\d*]/);
if (parts.length === 2 && parts[1] !== '') {
vectorPath = parts[0].substr(0, parts[0].length - 1);
return all;
}
return '';
return all;
});
// replace conditional string variables.
template = template.replace(/@([a-z0-9_.\[\]\-]+):\s*([a-z0-9_.\[\]]+)/gi, function(all, str, name) {
if (str.indexOf('media') !== -1) {
return all;
if (vectorPath) {
vector = path2obj(data, vectorPath);
for (i = 1; i < vector.length; i++) {
// if current object has empty values add it to emptyIndexs and don't render it.
if (!emptyValues(vector[i])) {
templ += `<li${attr}>${
repeater.replace(REGEX_VARIABLE,
(all) => all.replace('[]', '[0]').replace('[0]', '[' + i + ']'))
}</li>`;
} else {
emptyIndex.push(i);
}
}
return '';
});
// replace variables
template = template.replace(/@([a-z0-9_.\[\]\-]+)/gi, function(all, name) {
if (all.indexOf('media') !== -1) {
return all;
// remove all the emptyIndexs from vector.
for (i = 0; i < emptyIndex.length; i++) {
vector.splice(emptyIndex[i], 1);
}
return '{{' + SCOPE_FREETYPEDATA + '.' + name + '}}';
});
return template;
if (!emptyValues(vector[0])) {
return all.replace('[]', '[0]') + templ;
}
},
// create the html template that will be shown in the timeline and the live feed
htmlContent: function(template, data) {
var paths = {},
path,
wrapBefore = '',
wrapAfter = '';
obj2path(paths, data);
template = template.replace(/<li([^>]*)>((.|\n)*?)<\/li>/g, function(all, attr, repeater) {
var vector, vectorPath, parts, templ = '', emptyIndex = [], i;
repeater = repeater.replace(REGEX_VARIABLE, function(all, path) {
parts = path.split(/[\d*]/);
if (parts.length === 2 && parts[1] !== '') {
vectorPath = parts[0].substr(0, parts[0].length - 1);
return all;
}
return '';
}
return all.replace('[]', '[0]');
});
return all;
const attributeScoop = (attrParam) => {
let name;
let type;
let attr = _.trim(attrParam);
if (attr.substr(-1, 1) === '/') {
attr = attr.substr(0, attr.length - 1);
}
// transform `name` and `text` variables.
attr = attr.replace(/(name|text)\s*=\s*("|')?\$([$a-z0-9_.[\]]+)("|')?/gi,
(match, tag, quote, rname) => {
name = rname;
type = 'text';
// remove the dollar variable from the attributes.
return '';
});
if (vectorPath) {
vector = path2obj(data, vectorPath);
for (i = 1; i< vector.length; i++) {
// if current object has empty values add it to emptyIndexs and don't render it.
if (!emptyValues(vector[i])) {
templ += '<li' + attr + '>' + repeater.replace(REGEX_VARIABLE, function(all) {
return all.replace('[]', '[0]').replace('[0]', '[' + i + ']');
}) + '</li>';
} else {
emptyIndex.push(i);
}
}
// remove all the emptyIndexs from vector.
for (i = 0; i< emptyIndex.length; i++) {
vector.splice(emptyIndex[i], 1)
}
if (!emptyValues(vector[0])) {
return all.replace('[]', '[0]') + templ;
}
attr = attr.replace(/(image|graphic|rendition)\s*=\s*("|')?\$([$a-z0-9_.[\]]+)("|')?/gi,
(match, tag, quote, rname) => {
name = rname + '.picture_url';
type = 'image';
// remove the dollar variable from the attributes.
return '';
}
return all.replace('[]', '[0]');
});
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, function(all, tag, attr) {
var name, type;
attr = _.trim(attr);
if (attr.substr(-1, 1) === '/') {
attr = attr.substr(0, attr.length - 1);
}
// transform `name` and `text` variables.
attr = attr.replace(/(name|text)\s*=\s*("|')?\$([\$a-z0-9_.\[\]]+)("|')?/gi,
function(match, tag, quote, rname) {
name = rname;
type = 'text';
// remove the dollar variable from the attributes.
return '';
});
});
attr = attr.replace(/(image|graphic|rendition)\s*=\s*("|')?\$([\$a-z0-9_.\[\]]+)("|')?/gi,
function(match, tag, quote, rname) {
name = rname + '.picture_url';
type = 'image';
// remove the dollar variable from the attributes.
return '';
});
attr = attr.replace(/(wrap-link)\s*=\s*("|')?\$([$a-z0-9_.[\]]+)("|')?/gi,
(match, tag, quote, rname) => {
name = rname;
type = 'wrap-link';
// remove the dollar variable from the attributes.
return '';
});
attr = attr.replace(/(wrap-link)\s*=\s*("|')?\$([\$a-z0-9_.\[\]]+)("|')?/gi,
function(match, tag, quote, rname) {
name = rname;
type = 'wrap-link';
// remove the dollar variable from the attributes.
return '';
});
attr = attr.replace(/(embed)\s*=\s*("|')?\$([$a-z0-9_.[\]]+)("|')?/gi,
(match, tag, quote, rname) => {
name = rname;
type = 'embed';
// remove the dollar variable from the attributes.
return '';
});
attr = attr.replace(/(embed)\s*=\s*("|')?\$([\$a-z0-9_.\[\]]+)("|')?/gi,
function(match, tag, quote, rname) {
name = rname;
type = 'embed';
// remove the dollar variable from the attributes.
return '';
});
attr = attr.replace(/(select|dropdown)\s*=\s*("|')?\$([$a-z0-9_.[\]]+)("|')?/gi,
(match, tag, quote, rname) => {
name = rname;
type = 'select';
// remove the dollar variable from the attributes.
return '';
});
attr = attr.replace(/(select|dropdown)\s*=\s*("|')?\$([\$a-z0-9_.\[\]]+)("|')?/gi,
function(match, tag, quote, rname) {
name = rname;
type = 'select';
// remove the dollar variable from the attributes.
return '';
});
const removeAttr = ['number', 'necessary', 'maxlength', 'tandem'];
attr = attr.replace(
new RegExp([
`(${removeAttr.join('|')})`,
'\\s*=\\s*("|\')?',
'([^"]+)',
'("|\')?'
].join(''),
'gi'
const removeAttr = ['number', 'necessary', 'maxlength', 'tandem'];
attr = attr.replace(
new RegExp([
`(${removeAttr.join('|')})`,
'\\s*=\\s*("|\')?',
'([^"]+)',
'("|\')?',
].join(''),
'gi'
), '');
if (name || type) {
switch (type) {
case 'text':
if (paths[name]) {
return '<span '
+ injectClass(attr, 'freetype--element')
+ '>'
+ _.escape(paths[name])
+ '</span>';
}
return {
name,
type,
attr,
};
};
return '<span ' + injectClass(attr, 'freetype--empty') + '></span>';
/* eslint complexity: [0, 14] */
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>/gi, (all, tag, attrParam) => {
const {name, type, attr} = attributeScoop(attrParam);
case 'select':
if (paths[name]) {
return '<span '
+ injectClass(attr, 'freetype--element')
+ '>'
+ _.escape(paths[name])
+ '</span>';
}
if (!name || !type) {
return all;
}
return '<span ' + injectClass(attr, 'freetype--empty') + '></span>';
switch (type) {
case 'select':
case 'text':
return paths[name] ?
`<span ${injectClass(attr, 'freetype--element')}>${_.escape(paths[name])}</span>` :
`<span ${injectClass(attr, 'freetype--empty')}></span>`;
case 'image':
if (paths[name]) {
return '<img src="' + paths[name] + '"/>'
}
return '<span ' + injectClass(attr, 'freetype--empty') + '></span>';
case 'embed':
if (paths[name]) {
return paths[name]
}
return '<span ' + injectClass(attr, 'freetype--empty') + '></span>';
case 'wrap-link':
if (paths[name]) {
wrapBefore = '<a href="'
case 'image':
return paths[name] ?
`<img src="${paths[name]}"/>` :
`<span ${injectClass(attr, 'freetype--empty')}></span>`;
case 'embed':
return paths[name] ?
paths[name] :
`<span ${injectClass(attr, 'freetype--empty')}></span>`;
case 'wrap-link':
if (paths[name]) {
wrapBefore = '<a href="'
+ paths[name]

@@ -473,84 +487,91 @@ + '"'

+ ' target="_blank">';
wrapAfter = '</a>'
}
return '';
}
wrapAfter = '</a>';
}
return '';
}
return all;
});
// replace if not empty string variables.
template = template.replace(/@([a-z0-9_.[\]-]+)\?\s*([a-z0-9_.[\]]+)/gi, (all, str, name) => {
if (str.indexOf('media') !== -1) {
return all;
});
// replace if not empty string variables.
template = template.replace(/@([a-z0-9_.\[\]\-]+)\?\s*([a-z0-9_.\[\]]+)/gi, function(all, str, name) {
if (str.indexOf('media') !== -1) {
return all;
}
if (paths[name] || paths[name + '.picture_url']) {
return str;
}
return '';
});
// replace conditional string variables.
template = template.replace(/@([a-z0-9_.\[\]\-]+):\s*([a-z0-9_.\[\]]+)/gi, function(all, str, name) {
if (str.indexOf('media') !== -1) {
return all;
}
var prefix = '', sufix = '';
if (['background-image'].indexOf(str)!== -1) {
name = name + '.picture_url';
prefix = 'url(';
sufix = ')';
}
if (paths[name]) {
return str + ':' + prefix + paths[name] + sufix;
}
return '';
});
// replace variables
template = template.replace(/@([a-z0-9_.\[\]\-]+)/gi, function(all, name) {
if (all.indexOf('media') !== -1) {
return all;
}
if (paths[name]) {
return paths[name];
}
return '';
});
// remove elements with the hide-render attribute
template = (function recursiveContent(template) {
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>((.|\n)*?)<\/\1>?/gi,
function(all, tag, attr, content) {
var type;
attr = attr.replace(/hide-render/gi, function() {
type = 'hide-render';
// remove hide-render from attributes
return '';
});
}
if (paths[name] || paths[name + '.picture_url']) {
return str;
}
return '';
});
// replace conditional string variables.
template = template.replace(/@([a-z0-9_.[\]-]+):\s*([a-z0-9_.[\]]+)/gi, (all, str, nameParam) => {
let name = nameParam;
if (type === 'hide-render') {
return '';
} else if (content) {
content = recursiveContent(content);
}
return '<' + tag + attr + '>' + content + '</' + tag + '>';
if (str.indexOf('media') !== -1) {
return all;
}
let prefix = '';
let sufix = '';
if (['background-image'].indexOf(str) !== -1) {
name = nameParam + '.picture_url';
prefix = 'url(';
sufix = ')';
}
if (paths[name]) {
return str + ':' + prefix + paths[name] + sufix;
}
return '';
});
// replace variables
template = template.replace(/@([a-z0-9_.[\]-]+)/gi, (all, name) => {
if (all.indexOf('media') !== -1) {
return all;
}
if (paths[name]) {
return paths[name];
}
return '';
});
// remove elements with the hide-render attribute
template = (function recursiveContent(templateParam) {
let template = templateParam.replace(/<([a-z][a-z0-9]*)\b([^>]*)>((.|\n)*?)<\/\1>?/gi,
(all, tag, attrParam, contentParam) => {
let type;
let content = contentParam;
const attr = attrParam.replace(/hide-render/gi, () => {
type = 'hide-render';
// remove hide-render from attributes
return '';
});
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>?/gi,
function(all, tag, attr) {
var type;
attr = attr.replace(/hide-render/gi, function() {
type = 'hide-render';
// remove hide-render from attributes
return '';
});
if (type === 'hide-render') {
return '';
}
return '<' + tag + attr + '>';
if (type === 'hide-render') {
return '';
} else if (content) {
content = recursiveContent(content);
}
return '<' + tag + attr + '>' + content + '</' + tag + '>';
});
template = template.replace(/<([a-z][a-z0-9]*)\b([^>]*)>?/gi,
(all, tag, attrParam) => {
let type;
const attr = attrParam.replace(/hide-render/gi, () => {
type = 'hide-render';
// remove hide-render from attributes
return '';
});
return template;
})(template);
return wrapBefore + template + wrapAfter;
}
};
});
if (type === 'hide-render') {
return '';
}
return '<' + tag + attr + '>';
});
return template;
})(template);
return wrapBefore + template + wrapAfter;
},
}));

@@ -15,8 +15,8 @@

import mainTpl from 'scripts/liveblog-edit/views/main.html';
import settingsTpl from 'scripts/liveblog-edit/views/settings.html';
import analiticsTpl from 'scripts/liveblog-analytics/views/view-analytics.html';
import mainTpl from 'scripts/liveblog-edit/views/main.ng1';
import settingsTpl from 'scripts/liveblog-edit/views/settings.ng1';
import analiticsTpl from 'scripts/liveblog-analytics/views/view-analytics.ng1';
import BlogEditController from './controllers/blog-edit.js'
import BlogSettingsController from './controllers/blog-settings.js'
import BlogEditController from './controllers/blog-edit.js';
import BlogSettingsController from './controllers/blog-settings.js';

@@ -28,5 +28,4 @@ /**

function BlogResolver(api, $route, $location, notify, gettext, blogService) {
return blogService.get($route.current.params._id, {timestamp: new Date()}, false)
.then(null, function(response) {
.then(null, (response) => {
if (response.status === 404) {

@@ -40,3 +39,3 @@ notify.error(gettext('Blog was not found, sorry.'), 5000);

var app = angular.module('liveblog.edit', [
const app = angular.module('liveblog.edit', [
'SirTrevor',

@@ -52,152 +51,183 @@ 'SirTrevorBlocks',

'liveblog.security',
'liveblog.freetypes'
'liveblog.freetypes',
])
.config(['superdeskProvider', function(superdesk) {
superdesk.activity('/liveblog/edit/:_id', {
label: gettext('Blog Editor'),
auth: true,
controller: BlogEditController,
controllerAs: 'blogEdit',
templateUrl: mainTpl,
resolve: {blog: BlogResolver}
})
.activity('/liveblog/settings/:_id', {
label: gettext('Blog Settings'),
auth: true,
controller: BlogSettingsController,
controllerAs: 'settings',
templateUrl: settingsTpl,
resolve: {
blog: BlogResolver,
security: ['blogSecurityService', function(blogSecurityService) {
return blogSecurityService.goToSettings();
}]
}
})
.activity('/liveblog/analytics/:_id', {
label: gettext('Blog Analytics'),
auth: true,
controller: 'LiveblogAnalyticsController',
controllerAs: 'analytics',
templateUrl: analiticsTpl,
resolve: {
blog: BlogResolver,
security: ['blogSecurityService', function(blogSecurityService) {
return blogSecurityService.goToSettings();
}]
}
});
}])
.config(['apiProvider', function(apiProvider) {
apiProvider.api('posts', {
type: 'http',
backend: {rel: 'posts'}
});
apiProvider.api('items', {
type: 'http',
backend: {rel: 'items'}
});
apiProvider.api('archive', {
type: 'http',
backend: {rel: 'archive'}
});
// @TODO: remove this when theme at blog level.
apiProvider.api('global_preferences', {
type: 'http',
backend: {rel: 'global_preferences'}
});
apiProvider.api('themes', {
type: 'http',
backend: {rel: 'themes'}
});
}])
.config(['SirTrevorOptionsProvider', 'SirTrevorProvider', function(SirTrevorOptions, SirTrevor) {
// here comes all the sir trevor customization (except custom blocks which are in the SirTrevorBlocks module)
SirTrevor = SirTrevor.$get();
// change the remove trash icon by a cross
SirTrevor.BlockDeletion.prototype.attributes['data-icon'] = 'close';
// extends the options given as parameter to the editor contructor
SirTrevorOptions.$extend({
onEditorRender: function() {
var editor = this;
// when a new block is added, remove empty blocks
function removeEmptyBlockExceptTheBlock(new_block) {
_.each(editor.blocks, function(block) {
if (block !== new_block && block.isEmpty()) {
editor.removeBlock(block.blockID);
.config(['superdeskProvider', function(superdesk) {
superdesk.activity('/liveblog/edit/:_id', {
label: gettext('Blog Editor'),
auth: true,
controller: BlogEditController,
controllerAs: 'blogEdit',
templateUrl: mainTpl,
resolve: {blog: BlogResolver},
})
.activity('/liveblog/settings/:_id', {
label: gettext('Blog Settings'),
auth: true,
controller: BlogSettingsController,
controllerAs: 'settings',
templateUrl: settingsTpl,
resolve: {
blog: BlogResolver,
security: ['blogSecurityService', function(blogSecurityService) {
return blogSecurityService.goToSettings();
}],
},
})
.activity('/liveblog/analytics/:_id', {
label: gettext('Blog Analytics'),
auth: true,
controller: 'LiveblogAnalyticsController',
controllerAs: 'analytics',
templateUrl: analiticsTpl,
resolve: {
blog: BlogResolver,
security: ['blogSecurityService', function(blogSecurityService) {
return blogSecurityService.goToSettings();
}],
},
});
}])
.config(['apiProvider', function(apiProvider) {
apiProvider.api('posts', {
type: 'http',
backend: {rel: 'posts'},
});
apiProvider.api('items', {
type: 'http',
backend: {rel: 'items'},
});
apiProvider.api('archive', {
type: 'http',
backend: {rel: 'archive'},
});
// @TODO: remove this when theme at blog level.
apiProvider.api('global_preferences', {
type: 'http',
backend: {rel: 'global_preferences'},
});
apiProvider.api('themes', {
type: 'http',
backend: {rel: 'themes'},
});
}])
.config(['SirTrevorOptionsProvider', 'SirTrevorProvider', function(SirTrevorOptions, SirTrevorParam) {
// here comes all the sir trevor customization (except custom blocks which are in the SirTrevorBlocks module)
const SirTrevor = SirTrevorParam.$get();
// change the remove trash icon by a cross
SirTrevor.BlockDeletion.prototype.attributes['data-icon'] = 'close';
// extends the options given as parameter to the editor contructor
SirTrevorOptions.$extend({
onEditorRender: function() {
const self = this;
// when a new block is added, remove empty blocks
function removeEmptyBlockExceptTheBlock(newBlock) {
_.each(self.blocks, (block) => {
if (block !== newBlock && block.isEmpty()) {
self.removeBlock(block.blockID);
}
});
}
SirTrevor.EventBus.on('block:create:existing', removeEmptyBlockExceptTheBlock);
SirTrevor.EventBus.on('block:create:new', removeEmptyBlockExceptTheBlock);
var onRemoveBlock = function() {
const editorOptions = self.options;
if (editorOptions.isEditorClean()) {
editorOptions.disableSubmit(true);
}
});
}
SirTrevor.EventBus.on('block:create:existing', removeEmptyBlockExceptTheBlock);
SirTrevor.EventBus.on('block:create:new', removeEmptyBlockExceptTheBlock);
},
blockTypes: ['Text', 'Image', 'Embed', 'Quote', 'Comment'],
// render a default block when the editor is loaded
defaultType: 'Text',
transform: {
get: function(block) {
return {
type: block.blockStorage.type,
text: block.toHTML(),
meta: block.toMeta()
};
onRemoveBlock = onRemoveBlock.bind(self);
SirTrevor.EventBus.on('block:remove', onRemoveBlock);
},
set: function(block) {
return {
type: block.type,
data: block.data
};
}
blockTypes: ['Text', 'Image', 'Embed', 'Quote', 'Comment'],
// render a default block when the editor is loaded
defaultType: 'Text',
transform: {
get: function(block) {
return {
type: block.blockStorage.type,
text: block.toHTML(),
meta: block.toMeta(),
};
},
set: function(block) {
return {
type: block.type,
data: block.data,
};
},
},
});
}])
.filter('convertLinksWithRelativeProtocol', ['config', function fixProtocol(config) {
return function getRelativeProtocol(text) {
const absoluteProtocol = RegExp(/http(s)?:\/\//ig);
config.server.url.replace(absoluteProtocol, '//');
text.replace(absoluteProtocol, '//');
return text.replace(absoluteProtocol, '//');
};
}])
/**
* Returns relative date and auto updates values every 60s
*
* @param {Datetime} date iso format datetime
* @return {String} relative time
*/
.filter('reldateAutoUpdate', ['$interval', function reldateAutorUpdateFactory($interval) {
// trigger digest every 60 seconds
$interval(() => true, 60000);
function reldateAutoUpdate(date) {
return moment(date).fromNow();
}
});
}])
.filter('convertLinksWithRelativeProtocol', ['config', function fixProtocol(config) {
return function getRelativeProtocol(text) {
var absoluteProtocol = RegExp(/http(s)?:\/\//ig);
var serverpath = config.server.url.split('//').pop();
config.server.url.replace(absoluteProtocol, '//');
text.replace(absoluteProtocol, '//')
return text.replace(absoluteProtocol, '//')
};
}])
.filter('outboundAnchors', function() {
return function(text) {
return text.replace(/<a([^>]*)>/g, function(match, attr) {
if (attr.indexOf('target') === -1) {
return '<a' + attr + ' target="_blank">';
}
return match;
});
};
})
.factory('instagramService', ['$timeout', function($timeout) {
var insta = {};
insta.postHasEmbed = function(post) {
var hasInstagram = false;
angular.forEach(post, function(item) {
if (item.item && item.item.item_type === 'embed') {
if (item.item.text && item.item.text.indexOf('platform.instagram.com') !== -1) {
hasInstagram = true;
}
reldateAutoUpdate.$stateful = true;
return reldateAutoUpdate;
}])
.filter('outboundAnchors', () => function(text = '') {
return text.replace(/<a([^>]*)>/g, (match, attr) => {
if (attr.indexOf('target') === -1) {
return `<a${attr} target="_blank">`;
}
return match;
});
return hasInstagram;
}
insta.processEmbeds = function() {
// take in accound the animations
$timeout(function() {
window.instgrm.Embeds.process();
}, 1000);
}
return insta;
}])
.config(['embedlyServiceProvider', 'embedServiceProvider', 'config',
function(embedlyServiceProvider, embedServiceProvider, config) {
embedlyServiceProvider.setKey(config.embedly.key);
embedServiceProvider.setConfig('facebookAppId', config.facebookAppId);
})
.factory('instagramService', ['$timeout', function($timeout) {
const insta = {};
insta.postHasEmbed = function(post) {
let hasInstagram = false;
angular.forEach(post, (item) => {
if (item.item && item.item.item_type === 'embed') {
if (item.item.text && item.item.text.indexOf('platform.instagram.com') !== -1) {
hasInstagram = true;
}
}
});
return hasInstagram;
};
insta.processEmbeds = function() {
// take in accound the animations
$timeout(() => {
window.instgrm.Embeds.process();
}, 1000);
};
return insta;
}])
.config(['embedlyServiceProvider', 'embedServiceProvider', 'config',
function(embedlyServiceProvider, embedServiceProvider, config) {
embedlyServiceProvider.setKey(config.embedly.key);
embedServiceProvider.setConfig('facebookAppId', config.facebookAppId);
}])
.run(['embedService', 'ngEmbedTwitterHandler', 'ngEmbedFacebookHandler',
'ngEmbedYoutubeHandler', 'ngEmbedInstagramHandler', 'ngEmbedPictureHandler',
function(embedService, ngEmbedTwitterHandler, ngEmbedFacebookHandler,
ngEmbedYoutubeHandler, ngEmbedInstagramHandler, ngEmbedPictureHandler) {
ngEmbedYoutubeHandler, ngEmbedInstagramHandler, ngEmbedPictureHandler) {
// register all the special handlers we want to use for angular-embed

@@ -211,6 +241,6 @@ // use embed.ly and update the embed code with a max_width

embedService.registerHandler(ngEmbedPictureHandler);
}
},
]);
export default app;
//});
// });
pagesManagerFactory.$inject = ['postsService', '$q', 'lodash', 'moment', 'instagramService'];
export default function pagesManagerFactory(postsService, $q, _, moment, instagramService) {
function PagesManager (blog_id, status, max_results, sort, sticky, highlight, noSynd) {
var SORTS = {
'editorial': {order: {order: 'desc', missing: '_last', unmapped_type: 'long'}},
'updated_first': {_updated: {order: 'desc', missing: '_last', unmapped_type: 'long'}},
'newest_first': {_created: {order: 'desc', missing: '_last', unmapped_type: 'long'}},
'oldest_first': {_created: {order: 'asc', missing: '_last', unmapped_type: 'long'}}
function PagesManager(blogId, status, maxResults, sort, sticky, highlight, noSynd) {
const SORTS = {
editorial: {order: {order: 'desc', missing: '_last', unmapped_type: 'long'}},
updated_first: {_updated: {order: 'desc', missing: '_last', unmapped_type: 'long'}},
newest_first: {_created: {order: 'desc', missing: '_last', unmapped_type: 'long'}},
oldest_first: {_created: {order: 'asc', missing: '_last', unmapped_type: 'long'}},
};
var self = this;
const self = this;

@@ -21,3 +20,5 @@ /**

posts: posts || [],
addPost: function(post) {this.posts.push(post);}
addPost: function(post) {
this.posts.push(post);
},
};

@@ -32,24 +33,25 @@ }

*/
function retrievePage(page, max_results) {
function retrievePage(page, maxResults) {
const options = {status: self.status, authors: self.authors};
// only care about the sticky status if post if open otherwise show them all together
// @TODO refactor when refactoring the page manager
var options = {status: self.status, authors: self.authors}
//only care about the sticky status if post if open otherwise show them all together
//@TODO refactor when refactoring the page manager
if (self.status === 'open') {
options.sticky = sticky
options.sticky = sticky;
}
if (noSynd)
if (noSynd) {
options.noSyndication = true;
}
//only care about the highlight status if it is set to true
// only care about the highlight status if it is set to true
if (self.highlight) {
options.highlight = self.highlight;
}
return postsService.getPosts(self.blogId, options ,max_results || self.maxResults, page)
.then(function(data) {
return postsService.getPosts(self.blogId, options, maxResults || self.maxResults, page)
.then((data) => {
// update posts meta data (used to know the total number of posts and pages)
self.meta = data._meta;
return data;
});
self.meta = data._meta;
return data;
});
}

@@ -68,7 +70,7 @@ /**

* Change the order in the future posts request, remove exising post and load a new page
* @param {string} sort_name - The name of the new order (see self.SORTS)
* @param {string} sortName - The name of the new order (see self.SORTS)
* @returns {promise}
*/
function changeOrder(sort_name) {
self.sort = sort_name;
function changeOrder(sortName) {
self.sort = sortName;
self.pages = [];

@@ -94,12 +96,11 @@ return fetchNewPage();

function fetchNewPage() {
var promise = $q.when();
let promise = $q.when();
// for the first time, retrieve the updates just to know the latest update date
if (self.pages.length === 0) {
promise = self.retrieveUpdate().then(function(updates) {
promise = self.retrieveUpdate().then((updates) => {
updateLatestDates(updates._items);
});
}
return promise.then(function() {
return loadPage(self.pages.length + 1);
});
return promise.then(() => loadPage(self.pages.length + 1));
}

@@ -112,44 +113,42 @@

*/
function retrieveUpdate(should_apply_updates) {
should_apply_updates = should_apply_updates === true;
var date = self.latestUpdatedDate ? self.latestUpdatedDate.utc().format() : undefined;
var page = 1;
function retrieveUpdate(shouldApplyUpdates) {
const date = self.latestUpdatedDate ? self.latestUpdatedDate.utc().format() : undefined;
let page = 1;
return postsService.getPosts(self.blogId, {updatedAfter: date, excludeDeleted: false}, undefined, page)
.then(function(updates) {
var meta = updates._meta;
// if
// - there is no other page
// - or if we don't give a latest update date (b/c we look after the meta or the latest date)
// = then we return the first page of result
if (meta.total <= meta.max_results * meta.page || !angular.isDefined(date)) {
return updates;
// Otherwise we ask page after page and concatenate them in the response
}
.then((updates) => {
const meta = updates._meta;
// if
// - there is no other page
// - or if we don't give a latest update date (b/c we look after the meta or the latest date)
// = then we return the first page of result
var promises = [];
if (meta.total <= meta.max_results * meta.page || !angular.isDefined(date)) {
return updates;
// Otherwise we ask page after page and concatenate them in the response
}
for (var i = meta.page + 1; i <= Math.floor(meta.total / meta.max_results) + 1; i++) {
page = i;
promises.push(postsService.getPosts(
self.blogId,
{updatedAfter: date, excludeDeleted: false},
undefined,
page
));
}
return $q.all(promises).then(function(updates_pages) {
return angular.extend({}, updates_pages[0], {
_items: [].concat.apply([], updates_pages.map(function(update) {return update._items;})),
_meta: angular.extend(meta, {max_results: meta.max_results * updates_pages.length})
});
const promises = [];
for (let i = meta.page + 1; i <= Math.floor(meta.total / meta.max_results) + 1; i++) {
page = i;
promises.push(postsService.getPosts(
self.blogId,
{updatedAfter: date, excludeDeleted: false},
undefined,
page
));
}
return $q.all(promises).then((updatesPages) => angular.extend({}, updatesPages[0], {
_items: [].concat(...updatesPages.map((update) => update._items)),
_meta: angular.extend(meta, {max_results: meta.max_results * updatesPages.length}),
}));
})
// Apply the update if needed
.then((updates) => {
if (shouldApplyUpdates) {
applyUpdates(updates._items);
}
return updates;
});
})
// Apply the update if needed
.then(function(updates) {
if (should_apply_updates) {
applyUpdates(updates._items);
}
return updates;
});
}

@@ -162,5 +161,7 @@

function applyUpdates(updates) {
updates.forEach(function(post) {
var existing_post_indexes = getPostPageIndexes(post);
if (angular.isDefined(existing_post_indexes)) {
// eslint-disable-next-line
updates.forEach((post) => {
const existingPostIndexes = getPostPageIndexes(post);
if (angular.isDefined(existingPostIndexes)) {
// post already in the list

@@ -172,5 +173,5 @@ if (post.deleted) {

} if (post.post_status !== self.status
|| (self.status === 'open' && post.sticky !== sticky)
|| (self.highlight && !post.lb_highlight)) {
removePost(post);
|| self.status === 'open' && post.sticky !== sticky
|| self.highlight && !post.lb_highlight) {
removePost(post);
} else {

@@ -211,4 +212,5 @@ updatePost(post);

function updateLatestDates(posts) {
var date;
posts.forEach(function(post) {
let date;
posts.forEach((post) => {
date = moment(post._updated);

@@ -230,4 +232,5 @@ if (angular.isDefined(self.latestUpdatedDate)) {

*/
function createPagesWithPosts(posts, resetPages) {
posts = posts || self.allPosts();
function createPagesWithPosts(postsParams, resetPages) {
let posts = postsParams || self.allPosts();
if (resetPages) {

@@ -237,8 +240,10 @@ self.pages = [];

// respect the order
var sort_by = Object.keys(SORTS[self.sort])[0];
var order_by = SORTS[self.sort][sort_by].order;
posts = _.sortByOrder(posts, sort_by, order_by);
var page;
var processInstagram = false;
posts.forEach(function(post, index) {
const sortBy = Object.keys(SORTS[self.sort])[0];
const orderBy = SORTS[self.sort][sortBy].order;
posts = _.sortByOrder(posts, sortBy, orderBy);
let page;
let processInstagram = false;
posts.forEach((post, index) => {
if (index % self.maxResults === 0) {

@@ -260,3 +265,3 @@ page = new Page();

instagramService.processEmbeds();
};
}
}

@@ -270,7 +275,5 @@

function loadPage(page) {
page = page || self.pages.length;
return retrievePage(page).then(function(posts) {
return retrievePage(page || self.pages.length).then((posts) => {
createPagesWithPosts(posts._items, false);
return posts;
});

@@ -281,12 +284,16 @@ }

* Returns the page index and the post index of the given post in the local pages
* @param {Post} post_to_find - post to find in the pages
* @returns {array|undefined} - [page_index, post_index]
* @param {Post} postToFind - post to find in the pages
* @returns {array|undefined} - [pageIndex, postIndex]
*/
function getPostPageIndexes(post_to_find){
var page;
for (var page_index = 0; page_index < self.pages.length; page_index++) {
page = self.pages[page_index];
for (var post_index = 0; post_index < page.posts.length; post_index++) {
if (page.posts[post_index]._id === post_to_find._id) {
return [page_index, post_index];
function getPostPageIndexes(postToFind) {
if (!postToFind) {
return [0, 0];
}
let page;
for (let pageIndex = 0; pageIndex < self.pages.length; pageIndex++) {
page = self.pages[pageIndex];
for (let postIndex = 0; postIndex < page.posts.length; postIndex++) {
if (page.posts[postIndex]._id === postToFind._id) {
return [pageIndex, postIndex];
}

@@ -299,19 +306,18 @@ }

* Add a post or a list of posts to the local pages
* @param {Post|array<Post>} posts - posts to be added to the pages
* @param {Post|array<Post>} postsParams - posts to be added to the pages
*/
function addPost(posts) {
var all_posts = self.allPosts();
if (!angular.isArray(posts)) {
posts = [posts];
}
function addPost(postsParams) {
const allPosts = self.allPosts();
const posts = angular.isArray(postsParams) ? postsParams : [postsParams];
// for every post, check if exist before or add it
posts.forEach(function(post) {
posts.forEach((post) => {
if (!angular.isDefined(getPostPageIndexes(post))) {
all_posts.push(post);
allPosts.push(post);
}
});
// and recreate pages
createPagesWithPosts(all_posts, true);
createPagesWithPosts(allPosts, true);
// update date
updateLatestDates(all_posts);
updateLatestDates(allPosts);
}

@@ -321,11 +327,13 @@

* Remove a post in the local pages
* @param {Post} post_to_remove - posts to be removed from the pages
* @param {Post} postToRemove - posts to be removed from the pages
*/
function removePost(post_to_remove) {
var indexes = getPostPageIndexes(post_to_remove);
if (angular.isDefined(post_to_remove)) {
var page_index = indexes[0];
var post_index = indexes[1];
self.pages[page_index].posts.splice(post_index, 1);
function removePost(postToRemove) {
const indexes = getPostPageIndexes(postToRemove);
if (angular.isDefined(postToRemove)) {
const pageIndex = indexes[0];
const postIndex = indexes[1];
self.pages[pageIndex].posts.splice(postIndex, 1);
createPagesWithPosts(self.allPosts(), true);

@@ -348,5 +356,3 @@ }

function count() {
return self.pages.reduce(function(previous_value, current_value) {
return previous_value + current_value.posts.length;
}, 0);
return self.pages.reduce((previousValue, currentValue) => previousValue + currentValue.posts.length, 0);
}

@@ -367,3 +373,3 @@

sort: sort || 'editorial',
blogId: blog_id,
blogId: blogId,
status: status,

@@ -391,3 +397,3 @@ /**

*/
maxResults: max_results,
maxResults: maxResults,
/**

@@ -413,11 +419,5 @@ *

*/
allPosts: function () {
var posts = self.pages.map(function(page) {
return page.posts.map(function(post) {
return post;
});
});
allPosts: function() {
// flatten array
var merged = [];
return merged.concat.apply(merged, posts);
return [].concat(...self.pages.map((page) => page.posts));
},

@@ -427,3 +427,3 @@ /**

*/
count: count
count: count,
});

@@ -430,0 +430,0 @@ }

@@ -17,7 +17,43 @@ /**

'$q',
'userList'
'userList',
];
export default function postsService(api, $q, userList) {
let producersList = [];
function filterPosts(filters, postsCriteria) {
// filters.status
if (angular.isDefined(filters.status)) {
postsCriteria.source.query.filtered.filter.and.push({term: {post_status: filters.status}});
}
// filters.sticky
if (angular.isDefined(filters.sticky)) {
postsCriteria.source.query.filtered.filter.and.push({term: {sticky: filters.sticky}});
}
// filters.authors
if (angular.isDefined(filters.authors) && filters.authors.length > 0) {
postsCriteria.source.query.filtered.filter.and.push({
or: {
filters: filters.authors.map((author) => ({term: {original_creator: author}})),
},
});
}
// filters.updatedAfter
if (angular.isDefined(filters.updatedAfter)) {
postsCriteria.source.query.filtered.filter.and.push({
range: {
_updated: {
gt: filters.updatedAfter,
},
},
});
}
// filters.highlight
if (angular.isDefined(filters.highlight)) {
postsCriteria.source.query.filtered.filter.and.push({term: {lb_highlight: filters.highlight}});
}
// filters.sticky
if (angular.isDefined(filters.sticky)) {
postsCriteria.source.query.filtered.filter.and.push({term: {sticky: filters.sticky}});
}
}
/**

@@ -30,17 +66,13 @@ * Fetch a page of posts

*/
function getPosts(blog_id, filters, max_results, page) {
filters = filters || {};
page = page || 1;
max_results = max_results || 15;
function getPosts(blogId, filters = {}, maxResults = 15, page = 1) {
// excludeDeleted: default set to true
filters.excludeDeleted = angular.isDefined(filters.excludeDeleted) ? filters.excludeDeleted : true;
var posts_criteria = {
const postsCriteria = {
source: {
query: {filtered: {filter: {
and: []
}}}
and: [],
}}},
},
page: page,
max_results: max_results
max_results: maxResults,
};

@@ -50,3 +82,3 @@

if (filters.excludeDeleted) {
posts_criteria.source.query.filtered.filter.and.push({not: {term: {deleted: true}}});
postsCriteria.source.query.filtered.filter.and.push({not: {term: {deleted: true}}});
}

@@ -56,3 +88,3 @@ // filters.sort

// this converts the format '-_created' to the elasticsearch one
var order = 'asc';
let order = 'asc';

@@ -63,48 +95,12 @@ if (filters.sort.charAt(0) === '-') {

}
var sort = {};
const sort = {};
sort[filters.sort] = {order: order, missing: '_last', unmapped_type: 'long'};
posts_criteria.source.sort = [sort];
postsCriteria.source.sort = [sort];
}
filterPosts(filters, postsCriteria);
// filters.status
if (angular.isDefined(filters.status)) {
posts_criteria.source.query.filtered.filter.and.push({term: {post_status: filters.status}});
}
// filters.sticky
if (angular.isDefined(filters.sticky)) {
posts_criteria.source.query.filtered.filter.and.push({term: {sticky: filters.sticky}});
}
// filters.authors
if (angular.isDefined(filters.authors) && filters.authors.length > 0) {
posts_criteria.source.query.filtered.filter.and.push({
or: {
filters: filters.authors.map(function(author) {
return {term: {original_creator: author}};
})
}
});
}
// filters.updatedAfter
if (angular.isDefined(filters.updatedAfter)) {
posts_criteria.source.query.filtered.filter.and.push({
range: {
_updated: {
gt: filters.updatedAfter
}
}
});
}
// filters.highlight
if (angular.isDefined(filters.highlight)) {
posts_criteria.source.query.filtered.filter.and.push({term: {lb_highlight: filters.highlight}});
}
// filters.sticky
if (angular.isDefined(filters.sticky)) {
posts_criteria.source.query.filtered.filter.and.push({term: {sticky: filters.sticky}});
}
// filters.status
if (angular.isDefined(filters.syndicationIn)) {
posts_criteria.source.query.filtered.filter.and.push({
term: {syndication_in: filters.syndicationIn}
postsCriteria.source.query.filtered.filter.and.push({
term: {syndication_in: filters.syndicationIn},
});

@@ -114,8 +110,11 @@ }

if (angular.isDefined(filters.noSyndication)) {
posts_criteria.source.query.filtered.filter.and.push({
missing: {field: 'syndication_in'}
postsCriteria.source.query.filtered.filter.and.push({
missing: {field: 'syndication_in'},
});
postsCriteria.source.query.filtered.filter.or = [{
exists: {field: 'unpublished_date'},
}];
}
return retrievePosts(blog_id, posts_criteria);
return retrievePosts(blogId, postsCriteria);
}

@@ -127,3 +126,3 @@

} else if (obj.syndicated_creator) {
obj.user = obj.syndicated_creator;
obj.user = obj.syndicated_creator;
} else {

@@ -146,3 +145,3 @@ // TODO: way too many requests in there

return $q(function(resolve, reject) {
return $q((resolve, reject) => {
angular.extend(post, {

@@ -152,15 +151,15 @@ multipleItems: multipleItems,

mainItem: post.groups[1].refs[0],
items: post.groups[1].refs
items: post.groups[1].refs,
});
// if an item has a commenter then that post hasComments.
post.hasComments = _.reduce(post.groups[1].refs, function(is, val) {
return is || !_.isUndefined(val.item.commenter);
}, false);
post.hasComments = _.reduce(post.groups[1].refs,
(is, val) => is || !_.isUndefined(val.item.commenter)
, false);
// `fullDetails` is a business logic that can be compiled from other objects.
post.fullDetails = post.hasComments;
// special cases for comments.
post.showUpdate = (post.content_updated_date !== post.published_date) &&
(!post.hasComments) && (post.mainItem.item.item_type !== 'comment');
angular.forEach(post.items, function(val) {
post.showUpdate = post.content_updated_date !== post.published_date &&
!post.hasComments && post.mainItem.item.item_type !== 'comment';
angular.forEach(post.items, (val) => {
if (post.fullDetails) {

@@ -176,12 +175,10 @@ _completeUser(val.item);

function retrievePost(post_id) {
return api.posts.getById(post_id)
function retrievePost(postId) {
return api.posts.getById(postId)
.then(_completePost)
.then(function(post) {
return post;
});
.then((post) => post);
}
function retrieveSyndications(posts) {
let syndIds = [];
const syndIds = [];

@@ -210,16 +207,12 @@ // This means the syndication module is not enabled

return post;
})
}),
}));
}
function retrievePosts(blog_id, posts_criteria) {
return api('blogs/<regex(\"[a-f0-9]{24}\"):blog_id>/posts', {_id: blog_id})
.query(posts_criteria)
function retrievePosts(blogId, postsCriteria) {
return api('blogs/<regex("[a-f0-9]{24}"):blog_id>/posts', {_id: blogId})
.query(postsCriteria)
.then(retrieveSyndications)
.then(function(data) {
return $q.all(data._items.map(_completePost))
.then(function(result) {
return angular.extend(data, { _items: result });
});
});
.then((data) => $q.all(data._items.map(_completePost))
.then((result) => angular.extend(data, {_items: result})));
}

@@ -231,41 +224,44 @@

}
var latest_date, date;
let latestDate;
let date;
posts.forEach((post) => {
date = moment(post._updated);
if (angular.isDefined(latest_date)) {
if (latest_date.diff(date) < 0) {
latest_date = date;
if (angular.isDefined(latestDate)) {
if (latestDate.diff(date) < 0) {
latestDate = date;
}
} else {
latest_date = date;
latestDate = date;
}
});
return latest_date.utc().format();
return latestDate.utc().format();
}
function savePost(blog_id, post_to_update, items, post) {
post = post || {};
post.post_status = post.post_status || _.result(post_to_update, 'post_status') || 'open';
var dfds = [];
function savePost(blogId, postToUpdate, itemsParam, postParam = {}) {
const post = postParam;
let items = itemsParam;
post.post_status = post.post_status || _.result(postToUpdate, 'post_status') || 'open';
const dfds = [];
if (items && items.length > 0) {
// prepare the list of items if needed
if (angular.isDefined(items) && items.length > 0) {
if (_.difference(_.keys(items[0]), ['residRef', 'item']).length === 0) {
items = _.map(items, function(item) {
return item.item;
});
}
if (_.difference(_.keys(items[0]), ['residRef', 'item']).length === 0) {
items = _.map(items, (item) => item.item);
}
// save every items
_.each(items, function(item) {
_.each(items, (itemParam) => {
let item = {};
// because it fails when item has a `_id` field without `_links`
if (angular.isDefined(item, '_id')) {
if (angular.isDefined(items, '_id')) {
item = {
blog: blog_id,
text: item.text,
meta: item.meta,
group_type: item.group_type,
item_type: item.item_type,
commenter: item.meta && item.meta.commenter
blog: blogId,
text: itemParam.text,
meta: itemParam.meta,
group_type: itemParam.group_type,
item_type: itemParam.item_type,
commenter: itemParam.meta && itemParam.meta.commenter,
syndicated_creator: itemParam.syndicated_creator,
};

@@ -277,6 +273,6 @@ }

// save the post
return $q.all(dfds).then(function(items) {
return $q.all(dfds).then((items) => {
if (dfds.length > 0) {
angular.extend(post, {
blog: blog_id,
blog: blogId,
groups: [

@@ -286,19 +282,20 @@ {

refs: [{idRef: 'main'}],
role: 'grpRole:NEP'
role: 'grpRole:NEP',
}, {
id: 'main',
refs: [],
role: 'grpRole:Main'
}
]
role: 'grpRole:Main',
},
],
});
// update the post reference (links with items)
_.each(items, function(item) {
_.each(items, (item) => {
post.groups[1].refs.push({residRef: item._id});
});
}
var operation;
if (angular.isDefined(post_to_update)) {
let operation;
if (angular.isDefined(postToUpdate)) {
operation = function updatePost() {
return api.posts.save(post_to_update, post);
return api.posts.save(postToUpdate, post);
};

@@ -316,3 +313,3 @@ } else {

function removePost(post) {
var deleted = {deleted: true};
const deleted = {deleted: true};

@@ -327,20 +324,20 @@ return savePost(post.blog, post, [], deleted);

savePost: savePost,
saveDraft: function(blog_id, post, items, sticky, highlight) {
saveDraft: function(blogId, post, items, sticky, highlight) {
return savePost(
blog_id,
blogId,
post,
items,
{post_status: 'draft', 'sticky': sticky, 'lb_highlight': highlight}
{post_status: 'draft', sticky: sticky, lb_highlight: highlight}
);
},
saveContribution: function(blog_id, post, items, sticky, highlight) {
saveContribution: function(blogId, post, items, sticky, highlight) {
return savePost(
blog_id,
blogId,
post,
items,
{post_status: 'submitted', 'sticky': sticky, 'lb_highlight': highlight}
{post_status: 'submitted', sticky: sticky, lb_highlight: highlight}
);
},
remove: removePost
remove: removePost,
};
}

@@ -10,3 +10,2 @@ /**

*/
import angular from 'angular';
import _ from 'lodash';

@@ -17,8 +16,9 @@

export default function unreadPostsService($rootScope) {
var listener;
var contributions = [],
prevContributions = [],
comments = [],
prevComments = [];
let listener;
let contributions = [];
let prevContributions = [];
let comments = [];
let prevComments = [];
// check if the post is an unread comment.
function isComment(post) {

@@ -30,7 +30,8 @@ return _.indexOf(prevComments, post._id) !== -1;

function isContribution(post) {
var isContrib = false;
let isContrib = false;
prevContributions.forEach(function(contrib) {
if (contrib.id === post._id)
prevContributions.forEach((contrib) => {
if (contrib.id === post._id) {
isContrib = true;
}
});

@@ -64,18 +65,18 @@

// add the post in the contributions vector.
function onPostReceive(e, event_params) {
if (event_params.posts && event_params.posts[0].syndication_in) {
function onPostReceive(e, eventParams) {
if (eventParams.posts && eventParams.posts[0].syndication_in) {
return;
}
if (event_params.post_status === 'comment') {
comments = comments.concat(event_params.posts);
if (eventParams.post_status === 'comment') {
comments = comments.concat(eventParams.posts);
}
if (event_params.post_status === 'submitted') {
contributions = contributions.concat(event_params.posts);
if (eventParams.post_status === 'submitted') {
contributions = contributions.concat(eventParams.posts);
}
if (event_params.updated) {
if (eventParams.updated) {
// Update unread comment array
event_params.posts.forEach((post) => {
eventParams.posts.forEach((post) => {
comments = comments

@@ -103,4 +104,4 @@ .filter((comment) => comment.id !== post._id);

}
}
},
};
}

@@ -1,145 +0,150 @@

import listViewTpl from 'scripts/liveblog-freetypes/views/list.html'
import listViewTpl from 'scripts/liveblog-freetypes/views/list.ng1';
LiveblogFreetypesController.$inject = ['api', '$location', 'notify', 'gettext',
'$q', '$sce', 'config', 'lodash', 'upload', 'blogService', 'modal'];
'$q', '$sce', 'config', 'lodash', 'upload', 'blogService', 'modal'];
function LiveblogFreetypesController(api, $location, notify, gettext,
$q, $sce, config, _, upload, blogService, modal) {
var vm = this;
function getFreetypes(silent) {
silent = silent || false;
api.freetypes.query().then(function(data) {
angular.forEach(data._items, function(item){
item.isUsed = false;
api.items.query({
"max_results": 1,
"source": {
"query": {
"filtered": {
"filter": {
"and": [{
"term": {
"item_type": item.name
}
}]
}
}
}
}
}).then(function(items){
if (items._items.length) {
item.isUsed = true;
}
});
$q, $sce, config, _, upload, blogService, modal) {
const self = this;
function getFreetypes(silent = false) {
api.freetypes.query().then((data) => {
angular.forEach(data._items, (item) => {
item.isUsed = false;
api.items.query({
max_results: 1,
source: {
query: {
filtered: {
filter: {
and: [{
term: {
item_type: item.name,
},
}],
},
},
},
},
}).then((items) => {
if (items._items.length) {
item.isUsed = true;
}
});
vm.freetypes = data._items;
if (!silent) {
notify.info('Free types loaded');
});
self.freetypes = data._items;
if (!silent) {
notify.info('Free types loaded');
}
}, (data) => {
notify.error(gettext('There was an error getting the free type'));
});
}
angular.extend(self, {
// new item type modal is closed by default§
freetypeModalActive: false,
editFreetype: false,
dialogFreetype: {
loading: false,
name: '',
template: '',
},
// open dialog for adding editing an item type
openFreetypeDialog: function(freetype) {
self.checkItemIsUsed(freetype).then(() => {
// refresh freetypes to make sure we use a fresh title
getFreetypes();
self.editFreetype = freetype || false;
if (self.editFreetype) {
self.dialogFreetype.name = self.editFreetype.name;
self.dialogFreetype.template = self.editFreetype.template;
} else {
self.dialogFreetype.name = '';
self.dialogFreetype.template = '';
}
}, function(data) {
notify.error(gettext('There was an error getting the free type'));
})
};
self.freetypeModalActive = true;
});
},
handleSaveError: function(data) {
let errorMsg = gettext('Saving did not work, please try again later!');
angular.extend(vm, {
//new item type modal is closed by default§
freetypeModalActive: false,
editFreetype: false,
dialogFreetype: {
loading: false,
name: '',
template: ''
},
//open dialog for adding editing an item type
openFreetypeDialog: function(freetype) {
vm.checkItemIsUsed(freetype).then(function() {
//refresh freetypes to make sure we use a fresh title
getFreetypes();
vm.editFreetype = freetype || false;
if (data.data._issues.template) {
errorMsg = gettext(data.data._issues.template);
}
notify.error(errorMsg, 10000);
},
preSaveChecks: function(template, name) {
let valid = true;
let unique = true;
// check for variables
const patt = /\$([$a-z0-9_.[\]]+)/gi;
if (vm.editFreetype) {
vm.dialogFreetype.name = vm.editFreetype.name;
vm.dialogFreetype.template = vm.editFreetype.template;
} else {
vm.dialogFreetype.name = '';
vm.dialogFreetype.template = '';
if (!patt.test(template)) {
valid = false;
notify.error(gettext(
'Template must contain at least one variable! Check the documentation for further information'
), 10000);
}
// check for unique name
angular.forEach(self.freetypes, (freetype) => {
if (freetype.name === name) {
if (!self.editFreetype) {
// it's a new freetype so not unique
unique = false;
} else if (self.editFreetype._id !== freetype._id) {
// not editing the same freetype
unique = false;
}
vm.freetypeModalActive = true;
});
},
handleSaveError: function(data) {
var errorMsg = gettext('Saving did not work, please try again later!');
if (data.data._issues.template) {
errorMsg = gettext(data.data._issues.template);
}
notify.error(errorMsg, 10000);
},
preSaveChecks: function(template, name) {
var valid = true, unique = true;
//check for variables
var patt = /\$([\$a-z0-9_.\[\]]+)/gi;
if (!patt.test(template)) {
valid = false;
notify.error(gettext(
'Template must contain at least one variable! Check the documentation for further information'
), 10000);
});
if (!unique) {
valid = false;
notify.error(gettext('Free types titles must be unique'), 10000);
}
return valid;
},
saveFreetype: function() {
if (self.preSaveChecks(self.dialogFreetype.template, self.dialogFreetype.name)) {
self.dialogFreetype.loading = true;
if (self.editFreetype) {
api
.freetypes
.save(self.editFreetype, {
name: self.dialogFreetype.name,
template: self.dialogFreetype.template,
})
.then((data) => {
self.dialogFreetype.loading = false;
self.freetypeModalActive = false;
getFreetypes();
self.editFreetype = false;
}, (data) => {
self.handleSaveError(data);
});
} else {
api
.freetypes
.save({name: self.dialogFreetype.name, template: self.dialogFreetype.template})
.then((data) => {
self.dialogFreetype.loading = false;
self.freetypeModalActive = false;
getFreetypes();
}, (data) => {
self.handleSaveError(data);
});
}
//check for unique name
angular.forEach(vm.freetypes, function(freetype) {
if (freetype.name === name) {
if (!vm.editFreetype) {
//it's a new freetype so not unique
unique = false;
} else if (vm.editFreetype._id !== freetype._id) {
//not editing the same freetype
unique = false;
}
}
});
if (!unique) {
valid = false;
notify.error(gettext('Free types titles must be unique'), 10000);
}
return valid
},
saveFreetype: function() {
if (vm.preSaveChecks(vm.dialogFreetype.template, vm.dialogFreetype.name)) {
vm.dialogFreetype.loading = true;
if (vm.editFreetype) {
api
.freetypes
.save(vm.editFreetype, {name: vm.dialogFreetype.name, template: vm.dialogFreetype.template})
.then(function(data) {
vm.dialogFreetype.loading = false;
vm.freetypeModalActive = false;
getFreetypes();
vm.editFreetype = false;
}, function(data) {
vm.handleSaveError(data);
});
} else {
api
.freetypes
.save({name: vm.dialogFreetype.name, template: vm.dialogFreetype.template})
.then(function(data) {
vm.dialogFreetype.loading = false;
vm.freetypeModalActive = false;
getFreetypes();
}, function(data) {
vm.handleSaveError(data);
});
}
}
}
},
checkItemIsUsed: function(freetype) {
return $q(function(resolve, reject) {
return $q((resolve, reject) => {
if (!freetype) {
resolve();
}
else if (freetype.isUsed) {
} else if (freetype.isUsed) {
modal.confirm(gettext(`This free type template is currently used in an active live blog.<br/>
If you change or alter it, you may not be able to edit this kind of free types anymore.<br/>
Are you sure you want to rename, change or remove it?`)).then(function() {
Are you sure you want to rename, change or remove it?`)).then(() => {
resolve();
}, function() {
}, () => {
reject();

@@ -153,7 +158,7 @@ });

removeFreetype: function(freetype, $index) {
vm.checkItemIsUsed(freetype).then(function() {
modal.confirm(gettext('Are you sure you want to remove this free type?')).then(function() {
api.freetypes.remove(freetype).then(function(data) {
vm.freetypes.splice($index, 1);
}, function(data) {
self.checkItemIsUsed(freetype).then(() => {
modal.confirm(gettext('Are you sure you want to remove this free type?')).then(() => {
api.freetypes.remove(freetype).then((data) => {
self.freetypes.splice($index, 1);
}, (data) => {
notify.error(gettext('Can\'t remove free type'));

@@ -165,4 +170,4 @@ });

cancelCreate: function() {
vm.freetypeModalActive = false;
}
self.freetypeModalActive = false;
},
});

@@ -173,5 +178,5 @@

var liveblogFreetypesModule = angular.module('liveblog.freetypes', [])
const liveblogFreetypesModule = angular.module('liveblog.freetypes', [])
.config(['superdeskProvider', 'config', function(superdesk, config) {
if (config.subscriptionLevel !== 'solo')
if (config.subscriptionLevel !== 'solo') {
superdesk

@@ -181,9 +186,10 @@ .activity('/freetypes/', {

controller: LiveblogFreetypesController,
controllerAs: 'vm',
controllerAs: 'self',
betaMark: true,
category: superdesk.MENU_MAIN,
adminTools: true,
privileges: {'global_preferences': 1},
templateUrl: listViewTpl
privileges: {global_preferences: 1},
templateUrl: listViewTpl,
});
}
}])

@@ -193,13 +199,13 @@ .config(['apiProvider', function(apiProvider) {

type: 'http',
backend: {rel: 'freetypes'}
backend: {rel: 'freetypes'},
});
}])
.config(['apiProvider', function(apiProvider) {
apiProvider.api('freetypes', {
type: 'http',
backend: {rel: 'freetypes'}
});
}]);
}])
.config(['apiProvider', function(apiProvider) {
apiProvider.api('freetypes', {
type: 'http',
backend: {rel: 'freetypes'},
});
}]);
export default liveblogFreetypesModule;

@@ -6,5 +6,5 @@ marketplaceActions.$inject = ['Dispatcher', 'api', '$http', 'lodash'];

getBlogs: function(filters) {
var params = {
const params = {
where: filters,
sort: '-start_date'
sort: '-start_date',
};

@@ -17,3 +17,3 @@

blogs: blogs,
filters: filters
filters: filters,
});

@@ -26,3 +26,3 @@ });

type: 'ON_GET_MARKETERS',
marketers: marketers
marketers: marketers,
});

@@ -35,7 +35,9 @@ });

type: 'ON_GET_LANGUAGES',
languages: languages
languages: languages,
});
});
},
toggleFilter: function(filters, type, value) {
toggleFilter: function(filtersParam, type, value) {
let filters = filtersParam;
if (filters && filters[type] === value) {

@@ -47,5 +49,5 @@ filters = _.omit(filters, type);

var params = {
const params = {
where: filters,
sort: '-start_date'
sort: '-start_date',
};

@@ -59,3 +61,3 @@

blogs: blogs,
filters: filters
filters: filters,
});

@@ -67,3 +69,3 @@ })

blogs: {_items: {}},
filters: filters
filters: filters,
});

@@ -75,3 +77,3 @@ });

type: 'ON_TOGGLED_PANEL',
searchPanel: value
searchPanel: value,
});

@@ -83,3 +85,3 @@ },

embedModal: true,
currentBlog: blog
currentBlog: blog,
});

@@ -91,6 +93,6 @@ },

embedModal: false,
currentBlog: {}
currentBlog: {},
});
}
},
};
}

@@ -7,7 +7,7 @@ marketplaceController.$inject = [

'$route',
'moment'
'moment',
];
export default function marketplaceController($scope, Store, MarketplaceActions, MarketplaceReducers, $route, moment) {
var filters = {};
let filters = {};

@@ -20,3 +20,3 @@ if ($route.current.params.hasOwnProperty('filters')) {

'Marketers',
'Producers'
'Producers',
];

@@ -53,3 +53,3 @@

embedModal: false,
languages: []
languages: [],
});

@@ -64,3 +64,3 @@

$route.updateParams({
filters: JSON.stringify(state.filters)
filters: JSON.stringify(state.filters),
});

@@ -67,0 +67,0 @@

@@ -1,2 +0,2 @@

import previewModalTpl from 'scripts/liveblog-marketplace/views/blog-preview-modal.html';
import previewModalTpl from 'scripts/liveblog-marketplace/views/blog-preview-modal.ng1';

@@ -9,10 +9,10 @@ lbBlogPreviewModal.$inject = ['MarketplaceActions', '$sce'];

scope: {
store: '='
store: '=',
},
link: function(scope) {
var iframeAttrs = [
const iframeAttrs = [
'width="100%"',
'height="715"',
'frameborder="0"',
'allowfullscreen'
'allowfullscreen',
].join(' ');

@@ -27,20 +27,22 @@

// when closing the modal by clicking outside of it.
scope.$watch('embedModal', function(embedModal) {
if (!embedModal && scope.currentBlog)
scope.$watch('embedModal', (embedModal) => {
if (!embedModal && scope.currentBlog) {
MarketplaceActions.closeEmbedModal();
}
});
scope.store.connect(function(state) {
scope.store.connect((state) => {
scope.embedModal = state.embedModal;
scope.currentBlog = state.currentBlog;
if (state.currentBlog)
if (state.currentBlog) {
scope.currentBlog = angular.extend(scope.currentBlog, {
embed: '<iframe '+iframeAttrs+' src="'
+ scope.currentBlog.public_url+'"></iframe>',
iframeUrl: $sce.trustAsResourceUrl(scope.currentBlog.public_url)
embed: '<iframe ' + iframeAttrs + ' src="'
+ scope.currentBlog.public_url + '"></iframe>',
iframeUrl: $sce.trustAsResourceUrl(scope.currentBlog.public_url),
});
}
});
}
}
},
};
}

@@ -1,2 +0,2 @@

import blogsListTpl from 'scripts/liveblog-marketplace/views/blogs-list.html';
import blogsListTpl from 'scripts/liveblog-marketplace/views/blogs-list.ng1';

@@ -10,8 +10,8 @@ lbBlogsList.$inject = ['MarketplaceActions'];

title: '@',
blogs: '='
blogs: '=',
},
link: function(scope) {
scope.openEmbedModal = MarketplaceActions.openEmbedModal;
}
}
},
};
}

@@ -1,2 +0,2 @@

import marketplatplaceSwitchTpl from 'scripts/liveblog-marketplace/views/marketplace-switch.html';
import marketplatplaceSwitchTpl from 'scripts/liveblog-marketplace/views/marketplace-switch.ng1';

@@ -7,5 +7,5 @@ export default function lbMarketplaceSwitch() {

scope: {
marketEnabled: '='
}
marketEnabled: '=',
},
};
}

@@ -1,2 +0,2 @@

import searchFilterTpl from 'scripts/liveblog-marketplace/views/search-filter.html';
import searchFilterTpl from 'scripts/liveblog-marketplace/views/search-filter.ng1';

@@ -13,3 +13,3 @@ lbSearchFilter.$inject = ['MarketplaceActions'];

key: '@',
id: '@'
id: '@',
},

@@ -24,4 +24,4 @@ link: function(scope) {

&& scope.filters[type] === value;
}
},
};
}

@@ -1,2 +0,2 @@

import searchPanelTpl from 'scripts/liveblog-marketplace/views/search-panel.html';
import searchPanelTpl from 'scripts/liveblog-marketplace/views/search-panel.ng1';

@@ -9,3 +9,3 @@ lbSearchPanel.$inject = ['MarketplaceActions'];

scope: {
store: '='
store: '=',
},

@@ -20,3 +20,3 @@ link: function(scope) {

{code: 'Politics', name: 'Politics'},
{code: 'Others', name: 'Others'}
{code: 'Others', name: 'Others'},
];

@@ -33,4 +33,4 @@

};
}
},
};
}
import './styles/marketplace.scss';
import './../flux';
import marketplaceTpl from 'scripts/liveblog-marketplace/views/marketplace.html';
import marketplaceTpl from 'scripts/liveblog-marketplace/views/marketplace.ng1';

@@ -36,7 +36,9 @@ import marketplaceController from './controllers/marketplace';

adminTools: true,
resolve: {isArchivedFilterSelected: function() {
return false;
}}
resolve: {
isArchivedFilterSelected: function() {
return false;
},
},
});
}]);

@@ -21,3 +21,3 @@ const findMarketer = function(marketers, filters) {

filters: action.filters,
currentMarketer: findMarketer(state.marketers, action.filters)
currentMarketer: findMarketer(state.marketers, action.filters),
});

@@ -28,3 +28,3 @@

marketers: action.marketers,
currentMarketer: findMarketer(action.marketers, state.filters)
currentMarketer: findMarketer(action.marketers, state.filters),
});

@@ -34,3 +34,3 @@

return angular.extend(state, {
searchPanel: action.searchPanel
searchPanel: action.searchPanel,
});

@@ -41,3 +41,3 @@

embedModal: action.embedModal,
currentBlog: action.currentBlog
currentBlog: action.currentBlog,
});

@@ -47,5 +47,5 @@

return angular.extend(state, {
languages: action.languages
languages: action.languages,
});
}
};
angular.module('liveblog.security', [])
.service('blogSecurityService',
['$q', '$rootScope', '$route', 'blogService', '$location', 'privileges', 'config', 'api',
function($q, $rootScope, $route, blogService, $location, privileges, config, api) {
function canPublishAPost() {
return privileges.userHasPrivileges({'publish_post': 1});
}
function canCreateABlog() {
return privileges.userHasPrivileges({'blogs': 1});
}
function isMemberOfBlog(blog) {
// add the owner
var ids = (blog.original_creator) ? [blog.original_creator._id] : [];
.service('blogSecurityService',
['$q', '$rootScope', '$route', 'blogService', '$location', 'privileges', 'config', 'api',
function($q, $rootScope, $route, blogService, $location, privileges, config, api) {
function canPublishAPost() {
return privileges.userHasPrivileges({publish_post: 1});
}
function canCreateABlog() {
return privileges.userHasPrivileges({blogs: 1});
}
function isMemberOfBlog(blog) {
// add the owner
const ids = blog.original_creator ? [blog.original_creator._id] : [];
// add the members
if (blog.members) {
ids.push.apply(ids, blog.members.map(function(member) {return member.user;}));
}
return ids.indexOf($rootScope.currentUser._id) > -1;
}
function showUpgradeModal() {
if (!config.blogCreationRestrictions.hasOwnProperty(config.subscriptionLevel))
return $q.when(false);
// add the members
if (blog.members) {
ids.push(...blog.members.map((member) => member.user));
}
return ids.indexOf($rootScope.currentUser._id) > -1;
}
function showUpgradeModal() {
if (!config.blogCreationRestrictions.hasOwnProperty(config.subscriptionLevel)) {
return $q.when(false);
}
var numberOfAllowedBlogs = config.blogCreationRestrictions[config.subscriptionLevel];
const numberOfAllowedBlogs = config.blogCreationRestrictions[config.subscriptionLevel];
var criteria = {
source: {
query: {filtered: {filter: {term: {blog_status: 'open'}}}}
const criteria = {
source: {
query: {filtered: {filter: {term: {blog_status: 'open'}}}},
},
};
return api.blogs.query(criteria).then((blogs) => blogs._items.length >= numberOfAllowedBlogs);
}
};
function canAccessBlog(blog) {
return isAdmin() || isMemberOfBlog(blog);
}
function isAdmin() {
return $rootScope.currentUser.user_type === 'administrator';
}
function isUserOwnerOrAdmin(archive) {
return $rootScope.currentUser._id === archive.original_creator || isAdmin();
}
function isUserOwnerOrCanPublishAPost(archive) {
return $rootScope.currentUser._id === archive.original_creator || canPublishAPost();
}
function canAccessSettings(archive) {
return canCreateABlog() && (isUserOwnerOrAdmin(archive) || isMemberOfBlog(archive));
}
function goToSettings() {
const def = $q.defer();
return api.blogs.query(criteria).then(function(blogs) {
return (blogs._items.length >= numberOfAllowedBlogs);
});
}
function canAccessBlog(blog) {
return isAdmin() || isMemberOfBlog(blog);
}
function isAdmin() {
return $rootScope.currentUser.user_type === 'administrator';
}
function isUserOwnerOrAdmin(archive) {
return $rootScope.currentUser._id === archive.original_creator || isAdmin();
}
function isUserOwnerOrCanPublishAPost(archive) {
return $rootScope.currentUser._id === archive.original_creator || canPublishAPost();
}
function canAccessSettings(archive) {
return canCreateABlog() && (isUserOwnerOrAdmin(archive) || isMemberOfBlog(archive));
}
function goToSettings() {
var def = $q.defer();
blogService.get($route.current.params._id)
.then(function(response) {
if (canAccessSettings(response)) {
def.resolve();
} else {
def.reject();
$location.path('/liveblog/edit/' + $route.current.params._id);
blogService.get($route.current.params._id)
.then((response) => {
if (canAccessSettings(response)) {
def.resolve();
} else {
def.reject();
$location.path('/liveblog/edit/' + $route.current.params._id);
}
}, () => {
$location.path('/liveblog');
def.reject('You do not have permission to change the settings of this blog');
});
return def.promise;
}
}, function() {
$location.path('/liveblog');
def.reject('You do not have permission to change the settings of this blog');
});
return def.promise;
}
return {
goToSettings: goToSettings,
showUpgradeModal: showUpgradeModal,
isAdmin: isAdmin,
isUserOwnerOrAdmin: isUserOwnerOrAdmin,
isUserOwnerOrCanPublishAPost: isUserOwnerOrCanPublishAPost,
canAccessSettings: canAccessSettings,
canPublishAPost: canPublishAPost,
canCreateABlog: canCreateABlog,
canAccessBlog: canAccessBlog
};
}
]);
return {
goToSettings: goToSettings,
showUpgradeModal: showUpgradeModal,
isAdmin: isAdmin,
isUserOwnerOrAdmin: isUserOwnerOrAdmin,
isUserOwnerOrCanPublishAPost: isUserOwnerOrCanPublishAPost,
canAccessSettings: canAccessSettings,
canPublishAPost: canPublishAPost,
canCreateABlog: canCreateABlog,
canAccessBlog: canAccessBlog,
};
},
]);

@@ -1,2 +0,2 @@

import generalTpl from 'scripts/liveblog-settings/views/general.html';
import generalTpl from 'scripts/liveblog-settings/views/general.ng1';

@@ -6,14 +6,14 @@ (function() {

function LiveblogSettingsController($scope, api, $location, notify, gettext, $q) {
//prep the settings
$scope.liveblogSettings = {'language': {}, 'theme': {}};
api.languages.query().then(function(data) {
// prep the settings
$scope.liveblogSettings = {language: {}, theme: {}};
api.languages.query().then((data) => {
$scope.languages = data._items;
});
api.themes.query().then(function(data) {
api.themes.query().then((data) => {
// filter theme with label (without label are `generic` from inheritance)
$scope.themes = data._items.filter(function(theme) {return angular.isDefined(theme.label);});
$scope.themes = data._items.filter((theme) => angular.isDefined(theme.label));
});
$scope.settingsLoading = true;
api.global_preferences.query().then(function(data) {
_.map(data._items, function(setting) {
api.global_preferences.query().then((data) => {
_.map(data._items, (setting) => {
$scope.liveblogSettings[setting.key] = setting;

@@ -27,14 +27,16 @@ });

notify.info(gettext('Saving settings'));
var patch = {}, reqArr = [];
_.map($scope.liveblogSettings, function(item, key) {
let patch = {};
const reqArr = [];
_.map($scope.liveblogSettings, (item, key) => {
patch = {
key: key,
value: item.value
value: item.value,
};
reqArr.push(api('global_preferences').save(item, patch));
});
$q.all(reqArr).then(function() {
$q.all(reqArr).then(() => {
notify.pop();
notify.info(gettext('Settings saved'));
}, function() {
}, () => {
notify.pop();

@@ -45,30 +47,31 @@ notify.error(gettext('Saving settings failed. Please try again later'));

$scope.close = function() {
//return to blog list page
// return to blog list page
$location.path('/liveblog/');
};
}
var liveblogSettingsModule = angular.module('liveblog.settings', [])
.config(['superdeskProvider', function(superdesk) {
superdesk
.activity('/settings/', {
label: gettext('Liveblog'),
controller: LiveblogSettingsController,
templateUrl: generalTpl
const liveblogSettingsModule = angular.module('liveblog.settings', [])
.config(['superdeskProvider', function(superdesk) {
superdesk
.activity('/settings/', {
label: gettext('Liveblog'),
controller: LiveblogSettingsController,
templateUrl: generalTpl,
});
}])
.config(['apiProvider', function(apiProvider) {
apiProvider.api('themes', {
type: 'http',
backend: {rel: 'themes'},
});
}])
.config(['apiProvider', function(apiProvider) {
apiProvider.api('themes', {
type: 'http',
backend: {rel: 'themes'}
});
apiProvider.api('languages', {
type: 'http',
backend: {rel: 'languages'}
});
apiProvider.api('global_preferences', {
type: 'http',
backend: {rel: 'global_preferences'}
});
}]);
apiProvider.api('languages', {
type: 'http',
backend: {rel: 'languages'},
});
apiProvider.api('global_preferences', {
type: 'http',
backend: {rel: 'global_preferences'},
});
}]);
return liveblogSettingsModule;
})();

@@ -6,12 +6,12 @@ incomingSyndicationActions.$inject = ['Dispatcher', 'api', 'postsService'];

getPosts: function(blogId, syndicationId) {
var filters = {
const filters = {
status: 'submitted',
syndicationIn: syndicationId
syndicationIn: syndicationId,
};
postsService.getPosts(blogId, filters)
.then(function(posts) {
.then((posts) => {
Dispatcher.dispatch({
type: 'ON_GET_POSTS',
posts: posts
posts: posts,
});

@@ -21,4 +21,4 @@ });

getSyndication: function(syndicationId) {
api.syndicationIn.getById(syndicationId).then(function(syndication) {
api.producers.getById(syndication.producer_id).then(function(producer) {
api.syndicationIn.getById(syndicationId).then((syndication) => {
api.producers.getById(syndication.producer_id).then((producer) => {
syndication.producer = producer;

@@ -28,3 +28,3 @@

type: 'ON_GET_SYNDICATION',
syndication: syndication
syndication: syndication,
});

@@ -36,6 +36,6 @@ });

postsService.savePost(post.blog, post, undefined, {post_status: 'open'})
.then(function(post) {
.then((post) => {
Dispatcher.dispatch({
type: 'ON_SAVED_POST',
post: post
post: post,
});

@@ -45,10 +45,10 @@ });

destroy: function(post) {
postsService.remove(post).then(function(post) {
postsService.remove(post).then((post) => {
Dispatcher.dispatch({
type: 'ON_REMOVED_POST',
post: post
post: post,
});
});
}
}
};
},
};
}

@@ -6,6 +6,6 @@ ingestPanelActions.$inject = ['Dispatcher', 'api', '$http', 'config'];

getSyndication: function(consumerBlogId, unreadQueue) {
var params = {
const params = {
where: {
blog_id: consumerBlogId
}
blog_id: consumerBlogId,
},
};

@@ -17,3 +17,3 @@

type: 'ON_GET_SYND',
syndicationIn: syndicationIn
syndicationIn: syndicationIn,
});

@@ -24,3 +24,3 @@

type: 'ON_SET_UNREAD_QUEUE',
unreadQueue: unreadQueue
unreadQueue: unreadQueue,
});

@@ -32,3 +32,3 @@ }

type: 'ON_ERROR',
error: error
error: error,
});

@@ -42,3 +42,3 @@ });

type: 'ON_GET_PRODUCERS',
producers: producers
producers: producers,
});

@@ -49,3 +49,3 @@ })

type: 'ON_ERROR',
error: error
error: error,
});

@@ -55,10 +55,10 @@ });

syndicate: function(params) {
var uri = config.server.url +
const uri = config.server.url +
'/producers/' + params.producerId +
'/syndicate/' + params.producerBlogId;
let data = {
const data = {
consumer_blog_id: params.consumerBlogId,
auto_publish: params.autoPublish,
auto_retrieve: params.autoRetrieve
auto_retrieve: params.autoRetrieve,
};

@@ -71,18 +71,18 @@

headers: {
'Content-Type': 'application/json;charset=utf-8'
}
'Content-Type': 'application/json;charset=utf-8',
},
})
.then((response) => api('syndication_in').query())
.then((syndicationIn) => {
Dispatcher.dispatch({
type: 'ON_GET_SYND',
syndicationIn: syndicationIn
.then((response) => api('syndication_in').query())
.then((syndicationIn) => {
Dispatcher.dispatch({
type: 'ON_GET_SYND',
syndicationIn: syndicationIn,
});
})
.catch((error) => {
Dispatcher.dispatch({
type: 'ON_ERROR',
error: error,
});
});
})
.catch((error) => {
Dispatcher.dispatch({
type: 'ON_ERROR',
error: error
});
});
},

@@ -94,3 +94,3 @@ getProducerBlogs: function(producerId) {

type: 'ON_GET_PRODUCER_BLOGS',
producerBlogs: blogs
producerBlogs: blogs,
});

@@ -101,3 +101,3 @@ })

type: 'ON_ERROR',
error: error
error: error,
});

@@ -109,3 +109,3 @@ });

type: 'ON_TOGGLE_MODAL',
modalActive: value
modalActive: value,
});

@@ -120,11 +120,11 @@ },

'Content-Type': 'application/json;charset=utf-8',
'If-Match': etag
}
'If-Match': etag,
},
})
.then((response) => {
Dispatcher.dispatch({
type: 'ON_UPDATED_SYND',
syndEntry: response.data
.then((response) => {
Dispatcher.dispatch({
type: 'ON_UPDATED_SYND',
syndEntry: response.data,
});
});
});
},

@@ -134,3 +134,3 @@ flushErrors: function() {

type: 'ON_ERROR',
error: null
error: null,
});

@@ -141,6 +141,6 @@ },

type: 'ON_SET_UNREAD_QUEUE',
unreadQueue: unreadQueue
unreadQueue: unreadQueue,
});
}
},
};
}

@@ -1,2 +0,2 @@

import syndicationTpl from 'scripts/liveblog-syndication/views/syndication.html';
import syndicationTpl from 'scripts/liveblog-syndication/views/syndication.ng1';

@@ -14,5 +14,5 @@ activities.$inject = ['superdeskProvider'];

adminTools: true,
privileges: {'global_preferences': 1},
resolve: {isArchivedFilterSelected: function() {return false;}}
privileges: {global_preferences: 1},
resolve: {isArchivedFilterSelected: () => false},
});
};
}

@@ -7,16 +7,16 @@ api.$inject = ['apiProvider'];

type: 'http',
backend: {rel: 'syndication_in'}
backend: {rel: 'syndication_in'},
})
.api('syndicationOut', {
type: 'http',
backend: {rel: 'syndication_out'}
backend: {rel: 'syndication_out'},
})
.api('consumers', {
.api('consumers', {
type: 'http',
backend: {rel: 'consumers'}
backend: {rel: 'consumers'},
})
.api('producers', {
type: 'http',
backend: {rel: 'producers'}
backend: {rel: 'producers'},
});
};
}

@@ -17,3 +17,3 @@ baseController.$inject = ['$scope', 'api', 'notify', '$route'];

sort: '[("_created", 1)]',
page: getPageValue($route)
page: getPageValue($route),
};

@@ -47,3 +47,3 @@

$scope.render = function(newEntry) {
var isEditing = false;
let isEditing = false;

@@ -50,0 +50,0 @@ $scope[$scope.endPoint]._items = $scope[$scope.endPoint]._items

@@ -6,3 +6,3 @@ syndicationController.$inject = ['$scope', '$route'];

{name: 'producers', code: 'open', text: gettext('Producers')},
{name: 'consumers', code: 'closed', text: gettext('Consumers')}
{name: 'consumers', code: 'closed', text: gettext('Consumers')},
];

@@ -12,9 +12,10 @@

$scope.activeState = state.name;
$route.updateParams({ state: state.name });
$route.updateParams({state: state.name});
};
if ($route.current.params.hasOwnProperty('state'))
if ($route.current.params.hasOwnProperty('state')) {
$scope.activeState = $route.current.params.state;
else
} else {
$scope.changeState($scope.states[0]);
}
}

@@ -1,2 +0,2 @@

import attachSyndicatedBlogsModalTpl from 'scripts/liveblog-syndication/views/attach-syndicated-blogs-modal.html';
import attachSyndicatedBlogsModalTpl from 'scripts/liveblog-syndication/views/attach-syndicated-blogs-modal.ng1';

@@ -9,3 +9,3 @@ attachSyndicatedBlogsModal.$inject = ['$q', 'lodash', 'IngestPanelActions'];

scope: {
store: '='
store: '=',
},

@@ -32,3 +32,3 @@ link: function(scope) {

var compare = function() {
const compare = function() {
scope.hasChanged = angular.equals(

@@ -39,10 +39,10 @@ scope.localProducerBlogIds.sort(),

var toSyndicate = _.difference(
scope.blogsToAttach,
scope.localProducerBlogIds
),
toUnSyndicate = _.difference(
scope.localProducerBlogIds,
scope.blogsToAttach
);
const toSyndicate = _.difference(
scope.blogsToAttach,
scope.localProducerBlogIds
);
const toUnSyndicate = _.difference(
scope.localProducerBlogIds,
scope.blogsToAttach
);

@@ -100,13 +100,13 @@ if (toSyndicate.length > 0 && toUnSyndicate.length === 0) {

scope.attach = function() {
let toSyndicate = _.difference(
scope.blogsToAttach,
scope.localProducerBlogIds
),
toUnSyndicate = _.difference(
scope.localProducerBlogIds,
scope.blogsToAttach
);
const toSyndicate = _.difference(
scope.blogsToAttach,
scope.localProducerBlogIds
);
const toUnSyndicate = _.difference(
scope.localProducerBlogIds,
scope.blogsToAttach
);
scope.producerBlogs._items.forEach((blog) => {
var params = {
const params = {
producerId: scope.currentProducer._id,

@@ -117,3 +117,3 @@ producerBlogId: blog._id,

autoRetrieve: blog.auto_retrieve,
method: 'POST'
method: 'POST',
};

@@ -132,4 +132,4 @@

};
}
},
};
}

@@ -1,6 +0,6 @@

import consumerEditFormTpl from 'scripts/liveblog-syndication/views/consumer-edit-form.html';
import consumerEditFormTpl from 'scripts/liveblog-syndication/views/consumer-edit-form.ng1';
consumerEdit.$inject = ['api', 'notify', 'lodash'];
consumerEdit.$inject = ['api', 'notify', 'lodash', 'superdesk'];
export default function consumerEdit(api, notify, _) {
export default function consumerEdit(api, notify, _, superdesk) {
return {

@@ -12,8 +12,9 @@ templateUrl: consumerEditFormTpl,

oncancel: '&',
onupdate: '&'
onupdate: '&',
},
link: function(scope, elem) {
scope.consumerForm.attempted = false;
scope.dirty = false;
scope.$watch('consumer', function(consumer) {
scope.$watch('consumer', (consumer) => {
scope.isEditing = consumer.hasOwnProperty('_id');

@@ -23,29 +24,46 @@ scope.origConsumer = _.cloneDeep(consumer);

scope.editPicture = function() {
superdesk.intent('edit', 'avatar', scope.consumer).then((avatar) => {
scope.consumer.picture_url = avatar; // prevent replacing Avatar which would get into diff
scope.dirty = true;
});
};
scope.save = function() {
scope.consumerForm.attempted = true;
if (!scope.consumerForm.$valid)
if (!scope.consumerForm.$valid) {
return;
}
if (angular.equals(scope.origConsumer, scope.consumer))
if (angular.equals(scope.origConsumer, scope.consumer)) {
return;
}
var data = {};
var apiQuery;
const data = {};
let apiQuery;
data.contacts = scope.consumer.contacts;
if (scope.consumer.picture_url) {
data.picture_url = scope.consumer.picture_url;
} else {
data.picture_url = null;
}
if (!scope.consumerForm.name.$pristine)
if (!scope.consumerForm.name.$pristine) {
data.name = scope.consumer.name;
}
if (!scope.consumerForm.webhook_url.$pristine)
if (!scope.consumerForm.webhook_url.$pristine) {
data.webhook_url = scope.consumer.webhook_url;
}
if (scope.isEditing)
apiQuery = api.save('consumers', scope.origConsumer, data);
else
apiQuery = api.consumers.save(data);
if (scope.isEditing) {
apiQuery = api.save('consumers', scope.origConsumer, data);
} else {
apiQuery = api.consumers.save(data);
}
apiQuery.then(function(result) {
var successMsg = gettext('Consumer saved.');
apiQuery.then((result) => {
const successMsg = gettext('Consumer saved.');

@@ -55,22 +73,22 @@ notify.pop();

scope.onsave({ consumer: result });
scope.onsave({consumer: result});
})
.catch(function(err) {
var errorMsg = gettext('Fatal error!');
.catch((err) => {
const errorMsg = gettext('Fatal error!');
if (err.data.hasOwnProperty('_issues')) {
Object.keys(err.data._issues).forEach(function(key) {
var issue = err.data._issues[key];
if (err.data.hasOwnProperty('_issues')) {
Object.keys(err.data._issues).forEach((key) => {
let issue = err.data._issues[key];
if (typeof issue === 'object' && issue.unique === 1) {
issue = gettext('The selected field value is not unique.');
}
if (typeof issue === 'object' && issue.unique === 1) {
issue = gettext('The selected field value is not unique.');
}
scope.consumerForm[key].issue = issue;
});
}
scope.consumerForm[key].issue = issue;
});
}
notify.pop();
notify.error(errorMsg);
});
notify.pop();
notify.error(errorMsg);
});
};

@@ -80,5 +98,5 @@

scope.oncancel();
}
}
};
},
};
};
}

@@ -1,2 +0,2 @@

import consumerListItemTpl from 'scripts/liveblog-syndication/views/consumer-list-item.html';
import consumerListItemTpl from 'scripts/liveblog-syndication/views/consumer-list-item.ng1';

@@ -12,3 +12,3 @@ consumerList.$inject = ['api', 'notify', 'modal', '$http', 'config'];

selected: '=',
done: '='
done: '=',
},

@@ -44,3 +44,6 @@ link: function(scope, elem, attrs) {

modal.confirm(gettext('Are you sure you want to refresh the api key?'))
modal.confirm(gettext('When refreshing the API key, please be\n' +
'aware that syndication will fail, until the new key has been\n' +
'copied to the consumer instance! Are you sure you want to refresh\n' +
'the API key?'))
.then(() => api.save('consumers', consumer, {api_key: ''}))

@@ -53,3 +56,3 @@ .then((result) => {

if (err) {
let msg = err.data._error.message || 'Fatal error';
const msg = err.data._error.message || 'Fatal error';

@@ -69,4 +72,4 @@ notify.pop();

headers: {
'Content-Type': 'application/json;charset=utf-8'
}
'Content-Type': 'application/json;charset=utf-8',
},
});

@@ -77,5 +80,5 @@ };

if (scope.consumers
&& scope.consumers.length > 0
&& data.consumer
&& data.consumer.hasOwnProperty('webhook_enabled')) {
&& scope.consumers.length > 0
&& data.consumer
&& data.consumer.hasOwnProperty('webhook_enabled')) {
scope.consumers = scope.consumers.map((consumer) => {

@@ -100,4 +103,4 @@ if (consumer._id === data.consumer._id) {

});
}
},
};
}

@@ -1,2 +0,2 @@

import consumerListTpl from 'scripts/liveblog-syndication/views/consumer-list.html';
import consumerListTpl from 'scripts/liveblog-syndication/views/consumer-list.ng1';

@@ -11,4 +11,4 @@ export default function lbConsumers() {

angular.extend(this, $controller('BaseController', {$scope: $scope}));
}]
}],
};
}

@@ -1,2 +0,2 @@

import contactsEditFormTpl from 'scripts/liveblog-syndication/views/contacts-edit-form.html';
import contactsEditFormTpl from 'scripts/liveblog-syndication/views/contacts-edit-form.ng1';

@@ -8,5 +8,5 @@ export default function contactsEdit() {

contacts: '=',
attempted: '='
attempted: '=',
},
require: "^form",
require: '^form',
link: function(scope, elem, attrs, form) {

@@ -25,4 +25,4 @@ if (!scope.contacts) {

};
}
}
};
},
};
}

@@ -20,5 +20,5 @@ copyToClipboard.$inject = ['notify'];

var apiKey = document.getElementById(attrs.for),
range = document.createRange(),
selection = window.getSelection();
const apiKey = document.getElementById(attrs.for);
const range = document.createRange();
const selection = window.getSelection();

@@ -41,4 +41,4 @@ if (apiKey) {

};
}
},
};
}

@@ -9,7 +9,7 @@ export default function firstContact() {

link: function(scope) {
scope.$watch('prosumer', function(prosumer) {
scope.$watch('prosumer', (prosumer) => {
scope.contact = prosumer.contacts[0];
})
}
});
},
};
};
}

@@ -1,2 +0,2 @@

import incomingSyndicationTpl from 'scripts/liveblog-syndication/views/incoming-syndication.html';
import incomingSyndicationTpl from 'scripts/liveblog-syndication/views/incoming-syndication.ng1';

@@ -8,3 +8,3 @@ incomingSyndication.$inject = [

'Store',
'modal'
'modal',
];

@@ -24,3 +24,3 @@

openPanel: '=',
syndId: '='
syndId: '=',
},

@@ -32,3 +32,3 @@ link: function(scope) {

posts: {},
syndication: {}
syndication: {},
});

@@ -68,3 +68,3 @@

if (data.hasOwnProperty('deleted') && data.deleted === true
|| data.posts && data.posts[0].syndication_in) {
|| data.posts && data.posts[0].syndication_in) {
IncomingSyndicationActions

@@ -76,4 +76,4 @@ .getPosts(scope.blogId, scope.syndId);

scope.$on('$destroy', scope.store.destroy);
}
},
};
}

@@ -1,2 +0,2 @@

import ingestPanelDropdownTpl from 'scripts/liveblog-syndication/views/ingest-panel-dropdown.html';
import ingestPanelDropdownTpl from 'scripts/liveblog-syndication/views/ingest-panel-dropdown.ng1';

@@ -10,16 +10,5 @@ ingestPanelDropdown.$inject = ['IngestPanelActions', 'datetimeHelper'];

consumerBlogId: '=',
blog: '='
blog: '=',
},
link: function(scope) {
scope.toggleDropdown = function($event, blog) {
if (!blog.hasOwnProperty('isOpen')) {
blog.isOpen = false;
}
$event.preventDefault();
$event.stopPropagation();
blog.isOpen = !blog.isOpen;
};
scope.updateSyndication = function() {

@@ -30,3 +19,3 @@ IngestPanelActions.updateSyndication(

auto_publish: scope.blog.auto_publish,
auto_retrieve: scope.blog.auto_retrieve
auto_retrieve: scope.blog.auto_retrieve,
},

@@ -47,3 +36,3 @@ scope.blog._etag

autoRetrieve: scope.blog.auto_retrieve,
method: 'DELETE'
method: 'DELETE',
});

@@ -53,4 +42,4 @@ };

scope.open = false;
}
},
};
}

@@ -1,2 +0,2 @@

import ingestPanelTpl from 'scripts/liveblog-syndication/views/ingest-panel.html';
import ingestPanelTpl from 'scripts/liveblog-syndication/views/ingest-panel.ng1';

@@ -9,3 +9,3 @@ ingestPanel.$inject = [

'notify',
'$timeout'
'$timeout',
];

@@ -25,6 +25,6 @@

ingestQueue: '=',
openPanel: '='
openPanel: '=',
},
link: function(scope) {
var handleError = function() {
const handleError = function() {
notify.pop();

@@ -48,3 +48,3 @@ notify.error(gettext(`

locallySyndicatedItems: [],
unreadQueue: []
unreadQueue: [],
});

@@ -101,3 +101,3 @@

if (data.posts && data.hasOwnProperty('created')) {
let syndPosts = data.posts
const syndPosts = data.posts
.filter((post) => post.hasOwnProperty('syndication_in'));

@@ -120,4 +120,4 @@

scope.$on('$destroy', scope.store.destroy);
}
},
};
}

@@ -6,5 +6,5 @@ export default function notificationsCount() {

'ng-if="count > 0">{{count}}</span>' +
'<i class="big-icon-ingest" alt="ingest"></i>',
'<i class="lb-big-icon-ingest" alt="ingest"></i>',
link: function(scope) {
let ingestPanels = ['ingest', 'incoming-syndication'];
const ingestPanels = ['ingest', 'incoming-syndication'];

@@ -30,4 +30,4 @@ scope.count = 0;

});
}
},
};
}

@@ -1,6 +0,6 @@

import producerEditFormTpl from 'scripts/liveblog-syndication/views/producer-edit-form.html';
import producerEditFormTpl from 'scripts/liveblog-syndication/views/producer-edit-form.ng1';
producerEdit.$inject = ['api', 'notify', 'lodash'];
producerEdit.$inject = ['api', 'notify', 'lodash', 'adsUtilSevice', 'superdesk'];
export default function producerEdit(api, notify, _) {
export default function producerEdit(api, notify, _, adsUtilSevice, superdesk) {
return {

@@ -12,8 +12,10 @@ templateUrl: producerEditFormTpl,

oncancel: '&',
onupdate: '&'
onupdate: '&',
producers: '=',
},
link: function(scope, elem) {
scope.producerForm.attempted = false;
scope.dirty = false;
scope.$watch('producer', function(producer) {
scope.$watch('producer', (producer) => {
scope.isEditing = producer.hasOwnProperty('_id');

@@ -23,30 +25,50 @@ scope.origProducer = _.cloneDeep(producer);

scope.editPicture = function() {
superdesk.intent('edit', 'avatar', scope.producer).then((avatar) => {
scope.producer.picture_url = avatar; // prevent replacing Avatar which would get into diff
scope.dirty = true;
});
};
scope.save = function() {
scope.producerForm.attempted = true;
if (!scope.producerForm.$valid)
if (!scope.producerForm.$valid) {
return;
}
if (angular.equals(scope.origProducer, scope.producer))
if (angular.equals(scope.origProducer, scope.producer)) {
return;
}
var data = {}, apiQuery;
const data = {};
let apiQuery;
data.contacts = scope.producer.contacts;
if (!scope.producerForm.name.$pristine)
if (scope.producer.picture_url) {
data.picture_url = scope.producer.picture_url;
} else {
data.picture_url = null;
}
if (!scope.producerForm.name.$pristine) {
data.name = scope.producer.name;
}
if (!scope.producerForm.api_url.$pristine)
if (!scope.producerForm.api_url.$pristine) {
data.api_url = scope.producer.api_url;
}
if (!scope.producerForm.consumer_api_key.$pristine)
if (!scope.producerForm.consumer_api_key.$pristine) {
data.consumer_api_key = scope.producer.consumer_api_key;
}
if (scope.isEditing)
if (scope.isEditing) {
apiQuery = api.save('producers', scope.origProducer, data);
else
} else {
apiQuery = api.producers.save(data);
}
apiQuery.then(function(result) {
apiQuery.then((result) => {
var successMsg = gettext('Producer saved.');

@@ -57,24 +79,27 @@

scope.onsave({ producer: result });
scope.onsave({producer: result});
})
.catch(function(err) {
var errorMsg = gettext('An error has occurred. Please try again later.');
.catch((err) => {
var errorMsg = gettext('An error has occurred. Please try again later.');
if (err.data.hasOwnProperty('_error'))
errorMsg = err.data._error.message;
if (err.data.hasOwnProperty('_error')) {
errorMsg = err.data._error.message;
}
if (err.data.hasOwnProperty('_issues')) {
Object.keys(err.data._issues).forEach(function(key) {
var issue = err.data._issues[key];
if (typeof issue === 'object') {
if (issue.unique === true)
issue = gettext('The selected field value is not unique.');
}
scope.producerForm[key].issue = issue;
});
}
if (err.data.hasOwnProperty('_issues')) {
Object.keys(err.data._issues).forEach((key) => {
var issue = err.data._issues[key];
notify.pop();
notify.error(errorMsg);
});
if (typeof issue === 'object') {
if (issue.unique === true) {
issue = gettext('The selected field value is not unique.');
}
}
scope.producerForm[key].issue = issue;
});
}
notify.pop();
notify.error(errorMsg);
});
};

@@ -84,5 +109,7 @@

scope.oncancel();
}
}
};
scope.notValidName = adsUtilSevice.uniqueNameInItems;
},
};
};
}

@@ -1,2 +0,2 @@

import producerListItemTpl from 'scripts/liveblog-syndication/views/producer-list-item.html';
import producerListItemTpl from 'scripts/liveblog-syndication/views/producer-list-item.ng1';

@@ -12,3 +12,3 @@ producerList.$inject = ['api', '$http', 'modal', 'config', 'notify'];

selected: '=',
done: '='
done: '=',
},

@@ -41,4 +41,4 @@ link: function(scope, elem, attrs) {

headers: {
'Content-Type': 'application/json;charset=utf-8'
}
'Content-Type': 'application/json;charset=utf-8',
},
});

@@ -49,5 +49,5 @@ };

if (scope.producers
&& scope.producers.length > 0
&& data.producer
&& data.producer.hasOwnProperty('api_status')) {
&& scope.producers.length > 0
&& data.producer
&& data.producer.hasOwnProperty('api_status')) {
scope.producers = scope.producers.map((producer) => {

@@ -74,4 +74,4 @@ if (producer._id === data.producer._id) {

});
}
},
};
}

@@ -1,2 +0,2 @@

import producerListTpl from 'scripts/liveblog-syndication/views/producer-list.html';
import producerListTpl from 'scripts/liveblog-syndication/views/producer-list.ng1';

@@ -11,4 +11,4 @@ export default function lbProducers() {

angular.extend(this, $controller('BaseController', {$scope: $scope}));
}]
}
}],
};
}

@@ -6,16 +6,17 @@ syndRmBlog.$inject = ['api', '$routeParams'];

link: function(scope, elem, attrs) {
var params = {
const params = {
where: {
blog_id: $routeParams._id
}
blog_id: $routeParams._id,
},
};
api.syndicationOut.query(params).then(function(syndOuts) {
if (syndOuts._items.length > 0)
api.syndicationOut.query(params).then((syndOuts) => {
if (syndOuts._items.length > 0) {
attrs.$set('disabled', 'disabled');
else
} else {
elem.removeAttr('disabled');
}
});
}
},
};
};
}

@@ -1,2 +0,2 @@

import syndicationSwitchTpl from 'scripts/liveblog-syndication/views/syndication-switch.html';
import syndicationSwitchTpl from 'scripts/liveblog-syndication/views/syndication-switch.ng1';

@@ -12,9 +12,9 @@ syndicationSwitch.$inject = ['api', '$routeParams'];

var params = {
const params = {
where: {
blog_id: $routeParams._id
}
blog_id: $routeParams._id,
},
};
api.syndicationOut.query(params).then(function(syndOuts) {
api.syndicationOut.query(params).then((syndOuts) => {
if (syndOuts._items.length > 0) {

@@ -28,7 +28,7 @@ scope.enableSyndSwitch = false;

});
})
});
}
});
}
},
};
};
}

@@ -41,3 +41,3 @@ import './styles/syndication.scss';

'liveblog.security',
'liveblog.flux'
'liveblog.flux',
])

@@ -44,0 +44,0 @@

export default function incomingSyndicationReducers() {
return function(state, action) {
switch (action.type) {
case 'ON_GET_POSTS':
return angular.extend(state, {
posts: action.posts,
});
case 'ON_GET_POSTS':
return angular.extend(state, {
posts: action.posts,
});
case 'ON_GET_SYNDICATION':
return angular.extend(state, {
syndication: action.syndication
});
case 'ON_GET_SYNDICATION':
return angular.extend(state, {
syndication: action.syndication,
});
case 'ON_SAVED_POST':
case 'ON_REMOVED_POST':
return angular.extend(state, {
posts: angular.extend(state.posts, {
_items: state.posts._items.filter(function(item) {
return (item._id !== action.post._id);
})
})
});
case 'ON_SAVED_POST':
case 'ON_REMOVED_POST':
return angular.extend(state, {
posts: angular.extend(state.posts, {
_items: state.posts._items.filter((item) => item._id !== action.post._id),
}),
});
}
};
};
}

@@ -5,3 +5,3 @@ ingestPanelReducers.$inject = ['moment'];

// Associate a syndication to a producer blog via blog token
var locallySyndicatedItems = function(syndicationIn, localSyndTokens) {
const locallySyndicatedItems = function(syndicationIn, localSyndTokens) {
return syndicationIn._items

@@ -12,6 +12,10 @@ .filter((item) => localSyndTokens.indexOf(item.blog_token) !== -1);

return function(state, action) {
let localSyndTokens;
let syndicationIn;
let localProducerBlogIds;
switch (action.type) {
case 'ON_GET_SYND':
// Filters out syndicationIns that aren't corresponding to the current blog
var localSyndTokens = action.syndicationIn._items
// Filters out syndicationIns that aren't corresponding to the current blog
localSyndTokens = action.syndicationIn._items
.filter((syndication) => syndication.blog_id === state.consumerBlogId)

@@ -28,7 +32,7 @@ .map((syndication) => syndication.blog_token);

localProducerBlogIds: [], // Reset list after syndication
producerBlogs: [] // Same here
producerBlogs: [], // Same here
});
case 'ON_UPDATED_SYND':
var syndicationIn = angular.extend(state.syndicationIn, {
syndicationIn = angular.extend(state.syndicationIn, {
_items: state.syndicationIn._items.map((item) => {

@@ -40,3 +44,3 @@ if (item._id === action.syndEntry._id) {

return item;
})
}),
});

@@ -49,3 +53,3 @@

state.localSyndTokens
)
),
});

@@ -55,7 +59,7 @@

return angular.extend(state, {
producers: action.producers
producers: action.producers,
});
case 'ON_GET_PRODUCER_BLOGS':
var localProducerBlogIds = [];
localProducerBlogIds = [];

@@ -85,5 +89,5 @@ return angular.extend(state, {

return blog;
})
}),
}),
localProducerBlogIds: localProducerBlogIds
localProducerBlogIds: localProducerBlogIds,
});

@@ -94,3 +98,3 @@

return angular.extend(state, {
modalActive: action.modalActive
modalActive: action.modalActive,
});

@@ -102,3 +106,3 @@ }

localProducerBlogIds: [],
modalActive: action.modalActive
modalActive: action.modalActive,
});

@@ -108,3 +112,3 @@

return angular.extend(state, {
error: action.error
error: action.error,
});

@@ -126,3 +130,3 @@

return !isAutoPublished;
})
}),
});

@@ -129,0 +133,0 @@ }

@@ -0,1 +1,2 @@

/**

@@ -10,3 +11,3 @@ * This file is part of Superdesk.

*/
import dateFormTpl from 'scripts/liveblog-themes/views/date-format.html';
import dateFormTpl from 'scripts/liveblog-themes/views/date-format.ng1';

@@ -19,3 +20,3 @@ (function() {

options: '=',
value: '=ngModel'
value: '=ngModel',
},

@@ -31,3 +32,3 @@ templateUrl: dateFormTpl,

}
scope.$watch('radio + custom', function() {
scope.$watch('radio + custom', () => {
if (scope.radio === '') {

@@ -40,5 +41,5 @@ scope.value = scope.custom;

});
}
},
};
}])
}]);
})();

@@ -1,11 +0,11 @@

import listTpl from 'scripts/liveblog-themes/views/list.html';
import listTpl from 'scripts/liveblog-themes/views/list.ng1';
(function() {
LiveblogThemesController.$inject = ['api', '$location', 'notify', 'gettext',
'$q', '$sce', 'config', 'lodash', 'upload', 'blogService', '$window', 'modal',
'$http', 'session'];
'$q', '$sce', 'config', 'lodash', 'upload', 'blogService', '$window', 'modal',
'$http', 'session'];
function LiveblogThemesController(api, $location, notify, gettext,
$q, $sce, config, _, upload, blogService, $window, modal,
$http, session) {
var vm = this;
$q, $sce, config, _, upload, blogService, $window, modal,
$http, session) {
const self = this;
/**

@@ -16,57 +16,62 @@ * Return a collection that represent the hierachy of the themes

*/
function getHierachyFromThemesCollection(themes) {
var todo = [];
var themes_hierachy = {};
function getParentNode(name, collection) {
collection = collection || themes_hierachy;
for (var key in collection) {
if (collection.hasOwnProperty(key)) {
if (key === name) {
return collection[key];
const todo = [];
const themesHierachy = {};
function getParentNode(name, collectionParam) {
const collection = collectionParam || themesHierachy;
let ret;
Object.keys(collection).forEach((key) => {
if (key === name) {
ret = collection[key];
}
if (angular.isObject(collection[key])) {
const res = getParentNode(name, collection[key]);
if (angular.isDefined(res)) {
ret = res;
}
if (angular.isObject(collection[key])) {
var res = getParentNode(name, collection[key]);
if (angular.isDefined(res)) {
return res;
}
}
}
}
});
return ret;
}
function addToHierarchy(name, extend) {
if (angular.isDefined(extend)) {
var parent_node = getParentNode(extend);
var index = _.findIndex(todo, function(a) {
return a[0] === name;
});
if (angular.isDefined(parent_node)) {
const parentNode = getParentNode(extend);
const index = _.findIndex(todo, (a) => a[0] === name);
if (angular.isDefined(parentNode)) {
if (index > -1) {
todo.splice(index, 1);
}
parent_node[name] = {};
parentNode[name] = {};
} else if (index === -1) {
todo.push([name, extend]);
}
} else if (!angular.isDefined(themes_hierachy[name])) {
themes_hierachy[name] = {};
} else if (!angular.isDefined(themesHierachy[name])) {
themesHierachy[name] = {};
}
}
themes.forEach(function(theme) {
themes.forEach((theme) => {
addToHierarchy(theme.name, theme.extends);
});
var max_loops = todo.length * todo.length;
while (todo.length > 0 && max_loops > 0) {
for (var i = 0; i < todo.length; i++) {
let maxLoops = todo.length * todo.length;
while (todo.length > 0 && maxLoops > 0) {
for (let i = 0; i < todo.length; i++) {
addToHierarchy(todo[i][0], todo[i][1]);
}
max_loops--;
maxLoops--;
}
return themes_hierachy;
return themesHierachy;
}
// parse the theme and create or fix properties.
function parseTheme(theme) {
var authorRX = /^([^<(]+?)?[ \t]*(?:<([^>(]+?)>)?[ \t]*(?:\(([^)]+?)\)|$)/gm,
authorArray;
const authorRX = /^([^<(]+?)?[ \t]*(?:<([^>(]+?)>)?[ \t]*(?:\(([^)]+?)\)|$)/gm;
let authorArray;
// If the author is a string then use the format:
// Name <Email> (Url)
if (angular.isString(theme.author)) {

@@ -77,5 +82,5 @@ authorArray = authorRX.exec(theme.author);

theme.author = {
'name': authorArray[1],
'email': authorArray[2],
'url': authorArray[3]
name: authorArray[1],
email: authorArray[2],
url: authorArray[3],
};

@@ -87,19 +92,19 @@ }

// load only global preference for themes.
api.global_preferences.query({'where': {'key': 'theme'}}).then(function(global_preferences) {
vm.globalTheme = _.find(global_preferences._items, function(item) {
return item.key === 'theme';
});
api.global_preferences.query({where: {key: 'theme'}}).then((globalPreferences) => {
self.globalTheme = _.find(globalPreferences._items, (item) => item.key === 'theme');
});
// load all the themes.
// TODO: Pagination
return api.themes.query().then(function(data) {
var themes = data._items;
themes.forEach(function(theme) {
return api.themes.query().then((data) => {
const themes = data._items;
themes.forEach((theme) => {
// create criteria to load blogs with the theme.
var criteria = {
source: {
query: {match: {'blog_preferences.theme': theme.name}}
}
};
api.blogs.query(criteria).then(function(data) {
const criteria = {
source: {
query: {match: {'blog_preferences.theme': theme.name}},
},
};
api.blogs.query(criteria).then((data) => {
theme.blogs_count = data._meta.total;

@@ -109,4 +114,4 @@ // TODO: Pagination. Will only show the first results page

// retrieve the public url for each blog
theme.blogs.forEach(function(blog) {
blogService.getPublicUrl(blog).then(function(url) {
theme.blogs.forEach((blog) => {
blogService.getPublicUrl(blog).then((url) => {
blog.iframe_url = $sce.trustAsResourceUrl(url);

@@ -119,8 +124,9 @@ });

// object that represent the themes hierachy
var themes_hierachy = getHierachyFromThemesCollection(themes);
const themesHierachy = getHierachyFromThemesCollection(themes);
// update the scope
angular.extend(vm, {
themesHierachy: themes_hierachy,
angular.extend(self, {
themesHierachy: themesHierachy,
themes: themes,
loading: false
loading: false,
});

@@ -130,4 +136,4 @@ return themes;

}
angular.extend(vm, {
mailto: 'mailto:upgrade@liveblog.pro?subject='+
angular.extend(self, {
mailto: 'mailto:upgrade@liveblog.pro?subject=' +
encodeURIComponent(location.hostname) +

@@ -144,17 +150,17 @@ ' ' +

getTheme: function(name) {
return _.find(vm.themes, function(theme) {
return theme.name === name;
});
return _.find(self.themes, (theme) => theme.name === name);
},
isDefaultTheme: function(theme) {
if (angular.isDefined(vm.globalTheme)) {
return vm.getTheme(vm.globalTheme.value).name === theme.name;
if (angular.isDefined(self.globalTheme)) {
return self.getTheme(self.globalTheme.value).name === theme.name;
}
},
cannotRemove: function(theme) {
const hasChildren = vm.themes.some(function(t) {
return t.extends === theme.name;
});
const hasChildren = self.themes.some((t) => t.extends === theme.name);
// Removing simple theme https://dev.sourcefabric.org/browse/LBSD-2199
// const systemThemes = ['angular', 'classic', 'default', 'amp', 'simple'];
const systemThemes = ['angular', 'classic', 'default', 'amp'];
const isSystemTheme = systemThemes.indexOf(theme.name) !== -1;
return hasChildren || isSystemTheme;

@@ -164,15 +170,15 @@ },

if (theme.blogs.length) {
vm.selectedTheme = theme;
vm.themeBlogsModal = true;
self.selectedTheme = theme;
self.themeBlogsModal = true;
}
},
closeThemeBlogsModal: function(theme) {
if (vm.selectedBlog) {
vm.selectedBlog = false;
if (self.selectedBlog) {
self.selectedBlog = false;
} else {
vm.themeBlogsModal = false;
self.themeBlogsModal = false;
}
},
download: function(theme) {
api.themes.getUrl().then(function(url) {
api.themes.getUrl().then((url) => {
$window.location = url.replace('/themes', '/theme-download/' + theme.name);

@@ -183,7 +189,7 @@ });

$http.defaults.headers.common.Authorization = session.token;
api.themes.getUrl().then(function(url) {
api.themes.getUrl().then((url) => {
$http({
url: url.replace('/themes', '/theme-redeploy/' + theme.name),
method: 'GET'
}).then(function(){
method: 'GET',
}).then(() => {
notify.pop();

@@ -196,16 +202,16 @@ notify.info(gettext('Theme redeployed.'));

makeDefault: function(theme) {
if (vm.globalTheme) {
if (self.globalTheme) {
api
.global_preferences
.save(vm.globalTheme, {'key': 'theme', 'value': theme.name})
.then(function(data) {
.save(self.globalTheme, {key: 'theme', value: theme.name})
.then((data) => {
notify.pop();
notify.info(gettext('Default theme saved'));
vm.globalTheme = data;
self.globalTheme = data;
});
} else {
api.global_preferences.save({'key': 'theme', 'value': theme.name}).then(function(data) {
api.global_preferences.save({key: 'theme', value: theme.name}).then((data) => {
notify.pop();
notify.info(gettext('Default theme saved'));
vm.globalTheme = data;
self.globalTheme = data;
});

@@ -232,3 +238,3 @@ }

// copy the selected blog
vm.selectedBlog = angular.copy(blog);
self.selectedBlog = angular.copy(blog);
},

@@ -240,3 +246,3 @@ save: function() {

close: function() {
//return to blog list page
// return to blog list page
$location.path('/liveblog/');

@@ -248,17 +254,17 @@ },

notify.info(gettext('Uploading the theme, please wait...'), 120000);
api.themes.getUrl().then(function(url) {
api.themes.getUrl().then((url) => {
upload.start({
method: 'POST',
url: url.replace('/themes', '/theme-upload'),
data: {media: e.files[0]}
data: {media: e.files[0]},
})
.then(function(response) {
loadThemes().then(function() {
.then((response) => {
loadThemes().then(() => {
notify.pop();
notify.info(gettext('Theme uploaded and added'));
});
}, (error) => {
notify.pop();
notify.info(gettext('Theme uploaded and added'));
notify.error(error.data.error);
});
}, function(error) {
notify.pop();
notify.error(error.data.error);
});
});

@@ -271,19 +277,19 @@ },

}
vm.themePreviewModal = true;
vm.themePreviewModalTheme = theme;
self.themePreviewModal = true;
self.themePreviewModalTheme = theme;
},
openThemeSettings: function(theme) {
vm.themeSettingsModal = true;
vm.themeSettingsModalTheme = theme;
self.themeSettingsModal = true;
self.themeSettingsModalTheme = theme;
},
hasReachedThemesLimit: function() {
if (!vm.themes)
if (!self.themes) {
return false;
}
var themes = vm.themes.filter(function(theme) {
return (theme.name !== config.excludedTheme);
});
const themes = self.themes.filter((theme) => theme.name !== config.excludedTheme);
if (config.subscriptionLevel === 'team')
return (themes.length >= config.themeCreationRestrictions.team);
if (config.subscriptionLevel === 'team') {
return themes.length >= config.themeCreationRestrictions.team;
}

@@ -294,7 +300,7 @@ return false;

showUpgradeModal: function() {
vm.upgradeModal = true;
self.upgradeModal = true;
},
closeUpgradeModal: function() {
vm.upgradeModal = false;
}
self.upgradeModal = false;
},
});

@@ -305,18 +311,20 @@

var liveblogThemeModule = angular.module('liveblog.themes', [])
.config(['superdeskProvider', function(superdesk) {
superdesk
.activity('/themes/', {
label: gettext('Theme Manager'),
controller: LiveblogThemesController,
controllerAs: 'vm',
category: superdesk.MENU_MAIN,
adminTools: true,
privileges: {'global_preferences': 1},
templateUrl: listTpl
});
}])
.filter('githubUrlFromGit', function() {
return function(string) {
return angular.module('liveblog.themes', [])
.config(['superdeskProvider', function(superdesk) {
superdesk
.activity('/themes/', {
label: gettext('Theme Manager'),
controller: LiveblogThemesController,
controllerAs: 'self',
category: superdesk.MENU_MAIN,
adminTools: true,
privileges: {global_preferences: 1},
templateUrl: listTpl,
});
}])
.filter('githubUrlFromGit', () => function(string) {
function githubUrlFromGit(url, opts) {
if (!url) {
return '';
}
// from https://github.com/tj/node-github-url-from-git

@@ -326,41 +334,65 @@ // generate the git:// parsing regex

// to specify multiple GHE domains.
var github_re = function(opts) {
opts = opts || {};
const githubRe = function(opts = {}) {
// whitelist of URLs that should be treated as GitHub repos.
var baseUrls = ['gist.github.com', 'github.com'].concat(opts.extraBaseUrls || []);
const baseUrls = ['gist.github.com', 'github.com'].concat(opts.extraBaseUrls || []);
// build regex from whitelist.
return new RegExp(
/^(?:https?:\/\/|git:\/\/|git\+ssh:\/\/|git\+https:\/\/)?(?:[^@]+@)?/.source +
'(' + baseUrls.join('|') + ')' +
/[:\/]([^\/]+\/[^\/]+?|[0-9]+)$/.source
'(' + baseUrls.join('|') + ')' +
/[:/]([^/]+\/[^/]+?|[0-9]+)$/.source
);
};
try {
var m = github_re(opts).exec(url.replace(/\.git(#.*)?$/, ''));
var host = m[1];
var path = m[2];
return 'https://' + host + '/' + path;
} catch (err) {
// ignore
const matches = githubRe(opts).exec(url.replace(/\.git(#.*)?$/, ''));
if (matches) {
const [, host, path] = matches;
return `https://${host}/${path}`;
}
return '';
}
return githubUrlFromGit(string);
};
})
.config(['apiProvider', function(apiProvider) {
apiProvider.api('global_preferences', {
type: 'http',
backend: {rel: 'global_preferences'}
});
apiProvider.api('themes', {
type: 'http',
backend: {rel: 'themes'}
});
apiProvider.api('blogs', {
type: 'http',
backend: {rel: 'blogs'}
});
}]);
return liveblogThemeModule;
})
.filter('stashUrlFromGit', () => function(string) {
function stashUrlFromGit(url, opts) {
if (!url) {
return '';
}
const stashRe = function(opts = {}) {
// whitelist of URLs that should be treated as Stash, BitBucket repos.
const baseUrls = ['stash.sourcefabric.org'].concat(opts.extraBaseUrls || []);
// build regex from whitelist.
return new RegExp(
/^(?:https?:\/\/|git:\/\/|git\+ssh:\/\/|git\+https:\/\/)?(?:[^@]+@)?/.source +
'(' + baseUrls.join('|') + ')' +
/[:/]([^/]+\/)([^/]+\/)(.*?)$/.source
);
};
const matches = stashRe(opts).exec(url.replace(/\.git(#.*)?$/, ''));
if (matches) {
const [, host, , organization, project] = matches;
return `https://${host}/rest/api/latest/projects/${organization}repos/${project}`;
}
return '';
}
return stashUrlFromGit(string);
})
.config(['apiProvider', function(apiProvider) {
apiProvider.api('global_preferences', {
type: 'http',
backend: {rel: 'global_preferences'},
});
apiProvider.api('themes', {
type: 'http',
backend: {rel: 'themes'},
});
apiProvider.api('blogs', {
type: 'http',
backend: {rel: 'blogs'},
});
}]);
})();

@@ -1,53 +0,54 @@

import themeSettingsModalTpl from 'scripts/liveblog-themes/views/theme-settings-modal.html';
import themeSettingsModalTpl from 'scripts/liveblog-themes/views/theme-settings-modal.ng1';
(function() {
angular.module('liveblog.themes')
.filter('exampleDate', [ 'moment', function(moment) {
return function(string) {
return moment().format(string);
};
}])
.directive('themeSettingsModal', ['api', '$q', 'notify',
function(api, $q, notify) {
return {
templateUrl: themeSettingsModalTpl,
scope: {
theme: '=',
modalOpened: '='
},
link: function(scope) {
var vm = scope;
.filter('exampleDate', ['moment', function(moment) {
return function(string) {
return moment().format(string);
};
}])
.directive('themeSettingsModal', ['api', '$q', 'notify',
function(api, $q, notify) {
return {
templateUrl: themeSettingsModalTpl,
scope: {
theme: '=',
modalOpened: '=',
},
link: function(scope) {
const vm = scope;
angular.extend(vm, {
optionsAreloading: true,
settings: angular.copy(vm.theme.settings) || {},
options: [],
datetimeFormats: [
'MMMM Do, YYYY HH:mm',
'YYYY-MM-DD hh:mm a',
'DD/MM/YYYY hh:mm A',
'HH:mm D.M.YYYY',
'lll'
],
submitSettings: function(shouldClose) {
if (!angular.equals(vm.theme.settings, vm.settings)) {
api.themes.update(vm.theme, {settings: vm.settings}).then(function(data) {
vm.settings = angular.copy(data.settings);
// reset the dirty state to false
vm.themeSettingsForm.$setPristine();
if (shouldClose) {
vm.closeModal();
}
}, function(error) {
notify.error(error.data._error.message);
});
} else if (shouldClose) {
vm.closeModal();
}
},
closeModal: function() {
scope.modalOpened = false;
vm.theme = undefined;
},
/**
angular.extend(vm, {
optionsAreloading: true,
settings: angular.copy(vm.theme.settings) || {},
options: [],
datetimeFormats: [
'MMMM Do, YYYY HH:mm',
'YYYY-MM-DD hh:mm a',
'DD/MM/YYYY hh:mm A',
'HH:mm D.M.YYYY',
'lll',
],
submitSettings: function(shouldClose) {
if (!angular.equals(vm.theme.settings, vm.settings)) {
api.themes.update(vm.theme, {settings: vm.settings}).then((data) => {
vm.settings = angular.copy(data.settings);
// reset the dirty state to false
vm.themeSettingsForm.$setPristine();
if (shouldClose) {
vm.closeModal();
}
}, (error) => {
notify.error(error.data._error.message);
});
} else if (shouldClose) {
vm.closeModal();
}
},
closeModal: function() {
scope.modalOpened = false;
vm.theme = undefined;
},
/**
* Check if the option requirements are satified through the `dependsOn` property

@@ -57,17 +58,18 @@ * @param {object} option

*/
optionRequirementIsSatisfied: function(option) {
if (!angular.isDefined(option.dependsOn)) {
return true;
}
var isSatisfied = true;
angular.forEach(option.dependsOn, function(value, key) {
isSatisfied = isSatisfied && vm.settings[key] === value;
});
return isSatisfied;
}
});
optionRequirementIsSatisfied: function(option) {
if (!angular.isDefined(option.dependsOn)) {
return true;
}
let isSatisfied = true;
scope.vm = vm;
// Initialization
/**
angular.forEach(option.dependsOn, (value, key) => {
isSatisfied = isSatisfied && vm.settings[key] === value;
});
return isSatisfied;
},
});
scope.vm = vm;
// Initialization
/**
* Collect a list of options for the given theme and its parents

@@ -77,38 +79,39 @@ * @param {object} theme

*/
function collectOptions(theme, options) {
// options is used for recursiveness
options = options || [];
// keep the theme's options in `options`
if (theme.options) {
var alreadyPresent = _.map(options, function(o) {return o.name;});
// keep only options that are not already saved (children options are prioritary)
options = _.filter(theme.options, function(option) {
return alreadyPresent.indexOf(option.name) === -1;
}).concat(options);
function collectOptions(theme, optionsParam = {}) {
let options = optionsParam;
// keep the theme's options in `options`
if (theme.options) {
const alreadyPresent = _.map(options, (o) => o.name);
// keep only options that are not already saved (children options are prioritary)
options = _.filter(theme.options, (option) =>
alreadyPresent.indexOf(option.name) === -1
).concat(options);
}
// retrieve parent options
if (theme.extends) {
return api.themes.getById(theme.extends).then((parentTheme) =>
collectOptions(parentTheme, options)
);
}
// return the options when there is no more parent theme
return $q.when(options);
}
// retrieve parent options
if (theme.extends) {
return api.themes.getById(theme.extends).then(function(parentTheme) {
return collectOptions(parentTheme, options);
// collect the options for the theme and its parents
collectOptions(vm.theme).then((options) => {
// set default settings value from options default values
options.forEach((option) => {
if (!angular.isDefined(vm.settings[option.name])) {
vm.settings[option.name] = option.default;
}
});
}
// return the options when there is no more parent theme
return $q.when(options);
}
// collect the options for the theme and its parents
collectOptions(vm.theme).then(function(options) {
// set default settings value from options default values
options.forEach(function(option) {
if (!angular.isDefined(vm.settings[option.name])) {
vm.settings[option.name] = option.default;
}
angular.extend(vm, {
options: options,
optionsAreloading: false,
});
});
angular.extend(vm, {
options: options,
optionsAreloading: false
});
});
// watch the modalOpened model to reset the selected theme when the user close the modal
//scope.$watch(
// scope.$watch(
// function() {return vm.modalOpened;},

@@ -120,24 +123,25 @@ // function(isOpened) {

// }
//);
// );
//scope.$watch('themeSettingsModal', () => {
// scope.$watch('themeSettingsModal', () => {
// scope.vm.isOpened = vm.themeSettingsModal;
//});
}
//controllerAs: 'vm',
//bindToController: true,
//controller: ThemeSettingsModalController
};
}])
.filter('linkup', ['$sce', function($sce) {
return function(value) {
if (!value) {
return value;
}
var removeRegx = /(<([^>]+)>)/ig,
linkupRegx = /((http(s)?:)?\/\/[^\s]*)/ig,
linkReplace = '<a href="$1" target="_blank">$1</a>';
return $sce.trustAsHtml(value.replace(removeRegx, '').replace(linkupRegx, linkReplace));
}
}]);
// });
},
// controllerAs: 'vm',
// bindToController: true,
// controller: ThemeSettingsModalController
};
}])
.filter('linkup', ['$sce', function($sce) {
return function(value) {
if (!value) {
return value;
}
const removeRegx = /(<([^>]+)>)/ig;
const linkupRegx = /((http(s)?:)?\/\/[^\s]*)/ig;
const linkReplace = '<a href="$1" target="_blank">$1</a>';
return $sce.trustAsHtml(value.replace(removeRegx, '').replace(linkupRegx, linkReplace));
};
}]);
})();
(function() {
angular.module('liveblog.themes')
.service('themesService', ['$sce', 'api', 'blogService', function($sce, api, blogService) {
.service('themesService', ['$sce', 'api', 'blogService', function($sce, api, blogService) {
/**

@@ -9,9 +9,10 @@ * Return a collection that represent the hierachy of the themes

*/
function getHierachyFromThemesCollection(themes) {
var todo = [];
var themes_hierachy = {};
function getParentNode(name, collection) {
collection = collection || themes_hierachy;
for (var key in collection) {
if (collection.hasOwnProperty(key)) {
function getHierachyFromThemesCollection(themes) {
const todo = [];
const themesHierachy = {};
function getParentNode(name, collectionParam) {
const collection = collectionParam || themesHierachy;
Object.keys(collection).forEach((key) => {
if (key === name) {

@@ -21,3 +22,4 @@ return collection[key];

if (angular.isObject(collection[key])) {
var res = getParentNode(name, collection[key]);
const res = getParentNode(name, collection[key]);
if (angular.isDefined(res)) {

@@ -27,52 +29,52 @@ return res;

}
}
});
}
}
function addToHierarchy(name, extend) {
if (angular.isDefined(extend)) {
var parent_node = getParentNode(extend);
var index = _.findIndex(todo, function(a) {
return a[0] === name;
});
if (angular.isDefined(parent_node)) {
if (index > -1) {
todo.splice(index, 1);
function addToHierarchy(name, extend) {
if (angular.isDefined(extend)) {
const parentNode = getParentNode(extend);
const index = _.findIndex(todo, (a) => a[0] === name);
if (angular.isDefined(parentNode)) {
if (index > -1) {
todo.splice(index, 1);
}
parentNode[name] = {};
} else if (index === -1) {
todo.push([name, extend]);
}
parent_node[name] = {};
} else if (index === -1) {
todo.push([name, extend]);
} else if (!angular.isDefined(themesHierachy[name])) {
themesHierachy[name] = {};
}
} else if (!angular.isDefined(themes_hierachy[name])) {
themes_hierachy[name] = {};
}
themes.forEach((theme) => {
addToHierarchy(theme.name, theme.extends);
});
let maxLoops = todo.length * todo.length;
while (todo.length > 0 && maxLoops > 0) {
for (let i = 0; i < todo.length; i++) {
addToHierarchy(todo[i][0], todo[i][1]);
}
maxLoops--;
}
return themesHierachy;
}
themes.forEach(function(theme) {
addToHierarchy(theme.name, theme.extends);
});
var max_loops = todo.length * todo.length;
while (todo.length > 0 && max_loops > 0) {
for (var i = 0; i < todo.length; i++) {
addToHierarchy(todo[i][0], todo[i][1]);
// parse the theme and create or fix properties.
function parseTheme(theme) {
const authorRX = /^([^<(]+?)?[ \t]*(?:<([^>(]+?)>)?[ \t]*(?:\(([^)]+?)\)|$)/gm;
let authorArray;
// If the author is a string then use the format:
// Name <Email> (Url)
if (angular.isString(theme.author)) {
authorArray = authorRX.exec(theme.author);
theme.author = {
name: authorArray[1],
email: authorArray[2],
url: authorArray[3],
};
}
max_loops--;
}
return themes_hierachy;
}
// parse the theme and create or fix properties.
function parseTheme(theme) {
var authorRX = /^([^<(]+?)?[ \t]*(?:<([^>(]+?)>)?[ \t]*(?:\(([^)]+?)\)|$)/gm,
authorArray;
// If the author is a string then use the format:
// Name <Email> (Url)
if (angular.isString(theme.author)) {
authorArray = authorRX.exec(theme.author);
theme.author = {
'name': authorArray[1],
'email': authorArray[2],
'url': authorArray[3]
};
}
}
// Initialization
/**
// Initialization
/**
* Collect a list of options for the given theme and its parents

@@ -82,90 +84,97 @@ * @param {object} theme

*/
function collectOptions(theme, options, parent) {
var currenTheme = parent || theme;
// options is used for recursiveness
options = options || [];
theme.settings = theme.settings || {};
// keep the theme's options in `options`
if (currenTheme.options) {
var alreadyPresent = _.map(options, function(o) {return o.name;});
// keep only options that are not already saved (children options are prioritary)
options = _.filter(currenTheme.options, function(option) {
return alreadyPresent.indexOf(option.name) === -1;
}).concat(options);
}
// retrieve parent options
if (currenTheme.extends) {
return api.themes.getById(currenTheme.extends).then(function(parentTheme) {
return collectOptions(currenTheme, options, parentTheme);
function collectOptions(theme, optionsParam = [], parent) {
const currenTheme = parent || theme;
// options is used for recursiveness
let options = optionsParam;
theme.settings = theme.settings || {};
// keep the theme's options in `options`
if (currenTheme.options) {
const alreadyPresent = _.map(options, (o) => o.name);
// keep only options that are not already saved (children options are prioritary)
options = _.filter(currenTheme.options, (option) =>
alreadyPresent.indexOf(option.name) === -1
).concat(options);
}
// retrieve parent options
if (currenTheme.extends) {
return api.themes.getById(currenTheme.extends).then((parentTheme) =>
collectOptions(currenTheme, options, parentTheme)
);
}
// return the options when there is no more parent theme
// set default settings value from options default values
options.forEach((option) => {
if (!angular.isDefined(theme.settings[option.name])) {
theme.settings[option.name] = option.default;
}
});
}
return {
getHierachy: function(themes) {
return getHierachyFromThemesCollection(themes);
},
get: function(name, optionsParam = {}) {
let criteria = {};
// return the options when there is no more parent theme
// set default settings value from options default values
options.forEach(function(option) {
if (!angular.isDefined(theme.settings[option.name])) {
theme.settings[option.name] = option.default;
}
});
}
return {
getHierachy: function (themes) {
return getHierachyFromThemesCollection(themes);
},
get: function(name, options) {
var criteria = {};
options = options || {};
angular.extend(options, {
blogs: false,
details: true
});
if (name) {
criteria = {'where': {'name': name}};
}
return api.themes.query(criteria).then(function(data) {
var themes = data._items;
themes.forEach(function(theme) {
if (options.details) {
collectOptions(theme);
}
if (options.blogs) {
const options = optionsParam;
angular.extend(options, {
blogs: false,
details: true,
});
if (name) {
criteria = {where: {name: name}};
}
return api.themes.query(criteria).then((data) => {
const themes = data._items;
themes.forEach((theme) => {
if (options.details) {
collectOptions(theme);
}
if (options.blogs) {
// create criteria to load blogs with the theme.
var criteria = {
const criteria = {
source: {
query: {match: {'blog_preferences.theme': theme.name}}
}
query: {match: {'blog_preferences.theme': theme.name}},
},
};
api.blogs.query(criteria).then(function(data) {
theme.blogs_count = data._meta.total;
// TODO: Pagination. Will only show the first results page
theme.blogs = data._items;
// retrieve the public url for each blog
theme.blogs.forEach(function(blog) {
blogService.getPublicUrl(blog).then(function(url) {
blog.iframe_url = $sce.trustAsResourceUrl(url);
api.blogs.query(criteria).then((data) => {
theme.blogs_count = data._meta.total;
// TODO: Pagination. Will only show the first results page
theme.blogs = data._items;
// retrieve the public url for each blog
theme.blogs.forEach((blog) => {
blogService.getPublicUrl(blog).then((url) => {
blog.iframe_url = $sce.trustAsResourceUrl(url);
});
});
});
});
}
parseTheme(theme);
}
parseTheme(theme);
});
return themes;
});
return themes;
});
}
}
}])
.config(['apiProvider', function(apiProvider) {
apiProvider.api('global_preferences', {
type: 'http',
backend: {rel: 'global_preferences'}
});
apiProvider.api('themes', {
type: 'http',
backend: {rel: 'themes'}
});
apiProvider.api('blogs', {
type: 'http',
backend: {rel: 'blogs'}
});
}]);
},
};
}])
.config(['apiProvider', function(apiProvider) {
apiProvider.api('global_preferences', {
type: 'http',
backend: {rel: 'global_preferences'},
});
apiProvider.api('themes', {
type: 'http',
backend: {rel: 'themes'},
});
apiProvider.api('blogs', {
type: 'http',
backend: {rel: 'blogs'},
});
}]);
})();
import angular from 'angular';
export default angular
.module('SirTrevor', [])
.module('SirTrevor', [])
.provider('SirTrevor', function() {

@@ -12,3 +12,3 @@ this.$get = function() {

.provider('SirTrevorOptions', function() {
var options = {
let options = {
blockTypes: ['Text'],

@@ -19,3 +19,3 @@ transform: {

type: block.blockStorage.type,
data: block.blockStorage.data
data: block.blockStorage.data,
};

@@ -26,7 +26,8 @@ },

type: block.type,
data: block.data
data: block.data,
};
}
}
},
},
};
this.$get = function() {

@@ -43,6 +44,7 @@ return options;

.directive('ngSirTrevor', ['SirTrevor', 'SirTrevorOptions', function(SirTrevor, options) {
var directive = {
const directive = {
template: function(element, attr) {
var str = '<textarea class="sir-trevor" name="content"></textarea>';
let str = '<textarea class="sir-trevor" name="content"></textarea>';
// sir trevor needs a parent `form` tag.
if (!element.parent('form').length) {

@@ -54,8 +56,9 @@ str = '<form>' + str + '</form>';

scope: {
'editor': '=stModel',
'onChange': '=stChange',
'params': '=stParams'
editor: '=stModel',
onChange: '=stChange',
params: '=stParams',
},
link: function (scope, element, attrs) {
var opts = angular.copy(options);
link: function(scope, element, attrs) {
const opts = angular.copy(options);
angular.extend(opts, scope.params);

@@ -65,8 +68,7 @@ opts.el = $(element.find('textarea'));

scope.editor.get = function() {
var list = [];
const list = [];
// sort blocks by index.
scope.editor.blocks.sort(function(a, b) {
return (a.$el.index() - b.$el.index());
});
angular.forEach(scope.editor.blocks, function(block) {
scope.editor.blocks.sort((a, b) => a.$el.index() - b.$el.index());
angular.forEach(scope.editor.blocks, (block) => {
scope.editor.saveBlockStateToStore(block);

@@ -78,4 +80,5 @@ list.push(opts.transform.get(block));

scope.editor.set = function(list) {
var item;
angular.forEach(list, function(block) {
let item;
angular.forEach(list, (block) => {
item = opts.transform.set(block);

@@ -87,3 +90,3 @@ scope.editor.createBlock(item.type, item.data);

scope.editor.clear = function() {
angular.forEach(scope.editor.blocks, function(block) {
angular.forEach(scope.editor.blocks, (block) => {
block.remove();

@@ -97,3 +100,3 @@ });

// @TODO: investigate how to better `digest` out of $scope variables.
//scope.$watchCollection('editor.blocks', function(blocks) {
// scope.$watchCollection('editor.blocks', function(blocks) {
// var list = [];

@@ -104,8 +107,7 @@ // _.each(blocks, function(block) {

// scope.model = list;
//});
}
// });
},
};
return directive;
}]);
export default function handlePlaceholder(selector, placeHolderText, options) {
var onEvents = 'click';
let onEvents = 'click';

@@ -8,3 +8,3 @@ if (options && options.tabbedOrder) {

selector.on(onEvents, function(ev) {
var $this = $(this);
const $this = $(this);

@@ -16,3 +16,3 @@ if (_.trim($this.html()) === '') {

selector.on('focusout', function(ev) {
var $this = $(this);
const $this = $(this);

@@ -19,0 +19,0 @@ if (_.trim($this.html()) === '') {

import handlePlaceholder from './handle-placeholder';
var AddContentBtns = function() {
const AddContentBtns = function() {
this.top = $('.st-block-controls__top');

@@ -30,3 +30,4 @@ this.bottom = $('[data-icon-after="ADD CONTENT HERE"]');

loadData: function(data) {
let that = this, fileUrl = '';
const self = this;
let fileUrl = '';

@@ -42,3 +43,3 @@ if (typeof data.file !== 'undefined') {

this.$editor.html($('<img>', {
src: fileUrl
src: fileUrl,
})).show();

@@ -49,3 +50,3 @@ this.$editor.append($('<div>', {

contenteditable: true,
placeholder: that.descriptionPlaceholder
placeholder: self.descriptionPlaceholder,
}).html(data.caption));

@@ -58,5 +59,5 @@

role: 'alert',
style: 'display: none'
style: 'display: none',
})
.html(window.gettext('Max. amount of 300 characters is reached')));
.html(window.gettext('Max. amount of 300 characters is reached')));

@@ -67,3 +68,3 @@ this.$editor.append($('<div>', {

contenteditable: true,
placeholder: that.authorPlaceholder
placeholder: self.authorPlaceholder,
}).html(data.credit));

@@ -76,5 +77,5 @@

$(this).css('border', '1px solid red');
that.$editor.find('[name="credit-size-alert"]').css('display', 'block');
self.$editor.find('[name="credit-size-alert"]').css('display', 'block');
} else {
that.$editor.find('[name="credit-size-alert"]').css('display', 'none');
self.$editor.find('[name="credit-size-alert"]').css('display', 'none');
$(this).css({border: '0px', 'border-bottom': '1px solid #999'});

@@ -86,3 +87,3 @@ }

// Image size warning
var maxFileSize = 2; // in MB
const maxFileSize = 2; // in MB

@@ -95,8 +96,8 @@ if (data.file && data.file.size / 1048576 > maxFileSize) {

})
.html(window.gettext(
'The image is being uploaded, please stand by. ' +
.html(window.gettext(
'The image is being uploaded, please stand by. ' +
'It may take a while as the file is bigger than ' + maxFileSize + 'MB.'
)));
)));
window.setTimeout(() => {
that.$editor.find('[name="size-warning"]').css('display', 'none');
self.$editor.find('[name="size-warning"]').css('display', 'none');
}, 10000);

@@ -106,7 +107,7 @@ }

// Remove placeholders
handlePlaceholder(this.$('[name=caption]'), that.descriptionPlaceholder);
handlePlaceholder(this.$('[name=credit]'), that.authorPlaceholder, {tabbedOrder: true});
handlePlaceholder(this.$('[name=caption]'), self.descriptionPlaceholder);
handlePlaceholder(this.$('[name=credit]'), self.authorPlaceholder, {tabbedOrder: true});
},
onBlockRender: function() {
var that = this;
const self = this;

@@ -125,5 +126,6 @@ // assert we have an uploader function in options

this.$('[data-icon="close"]').on('click', function() {
that.getOptions().setPending(false);
let addContentBtns = new AddContentBtns();
this.$('[data-icon="close"]').on('click', () => {
self.getOptions().setPending(false);
const addContentBtns = new AddContentBtns();
addContentBtns.show();

@@ -140,5 +142,7 @@ });

if (transferData.getData('text/html')) {
let addContentBtns = new AddContentBtns();
var remoteTag = transferData.getData('text/html');
var srcAttr = remoteTag.match(/src="?([^"\s]+)"?\s*/)[1];
const addContentBtns = new AddContentBtns();
const remoteTag = transferData.getData('text/html');
const regex = /<img.*?src="(.*?)"/;
let sourceAttr = regex.exec(remoteTag)[1];
const srcAttr = sourceAttr.replace(/&amp;/g, '&');

@@ -151,4 +155,4 @@ addContentBtns.hide();

file: {
url: srcAttr
}
url: srcAttr,
},
});

@@ -163,3 +167,3 @@

Object.keys(data.media.renditions).forEach((key) => {
let rendition = data.media.renditions[key];
const rendition = data.media.renditions[key];

@@ -190,5 +194,5 @@ rendition.media = rendition.media.$oid;

onDrop: function(transferData) {
var file = transferData.files[0];
var urlAPI = window.URL;
var addContentBtns = new AddContentBtns();
const file = transferData.files[0];
let urlAPI = window.URL;
const addContentBtns = new AddContentBtns();

@@ -204,4 +208,4 @@ if (typeof urlAPI === 'undefined') {

if (file.size > config.maxContentLength) {
let maxContentLengthMB = config.maxContentLength / 1024 / 1024;
let message = `Image bigger than ${maxContentLengthMB}MB`;
const maxContentLengthMB = config.maxContentLength / 1024 / 1024;
const message = `Image bigger than ${maxContentLengthMB}MB`;

@@ -226,4 +230,4 @@ this.addMessage(message);

url: urlAPI.createObjectURL(file),
size: file.size
}
size: file.size,
},
});

@@ -240,3 +244,3 @@ this.getOptions().uploader(

addContentBtns.show();
var message = error || window.i18n.t('blocks:image:upload_error');
const message = error || window.i18n.t('blocks:image:upload_error');

@@ -253,10 +257,11 @@ this.addMessage(message);

caption: this.$('[name=caption]').text(),
credit: this.$('[name=credit]').text()
credit: this.$('[name=credit]').text(),
syndicated_creator: this.getData().syndicated_creator,
};
},
toHTML: function() {
var data = this.retrieveData();
const data = this.retrieveData();
if (data.media.hasOwnProperty('renditions')) {
var srcset = '';
let srcset = '';

@@ -275,3 +280,3 @@ _.forEach(data.media.renditions, (value) => {

'</figcaption>',
'</figure>'
'</figure>',
].join('');

@@ -284,4 +289,4 @@ }

return this.retrieveData();
}
},
});
}

@@ -13,4 +13,7 @@ /**

import sanitizeHtml from 'sanitize-html';
import imageBlock from './image-block';
import handlePlaceholder from './handle-placeholder';
import sanitizeConfig from './sanitizer-config';

@@ -20,12 +23,15 @@ function createCaretPlacer(atStart) {

el.focus();
if (typeof window.getSelection !== "undefined"
&& typeof document.createRange !== "undefined") {
if (typeof window.getSelection !== 'undefined'
&& typeof document.createRange !== 'undefined') {
var range = document.createRange();
range.selectNodeContents(el);
range.collapse(atStart);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (typeof document.body.createTextRange !== "undefined") {
} else if (typeof document.body.createTextRange !== 'undefined') {
var textRange = document.body.createTextRange();
textRange.moveToElementText(el);

@@ -38,12 +44,14 @@ textRange.collapse(atStart);

var placeCaretAtStart = createCaretPlacer(true);
createCaretPlacer(true);
var placeCaretAtEnd = createCaretPlacer(false);
var uriRegx = '(https?:)?\\/\\/[\\w-]+(\\.[\\w-]+)+([\\w.,@?^=%&amp;:\/~+#-]*[\\w@?^=%&amp;\/~+#-])?';
var uriRegx = '(https?:)?\\/\\/[\\w-]+(\\.[\\w-]+)+([\\w.,@?^=%&amp;:/~+#-]*[\\w@?^=%&amp;/~+#-])?';
var socialEmbedRegex = '(iframe|blockquote)+(?:.|\\n)*(youtube\\.com\\/embed|facebook\\.com'
+ '\\/plugins|instagram\\.com\\/p\\/|twitter\\.com\\/.*\\/status)(?:.|\\n)*(iframe|blockquote)';
+ '\\/plugins|instagram\\.com\\/p\\/|players\\.brightcove\\.net'
+ '|twitter\\.com\\/.*\\/status)(?:.|\\n)*(iframe|blockquote)';
function fixDataEmbed(data) {
if (data.html) {
var tmp = document.createElement("DIV");
tmp.innerHTML = data.html;
var tmp = document.createElement('DIV');
tmp.innerHTML = data.html;
data.html = tmp.innerHTML;

@@ -55,7 +63,7 @@ }

function fixSecureEmbed(string) {
var ret;
let ret;
if (window.location.protocol === 'https:') {
var pattern = new RegExp(uriRegx, 'i'),
matches = string.match(pattern);
const pattern = new RegExp(uriRegx, 'i');
const matches = string.match(pattern);

@@ -75,4 +83,19 @@ if (matches && matches.length && matches[1] === 'http:') {

function fixSocial(html, data) {
// remove link for some provider (included in the card)
if (['Facebook', 'Youtube', 'Twitter', 'Soundcloud'].indexOf(data.provider_name) > -1) {
html.find('.link-preview').remove();
}
// special case for twitter
if (data.provider_name === 'Twitter') {
// remove credit and title fields (duplicated with rendered card)
html.find('.credit-preview, .title-preview').remove();
// empty the description
html.find('.description-preview').html('');
}
}
function isURI(string) {
var pattern = new RegExp('^' + uriRegx, 'i');
return pattern.test(string);

@@ -88,2 +111,3 @@ }

var twitterPattern = /(https?:\/\/(?:www)?\.?twitter\.com\/\w+\/status\/\d+)/i;
var bcPattern = /(http|https)?:?\/\/players.brightcove.net\/\d*\/[a-zA-Z\d_-]*\/index\.html\?videoId=\d*/i;
var m;

@@ -93,16 +117,15 @@

if (generalPattern.test(string)) {
if ((m = youtubePattern.exec(string)) !== null){
return 'https://www.youtube.com/watch?v='+m[1];
}
else if ((m = facebookPattern.exec(string)) !== null) {
if ((m = youtubePattern.exec(string)) !== null) {
return 'https://www.youtube.com/watch?v=' + m[1];
} else if ((m = facebookPattern.exec(string)) !== null) {
return decodeURIComponent(m[1]);
}
else if ((m = instagramPattern.exec(string)) !== null) {
} else if ((m = instagramPattern.exec(string)) !== null) {
return m[1];
}
else if ((m = twitterPattern.exec(string)) !== null) {
} else if ((m = twitterPattern.exec(string)) !== null) {
return m[1];
} else if ((m = bcPattern.exec(string)) !== null) {
return m[0];
}
}
return string;

@@ -112,9 +135,8 @@ }

angular
.module('SirTrevorBlocks', [])
.module('SirTrevorBlocks', [])
.config(['SirTrevorProvider', 'config', function(SirTrevor, config) {
// replace the plus symbol with text description
SirTrevor.FloatingBlockControls.prototype.attributes = function() {
return {
'data-icon': 'ADD CONTENT HERE'
'data-icon': 'ADD CONTENT HERE',
};

@@ -124,9 +146,11 @@ };

return _.extend(SirTrevor.SimpleBlock.fn.attributes.call(this), {
'data-icon-after': 'ADD CONTENT HERE'
'data-icon-after': 'ADD CONTENT HERE',
});
};
// Add toMeta method to all blocks.
SirTrevor.Block.prototype.toMeta = function() {return;};
SirTrevor.Block.prototype.toMeta = function() {
return this.getData();
};
SirTrevor.Block.prototype.getOptions = function() {
var instance = SirTrevor.$get().getInstance(this.instanceID);
const instance = SirTrevor.$get().getInstance(this.instanceID);

@@ -144,10 +168,11 @@ return instance ? instance.options : null;

'<div class="st-required st-embed-block embed-input"',
' placeholder="' + this.embedPlaceholder + '" contenteditable="true"></div>'
' placeholder="' + this.embedPlaceholder + '" contenteditable="true"></div>',
].join('\n');
},
onBlockRender: function() {
var that = this;
var self = this;
// create and trigger a 'change' event for the $editor which is a contenteditable
this.$editor.filter('[contenteditable]').on('focus', function(ev) {
var $this = $(this);
const $this = $(this);

@@ -157,3 +182,3 @@ $this.data('before', $this.html());

this.$editor.filter('[contenteditable]').on('blur keyup paste input', function(ev) {
var $this = $(this);
const $this = $(this);

@@ -165,18 +190,19 @@ if ($this.data('before') !== $this.html()) {

});
handlePlaceholder(this.$editor.filter('[contenteditable]'), that.embedPlaceholder);
handlePlaceholder(this.$editor.filter('[contenteditable]'), self.embedPlaceholder);
// when the link field changes
var callServiceAndLoadData = function() {
var input = $(this)
const callServiceAndLoadData = function() {
let input = $(this)
.text()
.trim();
// exit if the input field is empty
if (_.isEmpty(input)) {
that.getOptions().disableSubmit(true);
self.getOptions().disableSubmit(true);
return false;
}
that.getOptions().disableSubmit(false);
self.getOptions().disableSubmit(false);
// reset error messages
that.resetMessages();
self.resetMessages();
// start a loader over the block, it will be stopped in the loadData function
that.loading();
self.loading();
input = replaceEmbedWithUrl(input);

@@ -187,10 +213,10 @@ input = fixSecureEmbed(input);

// request the embedService with the provided url
that.getOptions().embedService.get(input, that.getOptions().coverMaxWidth).then(
self.getOptions().embedService.get(input, self.getOptions().coverMaxWidth).then(
function successCallback(data) {
data.original_url = input;
that.loadData(data);
self.loadData(data);
},
function errorCallback(error) {
that.addMessage(error);
that.ready();
self.addMessage(error);
self.ready();
}

@@ -200,5 +226,6 @@ );

} else {
that.loadData({html: input});
self.loadData({html: input});
}
};
this.$editor.on('paste', _.debounce(callServiceAndLoadData, 200));

@@ -217,29 +244,31 @@

retrieveData: function() {
var that = this;
const self = this;
// retrieve new data from editor
var editor_data = {
title: that.$('.title-preview').text(),
description: that.$('.description-preview').text(),
credit: that.$('.credit-preview').text()
var editorData = {
title: self.$('.title-preview').text(),
description: self.$('.description-preview').text(),
credit: self.$('.credit-preview').text(),
syndicated_creator: this.getData().syndicated_creator,
liveblog_version: '3.4',
};
// remove thumbnail_url if it was removed by user
if (that.$('.cover-preview').hasClass('hidden')) {
editor_data.thumbnail_url = null;
if (self.$('.cover-preview').hasClass('hidden')) {
editorData.thumbnail_url = null;
}
// add data which are not in the editor but has been saved before (like thumbnail_width)
_.merge(that.data, editor_data);
_.merge(self.data, editorData);
// clean data by removing empty string
_.forEach(that.data, (value, key) => {
_.forEach(self.data, (value, key) => {
if (typeof value === 'string' && value.trim() === '') {
delete that.data[key];
delete self.data[key];
}
});
return that.data;
return self.data;
},
renderCard: function(data) {
var card_class = 'liveblog--card';
const cardClass = 'liveblog--card';
var html = $([
'<div class="' + card_class + ' hidden">',
const html = $([
'<div class="' + cardClass + ' hidden">',
' <div class="hidden st-embed-block embed-preview"></div>',

@@ -253,3 +282,3 @@ ' <div class="hidden st-embed-block cover-preview-handler">',

' <a class="hidden st-embed-block link-preview" target="_blank"></a>',
'</div>'
'</div>',
].join('\n'));

@@ -261,3 +290,3 @@

'.embed-preview',
'.cover-preview-handler'
'.cover-preview-handler',
].join(', ')

@@ -281,11 +310,11 @@ ).addClass('hidden');

if (!_.has(data, 'html') && !_.isEmpty(data.thumbnail_url)) {
var ratio = data.thumbnail_width / data.thumbnail_height;
var cover_width = Math.min(this.getOptions().coverMaxWidth, data.thumbnail_width);
var cover_height = cover_width / ratio;
const ratio = data.thumbnail_width / data.thumbnail_height;
const coverWidth = Math.min(this.getOptions().coverMaxWidth, data.thumbnail_width);
const coverHeight = coverWidth / ratio;
html.find('.cover-preview').css({
'background-image': 'url("' + data.thumbnail_url + '")',
width: cover_width,
height: cover_height,
'background-size': 'cover'
width: coverWidth,
height: coverHeight,
'background-size': 'cover',
});

@@ -306,9 +335,9 @@ html.find('.cover-preview-handler').removeClass('hidden');

if (_.has(data, 'provider_name')) {
var credit_text = data.provider_name;
let creditText = data.provider_name;
if (_.has(data, 'author_name')) {
credit_text += ' | <a href="' + data.author_url + '" target="_blank">' +
creditText += ' | <a href="' + data.author_url + '" target="_blank">' +
data.author_name + '</a>';
}
html.find('.credit-preview').html(credit_text);
html.find('.credit-preview').html(creditText);
}

@@ -320,36 +349,31 @@

// remove link for some provider (included in the card)
if (['Facebook', 'Youtube', 'Twitter', 'Soundcloud'].indexOf(data.provider_name) > -1) {
html.find('.link-preview').remove();
}
// special case for twitter
if (data.provider_name === 'Twitter') {
// remove credit and title fields (duplicated with rendered card)
html.find('.credit-preview, .title-preview').remove();
}
fixSocial(html, data);
// retrieve the final html code
var html_to_return = '';
html_to_return = '<div class="' + card_class + '">';
html_to_return += html.get(0).innerHTML;
html_to_return += '</div>';
return html_to_return;
let htmlToReturn = '';
htmlToReturn = '<div class="' + cardClass + '">';
htmlToReturn += html.get(0).innerHTML;
htmlToReturn += '</div>';
return htmlToReturn;
},
// render a card from data, and make it editable
loadData: function(dataParam) {
const that = this;
const self = this;
const data = _.has(dataParam, 'meta') ? dataParam.meta : dataParam;
that.data = fixDataEmbed(data);
self.data = fixDataEmbed(data);
// hide the embed input field, render the card and add it to the DOM
that.$('.embed-input')
self.$('.embed-input')
.addClass('hidden')
.after(that.renderCard(data));
.after(self.renderCard(data));
// set somes fields contenteditable
['title', 'description', 'credit'].forEach(function(field_name) {
that.$('.' + field_name + '-preview').attr({
['title', 'description', 'credit'].forEach((fieldName) => {
self.$('.' + fieldName + '-preview').attr({
contenteditable: true,
placeholder: field_name
placeholder: fieldName,
});
});
// remove the loader when media is loaded
var iframe = this.$('.embed-preview iframe');
// remove the loader when media is loadedhtml =
const iframe = this.$('.embed-preview iframe');
if (iframe.length > 0) {

@@ -362,29 +386,30 @@ // special case for iframe

// add a link to remove/show the cover
var $cover_handler = this.$('.cover-preview-handler');
if ($cover_handler.length > 0 && !$cover_handler.hasClass('hidden')) {
var $cover_preview = $cover_handler.find('.cover-preview');
var $remove_link = $('<a href="#">').text('hide the illustration');
var $show_link = $('<a href="#">')
const $coverHandler = this.$('.cover-preview-handler');
if ($coverHandler.length > 0 && !$coverHandler.hasClass('hidden')) {
const $coverPreview = $coverHandler.find('.cover-preview');
const $removeLink = $('<a href="#">').text('hide the illustration');
const $showLink = $('<a href="#">')
.text('show the illustration')
.addClass('hidden');
$remove_link.on('click', function removeCoverAndDisillustrationplayShowLink(e) {
that.saved_cover_url = that.data.thumbnail_url;
$cover_preview.addClass('hidden');
$removeLink.on('click', function removeCoverAndDisillustrationplayShowLink(e) {
self.saved_cover_url = self.data.thumbnail_url;
$coverPreview.addClass('hidden');
$(this).addClass('hidden');
$show_link.removeClass('hidden');
$showLink.removeClass('hidden');
e.preventDefault();
});
$show_link.on('click', function showCoverAndDisplayRemoveLink(e) {
that.data.thumbnail_url = that.saved_cover_url;
$cover_preview.removeClass('hidden');
$showLink.on('click', function showCoverAndDisplayRemoveLink(e) {
self.data.thumbnail_url = self.saved_cover_url;
$coverPreview.removeClass('hidden');
$(this).addClass('hidden');
$remove_link.removeClass('hidden');
$removeLink.removeClass('hidden');
e.preventDefault();
});
$cover_handler.append($remove_link, $show_link);
$coverHandler.append($removeLink, $showLink);
}
//if instagram process the embed code
// if instagram process the embed code
if (data.html && data.html.indexOf('platform.instagram.com') !== -1) {
setTimeout(function() {
setTimeout(() => {
window.instgrm.Embeds.process();

@@ -399,3 +424,4 @@ }, 1000);

toHTML: function() {
var data = this.retrieveData();
const data = this.retrieveData();
return this.renderCard(data);

@@ -405,3 +431,3 @@ },

return this.retrieveData();
}
},
});

@@ -417,7 +443,7 @@ SirTrevor.Blocks.Quote = SirTrevor.Block.extend({

editorHTML: function() {
var template = _.template([
const template = _.template([
'<div class="st-required st-quote-block quote-input" ',
' placeholder="' + this.quotePlaceholder + '" contenteditable="true"></div>',
'<div contenteditable="true" name="cite" placeholder="' + this.creditPlaceholder + '"',
' class="js-cite-input st-quote-block"></div>'
' class="js-cite-input st-quote-block"></div>',
].join('\n'));

@@ -429,4 +455,4 @@

const onEditorChange = () => {
var data = this.retrieveData(),
input = data.quote + data.credit;
const data = this.retrieveData();
const input = data.quote + data.credit;

@@ -442,3 +468,3 @@ if (_.isEmpty(input)) {

this.$editor.filter('[contenteditable]').on('focus', function(ev) {
var $this = $(this);
const $this = $(this);

@@ -448,3 +474,3 @@ $this.data('before', $this.html());

this.$editor.filter('[contenteditable]').on('blur keyup paste input', function(ev) {
var $this = $(this);
const $this = $(this);

@@ -467,3 +493,4 @@ if ($this.data('before') !== $this.html()) {

quote: this.$('.quote-input').text() || undefined,
credit: this.$('.js-cite-input').text() || undefined
credit: this.$('.js-cite-input').text() || undefined,
syndicated_creator: this.getData().syndicated_creator,
};

@@ -482,3 +509,3 @@ },

toHTML: function(html) {
var data = this.retrieveData();
const data = this.retrieveData();

@@ -490,3 +517,3 @@ return [

data.credit,
'</i></h4></blockquote>'
'</i></h4></blockquote>',
].join('');

@@ -496,7 +523,7 @@ },

return this.retrieveData();
}
},
});
// Image Block
var upload_options = {
const uploadOptions = {
// NOTE: responsive layout is currently disabled. so row and col-md-6 are useless

@@ -510,7 +537,7 @@ html: [

' </div>',
'</div>'
].join('\n')
'</div>',
].join('\n'),
};
SirTrevor.DEFAULTS.Block.upload_options = upload_options;
SirTrevor.DEFAULTS.Block.upload_options = uploadOptions;
SirTrevor.Locales.en.general.upload = 'Select from folder';

@@ -524,45 +551,57 @@

SirTrevor.Blocks.Text.prototype.toMeta = function() {
return {
syndicated_creator: this.getData().syndicated_creator,
};
};
SirTrevor.Blocks.Text.prototype.onBlockRender = function() {
var that = this, placeHolderText = window.gettext('Start writing here…');
const self = this;
const placeHolderText = window.gettext('Write here (or press Ctrl+Shift+V to paste unformatted text)...');
//add placeholder class and placeholder text
this.$editor.attr('placeholder', placeHolderText).addClass('st-placeholder');
// create and trigger a 'change' event for the $editor which is a contenteditable
this.$editor.filter('[contenteditable]').on('focus', function(ev) {
var $this = $(this);
// add placeholder class and placeholder text
this.$editor.attr('placeholder', placeHolderText).addClass('st-placeholder');
// create and trigger a 'change' event for the $editor which is a contenteditable
this.$editor.filter('[contenteditable]').on('focus', function(ev) {
const $this = $(this);
$this.data('before', $this.html());
});
this.$editor.filter('[contenteditable]').on('click', function(ev) {
const $this = $(this);
if (_.trim($this.html()) === '') {
$this.attr('placeholder', '');
}
});
this.$editor.filter('[contenteditable]').on('focusout', function(ev) {
const $this = $(this);
if (_.trim($this.html()) === '') {
$this.attr('placeholder', placeHolderText);
}
});
this.$editor.filter('[contenteditable]').on('blur keyup paste input', function(ev) {
const $this = $(this);
if ($this.data('before') !== $this.html()) {
$this.data('before', $this.html());
});
this.$editor.filter('[contenteditable]').on('click', function(ev) {
var $this = $(this);
if (_.trim($this.html()) === '') {
$this.attr('placeholder', '');
}
});
this.$editor.filter('[contenteditable]').on('focusout', function(ev) {
var $this = $(this);
if (_.trim($this.html()) === '') {
$this.attr('placeholder', placeHolderText);
}
});
this.$editor.filter('[contenteditable]').on('blur keyup paste input', function(ev) {
var $this = $(this);
if ($this.data('before') !== $this.html()) {
$this.data('before', $this.html());
$this.trigger('change');
}
});
// when the link field changes
this.$editor.on('change', _.debounce(function () {
var input = $(this)
.text()
.trim();
$this.trigger('change');
}
});
// when the link field changes
this.$editor.on('change', _.debounce(function() {
const input = $(this)
.text()
.trim();
if (_.isEmpty(input)) {
if (that.getOptions())
that.getOptions().disableSubmit(true);
return false;
} else if (that.getOptions()) {
that.getOptions().disableSubmit(false);
if (_.isEmpty(input)) {
if (self.getOptions()) {
self.getOptions().disableSubmit(true);
}
}, 200));
return false;
} else if (self.getOptions()) {
self.getOptions().disableSubmit(false);
}
}, 200));
};

@@ -578,13 +617,13 @@

};
SirTrevor.Blocks.Text.prototype.onContentPasted = _.debounce(function(event) {
SirTrevor.Blocks.Text.prototype.onContentPasted = _.debounce((event) => {
// Content pasted. Delegate to the drop parse method
var input = $(event.target).closest('[contenteditable]'),
val = input.html();
const input = $(event.target).closest('[contenteditable]');
let val = input.html();
if (val) {
val = val.replace(/(<style\b[^>]*>)[^<>]*(<\/style>)/ig, '');
val = val.replace(/(<script\b[^>]*>)[^<>]*(<\/script>)/ig, '');
// use paragraph tag `p` instead of `div` witch isn't supported.
val = val.replace(/<(\/)?div\b[^\/>]*>/ig, '<$1p>');
val = val.replace(/<(br|p|b|i|strike|ul|ol|li|a)\b[^\/>]+>/ig, '<$1>');
val = val.replace(/<(?!\s*\/?(br|p|b|i|strike|ul|ol|li|a|h4|h5)\b)[^>]+>/ig, '');
val = sanitizeHtml(val, sanitizeConfig);
val = (val || '').trim();
// let's also remove not needed line breaks
val = val.replace(/\r/g, ' ');
val = val.replace(/\n/g, ' ');
}

@@ -596,5 +635,7 @@ input.html(val);

SirTrevor.Blocks.Comment = SirTrevor.Block.extend({
type: "comment",
type: 'comment',
title: function() { return window.i18n.t('blocks:comment:title'); },
title: function() {
return window.i18n.t('blocks:comment:title');
},

@@ -614,2 +655,3 @@ editorHTML: '<div class="st-required st-text-block"></div>',

text: this.$('.st-text-block').text() || undefined,
syndicated_creator: this.getData().syndicated_creator,
};

@@ -625,43 +667,48 @@ },

toMeta: function() {
var data = this.getData();
const data = this.getData();
return {
text: data.text,
commenter: data.commenter,
_created: data._created
}
}
_created: data._created,
};
},
});
var Strikethrough = SirTrevor.Formatter.extend({
const Strikethrough = SirTrevor.Formatter.extend({
title: 'strikethrough',
iconName: 'strikethrough',
cmd: 'strikeThrough',
text: 'strike'
text: 'strike',
});
SirTrevor.Formatters.Strikethrough = new Strikethrough();
var OrderedList = SirTrevor.Formatter.extend({
const OrderedList = SirTrevor.Formatter.extend({
title: 'orderedlist',
iconName: 'orderedlist',
cmd: 'insertOrderedList',
text: 'orderedlist'
text: 'orderedlist',
});
SirTrevor.Formatters.NumberedList = new OrderedList();
var UnorderedList = SirTrevor.Formatter.extend({
const UnorderedList = SirTrevor.Formatter.extend({
title: 'unorderedlist',
iconName: 'unorderedlist',
cmd: 'insertUnorderedList',
text: 'unorderedlist'
text: 'unorderedlist',
});
SirTrevor.Formatters.BulletList = new UnorderedList();
var RemoveFormat = SirTrevor.Formatter.extend({
const RemoveFormat = SirTrevor.Formatter.extend({
title: 'removeformat',
iconName: 'removeformat',
cmd: 'removeformat',
text: 'removeformat'
text: 'removeformat',
});
SirTrevor.Formatters.RemoveFormat = new RemoveFormat();
var Bold = SirTrevor.Formatter.extend({
const Bold = SirTrevor.Formatter.extend({
title: 'bold',

@@ -671,7 +718,8 @@ iconName: 'bold',

keyCode: 66,
text: 'bold'
text: 'bold',
});
SirTrevor.Formatters.Bold = new Bold();
var Italic = SirTrevor.Formatter.extend({
const Italic = SirTrevor.Formatter.extend({
title: 'italic',

@@ -681,12 +729,14 @@ iconName: 'italic',

keyCode: 73,
text: 'italic'
text: 'italic',
});
SirTrevor.Formatters.Italic = new Italic();
var UnLink = SirTrevor.Formatter.extend({
const UnLink = SirTrevor.Formatter.extend({
title: 'unlink',
iconName: 'unlink',
cmd: 'unlink',
text: 'unlink'
text: 'unlink',
});
SirTrevor.Formatters.Unlink = new UnLink();

@@ -701,4 +751,5 @@

document.execCommand('formatBlock', false, '<h4>');
}
},
});
SirTrevor.Formatters.HeaderFour = new HeaderFour();

@@ -713,7 +764,8 @@

document.execCommand('formatBlock', false, '<h5>');
}
},
});
SirTrevor.Formatters.HeaderFive = new HeaderFive();
var Link = SirTrevor.Formatter.extend({
const Link = SirTrevor.Formatter.extend({
title: 'link',

@@ -724,8 +776,10 @@ iconName: 'link',

onClick: function() {
var selection_text = document.getSelection(),
link = prompt(window.i18n.t("general:link")),
link_regex = /((ftp|http|https):\/\/.)|mailto(?=\:[-\.\w]+@)/;
const selectionText = document.getSelection();
/* eslint-disable no-alert */
let link = prompt(window.i18n.t('general:link'));
const linkRegex = /((ftp|http|https):\/\/.)|mailto(?=:[-.\w]+@)/;
if (link && link.length > 0) {
if (!link_regex.test(link)) {
link = "http://" + link;
if (!linkRegex.test(link)) {
link = 'http://' + link;
}

@@ -736,3 +790,3 @@

false,
'<a href="' + link + '" target="_blank">' + selection_text + '</a>'
'<a href="' + link + '" target="_blank">' + selectionText + '</a>'
);

@@ -742,13 +796,15 @@ }

isActive: function() {
var selection = window.getSelection(),
node;
if (selection.rangeCount > 0) {
node = selection.getRangeAt(0)
.startContainer
.parentNode;
}
return (node && node.nodeName === 'A');
}
const selection = window.getSelection();
let node;
if (selection.rangeCount > 0) {
node = selection.getRangeAt(0)
.startContainer
.parentNode;
}
return node && node.nodeName === 'A';
},
});
SirTrevor.Formatters.Link = new Link();
}]);

@@ -1,2 +0,2 @@

module.exports = function (grunt) {
module.exports = function(grunt) {
// util for grunt.template

@@ -7,4 +7,4 @@ grunt.toJSON = function(input) {

var config = {
pkg: grunt.file.readJSON('../package.json'),
const config = {
pkg: grunt.file.readJSON('./package.json'),
appDir: 'app',

@@ -11,0 +11,0 @@ tmpDir: '.tmp',

{
"name": "liveblog-client",
"version": "3.3.7",
"version": "3.4.0",
"repository": {

@@ -8,2 +8,8 @@ "type": "git",

},
"scripts": {
"build": "grunt build",
"test": "grunt ci:travis",
"webdriver-update": "webdriver-manager update",
"e2e": "protractor protractor-conf.js"
},
"licenses": [

@@ -16,28 +22,31 @@ {

"devDependencies": {
"babel-core": "^6.10.4",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.16.0",
"bluebird": "^3.4.6",
"btoa": "^1.1.2",
"css-loader": "^0.23.1",
"eslint-loader": "^1.6.1",
"eslint-plugin-angular": "^1.4.1",
"file-loader": "^0.9.0",
"grunt": "^0.4.2",
"grunt-angular-gettext": "2.1.3",
"grunt-angular-templates": "0.5.7",
"grunt-contrib-clean": "0.6.0",
"grunt-contrib-concat": "0.5.1",
"grunt-contrib-connect": "0.11.2",
"grunt-contrib-copy": "0.8.1",
"grunt-contrib-cssmin": "0.13.0",
"grunt-contrib-jshint": "0.11.1",
"grunt-contrib-requirejs": "0.4.4",
"grunt-contrib-uglify": "0.9.2",
"grunt-contrib-watch": "0.6.1",
"grunt-eslint": "^19.0.0",
"babel-core": "6.26.0",
"babel-loader": "7.1.3",
"babel-plugin-transform-class-properties": "6.24.1",
"babel-plugin-transform-object-rest-spread": "6.26.0",
"babel-preset-es2015": "6.24.1",
"babel-preset-react": "6.24.1",
"bootstrap": "3.3.7",
"btoa": "1.1.2",
"classnames": "2.2.5",
"css-loader": "0.28.7",
"eslint": "4.11.0",
"eslint-loader": "1.9.0",
"eslint-plugin-angular": "3.1.1",
"eslint-plugin-react": "^7.5.1",
"grunt": "1.0.1",
"grunt-angular-gettext": "2.3.6",
"grunt-angular-templates": "1.1.0",
"grunt-contrib-clean": "1.1.0",
"grunt-contrib-concat": "1.0.1",
"grunt-contrib-connect": "1.0.2",
"grunt-contrib-copy": "1.0.0",
"grunt-contrib-cssmin": "2.2.1",
"grunt-contrib-less": "1.4.1",
"grunt-contrib-uglify": "3.1.0",
"grunt-contrib-watch": "1.0.0",
"grunt-eslint": "20.1.0",
"grunt-filerev": "2.3.1",
"grunt-jscs": "1.8.0",
"grunt-karma": "0.12.0",
"grunt-karma": "2.0.0",
"grunt-karma-coveralls": "2.5.4",

@@ -47,5 +56,5 @@ "grunt-open": "0.2.3",

"grunt-usemin": "3.1.1",
"grunt-webpack": "^1.0.14",
"grunt-webpack": "3.1.1",
"jasmine-reporters": "2.2.1",
"json-loader": "^0.5.4",
"json-loader": "0.5.4",
"karma": "1.7.1",

@@ -59,56 +68,53 @@ "karma-chrome-launcher": "2.2.0",

"karma-requirejs": "0.2.2",
"load-grunt-config": "0.17.1",
"load-grunt-tasks": "3.2.0",
"ngtemplate-loader": "^1.3.1",
"node-sass": "^4.3.0",
"load-grunt-config": "0.19.2",
"load-grunt-tasks": "3.5.2",
"ngtemplate-loader": "2.0.1",
"node-sass": "4.5.3",
"phantomjs": "^2.1.3",
"protractor": "5.2.1",
"protractor-flake": "3.0.1",
"react": "^15.3.2",
"react-dom": "^15.3.2",
"react": "16.2.0",
"react-dom": "16.2.0",
"request": "^2.79.0",
"sass-loader": "^4.1.1",
"style-loader": "^0.13.1",
"webpack": "^1.13.2",
"webpack-dev-server": "^1.16.1"
"sass-loader": "6.0.6",
"style-loader": "0.19.0",
"superdesk-code-style": "^1.0.0",
"webpack": "3.6.0",
"webpack-dev-server": "2.8.2"
},
"scripts": {
"test": "grunt ci:travis"
},
"dependencies": {
"adblock-detect": "^1.0.5",
"angular": "^1.5.8",
"angular-animate": "^1.6.1",
"angular-bootstrap-npm": "jusopi/angular-bootstrap-npm#0.13.1",
"angular-contenteditable": "0.0.2",
"angular-embed": "^2.1.1",
"adblock-detect": "1.0.5",
"angular": "1.6.9",
"angular-animate": "1.6.1",
"angular-contenteditable": "0.3.9",
"angular-embed": "eos87/angular-embed",
"angular-embedly": "Urigo/angular-embedly#0.0.8",
"angular-gettext": "^2.3.8",
"angular-messages": "^1.5.8",
"angular-mocks": "^1.6.1",
"angular-moment": "^1.0.1",
"angular-resource": "^1.5.8",
"angular-route": "^1.5.8",
"angular-vs-repeat": "^1.1.7",
"bootstrap": "^3.1.1",
"eventable": "0.0.0",
"gridster": "^0.5.6",
"jquery": "^2.2.3",
"jquery-jcrop": "^0.9.13",
"angular-gettext": "2.3.10",
"angular-messages": "1.6.6",
"angular-mocks": "1.6.9",
"angular-moment": "1.2.0",
"angular-resource": "1.6.6",
"angular-route": "1.6.9",
"angular-vs-repeat": "1.1.7",
"eventable": "madebymany/eventable",
"gridster": "0.5.6",
"jquery": "3.3.1",
"jquery-jcrop": "0.9.13",
"jquery-ui": "components/jqueryui#1.11.4",
"jquery.gridster": "dustmoo/gridster.js#c306335397816beceb74e4a176067baef34a0359",
"lodash": "^4.14.1",
"lodash.sortbyorder": "^3.4.4",
"lr-infinite-scroll": "^1.0.0",
"medium-editor": "^5.21.0",
"medium-editor-tables": "^0.5.3",
"ment.io": "^0.9.23",
"moment": "2.19.3",
"lodash": "4.17.5",
"lodash.sortbyorder": "3.4.4",
"lr-infinite-scroll": "1.0.0",
"medium-editor": "5.23.3",
"medium-editor-tables": "0.6.1",
"ment.io": "0.9.23",
"moment": "2.20.1",
"moment-timezone": "0.5.14",
"ng-file-upload": "^12.2.11",
"ng-file-upload": "12.2.13",
"ng-sir-trevor": "superdesk/ng-sir-trevor",
"rangy": "^1.3.0",
"raven-js": "^3.9.1",
"sir-trevor": "m0g/sir-trevor-js#liveblog",
"superdesk-core": "liveblog/superdesk-client-core#bd052590f93e1bcba88049cb404060c84ffa4363"
"rangy": "1.3.0",
"raven-js": "3.22.3",
"sanitize-html": "^1.18.2",
"sir-trevor": "liveblog/sir-trevor-js",
"superdesk-core": "github:eos87/superdesk-client-core#v1.17.0-liveblog"
},

@@ -115,0 +121,0 @@ "engines": {

@@ -14,3 +14,3 @@ 'use strict';

//chromeOptions.binary = '/usr/bin/chromium-browser';
// chromeOptions.binary = '/usr/bin/chromium-browser';

@@ -49,2 +49,3 @@ return chromeOptions;

var reporters = require('jasmine-reporters');
jasmine.getEnv().addReporter(

@@ -51,0 +52,0 @@ new reporters.JUnitXmlReporter({

var login = require('./../node_modules/superdesk-core/spec/helpers/utils').login,
aM = require('./helpers/pages').advertisingManager;
describe('Advertising Manager', function() {
'use strict';
beforeEach(function(done) {
browser.ignoreSynchronization = true;
login()
.then(() => browser.ignoreSynchronization = false)
.then(done);
describe('Advertising Manager', () => {
beforeEach((done) => {
login()
.then(done);
});
it('can open Adverts manager and do CRUD operations on them', function() {
it('can open Adverts manager and do CRUD operations on them', () => {
aM.openAdvertisingManager();

@@ -22,9 +18,12 @@

expect(aM.getAdverts().count()).toBe(0);
aM.openNewAdvertDialog();
aM.editFreetype().then(function(freeData) {
aM.editFreetype().then((freeData) => {
// we should not have two freetypes entered
expect(aM.getAdverts().count()).toBe(1);
//open 1st freetype and check contents
aM.getAdverts().get(0).click().all(by.css('[ng-click="openAdvertDialog(advert);"]')).click();
// open 1st freetype and check contents
aM.getAdverts().get(0)
.click()
.all(by.css('[ng-click="openAdvertDialog(advert);"]'))
.click();
expect(aM.advertTitle.getAttribute('value')).toEqual(freeData.title);

@@ -35,7 +34,11 @@ expect(aM.advertEmbed.getAttribute('value')).toEqual(freeData.embed);

var newData = aM.createAdvertData();
aM.advertTitle.sendKeys(newData.title);
aM.advertEmbed.sendKeys(newData.embed);
aM.saveAdvert().then(function() {
//check the new contents to match
aM.getAdverts().get(0).click().all(by.css('[ng-click="openAdvertDialog(advert);"]')).click();
aM.saveAdvert().then(() => {
// check the new contents to match
aM.getAdverts().get(0)
.click()
.all(by.css('[ng-click="openAdvertDialog(advert);"]'))
.click();
expect(aM.advertTitle.getAttribute('value')).toEqual(freeData.title + newData.title);

@@ -50,7 +53,6 @@ expect(aM.advertEmbed.getAttribute('value')).toEqual(freeData.embed + newData.embed);

expect(aM.getAdverts().count()).toBe(0);
});
});
it('can open Collections manager tab and do CRUD operations on them', function() {
it('can open Collections manager tab and do CRUD operations on them', () => {
aM.openAdvertisingManager();

@@ -60,27 +62,34 @@

aM.openNewAdvertDialog();
aM.editFreetype().then(function(freeData) {
aM.editFreetype().then((freeData) => {
// open the collections tab
aM.openCollectionsTab();
aM.openNewCollectionDialog();
aM.editCollection().then(function(freeData) {
aM.editCollection().then((freeData) => {
// we should now have one collection
expect(aM.getCollections().count()).toBe(1);
//open 1st collection and check contents
// open 1st collection and check contents
aM.getCollections().get(0).all(by.id('toggle-collection-menu')).click();
element(by.css('[ng-click="openCollectionDialog(collection)"]')).click();
aM.getCollections().get(0)
.all(by.id('toggle-collection-menu')).
click();
element(by.css('[ng-click="openCollectionDialog(collection)"]'))
.click();
expect(aM.collectionTitle.getAttribute('value')).toEqual(freeData.title);
// edit collection
var newData = aM.createAdvertData();
aM.collectionTitle.sendKeys(newData.title);
// add one advert
aM.getAdverts().get(0).all(by.css('[type="checkbox"]')).click();
aM.saveCollection().then(function() {
//check the new contents to match
// add one advert
aM.getAdverts().get(0)
.all(by.css('[type="checkbox"]'))
.click();
aM.saveCollection().then(() => {
// check the new contents to match
var newTitle = freeData.title + newData.title;
newTitle = newTitle.toUpperCase();

@@ -91,6 +100,6 @@ expect(element(by.id('collection-name')).getText()).toEqual(newTitle);

});
// remove first collection
aM.removeCollection(0);
// expect no collections available

@@ -100,3 +109,3 @@ expect(aM.getCollections().count()).toBe(0);

});
})
});
});

@@ -5,15 +5,12 @@ var login = require('./../node_modules/superdesk-core/spec/helpers/utils').login,

describe('Blog settings', function() {
'use strict';
beforeEach(function(done) {
browser.ignoreSynchronization = true;
login('editor', 'editor')
.then(() => browser.ignoreSynchronization = false)
.then(done);
describe('Blog settings', () => {
beforeEach((done) => {
login('editor', 'editor')
.then(done);
});
it('should modify title and description for blog', function() {
it('should modify title and description for blog', () => {
var blog = blogs.cloneBlog(0);
blog.title = randomString();

@@ -26,107 +23,112 @@ blog.description = randomString();

blogs.blog.settings.done()
.openList().then(function() {
blogs.expectBlog(blog, 0);
});
.openList()
.then(() => {
blogs.expectBlog(blog, 0);
});
});
it('should change the image for blog', function() {
it('should change the image for blog', () => {
var path = require('path'),
blog = blogs.cloneBlog(0);
blog.picture_url = './upload/-o-jpg-1600-900.jpg';
blogs.openBlog(0).openSettings().then(function(settingsPage) {
return settingsPage.openUploadModal();
})
.then(function() {
blogs.blog.settings.file.sendKeys(path.resolve(__dirname, blog.picture_url));
blogs.blog.settings
.upload()
.done()
.openList().then(function() {
blogs.openBlog(0).openSettings()
.then((settingsPage) => settingsPage.openUploadModal())
.then(() => {
blogs.blog.settings.file.sendKeys(path.resolve(__dirname, blog.picture_url));
blogs.blog.settings
.upload()
.done()
.openList()
.then(() => {
blogs.expectBlog(blog);
});
});
});
});
it('should remove the image from blog', function() {
it('should remove the image from blog', () => {
var blog = blogs.cloneBlog(0);
delete blog.picture_url;
blogs.openBlog(0).openSettings().then(function(settingsPage) {
return settingsPage.removeImage()
.waitForModal()
.okModal()
.waitDone()
.done()
.openList().then(function() {
blogs.expectBlog(blog);
blogs.openBlog(0).openSettings()
.then((settingsPage) => {
return settingsPage.removeImage()
.waitForModal()
.okModal()
.waitDone()
.done()
.openList()
.then(() => {
blogs.expectBlog(blog);
});
});
});
});
it('shows original creator full name and username', function() {
blogs.openBlog(0).openSettings().then(function(settingsPage) {
return settingsPage.openTeam();
})
.then(function() {
blogs.blog.settings.displayName.getText().then(function(text) {
expect(text).toEqual('Victor the Editor');
it('shows original creator full name and username', () => {
blogs.openBlog(0).openSettings()
.then((settingsPage) => settingsPage.openTeam())
.then(() => {
blogs.blog.settings.displayName.getText().then((text) => {
expect(text).toEqual('Victor the Editor');
});
blogs.blog.settings.userName.getText().then((text) => {
expect(text).toEqual('editor');
});
});
blogs.blog.settings.userName.getText().then(function(text) {
expect(text).toEqual('editor');
});
});
});
it('ads a team member from blog settings', function() {
blogs
.openBlog(0)
.openSettings()
.then(function(settingsPage) {
return settingsPage
.openTeam()
.then(settingsPage.editTeam);
})
.then(function() {
blogs.blog.settings.team
.searchUser('s')
.waitChooseUser()
.changeToUser();
blogs.blog.settings
.doneTeamEdit()
.done()
.openSettings().then(function(settingsPage) {
return settingsPage.openTeam();
})
.then(function() {
expect(blogs.blog.settings.contributors.count()).toBe(1);
it('ads a team member from blog settings', () => {
blogs.openBlog(0)
.openSettings()
.then((settingsPage) =>
settingsPage
.openTeam()
.then(settingsPage.editTeam)
)
.then(() => {
blogs.blog.settings.team
.searchUser('g')
.waitChooseUser()
.changeToUser();
blogs.blog.settings
.doneTeamEdit()
.done()
.openSettings()
.then((settingsPage) => settingsPage.openTeam())
.then(() => {
expect(blogs.blog.settings.contributors.count()).toBe(1);
});
});
});
});
it('should archive a blog', function() {
it('should archive a blog', () => {
var blog = blogs.cloneBlog(0);
blogs.openBlog(0).openSettings().then(function(settingsPage) {
settingsPage
.switchStatus()
.done()
.openList()
.then(function() {
blogs.selectState('archived')
.expectBlog(blog);
blogs.openBlog(0).openSettings()
.then((settingsPage) => {
settingsPage
.switchStatus()
.done()
.openList()
.then(() => {
blogs.selectState('archived')
.expectBlog(blog);
});
});
});
});
it('should activate a blog', function() {
it('should activate a blog', () => {
var blog = blogs.cloneBlog(0, 'archived');
blogs.selectState('archived')
.openBlog(0).openSettings().then(function(settingsPage) {
.openBlog(0).openSettings().then((settingsPage) => {
settingsPage.switchStatus()
.done()
.openList()
.then(function() {
blogs.selectState('active')
.expectBlog(blog);
});
.done()
.openList()
.then(() => {
blogs.selectState('active')
.expectBlog(blog);
});
});

@@ -136,95 +138,100 @@ });

it('changes blog ownership & admin can open settings for any blog & contributor can\'t access blog settings even if owner',
function() {
blogs.openBlog(0).openSettings().then(function(settingsPage) {
return settingsPage.openTeam().then(function() {
settingsPage.changeOwner()
.changeToOwner()
.selectOwner()
.done();
});
})
.then(function() {
browser.waitForAngular();
browser.get('/');
browser.sleep(2000); // it reloads page
var blog = blogs.openBlog(0);
browser.waitForAngular();
blog.openSettings().then(function(settingsPage) {
return settingsPage.openTeam()
.then(function() {
blogs.blog.settings.userName.getText().then(function(text) {
expect(text).toEqual('contributor');
() => {
blogs.openBlog(0).openSettings()
.then((settingsPage) => {
return settingsPage.openTeam().then(() => {
settingsPage.changeOwner()
.changeToOwner()
.selectOwner()
.done();
});
});
})
.then(function() {
browser.get('/');
element(by.css('button.current-user')).click();
browser.waitForAngular();
browser.sleep(1000); // it reloads page
element(by.buttonText('SIGN OUT')).click();
browser.ignoreSynchronization = true;
browser.sleep(2000); // it reloads page
browser.waitForAngular();
browser.sleep(2000); // it reloads page
})
.then(() => {
browser.get('/');
browser.sleep(2000); // it reloads page
var blog = blogs.openBlog(0);
login('contributor', 'contributor').then(function() {
browser.waitForAngular();
browser.ignoreSynchronization = false;
expect(element(by.css('.settings-link')).isPresent()).toBeFalsy();
blog.openSettings()
.then((settingsPage) => {
return settingsPage.openTeam()
.then(() => {
blogs.blog.settings.userName.getText()
.then((text) => {
expect(text).toEqual('contributor');
});
});
})
.then(() => {
browser.get('/');
element(by.css('button.current-user')).click();
browser.sleep(1000); // it reloads page
element(by.buttonText('SIGN OUT')).click();
browser.sleep(2000); // it reloads page
browser.sleep(2000); // it reloads page
login('contributor', 'contributor').then(() => {
expect(element(by.css('.settings-link')).isPresent()).toBeFalsy();
});
});
});
});
});
});
it('remove a blog', function() {
it('remove a blog', () => {
blogs.expectCount(4);
blogs.openBlog(0).openSettings().then(function(settingsPage) {
settingsPage.removeBlog();
browser.waitForAngular();
browser.get('/');
browser.sleep(2000); // it reloads page
blogs.expectCount(3);
});
blogs.openBlog(0)
.openSettings()
.then((settingsPage) => {
settingsPage.removeBlog();
browser.get('/');
browser.sleep(2000); // it reloads page
blogs.expectCount(3);
});
});
it('should do CRUD operations on output channels', function() {
it('should do CRUD operations on output channels', () => {
blogs.openBlog(0)
.openSettings()
.then((sp) => {
sp.openOutputs();
// no outputs by default
expect(sp.getOutputs().count()).toBe(0);
blogs.openBlog(0).openSettings().then(function(sp) {
sp.openOutputs();
// no outputs by default
expect(sp.getOutputs().count()).toBe(0);
sp.openOutputDialog();
sp.openOutputDialog();
sp.editOutput().then((outputData) => {
var outputTitle = element(by.css('[ng-model="self.output.name"]'));
sp.editOutput().then(function(outputData) {
var outputTitle = element(by.css('[ng-model="vm.output.name"]'));
// we should now have one output
expect(sp.getOutputs().count()).toBe(1);
//open 1st output and check contents
// we should now have one output
expect(sp.getOutputs().count()).toBe(1);
sp.getOutputs().get(0).click();
element(by.css('[ng-click="settings.openOutputDialog(output);"]')).click();
// open 1st output and check contents
sp.getOutputs()
.get(0)
.click();
element(by.css('[ng-click="settings.openOutputDialog(output);"]')).click();
expect(outputTitle.getAttribute('value')).toEqual(outputData.title);
// edit output
var newData = sp.createOutputData();
outputTitle.sendKeys(newData.title);
expect(outputTitle.getAttribute('value')).toEqual(outputData.title);
sp.saveOutput().then(function() {
//check the new contents to match
var newTitle = outputData.title + newData.title;
expect(element(by.id('output-name')).getText()).toEqual(newTitle);
// edit output
var newData = sp.createOutputData();
outputTitle.sendKeys(newData.title);
sp.saveOutput().then(() => {
// check the new contents to match
var newTitle = outputData.title + newData.title;
expect(element(by.id('output-name')).getText()).toEqual(newTitle);
});
// remove first output
sp.removeOutput(0);
// expect no outputs available
expect(sp.getOutputs().count()).toBe(0);
});
// remove first output
sp.removeOutput(0);
// expect no outputs available
expect(sp.getOutputs().count()).toBe(0);
});
});
});
});

@@ -6,32 +6,29 @@ var login = require('./../node_modules/superdesk-core/spec/helpers/utils').login,

describe('Blogs list', function() {
'use strict';
describe('Blogs list', () => {
var searchs = [
{blogs: [0, 1, 2, 3], search: 'title'},
{blogs: [1], search: 'thre'},
{blogs: [0, 1, 2, 3], search: 'to'}
], newBlog = {
title: 'new blog title',
description: 'new blog description',
username: 'Edwin the admin'
},
newBlogImage = {
title: 'new blog title',
description: 'new blog description',
username: 'Edwin the admin',
picture_url: './upload/-busstop-jpg-1600-900.jpg'
};
{blogs: [0, 1, 2, 3], search: 'title'},
{blogs: [1], search: 'thre'},
{blogs: [0, 1, 2, 3], search: 'to'}
], newBlog = {
title: 'new blog title',
description: 'new blog description',
username: 'Edwin the admin'
},
newBlogImage = {
title: 'new blog title',
description: 'new blog description',
username: 'Edwin the admin',
picture_url: './upload/-busstop-jpg-1600-900.jpg'
};
beforeEach(function(done) {
browser.ignoreSynchronization = true;
login()
.then(() => browser.ignoreSynchronization = false)
.then(done);
beforeEach((done) => {
login()
.then(done);
});
describe('list', function() {
it('can list blogs', function() {
describe('list', () => {
it('can list blogs', () => {
var activeBlogs = blogs.getActiveBlogs(),
count = activeBlogs.length;
blogs.expectCount(count);

@@ -43,5 +40,6 @@ for (var i = 0; i < count; i++) {

it('can list blogs in a listed view', function() {
it('can list blogs in a listed view', () => {
var activeBlogs = blogs.getActiveBlogs(),
count = activeBlogs.length;
// assert we have no <table> as inital state. We should arrive on the grid view.

@@ -57,18 +55,19 @@ expect(blogs.gridElement.isPresent()).toBe(false);

it('can search all blogs', function() {
it('can search all blogs', () => {
blogs.searchBlogs(searchs[0]);
});
it('can search just one blog', function() {
it('can search just one blog', () => {
blogs.searchBlogs(searchs[1]);
});
it('can search case insensitive blogs', function() {
it('can search case insensitive blogs', () => {
blogs.searchBlogs(searchs[2]);
});
it('can list archived blogs', function() {
it('can list archived blogs', () => {
var archivedBlogs = blogs.getArchivedBlogs(),
count = archivedBlogs.length;
blogs.selectState('archived');
browser.getCurrentUrl().then(function(url) {
browser.getCurrentUrl().then((url) => {
expect(url.indexOf('archived')).toBeGreaterThan(-1);

@@ -82,33 +81,32 @@ });

it('can request access to a blog by a non member', function() {
it('can request access to a blog by a non member', () => {
logout();
browser.ignoreSynchronization = true;
login('contributor', 'contributor').then(function() {
browser.ignoreSynchronization = false;
//request for blog dialog opens instead of the the blog
login('contributor', 'contributor').then(() => {
// request for blog dialog opens instead of the the blog
blogs.openBlog(1);
browser.wait(function() {
return element(by.css('button[ng-click="requestAccess(accessRequestedTo)"]')).isDisplayed();
});
browser.wait(() => element(by.css('button[ng-click="requestAccess(accessRequestedTo)"]')).isDisplayed());
element(by.css('button[ng-click="requestAccess(accessRequestedTo)"]')).click();
logout();
browser.ignoreSynchronization = true;
login('admin', 'admin').then(function() {
browser.ignoreSynchronization = false;
blogs.openBlog(1).openSettings().then(function(settingsPage) {
return settingsPage.openTeam();
})
.then(function() {
return waitAndClick(by.css('.pending-blog-member'));
})
.then(function() {
return waitAndClick(by.css('[data-button="ACCEPT-NEW-MEMBER"]'));
})
.then(function() {
browser.waitForAngular();
expect(blogs.blog.settings.contributors.count()).toBe(1);
login('admin', 'admin')
.then(() => {
blogs.openBlog(1)
.openSettings()
.then((settingsPage) =>
settingsPage.openTeam()
)
.then(() =>
waitAndClick(by.css('.pending-blog-member'))
)
.then(() =>
waitAndClick(by.css('[data-button="ACCEPT-NEW-MEMBER"]'))
)
.then(() => {
browser.waitForAngular();
expect(blogs.blog.settings.contributors.count()).toBe(1);
});
});
});
});

@@ -118,16 +116,18 @@ });

describe('add', function() {
it('should add a blog', function() {
describe('add', () => {
it('should add a blog', () => {
blogs.openCreateBlog().waitForModal();
blogs.title.sendKeys(newBlog.title);
blogs.description.sendKeys(newBlog.description);
blogs.createBlogNext().createBlogCreate().openList()
.then(function() {
blogs.expectBlog(newBlog);
});
blogs.createBlogNext()
.createBlogCreate()
.openList()
.then(() => {
blogs.expectBlog(newBlog);
});
});
it('should add blog with a image', function() {
it('should add blog with a image', () => {
var path = require('path');
blogs.openCreateBlog().waitForModal();

@@ -137,9 +137,11 @@ blogs.title.sendKeys(newBlog.title);

blogs.file.sendKeys(path.resolve(__dirname, newBlogImage.picture_url));
blogs.createBlogNext().createBlogCreate().openList()
.then(function() {
blogs.expectBlog(newBlogImage);
});
blogs.createBlogNext()
.createBlogCreate()
.openList()
.then(() => {
blogs.expectBlog(newBlogImage);
});
});
it('should add a blog with members', function() {
it('should add a blog with members', () => {
blogs.openCreateBlog().waitForModal();

@@ -150,14 +152,15 @@

blogs.createBlogNext();
blogs.team.searchUser('s')
.waitChooseUser()
.changeToUser();
blogs.createBlogCreate().openSettings().then(function(settingsPage) {
return settingsPage.openTeam();
})
.then(function() {
expect(blogs.blog.settings.contributors.count()).toBe(1);
});
blogs.team.searchUser('g')
.waitChooseUser()
.changeToUser();
blogs.createBlogCreate()
.openSettings()
.then((settingsPage) =>
settingsPage.openTeam()
)
.then(() => {
expect(blogs.blog.settings.contributors.count()).toBe(1);
});
});
});
});

@@ -10,23 +10,22 @@ var login = require('./../node_modules/superdesk-core/spec/helpers/utils').login,

describe('Comments Posts', function() {
'use strict';
beforeEach(function(done) {
browser.ignoreSynchronization = true;
login('editor', 'editor')
.then(() => browser.ignoreSynchronization = false)
.then(done);
describe('Comments Posts', () => {
beforeEach((done) => {
login('editor', 'editor')
.then(done);
});
it('can open comments panel from url', function() {
it('can open comments panel from url', () => {
var comments = blogs.openBlog(0).comments;
browser.getCurrentUrl().then(function(url) {
browser.get(url.split('?')[0] + '?panel=comments').then(function() {
expect(comments.column.isPresent()).toBe(true);
});
browser.getCurrentUrl().then((url) => {
browser.get(url.split('?')[0] + '?panel=comments')
.then(() => {
expect(comments.column.isPresent()).toBe(true);
});
});
});
it('can publish it', function() {
it('can publish it', () => {
var comments = blogs.openBlog(0).openComments();
comments.publish(comments.get(0));

@@ -37,9 +36,11 @@ expect(blogs.blog.timeline.get(0).isPresent()).toBe(true);

it('can open a comment in the editor and publish it', function() {
it('can open a comment in the editor and publish it', () => {
var blog = blogs.openBlog(0),
comments = blog.openComments();
comments.edit(comments.get(0));
var editor = blog.openEditor();
expect(editor.textElement.getText()).toEqual(comment.text);
editor.publish().then(function() {
editor.publish().then(() => {
expect(blogs.blog.timeline.get(0).isPresent()).toBe(true);

@@ -46,0 +47,0 @@ blog.openComments();

@@ -25,17 +25,15 @@ 'use strict';

describe('Consumers', function() {
describe('Consumers', () => {
beforeEach(function(done) {
browser.ignoreSynchronization = true;
login()
.then(() => browser.ignoreSynchronization = false)
.then(done);
beforeEach((done) => {
login()
.then(done);
});
describe('list', function() {
it('can open consumers managements and list the consumers', function() {
describe('list', () => {
it('can open consumers managements and list the consumers', () => {
consumersManagement.openConsumersManagement();
});
it('can switch to page 2', function() {
it('can switch to page 2', () => {
consumersManagement.openConsumersManagement();

@@ -48,6 +46,6 @@

expect(count).toEqual(11);
})
});
});
it('can show an error when some required field are empty', function() {
it('can show an error when some required field is empty', () => {
consumersManagement.openConsumersManagement();

@@ -57,16 +55,16 @@

.click()
.then(function() {
.then(() => {
return element(by.css('input#name')).isDisplayed();
})
.then(function() {
.then(() => {
return element(by.css('input[name="first_name"]'))
.sendKeys(contact.firstName);
})
.then(function() {
.then(() => {
return element(by.css('#save-edit-btn')).isDisplayed();
})
.then(function() {
.then(() => {
return element(by.css('#save-edit-btn')).click();
})
.then(function() {
.then(() => {
var fieldName = 'div[ng-show="consumerForm.attempted &&' +

@@ -79,3 +77,3 @@ ' consumerForm.name.$error.required"]';

})
.then(function() {
.then(() => {
var fieldName = 'div[ng-show="consumerForm.attempted &&' +

@@ -88,3 +86,3 @@ ' consumerForm.webhook_url.$error.required"]';

})
.then(function() {
.then(() => {
return expect(

@@ -95,3 +93,3 @@ $('div[ng-show="attempted && contactForm.first_name.$error.required"]')

})
.then(function() {
.then(() => {
return expect(

@@ -102,3 +100,3 @@ $('div[ng-show="attempted && contactForm.last_name.$error.required"]')

})
.then(function() {
.then(() => {
return expect(

@@ -111,3 +109,3 @@ $('div[ng-show="attempted && contactForm.email.$error.required"]')

it('can create a new consumer', function() {
it('can create a new consumer', () => {
consumersManagement.openConsumersManagement();

@@ -117,35 +115,36 @@

.click()
.then(function() {
.then(() => {
return element(by.css('input#name')).isDisplayed();
})
.then(function() {
.then(() => {
return element(by.css('input#name')).sendKeys(consumer.name);
})
.then(function() {
.then(() => {
return element(by.css('input#webhook-url')).sendKeys(consumer.webhookUrl);
})
.then(function() {
.then(() => {
return element(by.css('input[name="first_name"]'))
.sendKeys(contact.firstName);
})
.then(function() {
.then(() => {
return element(by.css('input[name="last_name"]'))
.sendKeys(contact.lastName);
})
.then(function() {
.then(() => {
return element(by.css('input[name="email"]'))
.sendKeys(contact.email);
})
.then(function() {
//var el = element(by.css('#save-edit-btn'));
//browser.driver.wait(protractor.until.elementIsVisible(el));
//return el.click();
.then(() => {
// var el = element(by.css('#save-edit-btn'));
// browser.driver.wait(protractor.until.elementIsVisible(el));
// return el.click();
return element(by.css('#save-edit-btn')).click();
})
.then(function() {
.then(() => {
var firstRowName = element(by.css('ul.table-body div.row-wrapper div.name'));
expect(firstRowName.getText()).toEqual(consumer.name);
return element.all(by.repeater('consumer in consumers')).count();
})
.then(function(count) {
.then((count) => {
expect(count).toEqual(originalCount + 1);

@@ -155,6 +154,7 @@ });

it('can update a consumer manyfold', function() {
it('can update a consumer manyfold', () => {
consumersManagement.openConsumersManagement();
var firstRowName = element(by.css('ul.table-body div.row-wrapper div.name'));
expect(firstRowName.getText()).toEqual('John Deere');

@@ -165,22 +165,22 @@

.click()
.then(function() {
.then(() => {
return element(by.css('input#name')).isDisplayed();
})
.then(function() {
.then(() => {
return element(by.css('input#name')).clear();
})
.then(function() {
.then(() => {
return element(by.css('input#name')).sendKeys(consumerName);
})
.then(function() {
.then(() => {
return element(by.css('input[name="email"]')).clear();
})
.then(function() {
.then(() => {
return element(by.css('input[name="email"]'))
.sendKeys(contactEmail);
})
.then(function() {
.then(() => {
return element(by.css('#save-edit-btn')).click();
})
.then(function() {
.then(() => {
var firstRowName = element(by.css('ul.table-body div.row-wrapper div.name'));

@@ -194,3 +194,3 @@ var firstRowEmail = element(by.css('ul.table-body div.row-wrapper div[lb-first-contact] a'));

})
.then(function(count) {
.then((count) => {
return expect(count).toEqual(originalCount);

@@ -200,3 +200,3 @@ });

updateConsumer(consumer.name, contact.email).then(function() {
updateConsumer(consumer.name, contact.email).then(() => {
return updateConsumer(consumer.name + '1', contact.email);

@@ -206,5 +206,6 @@ });

it('can delete a consumer', function() {
consumersManagement.openConsumersManagement();
it('can delete a consumer', () => {
consumersManagement.openConsumersManagement();
var firstRowName = element(by.css('ul.table-body div.row-wrapper div.name'));
expect(firstRowName.getText()).toEqual('John Deere');

@@ -215,14 +216,14 @@

browser.actions().mouseMove(elemToHover).perform()
.then(function() {
.then(() => {
return element(by.css('a.delete-consumer'))
.click();
})
.then(function() {
.then(() => {
return element(by.css('button[ng-click="ok()"]'))
.click();
})
.then(function() {
.then(() => {
return element.all(by.repeater('consumer in consumers')).count();
})
.then(function(count) {
.then((count) => {
expect(count).toEqual(originalCount - 1);

@@ -233,7 +234,8 @@ });

describe('Contacts', function() {
it('can add a contact to an existing entry', function() {
describe('Contacts', () => {
it('can add a contact to an existing entry', () => {
consumersManagement.openConsumersManagement();
var firstRowName = element(by.css('ul.table-body div.row-wrapper div.name'));
expect(firstRowName.getText()).toEqual('John Deere');

@@ -243,12 +245,12 @@

.click()
.then(function() {
.then(() => {
return element(by.css('button[ng-click="addContact()"]')).isDisplayed();
})
.then(function() {
.then(() => {
return element(by.css('button[ng-click="addContact()"]')).click();
})
.then(function() {
.then(() => {
return element.all(by.repeater('contact in contacts')).get(1).isDisplayed();
})
.then(function() {
.then(() => {
return element

@@ -260,3 +262,3 @@ .all(by.repeater('contact in contacts'))

})
.then(function() {
.then(() => {
return element

@@ -268,3 +270,3 @@ .all(by.repeater('contact in contacts'))

})
.then(function() {
.then(() => {
return element

@@ -276,7 +278,7 @@ .all(by.repeater('contact in contacts'))

})
.then(function() {
.then(() => {
return element(by.css('#save-edit-btn')).click();
});
});
});
});
});
var login = require('./../node_modules/superdesk-core/spec/helpers/utils').login,
blogs = require('./helpers/pages').blogs;
describe('Scorecards Posts', function() {
'use strict';
beforeEach(function(done) {
browser.ignoreSynchronization = true;
describe('Scorecards Posts', () => {
beforeEach((done) => {
login('editor', 'editor')
.then(() => browser.ignoreSynchronization = false)
.then(done);
});
it('can publish socrecard and edit it', function() {
it('can publish socrecard and edit it', () => {
var blog = blogs.openBlog(0);
var editor = blog.openFreetypesEditor(2);
editor.publishScorecard().then(function(data) {
editor.publishScorecard().then((data) => {
browser.waitForAngular();
browser.refresh();
//we should have the post in the timeline
// we should have the post in the timeline
expect(blogs.blog.timeline.get(0).isPresent()).toBe(true);
blogs.blog.timeline.edit(0);
//check that edit is loading the initial values
//usign getAttribute('value') instead of getText() because of known webdriver quirk
// check that edit is loading the initial values
// usign getAttribute('value') instead of getText() because of known webdriver quirk
expect(editor.homeName.getAttribute('value')).toEqual(data.homeName);

@@ -34,7 +29,9 @@ expect(editor.homeScore.getAttribute('value')).toEqual(data.homeScore);

expect(editor.player1Time.getAttribute('value')).toEqual(data.player1Time);
expect(editor.player2Name.getAttribute('value')).toEqual(data.player2Name);
expect(editor.player2Time.getAttribute('value')).toEqual(data.player2Time);
//now do an actual edit like adding another scoarer
// now do an actual edit like adding another scoarer
element(by.css('[ng-click="ftca.add()"]')).click();
editor.player2Name.sendKeys(data.player2Name);
editor.player2Time.sendKeys(data.player2Time);
editor.player3Name.sendKeys(data.player3Name);
editor.player3Time.sendKeys(data.player3Time);

@@ -45,3 +42,3 @@ editor.publish();

//check for the edited content
// check for the edited content
blogs.blog.timeline.edit(0);

@@ -51,3 +48,3 @@ expect(editor.player2Name.getAttribute('value')).toEqual(data.player2Name);

//now try to reset
// now try to reset
editor.resetEditor(true);

@@ -54,0 +51,0 @@ expect(editor.homeName.getAttribute('value')).toEqual('');

var login = require('./../node_modules/superdesk-core/spec/helpers/utils').login,
freetypesManager = require('./helpers/pages').freetypesManager;
describe('Free types Manager', function() {
'use strict';
beforeEach(function(done) {
browser.ignoreSynchronization = true;
login()
.then(() => browser.ignoreSynchronization = false)
.then(done);
describe('Free types Manager', () => {
beforeEach((done) => {
login()
.then(done);
});
it('can open freetypes manager and do CRUD operations on them', function() {
it('can open freetypes manager and do CRUD operations on them', () => {
freetypesManager.openFreetypesManager();

@@ -20,23 +16,32 @@ // no freetypes initialy

freetypesManager.openNewFreetypeDialog();
freetypesManager.editFreetype().then(function(freeData) {
//we should not have two freetypes entered
freetypesManager.editFreetype().then((freeData) => {
// we should not have two freetypes entered
expect(freetypesManager.getFreetypes().count()).toBe(1);
//open 1st freetype and check contents
freetypesManager.getFreetypes().get(0).click().all(by.css('[ng-click="vm.openFreetypeDialog(freetype);"]')).click();
// open 1st freetype and check contents
freetypesManager.getFreetypes()
.get(0)
.click()
.all(by.css('[ng-click="self.openFreetypeDialog(freetype);"]'))
.click();
expect(freetypesManager.title.getAttribute('value')).toEqual(freeData.title);
expect(freetypesManager.template.getAttribute('value')).toEqual(freeData.template);
//edit freetype
// edit freetype
var newData = freetypesManager.createFreetypeData();
freetypesManager.title.sendKeys(newData.title);
freetypesManager.template.sendKeys(newData.template);
freetypesManager.saveFreetype().then(function() {
//check the new contents to match
freetypesManager.getFreetypes().get(0).click().all(by.css('[ng-click="vm.openFreetypeDialog(freetype);"]')).click();
freetypesManager.saveFreetype().then(() => {
// check the new contents to match
freetypesManager.getFreetypes()
.get(0)
.click()
.all(by.css('[ng-click="self.openFreetypeDialog(freetype);"]'))
.click();
expect(freetypesManager.title.getAttribute('value')).toEqual(freeData.title + newData.title);
expect(freetypesManager.template.getAttribute('value')).toEqual(freeData.template + newData.template);
});
//close edit freetype dialog
element(by.css('[ng-click="vm.cancelCreate()"]')).click();
//remove first freetype
// close edit freetype dialog
element(by.css('[ng-click="self.cancelCreate()"]')).click();
// remove first freetype
freetypesManager.removeFreetype(0);

@@ -43,0 +48,0 @@ // expect no freetypes available

var waitAndClick = require('./utils').waitAndClick;
var blogs = [
[
{
title: 'title: end to end image',
description: 'description: end to end image',
username: 'Victor the Editor',
picture_url: 'http://i.imgur.com/L0Ci8Yj.png'
},
{title: 'title: end To end three', description: 'description: end to end three', username: 'Victor the Editor'},
{title: 'title: end to end two', description: 'description: end to end two', username: 'Victor the Editor'},
{title: 'title: end to end One', description: 'description: end to end one', username: 'Victor the Editor'}
], [
{title: 'title: end to end closed', description: 'description: end to end closed', username: 'Victor the Editor'}
]
], stateMap = {
'active': 0,
'archived': 1
};
[
{
title: 'title: end to end image',
description: 'description: end to end image',
username: 'Victor the Editor',
picture_url: 'http://i.imgur.com/L0Ci8Yj.png'
},
{title: 'title: end To end three', description: 'description: end to end three', username: 'Victor the Editor'},
{title: 'title: end to end two', description: 'description: end to end two', username: 'Victor the Editor'},
{title: 'title: end to end One', description: 'description: end to end one', username: 'Victor the Editor'}
], [
{title: 'title: end to end closed', description: 'description: end to end closed', username: 'Victor the Editor'}
]
], stateMap = {
active: 0,
archived: 1
};
function waitForModal() {
'use strict';
/*jshint validthis: true */
browser.wait(function() {
return element(by.css('.modal-footer')).isDisplayed();
}, 1000);
/* jshint validthis: true */
browser.wait(() => element(by.css('.modal__dialog')).isDisplayed(), 1000);
return this;
}
function okModal() {
'use strict';
/*jshint validthis: true */
/* jshint validthis: true */
element(by.css('[ng-click="ok()"]')).click();

@@ -37,3 +33,2 @@ return this;

function BlogsPage() {
'use strict';
var self = this;

@@ -49,3 +44,3 @@

state = state || 0;
if (parseInt(state, 10) !== state){
if (parseInt(state, 10) !== state) {
state = stateMap[state];

@@ -78,17 +73,18 @@ }

element(by.css('[ng-click="flags.extended = !flags.extended"]')).click()
.then(function() {
element(by.model('q')).waitReady()
.then(function(elem) {
elem.clear().sendKeys(search.search);
browser.getCurrentUrl().then(function(url) {
expect(url.indexOf('q=' + search.search)).toBeGreaterThan(-1);
})
.then(function () {
self.expectCount(search.blogs.length);
for (var j = 0, countj = search.blogs.length; j < countj; j++) {
self.expectBlog(self.blogs[0][search.blogs[j]], j);
}
});
.then(() => {
element(by.model('q')).waitReady()
.then((elem) => {
elem.clear().sendKeys(search.search);
browser
.getCurrentUrl().then((url) => {
expect(url.indexOf('q=' + search.search)).toBeGreaterThan(-1);
})
.then(() => {
self.expectCount(search.blogs.length);
for (var j = 0, countj = search.blogs.length; j < countj; j++) {
self.expectBlog(self.blogs[0][search.blogs[j]], j);
}
});
});
});
});
return self;

@@ -122,2 +118,3 @@ };

var currentBlog = element.all(by.repeater('blog in blogs._items')).get(index);
expect(currentBlog.element(by.binding('blog.title')).getText()).toBe(blog.title);

@@ -131,3 +128,3 @@ expect(currentBlog.element(by.binding('blog.description')).getText()).toBe(blog.description);

expect(currentBlog.element(by.binding('blog.original_creator | username')).getText())
.toBe(blog.username);
.toBe(blog.username);
};

@@ -142,3 +139,3 @@

state = state || 1;
if (parseInt(state, 10) !== state){
if (parseInt(state, 10) !== state) {
state = stateMap[state];

@@ -153,15 +150,13 @@ }

function FreetypesManagerPage() {
'use strict';
var self = this;
self.title = element(by.css('[ng-model="vm.dialogFreetype.name"]'));
self.template = element(by.css('[ng-model="vm.dialogFreetype.template"]'));
self.title = element(by.css('[ng-model="self.dialogFreetype.name"]'));
self.template = element(by.css('[ng-model="self.dialogFreetype.template"]'));
self.getFreetypes = function() {
return element.all(by.repeater('freetype in vm.freetypes'));
return element.all(by.repeater('freetype in self.freetypes'));
};
self.openFreetypesManager = function() {
element(by.css('[ng-click="toggleMenu()"]')).click();
browser.wait(function() {
return element(by.css('[href="#/freetypes/"][title]')).isDisplayed();
});
browser.wait(() => element(by.css('[href="#/freetypes/"][title]')).isDisplayed());
waitAndClick(by.css('[href="#/freetypes/"][title]'));

@@ -171,6 +166,6 @@ return self;

self.saveFreetype = function() {
return element(by.css('[ng-click="vm.saveFreetype()"]')).click();
return element(by.css('[ng-click="self.saveFreetype()"]')).click();
};
self.openNewFreetypeDialog = function() {
element(by.css('[ng-click="vm.openFreetypeDialog();"]')).click();
element(by.css('[ng-click="self.openFreetypeDialog();"]')).click();
};

@@ -187,7 +182,11 @@ self.createFreetypeData = function() {

self.template.sendKeys(freeData.template);
return self.saveFreetype().then(function() {return freeData;});
return self.saveFreetype().then(() => freeData);
};
self.removeFreetype = function(index) {
index = index || 0;
self.getFreetypes().get(index).click().all(by.css('[ng-click="vm.removeFreetype(freetype, $index);"]')).click();
self.getFreetypes()
.get(index)
.click()
.all(by.css('[ng-click="self.removeFreetype(freetype, $index);"]'))
.click();
okModal();

@@ -198,4 +197,4 @@ };

function AdvertisingManagerPage() {
'use strict';
var self = this;
self.advertTitle = element(by.css('[ng-model="advert.name"]'));

@@ -281,7 +280,7 @@ self.collectionTitle = element(by.css('[ng-model="collection.name"]'));

self.themes = element.all(by.css('.theme'));
self.blogsRows = element.all(by.repeater('blog in vm.selectedTheme.blogs'));
self.blogsRows = element.all(by.repeater('blog in self.selectedTheme.blogs'));
self.fileThemeElement = element(by.css('#uploadAThemeFile'));
self.byRemove = by.css('[ng-click="vm.removeTheme(theme)"]');
self.bySettings = by.css('[ng-click="vm.openThemeSettings(theme)"]');
self.byPreview = by.css('[ng-click="theme.screenshot_url && vm.openThemePreview(theme)"]');
self.byRemove = by.css('[ng-click="self.removeTheme(theme)"]');
self.bySettings = by.css('[ng-click="self.openThemeSettings(theme)"]');
self.byPreview = by.css('[ng-click="theme.screenshot_url && self.openThemePreview(theme)"]');

@@ -298,3 +297,3 @@ self.openThemesManager = function() {

self.setAsDefault = function(theme_index) {
return self.themes.get(theme_index).element(by.css('[ng-click="vm.makeDefault(theme)"]')).click();
return self.themes.get(theme_index).element(by.css('[ng-click="self.makeDefault(theme)"]')).click();
};

@@ -329,4 +328,4 @@

self.themes.get(theme_index).element(self.byPreview).click().then(function() {
expect(element(by.css('.theme-preview-modal .modal-dialog')).isDisplayed()).toBe(true);
element(by.css('.theme-preview-modal .close')).click();
expect(element(by.css('.theme-preview-modal .modal__dialog')).isDisplayed()).toBe(true);
element(by.css('.theme-preview-modal .modal__close')).click();
});

@@ -357,3 +356,3 @@ return self;

expect(self.blogsRows.count()).toBe(params.number_of_blogs_expected);
var close_modal = element(by.css('[ng-click="vm.closeThemeBlogsModal()"]'));
var close_modal = element(by.css('[ng-click="self.closeThemeBlogsModal()"]'));
close_modal.isPresent().then(function(is_present) {

@@ -394,8 +393,10 @@ if (is_present) {

self.openFreetypesEditor = function(index) {
self.openFreetypesEditor = (index) => {
var freetypeIndex = index || 0;
element(by.css('[ng-click="toggleTypePostDialog()"]')).click()
.then(function() {
element(by.repeater('freetype in freetypes').row(freetypeIndex)).click();
});
element(by.css('[ng-click="toggleTypePostDialog()"]'))
.click()
.then(() => {
element(by.repeater('freetype in freetypes').row(freetypeIndex)).click();
});
return self.editor;

@@ -498,3 +499,3 @@ };

self.openFiterByMember = function() {
return self.column.element(by.css('.btn--plus')).click();
return self.column.element(by.css('[ng-click="self.toggleSelector()"]')).click();
};

@@ -614,3 +615,3 @@

self.publishElement = element(by.css('[ng-click="publish()"]'));
//for scorecards
// for scorecards
self.homeName = element(by.css('[text="freetypeData.home.name"] [ng-model="text"]'));

@@ -622,4 +623,6 @@ self.homeScore = element(by.css('[text="freetypeData.home.score"] [ng-model="text"]'));

self.player1Time = element.all(by.css('[text="iterator__1.time"] [ng-model="text"]')).get(0);
self.player2Name = element.all(by.css('[text="iterator__1.name"] [ng-model="text"]')).get(1);
self.player2Time = element.all(by.css('[text="iterator__1.time"] [ng-model="text"]')).get(1);
self.player2Name = element.all(by.css('[text="iterator__2.name"] [ng-model="text"]')).get(0);
self.player2Time = element.all(by.css('[text="iterator__2.time"] [ng-model="text"]')).get(0);
self.player3Name = element.all(by.css('[text="iterator__1.name"] [ng-model="text"]')).get(1);
self.player3Time = element.all(by.css('[text="iterator__1.time"] [ng-model="text"]')).get(1);

@@ -660,3 +663,3 @@ self.addTop = function() {

self.waitForPublish = function() {
browser.wait(function() {
browser.wait(() => {
return self.publishElement.isEnabled();

@@ -688,3 +691,6 @@ }, 2000);

player2Time: randomNumber(2),
player3Name: randomString(10),
player3Time: randomNumber(2)
};
self.homeName.sendKeys(data.homeName);

@@ -696,3 +702,6 @@ self.homeScore.sendKeys(data.homeScore);

self.player1Time.sendKeys(data.player1Time);
self.player2Name.sendKeys(data.player2Name);
self.player2Time.sendKeys(data.player2Time);
return self.publish().then(function() {return data;});

@@ -813,3 +822,3 @@ };

self.saveOutput = function() {
return element(by.css('[ng-click="vm.saveOutput()"]')).click();
return element(by.css('[ng-click="self.saveOutput()"]')).click();
}

@@ -819,3 +828,3 @@

var outputData = self.createOutputData();
element(by.css('[ng-model="vm.output.name"]')).sendKeys(outputData.title);
element(by.css('[ng-model="self.output.name"]')).sendKeys(outputData.title);
return self.saveOutput().then(function() {return outputData;});

@@ -964,3 +973,2 @@ }

function randomNumber(maxLen) {
'use strict';
maxLen = maxLen || 15;

@@ -976,14 +984,14 @@ var text = '';

function ConsumersManagementPage() {
'use strict';
var self = this;
self.themes = element.all(by.css('.theme'));
self.blogsRows = element.all(by.repeater('blog in vm.selectedTheme.blogs'));
self.blogsRows = element.all(by.repeater('blog in self.selectedTheme.blogs'));
self.fileThemeElement = element(by.css('#uploadAThemeFile'));
self.byRemove = by.css('[ng-click="vm.removeTheme(theme)"]');
self.bySettings = by.css('[ng-click="vm.openThemeSettings(theme)"]');
self.byPreview = by.css('[ng-click="theme.screenshot_url && vm.openThemePreview(theme)"]');
self.byRemove = by.css('[ng-click="self.removeTheme(theme)"]');
self.bySettings = by.css('[ng-click="self.openThemeSettings(theme)"]');
self.byPreview = by.css('[ng-click="theme.screenshot_url && self.openThemePreview(theme)"]');
self.openConsumersManagement = function() {
element(by.css('[ng-click="toggleMenu()"]')).click();
browser.wait(function() {
browser.wait(() => {
return element(by.css('[href="#/syndication/"][title]')).isDisplayed();

@@ -993,3 +1001,3 @@ });

browser.waitForAngular();
// browser.waitForAngular();
element.all(by.repeater('state in states').row(1)).click();

@@ -1002,3 +1010,2 @@

function ProducersManagementPage() {
'use strict';
var self = this;

@@ -1005,0 +1012,0 @@

@@ -57,4 +57,3 @@ function openBlog(index) {

function waitAndClick(elmBy) {
'use strict';
browser.wait(function() {
browser.wait(() => {
return element(elmBy);

@@ -61,0 +60,0 @@ }, 5000);

@@ -1,9 +0,8 @@

var Login = require('./../node_modules/superdesk-core/spec/helpers/pages').login;
var waitForSuperdesk = require('./../node_modules/superdesk-core/spec/helpers/utils').waitForSuperdesk;
const Login = require('./../node_modules/superdesk-core/spec/helpers/pages').login;
const waitForSuperdesk = require('./../node_modules/superdesk-core/spec/helpers/utils').waitForSuperdesk;
describe('login', () => {
var modal;
let modal;
beforeEach(() => {
browser.ignoreSynchronization = true;
modal = new Login();

@@ -14,3 +13,2 @@ });

expect(modal.btn.isDisplayed()).toBe(true);
browser.ignoreSynchronization = false;
});

@@ -20,14 +18,11 @@

modal.login('admin', 'admin');
waitForSuperdesk().then(() => {
browser.ignoreSynchronization = false;
expect(modal.btn.isDisplayed()).toBe(false);
expect(browser.getCurrentUrl()).toBe(browser.baseUrl + '/#/liveblog');
element(by.css('button.current-user')).click();
expect(
element(by.css('.user-info .displayname'))
.waitReady()
.then((elem) => elem.getText())
).toBe('admin');
});
waitForSuperdesk();
expect(modal.btn.isDisplayed()).toBe(false);
expect(browser.getCurrentUrl()).toBe(browser.baseUrl + '/#/liveblog');
element(by.css('button.current-user')).click();
expect(
element(by.css('.user-info .displayname'))
.waitReady()
.then((elem) => elem.getText())
).toBe('admin');
});

@@ -37,14 +32,9 @@

modal.login('admin', 'admin');
waitForSuperdesk().then(() => {
browser.ignoreSynchronization = false;
element(by.css('button.current-user')).click();
// wait for sidebar animation to finish
browser.wait(() => element(by.buttonText('SIGN OUT')).isDisplayed(), 200);
element(by.buttonText('SIGN OUT')).click();
browser.wait(() => element(by.id('login-btn')), 5000);
});
waitForSuperdesk();
element(by.css('button.current-user')).click();
// wait for sidebar animation to finish
browser.wait(() => element(by.buttonText('SIGN OUT')).isDisplayed(), 200);
element(by.buttonText('SIGN OUT')).click();
browser.sleep(2000);
expect(modal.btn.isDisplayed()).toBe(true);
});

@@ -58,3 +48,2 @@

});
});
});

@@ -60,2 +60,6 @@ 'use strict';

.then(function() {
return element(by.css('input#name'))
.sendKeys(producer.name);
})
.then(function() {
return element(by.css('input[name="first_name"]'))

@@ -72,10 +76,2 @@ .sendKeys(contact.firstName);

var fieldName = 'div[ng-show="producerForm.attempted &&' +
' producerForm.name.$error.required"]';
return expect(
$(fieldName).isDisplayed()
).toBeTruthy();
})
.then(function() {
var fieldName = 'div[ng-show="producerForm.attempted &&' +
' producerForm.api_url.$error.required"]';

@@ -82,0 +78,0 @@

var login = require('./../node_modules/superdesk-core/spec/helpers/utils').login,
themeManager = require('./helpers/pages').themeManager;
describe('Themes Manager', function() {
'use strict';
beforeEach(function(done) {
browser.ignoreSynchronization = true;
login()
.then(() => browser.ignoreSynchronization = false)
.then(done);
describe('Themes Manager', () => {
beforeEach((done) => {
login().then(done);
});
it('can open theme manager and list the themes', function() {
it('can open theme manager and list the themes', () => {
themeManager.openThemesManager()
.themes
.then(function(themes) {
expect(themes.length).toBe(3);
// angular
themeManager.expectTheme(0, {
number_of_blogs_expected: 0,
is_default_theme: false,
name: 'forest'});
// classic
themeManager.expectTheme(1, {
number_of_blogs_expected: 0,
is_default_theme: false,
name: 'Angular Based Theme'
.themes
.then((themes) => {
expect(themes.length).toBe(3);
// angular
themeManager.expectTheme(0, {
number_of_blogs_expected: 0,
is_default_theme: false,
name: 'forest'
});
// classic
themeManager.expectTheme(1, {
number_of_blogs_expected: 0,
is_default_theme: false,
name: 'Angular Based Theme'
});
// open a thumbnail
themeManager.openPreview(2);
// forest
themeManager.expectTheme(2, {
number_of_blogs_expected: 0,
is_default_theme: true,
name: 'Classic Theme'
});
});
// open a thumbnail
themeManager.openPreview(2);
// forest
themeManager.expectTheme(2, {
number_of_blogs_expected: 0,
is_default_theme: true,
name: 'Classic Theme'
});
});
});
it('can set a theme as default', function() {
it('can set a theme as default', () => {
themeManager.openThemesManager()
.setAsDefault(0)
.then(function() {
themeManager.expectTheme(2, {
number_of_blogs_expected: 0,
is_default_theme: false,
name: 'Classic Theme'
.setAsDefault(0)
.then(() => {
themeManager.expectTheme(2, {
number_of_blogs_expected: 0,
is_default_theme: false,
name: 'Classic Theme'
});
themeManager.expectTheme(1, {
number_of_blogs_expected: 0,
is_default_theme: false,
name: 'Angular Based Theme'
});
});
themeManager.expectTheme(1, {
number_of_blogs_expected: 0,
is_default_theme: false,
name: 'Angular Based Theme'
});
});
});
//it('can upload a new theme', function() {
// it('can upload a new theme', function() {
// themeManager.openThemesManager()

@@ -71,5 +67,5 @@ // .fileThemeElement.sendKeys(path.resolve(__dirname, './upload/dog-theme.zip'));

// });
//});
// });
//it('can remove a theme', function() {
// it('can remove a theme', function() {
// themeManager.openThemesManager()

@@ -85,17 +81,19 @@ // .themes

// });
//});
// });
it('can change theme settings', function() {
it('can change theme settings', () => {
themeManager.openThemesManager()
.themes
.then(() => themeManager.openSettingsForTheme(1))
.then(() => element(by.css('[name="postsPerPage"]')).clear().sendKeys('111'))
.then(() => themeManager.saveSettings())
.then(() => browser.waitForAngular())
.then(() => themeManager.openSettingsForTheme(1))
.then(() => {
return expect(element(by.css('[name="postsPerPage"]')).getAttribute('value'))
.toEqual('111');
});
//.then(function(themes) {
.themes
.then(() => themeManager.openSettingsForTheme(1))
.then(() => element(by.css('[name="postsPerPage"]'))
.clear()
.sendKeys('111')
)
.then(() => themeManager.saveSettings())
.then(() => browser.waitForAngular())
.then(() => themeManager.openSettingsForTheme(1))
.then(() => expect(element(by.css('[name="postsPerPage"]')).getAttribute('value'))
.toEqual('111')
);
// .then(function(themes) {
// themeManager.openSettingsForTheme(1);

@@ -107,4 +105,4 @@ // element(by.css('[name="postsPerPage"]')).clear().sendKeys('111');

// //expect(element(by.css('[name="postsPerPage"]')).getAttribute('value')).toEqual('111');
//});
// });
});
});
});

@@ -6,3 +6,3 @@ var path = require('path');

options: {
configFile: path.join(root, '.eslintrc.json'),
configFile: path.join(root, '.eslintrc.js'),
quiet: true

@@ -9,0 +9,0 @@ },

@@ -1,8 +0,8 @@

'use strict';
var path = require('path');
var makeConfig = require('../../webpack.config.js');
const path = require('path');
const makeConfig = require('../../webpack.config.js');
module.exports = function(grunt) {
var webpackConfig = makeConfig(grunt);
const webpackConfig = makeConfig(grunt);

@@ -12,3 +12,2 @@ return {

webpack: webpackConfig,
//publicPath: './dist',
port: 9000,

@@ -23,6 +22,4 @@ host: '0.0.0.0',

start: {
keepAlive: true,
webpack: {
devtool: 'eval',
debug: true,
devtool: 'source-map',
entry: {

@@ -48,4 +45,3 @@ app: ['webpack-dev-server/client?http://0.0.0.0:9000/'].concat(webpackConfig.entry.app)

},
devtool: 'eval',
debug: true
devtool: 'eval'
}

@@ -52,0 +48,0 @@ }

@@ -1,7 +0,8 @@

var webpack = require('webpack');
const webpack = require('webpack');
module.exports = function(grunt) {
'use strict';
var config = require('../../webpack.config.js')(grunt);
const config = require('../../webpack.config.js')(grunt);
return {
entry: 'webpack-dev-server/client?http://0.0.0.0:9000/',
options: config,

@@ -11,9 +12,9 @@ build: {

new webpack.DefinePlugin({
'process.env': {'NODE_ENV': JSON.stringify('production')}
'process.env': {NODE_ENV: JSON.stringify('production')}
}),
new webpack.optimize.DedupePlugin()
//new webpack.optimize.UglifyJsPlugin()
// new webpack.optimize.UglifyJsPlugin()
)
}
};
};
};

@@ -1,8 +0,8 @@

var path = require('path');
var webpack = require('webpack');
var lodash = require('lodash');
const path = require('path');
const webpack = require('webpack');
const lodash = require('lodash');
// makeConfig creates a new configuration file based on the passed options.
module.exports = function makeConfig(grunt) {
var appConfigPath = path.join(process.cwd(), 'superdesk.config.js');
let appConfigPath = path.join(process.cwd(), 'superdesk.config.js');

@@ -16,5 +16,4 @@ if (process.env.SUPERDESK_CONFIG) {

var sdConfig = lodash.defaultsDeep(require(appConfigPath)(grunt), getDefaults(grunt));
const sdConfig = lodash.defaultsDeep(require(appConfigPath)(grunt), getDefaults(grunt));
// shouldExclude returns true if the path p should be excluded from loaders

@@ -28,13 +27,18 @@ // such as 'babel' or 'eslint'. This is to avoid including node_modules into

}
// include only 'superdesk-core' and valid modules inside node_modules
let validModules = ['superdesk-core'].concat(sdConfig.apps);
const validModules = ['superdesk-core'].concat(sdConfig.apps);
return !validModules.some((app) => p.indexOf(app) > -1);
};
// isEmbedded will be true when the app is embedded into the main repo as a
// node module.
const isEmbedded = require('fs').existsSync('./node_modules/superdesk-core');
return {
cache: true,
debug: true,
entry: {
app: ['app/scripts/index.js']
app: 'app/scripts/index.js'
},
output: {

@@ -45,15 +49,13 @@ path: path.join(process.cwd(), 'dist'),

},
stats: {
errorDetails: true,
},
plugins: [
new webpack.ProvidePlugin({
'$': 'jquery',
$: 'jquery',
'window.$': 'jquery',
'jQuery': 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'moment': 'moment',
moment: 'moment',
// MediumEditor needs to be globally available, because
// its plugins will not be able to find it otherwise.
'MediumEditor': 'medium-editor'
MediumEditor: 'medium-editor'
}),

@@ -64,6 +66,6 @@ new webpack.DefinePlugin({

],
resolve: {
root: [
modules: [
__dirname,
//path.join(__dirname, '/scripts'),
path.join(__dirname, '/app'),

@@ -74,7 +76,7 @@ path.join(__dirname, '/app/scripts'),

path.join(__dirname, '/node_modules/superdesk-core/styles/sass'),
path.join(__dirname, '/node_modules/superdesk-core')
path.join(__dirname, '/node_modules/superdesk-core'),
'node_modules'
],
modulesDirectories: [ 'node_modules' ],
alias: {
//'moment-timezone': 'moment-timezone/builds/moment-timezone-with-data-2010-2020',
// 'moment-timezone': 'moment-timezone/builds/moment-timezone-with-data-2010-2020',
'rangy-saverestore': 'rangy/lib/rangy-selectionsaverestore',

@@ -84,16 +86,30 @@ 'angular-embedly': 'angular-embedly/em-minified/angular-embedly.min',

'external-apps': path.join(process.cwd(), 'dist', 'app-importer.generated.js'),
'i18n': path.join(process.cwd(), 'dist', 'locale.generated.js'),
i18n: path.join(process.cwd(), 'dist', 'locale.generated.js'),
// ensure that react is loaded only once (3rd party apps can load more...)
'react': path.resolve('./node_modules/react')
react: path.resolve('./node_modules/react')
},
extensions: ['', '.js', '.jsx']
extensions: ['.js', '.jsx']
},
module: {
loaders: [
rules: [
{
enforce: 'pre',
test: /\.jsx?$/,
loader: 'eslint-loader',
// superdesk apps handle their own linter
exclude: (p) => p.indexOf('node_modules') !== -1 || sdConfig.apps && sdConfig.apps.some(
(app) => p.indexOf(app) > -1
),
options: {
configFile: './.eslintrc.js',
ignorePath: './.eslintignore'
}
},
{
test: /\.jsx?$/,
exclude: shouldExclude,
loader: 'babel',
query: {
loader: 'babel-loader',
options: {
cacheDirectory: true,

@@ -106,13 +122,27 @@ presets: ['es2015', 'react'],

test: /\.html$/,
loader: 'ngtemplate!html'
use: [
'html-loader'
]
},
{
test: /\.css/,
loader: 'style!css'
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader',
]
},
{
test: /\.scss$/,
loader: 'style!css!sass'
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.json$/,
use: ['json-loader']
},
{
test: /\.(png|gif|jpeg|jpg|woff|woff2|eot|ttf|svg)(\?.*$|$)/,

@@ -122,4 +152,7 @@ loader: 'file-loader'

{
test: /\.json$/,
loader: 'json-loader'
test: /\.ng1$/,
use: [
'ngtemplate-loader',
'html-loader'
]
}

@@ -131,5 +164,6 @@ ]

// getDefaults returns the default configuration for the app
function getDefaults(grunt) {
var version;
let version;

@@ -142,56 +176,70 @@ try {

return {
return Object.assign(
{
// application version
version: version || grunt.file.readJSON(path.join(__dirname, 'package.json')).version,
version: version || grunt.file.readJSON(path.join(__dirname, 'package.json')).version,
// raven settings
raven: {
dsn: process.env.SUPERDESK_RAVEN_DSN || ''
},
// iframely settings
iframely: {
key: process.env.IFRAMELY_KEY || ''
},
// backend server URLs configuration
server: {
url: grunt.option('server') || process.env.SUPERDESK_URL || 'http://localhost:5000/api',
ws: grunt.option('ws') || process.env.SUPERDESK_WS_URL || 'ws://0.0.0.0:5100'
},
// google settings
google: {
key: process.env.GOOGLE_KEY || ''
},
// iframely settings
iframely: {
key: process.env.IFRAMELY_KEY || ''
},
// settings for various analytics
analytics: {
piwik: {
url: process.env.PIWIK_URL || '',
id: process.env.PIWIK_SITE_ID || ''
},
ga: {
id: process.env.TRACKING_ID || ''
// settings for various analytics
analytics: {
piwik: {
url: process.env.PIWIK_URL || '',
id: process.env.PIWIK_SITE_ID || ''
},
ga: {
id: process.env.TRACKING_ID || ''
}
}
},
configServer(grunt),
configApp(grunt),
configLiveblog(grunt)
);
}
const configServer = (grunt) => ({
// raven settings
raven: {
dsn: process.env.SUPERDESK_RAVEN_DSN || ''
},
// editor configuration
editor: {
// if true, the editor will not have a toolbar
disableEditorToolbar: grunt.option('disableEditorToolbar')
},
// backend server URLs configuration
server: {
url: grunt.option('server') || process.env.SUPERDESK_URL || 'http://localhost:5000/api',
ws: grunt.option('ws') || process.env.SUPERDESK_WS_URL || 'ws://0.0.0.0:5100'
},
});
// if environment name is not set
isTestEnvironment: !!grunt.option('environmentName'),
const configApp = (grunt) => ({
// editor configuration
editor: {
// if true, the editor will not have a toolbar
disableEditorToolbar: grunt.option('disableEditorToolbar')
},
// environment name
environmentName: grunt.option('environmentName'),
// default timezone for the app
defaultTimezone: grunt.option('defaultTimezone') || 'Europe/London',
// route to be redirected to from '/'
defaultRoute: '/liveblog',
// model date and time formats
model: {
dateformat: 'DD/MM/YYYY',
timeformat: 'HH:mm:ss'
},
// override language translations
langOverride: {},
// view formats for datepickers/timepickers
view: {
dateformat: process.env.VIEW_DATE_FORMAT || 'DD/MM/YYYY',
timeformat: process.env.VIEW_TIME_FORMAT || 'HH:mm'
},
// app features
features: {
// tansa spellchecker
useTansaProofing: false
},
// if environment name is not set
isTestEnvironment: !!grunt.option('environmentName') || !!process.env.SUPERDESK_ENVIRONMENT,

@@ -217,27 +265,63 @@ debug: grunt.option('debug-mode') || false,

maxContentLength: process.env.MAX_CONTENT_LENGTH || 8 * 1024 * 1024,
// override language translations
langOverride: {},
// default timezone for the app
defaultTimezone: grunt.option('defaultTimezone') || 'Europe/London',
// app features
features: {
// tansa spellchecker
useTansaProofing: false,
// model date and time formats
model: {
dateformat: 'DD/MM/YYYY',
timeformat: 'HH:mm:ss'
},
// replace editor2
onlyEditor3: false,
// view formats for datepickers/timepickers
view: {
dateformat: process.env.VIEW_DATE_FORMAT || 'DD/MM/YYYY',
timeformat: process.env.VIEW_TIME_FORMAT || 'HH:mm'
},
// enable highlights (commenting and annotations) in editor3
editorHighlights: false
},
system: {
dateTimeTZ: 'YYYY-MM-DD[T]HH:mm:ssZ'
},
// tansa config
tansa: {
profile: {
nb: 1,
nn: 2
}
},
// You might think this empty object is useless.
// That would be a terrible mistake to make.
validatorMediaMetadata: {}
};
// workspace defaults
workspace: {
ingest: false,
content: false,
tasks: false,
analytics: false
}
}
);
const configLiveblog = (grunt) => ({
// route to be redirected to from '/'
defaultRoute: '/liveblog',
system: {
dateTimeTZ: 'YYYY-MM-DD[T]HH:mm:ssZ'
},
embedly: {
key: grunt.option('embedly-key') || process.env.EMBEDLY_KEY || ''
},
facebookAppId: grunt.option('facebook-appid') || process.env.FACEBOOK_APP_ID || '',
syndication: process.env.SYNDICATION || false,
marketplace: process.env.MARKETPLACE || false,
themeCreationRestrictions: {team: 3},
excludedTheme: 'angular',
assignableUsers: {
solo: 2,
team: 4
},
subscriptionLevel: process.env.SUBSCRIPTION_LEVEL || '',
blogCreationRestrictions: {
solo: 1,
team: 3
},
maxContentLength: process.env.MAX_CONTENT_LENGTH || 8 * 1024 * 1024,
// You might think this empty object is useless.
// That would be a terrible mistake to make.
validatorMediaMetadata: {}
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc