OSDN Git Service

now supporting url only submission
[newslash/newslash.git] / src / newslash_web / public / js / article-item2.js
1 /* article-item2.js */
2
3 var articleItem = {};
4
5 articleItem.init = function init () {
6   function data() {
7     var data = {
8       editor: {
9         title: "",
10         introtext: "",
11         bodytext: "",
12         createtime: "",
13         author: "",
14         dept: "",
15         commentstatus: "enabled",
16         submissioncopy: 0,
17         url: "",
18         email: "",
19         tags_string: "",
20         related_urls: "",
21       },
22
23       showForm: true,
24       showSubmit: false,
25       disablePost: false,
26       message: "",
27       createdUrl: "",
28       currentTopics: [],
29       
30       // common
31       primaryTopicIconURL: "",
32       editable: 0,
33       cancelable: 0,
34       editing: 0,
35     };
36     return data;
37   }
38
39   var props = {
40     item: {
41       type: Object,
42       default: function () {return new Contents();},
43     },
44     showEditor: {
45       type: [Boolean, Number],
46       default: false,
47     },
48     csrfToken: String,
49   };
50
51   /*
52    * watch
53    */
54   var watch = {
55     'editor.introtext': watchIntrotext,
56     'editor.bodytext': watchBodytext,
57     'editor.title': watchTitle,
58     'editor.url': watchURL,
59     'editor.createtime': watchCreatetime,
60     'editor.author': watchAuthor,
61     'editor.dept': watchDept,
62     'editor.tags_string': updateTopics,
63   };
64
65   function watchIntrotext(val, oldVal) {
66     this.item.introtext = (val.length > 0) ? quoteHtml(val) : "";
67   };
68
69   function watchBodytext(val, oldVal) {
70     this.item.bodytext = (val.length > 0) ? quoteHtml(val) : "";
71   };
72
73   function watchTitle(val, oldVal) {
74     this.item.title = (val.length > 0) ? quoteTitle(val) : "";
75   };
76
77   function watchURL(val, oldVal) {
78     this.item.url = (val.length > 0) ? val : "";
79   };
80
81   function watchCreatetime(val, oldVal) {
82     this.item.time_string = nsUtil.formatToLocalDateTime(new Date(val));
83   };
84
85   function watchAuthor(val, oldVal) {
86     this.item.author = val;
87   };
88
89   function watchDept(val, oldVal) {
90     this.item.dept = val;
91   };
92
93   /*
94    * computed
95    */
96   var computed = {
97     editable: editable,
98     url: url,
99   };
100
101   function editable() {
102     return (this.vm.user.uid == this.item.uid);
103   }
104
105   function url() {
106     if (this.item.content_type == 'story') {
107       return "/story/" + this.item.sid + "/";
108     } else if (this.item.content_type == 'journal') {
109       return "/journal/" + this.item.id + "/";
110     } else if (this.item.content_type == 'submission') {
111       return "/submission/" + this.item.subid + "/";
112     }
113       return "";
114   }
115
116   /*
117    * methods and relative private functions
118    */
119   var methods = {
120     editItem: editItem,
121     showPreview: showPreview,
122     postItem: postItem,
123     leavePreview: leavePreview,
124     startEdit: startEdit,
125     cancelEdit: cancelEdit,
126     updateTopics: updateTopics,
127     topicIconURL: topicIconURL,
128     updatePrimaryTopicIconURL: updatePrimaryTopicIconURL,
129   };
130
131   function updatePrimaryTopicIconURL() {
132     if (this.item.primary_topic) {
133       this.primaryTopicIconURL = nsUtil.topicIconURL(this.item.primary_topic.keyword);
134       return;
135     }
136     this.primaryTopicIconURL = "";
137   }
138
139   function editItem(item) {
140     this.editing = true;
141     item.editor.startEdit();
142   }
143
144   function showPreview(event) {
145     var type = this.item.content_type;
146     if (!type) {
147       console.log("no content_type!");
148       return;
149     }
150     var postData = _preparePostData(this, "preview");
151
152     this.$newslash.post(type,
153                         postData,
154                         { csrfToken: this.csrfToken,
155                           noCaptcha: 1 },
156       (response) => { // success
157         this.message = "";
158         this.previewTitle = response.body.item.title;
159         this.previewIntro = response.body.item.introtext;
160         this.item.primary_topic = response.body.item.topic;
161         this.item.url = response.body.item.url;
162         this.updatePrimaryTopicIconURL();
163
164         this.showSubmit = true;
165         this.showForm = false;
166         this.disablePost= false;
167       },
168       (response) => { // fail
169         if (response.body.message) {
170           this.message = response.body.message;
171         }
172       }
173     );
174   }
175
176   function postItem(event) {
177     this.disablePost = true;
178     var postData = _preparePostData(this, "post");
179     var type = this.item.content_type;
180     if (!type) {
181       console.log("no content_type!");
182       return;
183     }
184
185     this.$newslash.post(type, postData, {csrfToken: this.csrfToken},
186       (response) => { // success
187         this.message = "";
188         var id = response.body.id;
189         var type = response.body.type;
190         var url = '/' + type + '/' + id;
191
192         // check if new post
193         if (!postData.id) {
194           this.createdUrl = url;
195           this.message = "post_success";
196         }
197
198         this.editing = false;
199         this.showSubmit = false;
200         this.showForm = false;
201       },
202       (response) => { // fail
203         this.message = response.body.message;
204         this.disablePost= false;
205       }
206     );
207
208   }
209
210   function _preparePostData(vm, action) {
211     action = action || "preview";
212
213     vm.message = "";
214     var postData = {};
215     postData.item = {};
216     postData.action = action;
217     
218     if (articleItem.recaptchaToken) {
219       postData.recaptcha_token = articleItem.recaptchaToken;
220     }
221
222     Object.keys(vm.editor).forEach(k => {
223       postData.item[k] = vm.editor[k];
224     });
225
226     return postData;
227   }
228
229   function leavePreview(event) {
230     this.previewTitle = "";
231     this.previewIntro = "";
232     this.previewBody = "";
233     this.showSubmit = false;
234     this.showForm = true;
235   }
236
237   function quoteHtml(html) {
238     return nsUtil.quoteHtml(html, editorConfig.allowed_tags);
239   }
240
241   function quoteTitle(html) {
242     return nsUtil.quoteTitle(html, {});
243   }
244
245   function startEdit() {
246     _initEditor(this);
247   }
248
249   function cancelEdit() {
250     for (k in this.originalItem) {
251       this.item[k] = this.originalItem[k];
252     }
253     this.editing = false;
254   }
255
256   function updateTopics() {
257     var tags = this.editor.tags_string.split(" ");
258     this.currentTopics.splice(0);
259     if (tags.length == 0) {
260       return;
261     }
262     var pushed = {};
263     tags.forEach((tag) => {
264       if (topics[tag]) {
265         var keyword = topics[tag].keyword;
266         if (!pushed[keyword]) {
267           this.currentTopics.push(keyword);
268           pushed[keyword] = 1;
269         }
270       }
271     });
272   }
273
274   function topicIconURL(topic) {
275     return nsUtil.topicIconURL(topic);
276   }
277
278   /*
279    * created and related private functions
280    */
281   function created() {
282     if (this.showEditor) {
283       this.editing = 1;
284       _initEditor(this);
285     }
286     this.updatePrimaryTopicIconURL();
287   }
288
289   function _initEditor(vm) {
290     // backup original item
291     // copy item property to vm
292     vm.originalItem = {};
293     for (k in vm.$data.item) {
294       if (vm.item[k]) {
295         vm.originalItem[k] = vm.item[k];
296       }
297     }
298
299     // set createtime
300     if (vm.item.createtime) {
301       var dt = nsUtil.decodeMySQLDateTime(vm.item.createtime);
302       vm.editor.createtime = nsUtil.formatToLocalISOString(dt);
303     } else {
304       vm.editor.createtime = nsUtil.formatToLocalISOString(new Date());
305     }
306     vm.editor.author = user.nickname;
307
308     if (vm.item.tags) {
309       var tagnames = vm.item.tags.map(x => {return x.tagname});
310       vm.editor.tags_string = tagnames.join(" ");
311     }
312     updateTopics.call(vm);
313
314
315     // story edit mode
316     if (page.type == 'story' && page.stoid) {
317       vm.cancelable = 1;
318
319       vm.$newslash.getStoryByID(page.stoid,
320         (resp) => { // succeed
321           for (k in resp.body.item) {
322             vm.editor.item[k] = resp.body.item[k];
323           }
324         },
325         (resp) => { //failed
326           vm.message = resp.body.message;
327         });
328     }
329     
330     // submission to story mode
331     if (vm.item.submission_id) {
332       vm.$newslash.getSubmissionByID(vm.item.submission_id, 
333         (resp) => { // succeed
334           vm.editor.title = resp.body.item.title;
335           vm.editor.introtext = resp.body.item.drafttext;
336         },
337         (resp) => { //failed
338           vm.message = resp.body.message;
339         });
340     }
341   }
342
343   /*
344    * register component
345    */
346    Vue.component('article-item', {
347     template: '#article-item-template',
348     props: props,
349     data: data,
350     computed: computed,
351     watch: watch,
352     methods: methods,
353     created: created,
354   });
355 };
356
357 articleItem.run = function (params) {
358   params = params || {};
359   if (!params.el) {
360     console.log('error in articleItem.run(): no element given');
361     return;
362   }
363   this.vm = new Vue({el: params.el});
364 };
365
366 articleItem.addTrigger = function addTrigger (selector, params) {
367   params = params || {};
368   if (!params.el) {
369     console.log('error in articleItem.addTrigger(): no element given');
370     return;
371   }
372   if (!selector) {
373     console.log('error in articleItem.addTrigger(): no selector given');
374     return;
375   }
376   $(selector).on('click', function (e) {
377     articleItem.run(params);
378   });
379 };
380
381 articleItem.init();
382