From: hylom Date: Fri, 10 May 2019 15:33:30 +0000 (+0900) Subject: fix journal re-editing X-Git-Tag: v0.1.12~18 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=35b46636b46dea3381ff2d9bbf4890d9190e4fe5;p=newslash%2Fnewslash.git fix journal re-editing --- diff --git a/src/newslash_web/lib/Newslash/Web/Controller/API/Journal.pm b/src/newslash_web/lib/Newslash/Web/Controller/API/Journal.pm index d84b9989..67d7c287 100644 --- a/src/newslash_web/lib/Newslash/Web/Controller/API/Journal.pm +++ b/src/newslash_web/lib/Newslash/Web/Controller/API/Journal.pm @@ -68,7 +68,7 @@ sub post { my $item = $data->{item}; my $message = ""; - $params->{description} = $c->format_htmltext($item->{title}, "text"); + $params->{description} = $c->format_htmltext($item->{title}, "title"); $message = "no title!" if !$params->{description}; # check user is valid diff --git a/src/newslash_web/public/js/article-editor.js b/src/newslash_web/public/js/article-editor.js new file mode 100644 index 00000000..985dfe27 --- /dev/null +++ b/src/newslash_web/public/js/article-editor.js @@ -0,0 +1,519 @@ +/* article-editor.js */ + +var articleEditor = { _initialized: 0 }; + +articleEditor.init = function init () { + if (this._initialized) { return; } + + function data() { + var data = { + // only editor's property will be send when preview/post + editor: { + title: "", + intro_text: "", + body_text: "", + create_time: "", + author: "", + dept: "", + comment_status: "enabled", + submissioncopy: 0, + url: "", + email: "", + tags_string: "", + related_urls: "", + display: "1", + posttype: 1, + formatter: "modern", + id: "", + }, + + message: "", + createdUrl: "", + currentTopics: [], + + enableAutoPreview: 1, + mode: "editing", + + primaryTopicIconURL: "", + cancelable: 0, + }; + return data; + } + + var props = { + item: { + type: Object, + default: function () {return new Content();}, + }, + contentType: { type: String }, + contentId: { type: String }, + csrfToken: String, + }; + + /* + * watch + */ + var watch = { + 'editor.intro_text': watchIntrotext, + 'editor.body_text': watchBodytext, + 'editor.title': watchTitle, + 'editor.url': watchURL, + 'editor.create_time': watchCreatetime, + 'editor.author': watchAuthor, + 'editor.dept': watchDept, + 'editor.tags_string': updateTopics, + }; + + function watchIntrotext(val, oldVal) { + this.item.intro_text = (val.length > 0) ? quoteHtml(val) : ""; + }; + + function watchBodytext(val, oldVal) { + this.item.body_text = (val.length > 0) ? quoteHtml(val) : ""; + }; + + function watchTitle(val, oldVal) { + this.item.title = (val.length > 0) ? quoteTitle(val) : ""; + }; + + function watchURL(val, oldVal) { + this.item.url = (val.length > 0) ? val : ""; + }; + + function watchCreatetime(val, oldVal) { + this.item.time_string = nsUtil.formatToLocalDateTime(new Date(val)); + }; + + function watchAuthor(val, oldVal) { + this.item.author = val; + }; + + function watchDept(val, oldVal) { + this.item.dept = val; + }; + + /* + * computed + */ + var computed = { + editable: editable, + url: url, + }; + + function editable() { + return (user.uid == this.item.uid); + } + + function url() { + if (this.item.content_type == 'story') { + return "/story/" + this.item.sid + "/"; + } else if (this.item.content_type == 'journal') { + return "/journal/" + this.item.id + "/"; + } else if (this.item.content_type == 'submission') { + return "/submission/" + this.item.subid + "/"; + } + return ""; + } + + /* + * methods and relative private functions + */ + var methods = { + showPreview: showPreview, + postItem: postItem, + leavePreview: leavePreview, + startEdit: startEdit, + cancelEdit: cancelEdit, + updateTopics: updateTopics, + topicIconURL: topicIconURL, + updatePrimaryTopicIconURL: updatePrimaryTopicIconURL, + }; + + function updatePrimaryTopicIconURL() { + if (this.item.primary_topic) { + this.primaryTopicIconURL = nsUtil.topicIconURL(this.item.primary_topic.keyword); + return; + } + this.primaryTopicIconURL = ""; + } + + function showPreview(event) { + var postData = _preparePostData(this, "preview"); + + if (this.contentType == "journal") { + newslash.previewJournal(postData).then( + (resp) => { // success + this.message = ""; + this.previewTitle = resp.item.title; + this.previewIntro = resp.item.intro_text; + this.item.url = this.editor.url; + this.item.primary_topic = resp.item.topic; + this.updatePrimaryTopicIconURL(); + + this.mode = "preview"; + }, + (resp) => { // fail + if (resp.message) { + this.message = resp.message; + } + } + ); + return; + } + + this.$newslash.post(type, + postData, + { csrfToken: this.csrfToken, + noCaptcha: 1 }, + (response) => { // success + this.message = ""; + this.previewTitle = response.body.item.title; + this.previewIntro = response.body.item.intro_text; + this.item.primary_topic = response.body.item.topic; + this.item.url = response.body.item.url; + this.item.dept = response.body.item.dept; + this.updatePrimaryTopicIconURL(); + + this.mode = "preview"; + }, + (response) => { // fail + if (response.body.message) { + this.message = response.body.message; + } + } + ); + } + + function postItem(event) { + this.mode = "posting"; + var postData = _preparePostData(this, "post"); + + // journal post + if (this.contentType == "journal") { + postData.csrf_token = this.csrfToken; + newslash.postJournal(postData).then( + (resp) => { // success + this.message = ""; + var id = resp.id; + var type = resp.type; + var url = '/' + type + '/' + id; + + // check if new post + if (!postData.id) { + this.createdUrl = url; + this.item.subid = id; + } + this.message = ""; + this.mode = "posted"; + }, + (resp) => { // fail + this.message = resp.message; + this.mode = "preview"; + } + ); + return; + } + + // submission post + this.$newslash.post(type, postData, {csrfToken: this.csrfToken}, + (response) => { // success + this.message = ""; + var id = response.body.url_id || response.body.id; + var type = response.body.type; + var url = '/' + type + '/' + id; + + // check if new post + if (!postData.id) { + this.createdUrl = url; + if (page.type == "submission") { + this.item.subid = id; + } + this.editor.id = response.body.id; + } + this.message = ""; + this.mode = "posted"; + }, + (response) => { // fail + this.message = response.body.message; + this.mode = "preview"; + } + ); + + } + + function _preparePostData(vm, action) { + action = action || "preview"; + + vm.message = ""; + var postData = {}; + postData.item = {}; + postData.action = action; + + if (articleEditor.recaptchaToken) { + postData.recaptcha_token = articleEditor.recaptchaToken; + } + + Object.keys(vm.editor).forEach(k => { + postData.item[k] = vm.editor[k]; + }); + + // prepare ID + if (vm.editor.id) { + if (vm.contentType == "story") { + postData.item.stoid = vm.editor.id; + } + } + + return postData; + } + + function leavePreview(event) { + this.mode = "editing"; + } + + function quoteHtml(html) { + return nsUtil.quoteHtml(html, siteConfig.editorConfig.allowed_tags); + } + + function quoteTitle(html) { + return nsUtil.quoteTitle(html, {}); + } + + function startEdit() { + _startEdit(this); + } + + function cancelEdit() { + for (k in this.originalItem) { + this.item[k] = this.originalItem[k]; + } + this.mode = "show_all"; + } + + function updateTopics() { + var tags = this.editor.tags_string.split(" "); + this.currentTopics.splice(0); + if (tags.length == 0) { + return; + } + var pushed = {}; + tags.forEach((tag) => { + if (siteConfig.topics[tag]) { + var keyword = siteConfig.topics[tag].keyword; + if (!pushed[keyword]) { + this.currentTopics.push(keyword); + pushed[keyword] = 1; + } + } + }); + } + + function topicIconURL(topic) { + return nsUtil.topicIconURL(topic); + } + + /* + * created and related private functions + */ + function created() { + _startEdit(this); + } + + function _startEdit(c) { + c.mode = "editing"; + // backup original item + // copy item property to c (component) + c.originalItem = {}; + for (k in c.$data.item) { + if (c.item[k]) { + c.originalItem[k] = c.item[k]; + } + } + + // load item data + _loadItem(c); + + c.updatePrimaryTopicIconURL(); + + } + + function _loadItem(c) { + if (c.contentType == "journal") { + if (c.contentId) { + // edit already existing journal + newslash.getJournal(c.contentId).then( + resp => { // succeed + var item = resp.journal; + c.cancelable = 1; + c.editor.title = item.title; + c.editor.intro_text = item.article; + c.editor.tags_string = item.tags_string || ""; + c.editor.comment_status = item.comment_status; + c.editor.formatter = item.formatter; + c.editor.posttype = item.posttype; + c.editor.id = item.id; + + // check formatter + if (c.editor.formatter == "legacy") { + c.enableAutoPreview = 0; + } + + c.updatePrimaryTopicIconURL(); + + // start editing + c.mode = "editing"; + }, + resp => { // failed + c.message = resp.body.message; + }); + } else { + // create new journal + // start editing + c.mode = "editing"; + } + } + } + + function _initEditor(c) { + + // set createtime + if (c.item.createtime) { + var dt = nsUtil.decodeMySQLDateTime(c.item.createtime); + c.editor.createtime = nsUtil.formatToLocalISOString(dt); + } else { + c.editor.createtime = nsUtil.formatToLocalISOString(new Date()); + } + c.editor.author = user.nickname; + + if (c.item.tags) { + var tagnames = c.item.tags.map(x => {return x.tagname}); + c.editor.tags_string = tagnames.join(" "); + } + updateTopics.call(c); + + // journal edit mode + if (page.content_type == 'journal') { + c.item.content_type = "story"; + if (page.id) { + // edit mode + newslash.getJournal(page.id).then( + resp => { // succeed + var item = resp.journal; + c.cancelable = 1; + c.editor.title = item.title; + c.editor.intro_text = item.article; + c.editor.tags_string = item.tags_string || ""; + c.editor.comment_status = item.comment_status; + c.editor.formatter = item.formatter; + c.editor.posttype = item.posttype; + c.editor.id = item.id; + }, + resp => { // failed + c.message = resp.body.message; + }); + } else { + // create + } + } + + // story edit mode + if (page.content_type == 'story' && page.stoid) { + c.cancelable = 1; + c.item.content_type = "story"; + + c.$newslash.getStoryByID(page.stoid, + (resp) => { + // succeed + var item = resp.body.item; + for (var k in c.editor) { + if (item[k] !== undefined) { + c.editor[k] = item[k]; + } + } + // convert tags to tags_string + if (item.tags) { + var tagnames = item.tags.map(tag => tag.tagname); + c.editor.tags_string = tagnames.join(" "); + } + // TODO: related stories + // convert public to display + c.editor.display = (item.public == "yes"); + c.editor.createtime = nsUtil.formatToLocalISOString(nsUtil.decodeMySQLDateTime(item.create_time)); + c.editor.id = item.stoid; + }, + (resp) => { //failed + c.message = resp.body.message; + }); + } + + // submission to story mode + if (c.item.submission_id) { + c.$newslash.getSubmissionByID(c.item.submission_id, + (resp) => { // succeed + c.editor.title = resp.body.item.title; + c.editor.intro_text = resp.body.item.drafttext; + c.item.content_type = "story"; + }, + (resp) => { //failed + c.message = resp.body.message; + }); + } + + // check formatter + if (c.editor.formatter == "legacy") { + c.enableAutoPreview = 0; + } + c.mode = "editing"; + } + + /* + * register component + */ + this._component = Vue.component('article-editor', { + template: '#article-editor-template', + props: props, + data: data, + computed: computed, + watch: watch, + methods: methods, + created: created, + }); + + this._initialized = 1; +}; + +/* + * utilities + */ +articleEditor.instances = []; + +articleEditor.ArticleEditor = class ArticleEditor { + constructor(targetElement) { + if (!targetElement) { + console.error('error in articleEditor.run(): no element given'); + return; + } + this.vm = new Vue({el: targetElement}); + } +}; + +articleEditor.addTrigger = function addTrigger (selector, targetElement) { + if (!targetElement) { + console.error('error in articleEditor.addTrigger(): no element given'); + return; + } + if (!selector) { + console.error('error in articleEditor.addTrigger(): no selector given'); + return; + } + + var els = document.querySelectorAll(selector); + for (var i = 0; i < els.length; i++) { + els[i].addEventListener('click', function (e) { + articleEditor.init(); + articleEditor.instances.push(new articleEditor.ArticleEditor(targetElement)); + }); + } +}; + + diff --git a/src/newslash_web/public/js/article-item2.js b/src/newslash_web/public/js/article-item2.js index 97334b6b..1befdefe 100644 --- a/src/newslash_web/public/js/article-item2.js +++ b/src/newslash_web/public/js/article-item2.js @@ -333,29 +333,9 @@ articleItem.init = function init () { } function _startEdit(c) { - _loadItem(c, () => { _initEditor(c); }); + _initEditor(c); } - function _loadItem(c, callback) { - if (!page) { return callback(); } - - if (page.contentType == "journal") { - newslash.getJournal(page.id).then( - (resp) => { - for (k in resp.journal) { - c.item[k] = resp.journal[k]; - } - callback(); - }, - (resp) => { - statusBar.error(resp.message); - } - ); - return 0; - } - return callback(); - } - function _initEditor(c) { // backup original item // copy item property to c (component) @@ -382,19 +362,32 @@ articleItem.init = function init () { updateTopics.call(c); // journal edit mode - if (page.type == 'journal' && page.id) { - c.cancelable = 1; - c.editor.title = c.item.title; - c.editor.intro_text = c.item.article; - c.editor.tags_string = c.item.tags_string || ""; - c.editor.comment_status = c.item.comment_status; - c.editor.formatter = c.item.formatter; - c.editor.posttype = c.item.posttype; - c.editor.id = c.item.id; + if (page.content_type == 'journal') { + c.item.content_type = "story"; + if (page.id) { + // edit mode + newslash.getJournal(page.id).then( + resp => { // succeed + var item = resp.journal; + c.cancelable = 1; + c.editor.title = item.title; + c.editor.intro_text = item.article; + c.editor.tags_string = item.tags_string || ""; + c.editor.comment_status = item.comment_status; + c.editor.formatter = item.formatter; + c.editor.posttype = item.posttype; + c.editor.id = item.id; + }, + resp => { // failed + c.message = resp.body.message; + }); + } else { + // create + } } // story edit mode - if (page.type == 'story' && page.stoid) { + if (page.content_type == 'story' && page.stoid) { c.cancelable = 1; c.item.content_type = "story"; @@ -487,5 +480,5 @@ articleItem.addTrigger = function addTrigger (selector, params) { }); }; -articleItem.init(); +// articleItem.init(); diff --git a/src/newslash_web/templates/common/article/article.html.tt2 b/src/newslash_web/templates/common/article/article.html.tt2 index b6676f56..9b727989 100644 --- a/src/newslash_web/templates/common/article/article.html.tt2 +++ b/src/newslash_web/templates/common/article/article.html.tt2 @@ -42,10 +42,10 @@ END; -%]
+ [% IF template_mode %]v-if="enableAutoPreview || mode != 'editing'"[% ELSE %]v-if=0[% END %]>

- [%- IF item.primary_topic.image.length || x_template -%] + [%- IF item.primary_topic.image.length || template_mode -%] [% item.primary_topic.textname %] [%- END -%] @@ -62,7 +62,7 @@ END; by [% item.author %] [% dtf.mysql_to_user(item.create_time, user.config.ui.offset_sec, user.config.ui.time_format) %] - [%- IF x_template || user.is_admin %] + [%- IF user.is_admin %] pop: [% item.popularity %] epop: [% item.editorpop %] @@ -71,24 +71,30 @@ END; [%- END %] - [%- IF x_template || item.content_type == 'story' %] + [%- IF template_mode || item.content_type == 'story' %] [% item.dept %] 部門より [%- END %] -
- [%- IF x_template || page.type == 'single' && item.content_type == 'journal' && item.uid == user.uid -%] - [%- END -%] - [%- IF x_template || item.content_type == 'story' && user.is_admin || user.editor -%] + [%- IF item.content_type == 'story' && user.is_admin || user.editor -%] [編集] [%- END -%] - [%- IF item.content_type == 'submission' && (user.author || x_template) -%] + [%- IF item.content_type == 'submission' && user.author -%] [[accept]] [%- END -%]
@@ -111,59 +117,61 @@ END; [%- IF hide_bodytext %] - [%- IF item.intro_text || x_template -%] + [%- IF item.intro_text || template_mode -%]
[% item.intro_text %]
[%- END -%] [%- ELSE %] - [%- IF item.body_text || x_template -%] + [%- IF item.body_text || template_mode -%]
[% item.intro_text %]
[% item.body_text %]
[%- ELSE %]
[% item.full_text %]
[%- END -%] - [%- IF item.media || x_template %] + [%- IF item.media || template_mode %]
[% item.media %]
[%- END %] [%- END %] - [%- IF x_template -%] - - [%- ELSIF item.url -%] - + [%- IF item.url || template_mode -%] + [%- END -%]