liveblog-client
Advanced tools
Comparing version 3.3.7 to 3.4.0
{ | ||
"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(/&/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.,@?^=%&:\/~+#-]*[\\w@?^=%&\/~+#-])?'; | ||
var uriRegx = '(https?:)?\\/\\/[\\w-]+(\\.[\\w-]+)+([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?'; | ||
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', |
146
package.json
{ | ||
"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
GitHub dependency
Supply chain riskContains a dependency which resolves to a GitHub URL. Dependencies fetched from GitHub specifiers are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 4 instances in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 3 instances in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
GitHub dependency
Supply chain riskContains a dependency which resolves to a GitHub URL. Dependencies fetched from GitHub specifiers are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 3 instances in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 3 instances in 1 package
1576904
34
288
13138
59
8
29
8
+ Addedsanitize-html@^1.18.2
+ Addedangular@1.6.9(transitive)
+ Addedangular-animate@1.6.1(transitive)
+ Addedangular-contenteditable@0.3.9(transitive)
+ Addedangular-gettext@2.3.10(transitive)
+ Addedangular-messages@1.6.6(transitive)
+ Addedangular-mocks@1.6.9(transitive)
+ Addedangular-moment@1.2.0(transitive)
+ Addedangular-resource@1.6.6(transitive)
+ Addedangular-route@1.6.9(transitive)
+ Addedangular-vs-repeat@1.1.7(transitive)
+ Addeddom-serializer@1.4.1(transitive)
+ Addeddomelementtype@2.3.0(transitive)
+ Addeddomhandler@3.3.04.3.1(transitive)
+ Addeddomutils@2.8.0(transitive)
+ Addedentities@2.2.0(transitive)
+ Addedhtmlparser2@4.1.0(transitive)
+ Addedjquery@3.3.1(transitive)
+ Addedjquery-jcrop@0.9.13(transitive)
+ Addedlodash@4.17.5(transitive)
+ Addedmedium-editor-tables@0.6.1(transitive)
+ Addedmoment@2.20.1(transitive)
+ Addedparse-srcset@1.0.2(transitive)
+ Addedpicocolors@0.2.1(transitive)
+ Addedpostcss@7.0.39(transitive)
+ Addedrangy@1.3.0(transitive)
+ Addedraven-js@3.22.3(transitive)
+ Addedsanitize-html@1.27.5(transitive)
+ Addedsource-map@0.6.1(transitive)
- Removedangular-bootstrap-npm@jusopi/angular-bootstrap-npm#0.13.1
- Removedbootstrap@^3.1.1
- Removedangular@1.8.3(transitive)
- Removedangular-animate@1.8.3(transitive)
- Removedangular-contenteditable@0.0.2(transitive)
- Removedangular-embed@2.1.1(transitive)
- Removedangular-gettext@2.4.2(transitive)
- Removedangular-messages@1.8.3(transitive)
- Removedangular-mocks@1.8.3(transitive)
- Removedangular-moment@1.3.0(transitive)
- Removedangular-resource@1.8.3(transitive)
- Removedangular-route@1.8.3(transitive)
- Removedangular-vs-repeat@1.1.11(transitive)
- Removedbootstrap@3.4.1(transitive)
- Removedeventable@0.0.0(transitive)
- Removedjquery@2.2.4(transitive)
- Removedjquery-jcrop@0.9.15(transitive)
- Removedmedium-editor-tables@0.5.3(transitive)
- Removedmoment@2.19.3(transitive)
- Removedrangy@1.3.1(transitive)
- Removedraven-js@3.27.2(transitive)
Updatedadblock-detect@1.0.5
Updatedangular@1.6.9
Updatedangular-animate@1.6.1
Updatedangular-gettext@2.3.10
Updatedangular-messages@1.6.6
Updatedangular-mocks@1.6.9
Updatedangular-moment@1.2.0
Updatedangular-resource@1.6.6
Updatedangular-route@1.6.9
Updatedangular-vs-repeat@1.1.7
Updatedgridster@0.5.6
Updatedjquery@3.3.1
Updatedjquery-jcrop@0.9.13
Updatedlodash@4.17.5
Updatedlodash.sortbyorder@3.4.4
Updatedlr-infinite-scroll@1.0.0
Updatedmedium-editor@5.23.3
Updatedmedium-editor-tables@0.6.1
Updatedment.io@0.9.23
Updatedmoment@2.20.1
Updatedng-file-upload@12.2.13
Updatedrangy@1.3.0
Updatedraven-js@3.22.3
Updatedsuperdesk-core@github:eos87/superdesk-client-core#v1.17.0-liveblog