PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/core/js/admin-panel/page.js

https://gitlab.com/GeekSir/Cosmo
JavaScript | 448 lines | 313 code | 60 blank | 75 comment | 40 complexity | bd26b7dcbf82da0d6ccce8a78b3e7041 MD5 | raw file
  1. /**************************************************
  2. * Page Controller *
  3. * Make new pages and edit old pages. *
  4. **************************************************/
  5. angular.module('cosmo').controller('pageCtrl', ['$scope', 'REST', '$location', 'Page', '$rootScope', '$routeParams', '$upload', 'Users', function($scope, REST, $location, Page, $rootScope, $routeParams, $upload, Users){
  6. // Initialize variables
  7. $scope.page = {
  8. id: Page.id,
  9. title: Page.title,
  10. description: Page.description,
  11. url: Page.url,
  12. publish: Page.publish,
  13. scheduleDate: Page.scheduleDate,
  14. tags: Page.tags,
  15. type: Page.type,
  16. themePages: []
  17. };
  18. // Set the date to today if no date was set
  19. if(!$scope.page.scheduleDate || $location.path() === '/new')
  20. $scope.page.scheduleDate = new Date(); // Math.round(+new Date().getTime()/1000); Depreciate?
  21. // Initialize schedule date - Depreciate?
  22. var date = new Date($scope.page.scheduleDate * 1000);
  23. var hours = date.getHours() > 12 ? date.getHours() - 12 : date.getHours();
  24. var ampm = date.getHours() > 12 ? 'PM' : 'AM';
  25. var formattedDate = date.getMonth() + 1 +'/'+ date.getDate() +'/'+ date.getFullYear() +' '+ hours +':'+ date.getMinutes() +' '+ ampm;
  26. // $scope.page.scheduleDate = formattedDate;
  27. // Get the pages available to this theme
  28. $scope.page.themePages = Page.themePages;
  29. // Initialize the page type
  30. if(Page.type)
  31. $scope.page.type = Page.type;
  32. else
  33. $scope.page.type = $scope.page.themePages[0];
  34. // todo: Save Page.extras save locally too
  35. // Check if there's an unsaved version from a previous session
  36. var elements = ['title', 'description', 'publish', 'scheduleDate', 'header', 'subheader', 'body', 'url'];
  37. if($location.path() !== '/new'){ // Don't apply this to new pages
  38. angular.forEach(elements, function(value){
  39. if(localStorage.getItem($routeParams.url + value) !== Page[value] && localStorage.getItem($routeParams.url + value) !== 'null')
  40. $scope.newerVersion = true;
  41. });
  42. }
  43. // Revert to the previously saved version
  44. $scope.localVersion = function(){
  45. var elements = ['title', 'description', 'publish', 'scheduleDate', 'header', 'subheader', 'body', 'url'];
  46. angular.forEach(elements, function(value){
  47. // Restore item
  48. if(localStorage.getItem($routeParams.url + value) !== 'null')
  49. Page[value] = localStorage.getItem($routeParams.url + value);
  50. // Clear item from storage
  51. localStorage.setItem($routeParams.url + value, null);
  52. });
  53. $scope.newerVersion = false;
  54. $rootScope.$broadcast('contentGet');
  55. };
  56. // Delete newer version
  57. $scope.deleteNewerVersion = function(){
  58. var elements = ['title', 'description', 'publish', 'scheduleDate', 'header', 'subheader', 'body', 'url'];
  59. angular.forEach(elements, function(value){
  60. localStorage.setItem($routeParams.url + value, null);
  61. });
  62. $scope.newerVersion = false;
  63. };
  64. // Delete the page
  65. $scope.deletePage = function(){
  66. // Delete the page
  67. REST.content.delete({ contentID: $scope.page.id }, function(data){
  68. // Success message
  69. $translate('deleted').then(function(translatedText){
  70. $rootScope.$broadcast('notify', {message: translatedText});
  71. });
  72. });
  73. // Delete all revisions of this page
  74. REST.contentRevisions.delete({ contentID: $scope.page.id });
  75. // Delte all extra revisions
  76. REST.contentRevisionsExtras.delete({ contentID: $scope.page.id });
  77. // Delete all extras from this page
  78. REST.contentExtras.delete({ contentID: $scope.page.id });
  79. // Delete all tags for this page
  80. REST.contentTags.delete({ contentID: $scope.page.id });
  81. // Redirect to the default new page
  82. $location.path('new');
  83. };
  84. // Watch for page change
  85. var updatePage = function() {
  86. $scope.page.title = Page.title;
  87. $scope.page.description = Page.description;
  88. $scope.page.url = Page.url;
  89. $scope.page.type = Page.type;
  90. $scope.page.tags = Page.tags;
  91. };
  92. updatePage();
  93. $scope.$on('contentGet', function(){
  94. updatePage();
  95. });
  96. // Update the page type
  97. $scope.updatePageType = function(){
  98. Page.type = $scope.page.type;
  99. $rootScope.$broadcast('settingsGet');
  100. };
  101. // Auto-generate the url from the title
  102. $scope.titleChange = function(){
  103. // Log changes to the Page object
  104. Page.title = $scope.page.title;
  105. // Only auto-generate urls for new pages
  106. if($scope.page.url === '/new' || $scope.page.url === 'new' || !$scope.page.url)
  107. $scope.autoURL = true;
  108. if($scope.autoURL){
  109. // Change spaces to hyphens, convert to lowercase, and remove punctuation
  110. $scope.page.url = $scope.page.title.toLowerCase().replace(/ /g, '-').replace(/[\.,\/#!$%\^&\*;:{}=_'~()\?]/g, '');
  111. Page.url = $scope.page.url;
  112. }
  113. };
  114. // Save changes to the description
  115. $scope.descriptionChange = function(){
  116. Page.description = $scope.page.description;
  117. };
  118. // Save changes to the url
  119. $scope.urlChange = function(){
  120. Page.url = $scope.page.url;
  121. };
  122. // Update page variables when they are changed
  123. $scope.saveLocal = function(){
  124. Page.title = $scope.page.title;
  125. Page.description = $scope.page.description;
  126. Page.url = $scope.page.url;
  127. Page.type = $scope.page.type;
  128. // Save to local Storage
  129. localStorage.setItem($routeParams.url + 'title', Page.title);
  130. localStorage.setItem($routeParams.url + 'description', Page.description);
  131. localStorage.setItem($routeParams.url + 'url', Page.url);
  132. localStorage.setItem($routeParams.url + 'publish', Page.publish);
  133. localStorage.setItem($routeParams.url + 'scheduleDate', Page.scheduleDate);
  134. localStorage.setItem($routeParams.url + 'type', Page.type);
  135. };
  136. // Autocomplete tags
  137. $scope.autocompleteTags = function(){
  138. var tag = $scope.page.tags[$scope.page.tags.length - 1];
  139. if(tag){
  140. REST.contentTags.query({ tag: tag }, function(data){
  141. $scope.page.suggestions = data;
  142. }, function(){ // no tag found
  143. $scope.page.suggestions = [];
  144. });
  145. } else
  146. $scope.page.suggestions = [];
  147. };
  148. // Select tag from autocomplete
  149. $scope.selectSuggestion = function(tag){
  150. var tags = angular.copy($scope.page.tags);
  151. tags[tags.length - 1] = tag;
  152. tags[tags.length] = '';
  153. $scope.page.tags = tags;
  154. $scope.page.suggestions = [];
  155. };
  156. // Save the page
  157. $scope.savePage = function(duplicate){
  158. // Check for duplicate URL
  159. if(duplicate && $scope.page.url === $location.path()){
  160. $translate('page_different_url').then(function(translatedText){
  161. $rootScope.$broadcast('notify', {message: translatedText, classes: 'alert-error'});
  162. });
  163. return;
  164. }
  165. // Make sure there is a page type
  166. if(!$scope.page.type){
  167. $translate('page_no_type_selected').then(function(translatedText){
  168. $rootScope.$broadcast('notify', {message: translatedText, classes: 'alert-error'});
  169. });
  170. return;
  171. }
  172. // If there's no custom title tag, use the header
  173. if($scope.page.title){
  174. if($scope.page.title.length === 0)
  175. $scope.page.title = Page.header;
  176. }
  177. // If there's no custom url, throw an error
  178. if($scope.page.url.length === 0 || $scope.page.url === 'new'){
  179. $translate('page_no_url').then(function(translatedText){
  180. $rootScope.$broadcast('notify', { message: translatedText, classes: 'alert-error' });
  181. });
  182. return;
  183. }
  184. // Get the scheduled date to publish
  185. var scheduleDate;
  186. if($scope.page.publish === 'Y' && Page.publish === 'Y') // If this was already published, don't update the published date
  187. scheduleDate = Page.scheduleDate;
  188. else if($scope.page.publish === 'Y') // If publishing now, set the publish date to the current time
  189. scheduleDate = Math.round(+new Date().getTime()/1000);
  190. else if($scope.page.publish === 'schedule'){
  191. scheduleDate = Date.parse($scope.page.scheduleDate).getTime()/1000;
  192. // Check if this is back dated
  193. if(Date.parse($scope.page.scheduleDate).getTime() < Math.round(+new Date().getTime()))
  194. $scope.page.publish = 'Y';
  195. else
  196. $scope.page.publish = 'N';
  197. }
  198. // Get the featured image URL
  199. if(Page.extras.featured)
  200. var featured = Page.extras.featured.src;
  201. else
  202. var featured = null;
  203. // Create a new page or a duplicate
  204. if($location.path() === '/new' || duplicate){
  205. // Save content
  206. REST.content.save({
  207. title: $scope.page.title,
  208. description: $scope.page.description,
  209. header: Page.header,
  210. subheader: Page.subheader,
  211. featured: featured,
  212. body: Page.body,
  213. url: $scope.page.url,
  214. type: $scope.page.type,
  215. published: $scope.page.publish,
  216. published_date: scheduleDate,
  217. author: Users.id
  218. }, newPagePromise, function(){ // Error
  219. $translate('page_error_saving').then(function(translatedText){
  220. $rootScope.$broadcast('notify', {message: translatedText, classes: 'alert-error'});
  221. });
  222. });
  223. } else { // Update existing page
  224. var revisionID;
  225. // Update the page
  226. REST.content.update({
  227. contentID: $scope.page.id,
  228. title: $scope.page.title,
  229. description: $scope.page.description,
  230. header: Page.header,
  231. subheader: Page.subheader,
  232. featured: featured,
  233. body: Page.body,
  234. url: $scope.page.url,
  235. type: $scope.page.type,
  236. published: $scope.page.publish,
  237. published_date: scheduleDate,
  238. author: Users.id
  239. }, updatePagePromise, function(data){ // Error
  240. $translate('page_error_updating').then(function(translatedText){
  241. $rootScope.$broadcast('notify', {message: translatedText, classes: 'alert-error'});
  242. });
  243. });
  244. }
  245. // Update the page after a new page was saved
  246. function newPagePromise(data){
  247. var contentID = data.id;
  248. // Reset variables to edit page
  249. $scope.page.id = contentID;
  250. $scope.autoURL = false;
  251. // Save new tags
  252. if($scope.page.tags){
  253. angular.forEach($scope.page.tags, function(value){
  254. REST.contentTags.save({ contentID: contentID, tag: value });
  255. });
  256. }
  257. // Save page as a revision
  258. REST.contentRevisions.save({
  259. contentID: contentID,
  260. title: $scope.page.title,
  261. description: $scope.page.description,
  262. header: Page.header,
  263. subheader: Page.subheader,
  264. featured: featured,
  265. body: Page.body,
  266. url: $scope.page.url,
  267. type: $scope.page.type,
  268. published: $scope.page.publish,
  269. published_date: scheduleDate,
  270. author: Users.id
  271. }, saveRevisionPromise);
  272. }
  273. // Update the page after saving a page revision
  274. function saveRevisionPromise(data){
  275. revisionID = data.id;
  276. var extrasCounter = {
  277. i: 1
  278. };
  279. // Save additional data if there is any
  280. if(Object.keys(Page.extras).length === 0){
  281. // Success message
  282. $translate('saved').then(function(translatedText){
  283. $rootScope.$broadcast('notify', {message: translatedText});
  284. });
  285. // Redirect to new page
  286. $location.path($scope.page.url);
  287. } else {
  288. for(var key in Page.extras){
  289. // Stringify arrays and objects
  290. if(typeof Page.extras[key] === 'object')
  291. Page.extras[key] = angular.toJson(Page.extras[key]);
  292. // Save extra
  293. REST.contentExtras.save({
  294. contentID: contentID,
  295. name: key,
  296. extra: Page.extras[key]
  297. }, saveExtrasPromise, saveExtrasPromise);
  298. // Save extra to revisions
  299. REST.contentRevisionsExtras.save({
  300. revisionID: revisionID,
  301. contentID: contentID,
  302. name: key,
  303. extra: Page.extras[key]
  304. });
  305. };
  306. }
  307. $translate('page_created').then(function(translatedText){
  308. $rootScope.$broadcast('notify', {message: translatedText});
  309. });
  310. }
  311. // Notify the user after saving the last extra
  312. function saveExtrasPromise(){
  313. // Wait for the last extra to be saved, then redirect the user
  314. if(extrasCounter.i === Object.keys(Page.extras).length){
  315. // Success message
  316. $translate('page_created').then(function(translatedText){
  317. $rootScope.$broadcast('notify', {message: translatedText});
  318. });
  319. // Redirect to new page
  320. $location.path($scope.page.url);
  321. } else
  322. extrasCounter.i++;
  323. }
  324. // Update the page after it's been saved
  325. function updatePagePromise(data){
  326. // Delete old tags
  327. REST.contentTags.delete({ contentID: $scope.page.id }, deleteTagsPromise);
  328. // Save page as a revision
  329. REST.contentRevisions.save({
  330. contentID: $scope.page.id,
  331. title: $scope.page.title,
  332. description: $scope.page.description,
  333. header: Page.header,
  334. subheader: Page.subheader,
  335. featured: featured,
  336. body: Page.body,
  337. url: $scope.page.url,
  338. type: $scope.page.type,
  339. published: $scope.page.publish,
  340. published_date: $scope.page.scheduleDate,
  341. author: Users.id
  342. }, savePageRevisionPromise);
  343. }
  344. // Callback for saving a page revision
  345. function savePageRevisionPromise(data){
  346. revisionID = data.id;
  347. // Delete old extras
  348. REST.contentExtras.delete({ contentID: $scope.page.id }, deleteExtrasPromise);
  349. }
  350. // Callback after tags are deleted
  351. function deleteTagsPromise(){
  352. // Save new tags
  353. angular.forEach($scope.page.tags, function(value){
  354. REST.contentTags.save({ contentID: $scope.page.id, tag: value });
  355. });
  356. }
  357. // Callback after deleting extras
  358. function deleteExtrasPromise(){
  359. // Save additional data
  360. for (var key in Page.extras){
  361. if (Page.extras.hasOwnProperty(key)){
  362. // Stringify arrays and objects
  363. if(typeof Page.extras[key] === 'object')
  364. Page.extras[key] = angular.toJson(Page.extras[key]);
  365. // Save new extra
  366. REST.contentExtras.save({
  367. contentID: $scope.page.id,
  368. name: key,
  369. extra: Page.extras[key]
  370. }, saveExtrasPromise, saveExtrasPromise);
  371. // Save new extra to revisions
  372. REST.contentRevisionsExtras.save({
  373. revisionID: revisionID,
  374. contentID: $scope.page.id,
  375. name: key,
  376. extra: Page.extras[key]
  377. });
  378. }
  379. }
  380. // If there were no extras, notify right away
  381. if(!Page.extras.length) {
  382. $translate('page_updated').then(function(translatedText){
  383. $rootScope.$broadcast('notify', {message: translatedText});
  384. });
  385. }
  386. }
  387. };
  388. }]);