1 /* article-editor.js */
8 articleEditor.init = function init () {
9 if (this._initialized) { return; }
13 // only properties of editor will be send when preview/post
21 comment_status: "enabled",
40 primaryTopicIconURL: "",
49 default: function () {return new Content();},
51 contentType: { type: String, required: true },
52 contentId: { type: Number, dafault: 0 },
53 sourceType: { type: String },
54 sourceId: { type: Number, default: 0 },
55 csrfToken: { type: String },
62 'editor.intro_text': function watchIntrotext(val, oldVal) {
63 this.item.intro_text = (val.length > 0) ? _quoteHtml(val) : "";
65 'editor.body_text': function watchBodytext(val, oldVal) {
66 this.item.body_text = (val.length > 0) ? _quoteHtml(val) : "";
68 'editor.title': function watchTitle(val, oldVal) {
69 this.item.title = (val.length > 0) ? _quoteTitle(val) : "";
71 'editor.url': function watchURL(val, oldVal) {
72 this.item.url = (val.length > 0) ? val : "";
74 'editor.create_time': function watchCreatetime(val, oldVal) {
75 this.item.time_string = newslash.util.formatToLocalDateTime(new Date(val));
77 'editor.author': function watchAuthor(val, oldVal) {
78 this.item.author = val;
80 'editor.dept': function watchDept(val, oldVal) {
83 'editor.tags_string': _updateTopics,
86 function _quoteHtml(html) {
87 return newslash.util.quoteHtml(html, siteConfig.editorConfig.allowed_tags);
90 function _quoteTitle(html) {
91 return newslash.util.quoteTitle(html, {});
101 * methods and relative private functions
104 showPreview: _showPreview,
106 leavePreview: function leavePreview(event) {
107 this.mode = "editing";
108 this.item.intro_text = _quoteHtml(this.editor.intro_text);
109 this.item.body_text = _quoteHtml(this.editor.body_text);
110 this.item.title = _quoteTitle(this.editor.title);
112 startEdit: function startEdit() {
113 _startEdit.call(this);
115 cancelEdit: function cancelEdit() {
116 for (k in this.originalItem) {
117 this.item[k] = this.originalItem[k];
119 this.mode = "show_all";
121 updateTopics: _updateTopics,
122 topicIconURL: function topicIconURL(topic) {
123 return newslash.util.topicIconURL(topic);
125 updatePrimaryTopicIconURL: function updatePrimaryTopicIconURL() {
126 if (this.item.primary_topic) {
127 this.primaryTopicIconURL = newslash.util.topicIconURL(this.item.primary_topic.keyword);
130 this.primaryTopicIconURL = "";
135 function _showPreview(event) {
136 var postData = _preparePostData.call(this, "preview");
138 if (this.contentType == "journal") {
139 newslash.previewJournal(postData).then(
140 (resp) => { // success
142 this.item.title = resp.item.title;
143 this.item.intro_text = resp.item.intro_text;
144 this.item.url = this.editor.url;
145 this.item.primary_topic = resp.item.topic;
146 this.updatePrimaryTopicIconURL();
148 this.mode = "preview";
152 this.message = resp.message;
159 if (this.contentType == "story") {
160 newslash.previewStory(postData).then(
161 (resp) => { // success
163 this.previewTitle = resp.item.title;
164 this.previewIntro = resp.item.intro_text;
165 this.item.url = this.editor.url;
166 this.item.primary_topic = resp.item.topic;
167 this.updatePrimaryTopicIconURL();
169 this.mode = "preview";
173 this.message = resp.message;
180 if (this.contentType == "submission") {
181 newslash.previewSubmission(postData).then(
182 (resp) => { // success
184 this.item.title = resp.item.title;
185 this.item.intro_text = resp.item.intro_text;
186 this.item.url = this.editor.url;
187 this.item.primary_topic = resp.item.topic;
188 this.updatePrimaryTopicIconURL();
190 this.mode = "preview";
194 this.message = resp.message;
201 console.log("no contentType defined!");
204 function _postItem(event) {
205 this.mode = "posting";
206 var postData = _preparePostData.call(this, "post");
209 if (this.contentType == "journal") {
210 postData.csrf_token = this.csrfToken;
211 newslash.postJournal(postData).then(
212 (resp) => { // success
215 var type = resp.type;
216 var url = '/' + type + '/' + id;
220 this.createdUrl = url;
221 this.item.subid = id;
224 this.mode = "posted";
227 this.message = resp.message;
228 this.mode = "preview";
235 if (this.contentType == "submission") {
236 postData.csrf_token = this.csrfToken;
237 newslash.postSubmission(postData).then(
238 (resp) => { // success
241 var type = resp.type;
242 var url = '/' + type + '/' + id;
246 this.createdUrl = url;
247 this.item.subid = id;
250 this.mode = "posted";
253 this.message = resp.message;
254 this.mode = "preview";
261 if (this.contentType == "story") {
262 postData.csrf_token = this.csrfToken;
263 newslash.postStory(postData).then(
264 (resp) => { // success
267 var type = resp.type;
268 var url = '/' + type + '/' + id;
272 this.createdUrl = url;
273 this.item.subid = id;
276 this.mode = "posted";
279 this.message = resp.message;
280 this.mode = "preview";
288 function _preparePostData(action) {
289 action = action || "preview";
293 postData.action = action;
295 if (articleEditor.recaptchaToken) {
296 postData.recaptcha_token = articleEditor.recaptchaToken;
299 Object.keys(this.editor).forEach(k => {
300 postData.item[k] = this.editor[k];
304 if (this.contentType == "story") {
305 if (this.sourceType == "submission") {
306 postData.item.submission_id = "this.sourceId";
307 } else if (this.sourceType == "journal") {
308 postData.item.journal_id = "this.sourceId";
315 function _updateTopics() {
316 var tags = this.editor.tags_string.split(" ");
317 this.currentTopics.splice(0);
318 if (tags.length == 0) {
322 tags.forEach((tag) => {
323 if (siteConfig.topics[tag]) {
324 var keyword = siteConfig.topics[tag].keyword;
325 if (!pushed[keyword]) {
326 this.currentTopics.push(keyword);
334 * created and related private functions
337 _startEdit.call(this);
340 function _startEdit() {
341 this.mode = "editing";
342 // backup original item
343 // copy item property to c (component)
344 this.originalItem = {};
345 for (k in this.$data.item) {
347 this.originalItem[k] = this.item[k];
352 if (this.contentType == "journal") {
353 if (this.contentId) {
354 _loadJournal.call(this);
356 // create new journal
357 this.mode = "editing";
362 if (this.contentType == "story") {
363 if (this.contentId) {
364 _loadStory.call(this);
366 if (this.sourceType == "submission") {
367 _loadStoryFromSubmission.call(this);
368 } else if (this.sourceType == "journal") {
369 _loadStoryFromJournal.call(this);
372 _createNewStory.call(this);
378 if (this.contentType == "submission") {
379 // create new submission
380 this.mode = "editing";
386 function _loadJournal() {
387 newslash.getJournal(this.contentId).then(
389 var item = resp.journal;
391 this.editor.title = item.title;
392 this.editor.intro_text = item.article;
393 this.editor.tags_string = item.tags_string || "";
394 this.editor.comment_status = item.comment_status;
395 this.editor.formatter = item.formatter;
396 this.editor.posttype = item.posttype;
397 this.editor.id = item.id;
400 if (this.editor.formatter == "legacy") {
401 this.enableAutoPreview = 0;
405 this.updatePrimaryTopicIconURL();
406 this.mode = "editing";
409 this.message = resp.body.message;
414 function _createNewStory() {
416 this.editor.createtime = newslash.util.formatToLocalISOString(new Date());
417 this.editor.author = user.nickname;
420 this.mode = "editing";
424 function _prepareStory(item) {
425 for (var k in this.editor) {
426 if (item[k] !== undefined) {
427 this.editor[k] = item[k];
430 // convert tags to tags_string
432 var tagnames = item.tags.map(tag => tag.tagname);
433 this.editor.tags_string = tagnames.join(" ");
437 // TODO: related stories
438 // convert public to display
439 this.editor.display = (item.public == "yes");
440 if (item.create_time) {
441 this.editor.createtime = newslash.util.formatToLocalISOString(newslash.util.decodeMySQLDateTime(item.create_time));
443 this.editor.createtime = newslash.util.formatToLocalISOString(new Date());
445 this.editor.id = item.stoid;
446 this.editor.author = user.nickname;
449 function _loadStory() {
450 newslash.admin.getStory(this.contentId).then(
452 _prepareStory.call(this, resp.item);
455 this.message = fail.body.message;
456 console.log("story fetch failed");
461 function _loadStoryFromSubmission() {
462 newslash.admin.getStoryFromSubmission(this.sourceId).then(
464 _prepareStory.call(this, resp.item);
467 this.message = fail.body.message;
468 console.log("story fetch failed");
473 function _loadStoryFromJournal() {
474 newslash.admin.getStoryFromJournal(this.sourceId).then(
476 _prepareStory.call(this, resp.item);
479 this.message = fail.body.message;
480 console.log("story fetch failed");
489 this._component = Vue.component('article-editor', {
490 template: '#article-editor-template',
499 this._initialized = 1;
506 articleEditor.ArticleEditor = class ArticleEditor {
507 constructor(targetElement) {
508 if (!targetElement) {
509 console.error('error in ArticleEditor(): no element given');
512 this.vm = new Vue({el: targetElement});
516 articleEditor.addTrigger = function addTrigger (selector, targetElement) {
517 if (!targetElement) {
518 console.error('error in articleEditor.addTrigger(): no element given');
522 console.error('error in articleEditor.addTrigger(): no selector given');
526 var els = document.querySelectorAll(selector);
527 for (var i = 0; i < els.length; i++) {
528 els[i].addEventListener('click', function (e) {
529 articleEditor.init();
530 articleEditor.instances.push(new articleEditor.ArticleEditor(targetElement));