diff --git a/wire/modules/Process/ProcessCommentsManager/ProcessCommentsManager.css b/wire/modules/Process/ProcessCommentsManager/ProcessCommentsManager.css index 296cc324..fe239f34 100644 --- a/wire/modules/Process/ProcessCommentsManager/ProcessCommentsManager.css +++ b/wire/modules/Process/ProcessCommentsManager/ProcessCommentsManager.css @@ -1 +1,279 @@ -#CommentListHeader{padding-top:.5em;padding-bottom:.5em}#CommentListHeader>p{line-height:2.25em;padding-right:1em;margin-top:.25em;margin-bottom:.25em}#CommentListHeader .MarkupPagerNav{margin-top:0;margin-bottom:.5em}#CommentListHeader .CommentLimitSelect{float:left}#CommentListHeader .CommentCheckAll{display:block;float:left;padding-left:.75em}#CommentListHeader .CommentActions{float:left}#CommentListHeader .CommentSorts{float:left}.CommentItems{clear:both;border-bottom:1px solid #777}.CommentItems+button.ui-button{margin-top:1em}.CommentItem{clear:both;border-top:1px solid #777;padding:.75em 0;margin:0;width:100%}.CommentItem.CommentChecked{background-color:#eee}.CommentItem.CommentChecked th{color:#999}.CommentItem table{width:45%;float:left}.CommentItem table th,.CommentItem table td{padding:4px 10px 4px 0;border-bottom:1px solid #ddd;vertical-align:top;line-height:1.8}.CommentItem table th{font-weight:bold;white-space:nowrap;text-align:left;padding-left:.75em !important}.CommentItem table th:first-child{width:80px}.CommentItem table tr:last-child td,.CommentItem table tr:last-child th{border-bottom:none}.CommentItem .CommentTitle th,.CommentItem .CommentTitle td{padding-top:0}.CommentItem .CommentInput{max-width:80%}.CommentItem .CommentChangedIcon{display:none}.CommentItem.CommentItemChanged .CommentChangedIcon{display:inline;float:right;opacity:.3}.CommentItem input[type=number]{width:4em}.CommentItem .CommentVotes label{margin-right:5px}.CommentItem .CommentVotes .CommentUpvotes span{font-weight:bold;color:green;margin-right:2px}.CommentItem .CommentVotes .CommentDownvotes span{font-weight:bold;color:red;margin-right:2px}.CommentItem .CommentID{font-weight:normal;color:#333}.CommentItem .CommentWhere small{margin-right:2px}.CommentItem .CommentWhere input{width:80px}.CommentItem .CommentStars>span{display:inline;cursor:pointer;padding-right:3px}.CommentItem .CommentStars>span i.fa{font-size:18px !important}.CommentItem .CommentContent{float:left;width:55%;padding-left:1em;border:none}.CommentItem .CommentContent .CommentChildrenInfo{margin-top:.5em}.CommentItem .CommentContent .CommentReplyInfo{margin-bottom:0}.CommentItem .CommentContent .CommentText{cursor:pointer;padding-right:1em}.CommentItem .CommentContent .CommentText textarea{font-size:1em;width:100%;min-height:18em;margin-top:1em;margin-bottom:1em}.CommentItem .CommentContent .CommentText .CommentTextEdit{white-space:nowrap}.CommentItem .CommentContent .CommentTextOverflow{overflow-y:scroll;max-height:18em}.CommentItem .CommentContent.CommentContentLarge .CommentTextOverflow{max-height:24em}.CommentItem label.CommentStatus{white-space:nowrap;display:inline-block}.CommentItem.CommentItemStatus999{display:none}.CommentCheckAll label .detail,.CommentItem .CommentTitle th label .detail{font-weight:bold;color:#444}.pw-content .MarkupPagerNav{padding-top:.5em;float:right}.pw-content .MarkupPagerNav+button{margin-top:1em}.AdminThemeReno .pw-content .MarkupPagerNav li a,.AdminThemeReno .pw-content .MarkupPagerNav li:first-child a,.AdminThemeReno .pw-content .MarkupPagerNav li.MarkupPagerNavOn a{border-color:#fff !important;border:none !important;border-left:1px solid #fff !important}.AdminThemeReno .pw-content .MarkupPagerNav li{margin-bottom:1px}.AdminThemeReno .pw-content #CommentListHeader{border-top:1px solid #eee}.AdminThemeReno .pw-content #CommentListHeader .MarkupPagerNav{margin-top:.5em}@media only screen and (max-width: 960px){.pw-content .MarkupPagerNav{float:none}#CommentListHeader{padding-bottom:1em;padding-top:1em}#CommentListHeader .MarkupPagerNav{float:none}#CommentListHeader p{margin-top:0;margin-bottom:0;padding-right:1em;padding-left:0 !important}#CommentListHeader .CommentCheckAll{width:auto}}@media only screen and (max-width: 768px){.CommentItem table{width:100%;float:none}.CommentItem table th{padding-left:0 !important}.CommentItem .CommentContent{width:100%;float:none;padding-left:0}.CommentItem .CommentContent .CommentText{padding-right:0}.CommentItem .CommentContent .CommentTextOverflow{overflow-y:auto;max-height:inherit}}.WireTabs{opacity:0} +#CommentListHeader { + padding-top: 0.5em; + padding-bottom: 0.5em; +} +#CommentListHeader > p { + line-height: 2.25em; + padding-right: 1em; + margin-top: 0.25em; + margin-bottom: 0.25em; +} +#CommentListHeader .MarkupPagerNav { + margin-top: 0; + margin-bottom: 0.5em; +} +#CommentListHeader .CommentLimitSelect { + float: left; +} +#CommentListHeader .CommentCheckAll { + display: block; + float: left; + padding-left: 0.75em; +} +#CommentListHeader .CommentActions { + float: left; +} +#CommentListHeader .CommentSorts { + float: left; +} + +.CommentItems { + clear: both; + border-bottom: 1px solid #777; +} +.CommentItems + button.ui-button { + margin-top: 1em; +} + +.CommentItem { + clear: both; + border-top: 1px solid #777; + padding: 0.75em 0; + margin: 0; + width: 100%; + /* + &.CommentItemStatus-2 .CommentText { + background: #ffffcc; + } + + &.CommentItemStatus0 .CommentText { + background: #ffffdd; + } + */ +} +.CommentItem.CommentChecked { + background-color: #eee; +} +.CommentItem.CommentChecked th { + color: #999; +} +.CommentItem table { + /* + margin-top: 0.7em; + margin-bottom: 0.7em; + */ + width: 45%; + float: left; +} +.CommentItem table th, +.CommentItem table td { + padding: 4px 10px 4px 0; + border-bottom: 1px solid #ddd; + vertical-align: top; + line-height: 1.8; +} +.CommentItem table th { + font-weight: bold; + white-space: nowrap; + text-align: left; + padding-left: 0.75em !important; +} +.CommentItem table th:first-child { + width: 80px; +} +.CommentItem table tr:last-child td, .CommentItem table tr:last-child th { + border-bottom: none; +} +.CommentItem .CommentTitle th, +.CommentItem .CommentTitle td { + padding-top: 0; +} +.CommentItem .CommentInput { + max-width: 80%; +} +.CommentItem .CommentChangedIcon { + display: none; +} +.CommentItem.CommentItemChanged .CommentChangedIcon { + display: inline; + float: right; + opacity: 0.3; +} +.CommentItem input[type=number] { + width: 4em; +} +.CommentItem .CommentVotes label { + margin-right: 5px; +} +.CommentItem .CommentVotes .CommentUpvotes span { + font-weight: bold; + color: green; + margin-right: 2px; +} +.CommentItem .CommentVotes .CommentDownvotes span { + font-weight: bold; + color: red; + margin-right: 2px; +} +.CommentItem .CommentID { + font-weight: normal; + color: #333; +} +.CommentItem .CommentWhere small { + margin-right: 2px; +} +.CommentItem .CommentWhere input { + width: 80px; +} +.CommentItem .CommentContent { + float: left; + width: 55%; + padding-left: 1em; + border: none; +} +.CommentItem .CommentContent .CommentChildrenInfo { + margin-top: 0.5em; +} +.CommentItem .CommentContent .CommentReplyInfo { + margin-bottom: 0; +} +.CommentItem .CommentContent .CommentText { + cursor: pointer; + padding-right: 1em; +} +.CommentItem .CommentContent .CommentText textarea { + font-size: 1em; + width: 100%; + min-height: 18em; + margin-top: 1em; + margin-bottom: 1em; +} +.CommentItem .CommentContent .CommentText .CommentTextEdit { + white-space: nowrap; +} +.CommentItem .CommentContent .CommentText .CommentTextEditable { + /* + p { + margin: 1em 0; + } + & > p:first-child { + margin-top: 0; + } + */ +} +.CommentItem .CommentContent .CommentTextOverflow { + overflow-y: scroll; + max-height: 18em; +} +.CommentItem .CommentContent.CommentContentLarge .CommentTextOverflow { + max-height: 24em; +} +.CommentItem label.CommentStatus { + white-space: nowrap; + display: inline-block; +} +.CommentItem select.CommentStatus { + width: auto; +} +.CommentItem select.CommentStatus.uk-select { + padding-right: 30px; +} +.CommentItem.CommentItemStatus999 { + display: none; +} + +.CommentCheckAll label .detail, +.CommentItem .CommentTitle th label .detail { + font-weight: bold; + color: #444; +} + +.pw-content .MarkupPagerNav { + padding-top: 0.5em; + float: right; +} +.pw-content .MarkupPagerNav + button { + margin-top: 1em; +} + +.AdminThemeReno .pw-content .MarkupPagerNav li a, +.AdminThemeReno .pw-content .MarkupPagerNav li:first-child a, +.AdminThemeReno .pw-content .MarkupPagerNav li.MarkupPagerNavOn a { + border-color: #fff !important; + border: none !important; + border-left: 1px solid #fff !important; +} +.AdminThemeReno .pw-content .MarkupPagerNav li { + margin-bottom: 1px; +} +.AdminThemeReno .pw-content #CommentListHeader { + border-top: 1px solid #eee; +} +.AdminThemeReno .pw-content #CommentListHeader .MarkupPagerNav { + margin-top: 0.5em; +} + +@media only screen and (max-width: 960px) { + .pw-content .MarkupPagerNav { + float: none; + } + + #CommentListHeader { + padding-bottom: 1em; + padding-top: 1em; + } + #CommentListHeader .MarkupPagerNav { + float: none; + } + #CommentListHeader p { + margin-top: 0; + margin-bottom: 0; + padding-right: 1em; + padding-left: 0 !important; + } + #CommentListHeader .CommentCheckAll { + width: auto; + } +} +@media only screen and (max-width: 768px) { + .CommentItem table { + width: 100%; + float: none; + } + .CommentItem table th { + padding-left: 0 !important; + } + .CommentItem .CommentContent { + width: 100%; + float: none; + padding-left: 0; + } + .CommentItem .CommentContent .CommentText { + padding-right: 0; + } + .CommentItem .CommentContent .CommentTextOverflow { + overflow-y: auto; + max-height: inherit; + } +} +.CommentItem .CommentStars > span, +.InputfieldForm .CommentStars > span { + display: inline; + cursor: pointer; + padding-right: 3px; +} +.CommentItem .CommentStars > span i.fa, +.InputfieldForm .CommentStars > span i.fa { + font-size: 18px !important; +} + +.WireTabs { + opacity: 0; +} + +blockquote { + padding-left: 30px; + border-left: 3px solid #ccc; + color: #777; +} + diff --git a/wire/modules/Process/ProcessCommentsManager/ProcessCommentsManager.module b/wire/modules/Process/ProcessCommentsManager/ProcessCommentsManager.module index f1af27b6..57762288 100644 --- a/wire/modules/Process/ProcessCommentsManager/ProcessCommentsManager.module +++ b/wire/modules/Process/ProcessCommentsManager/ProcessCommentsManager.module @@ -10,6 +10,8 @@ * This file licensed under Mozilla Public License v2.0 http://mozilla.org/MPL/2.0/ * * https://processwire.com + * + * @method string renderComment(Comment $comment, array $options = array()) * */ @@ -23,7 +25,7 @@ class ProcessCommentsManager extends Process { return array( 'title' => __('Comments', __FILE__), 'summary' => __('Manage comments in your site outside of the page editor.', __FILE__), - 'version' => 11, + 'version' => 12, 'author' => 'Ryan Cramer', 'icon' => 'comments', 'requires' => 'FieldtypeComments', @@ -120,12 +122,20 @@ class ProcessCommentsManager extends Process { Comment::statusSpam => $this->_('Spam'), Comment::statusDelete => $this->_('Delete') ); + $this->labelAll = $this->_('All'); $this->notifyFlagsTranslations = array( 0 => $this->_('No'), - Comment::flagNotifyAll => $this->_('All'), + Comment::flagNotifyAll => $this->labelAll, Comment::flagNotifyReply => $this->_('Replies'), ); - $this->labelAll = $this->_('All'); + if(wireClassExists("CommentStars")) { + $config = $this->config; + $cssFile = $config->urls('FieldtypeComments') . 'comments.css'; + $jsFile = $config->urls('FieldtypeComments') . 'comments.js'; + $config->styles->add($cssFile); + $config->scripts->add($jsFile); + CommentStars::setDefault('star', wireIconMarkup('star')); + } } /** @@ -141,6 +151,7 @@ class ProcessCommentsManager extends Process { // locate all the FieldtypeComments fields $fields = array(); foreach($this->fields as $field) { + /** @var Field $field */ if($field->type instanceof FieldtypeComments) $fields[] = $field; } @@ -179,15 +190,6 @@ class ProcessCommentsManager extends Process { */ public function ___executeList() { - if(wireClassExists("CommentStars")) { - $config = $this->config; - $cssFile = $config->urls('FieldtypeComments') . 'comments.css'; - $jsFile = $config->urls('FieldtypeComments') . 'comments.js'; - $config->styles->add($cssFile); - $config->scripts->add($jsFile); - CommentStars::setDefault('star', wireIconMarkup('star')); - } - $session = $this->wire('session'); /** @var Session $session */ $input = $this->wire('input'); /** @var WireInput $input */ $sanitizer = $this->wire('sanitizer'); /** @var Sanitizer $sanitizer */ @@ -369,7 +371,7 @@ class ProcessCommentsManager extends Process { /** @var InputfieldSubmit $f */ $f = $modules->get('InputfieldButton'); $f->attr('name', 'submit_cancel'); - $f->setSecondary(true); + $f->setSecondary(); $f->val($this->_('Cancel')); $form->add($f); @@ -402,14 +404,364 @@ class ProcessCommentsManager extends Process { return $out; } + /** + * Edit or add comment + * + * @return string + * @throws WireException + * @throws WirePermissionException + * + */ + protected function ___executeEdit() { + + $input = $this->wire()->input; + $user = $this->wire()->user; + $submit = false; + $out = ''; + + if($input->post('submit_save_comment')) { + $submit = true; + $pageId = (int) $input->post('page_id'); + $fieldId = (int) $input->post('field_id'); + $parentId = (int) $input->post('parent_id'); + $commentId = (int) $input->post('comment_id'); + } else { + $pageId = (int) $input->get('page_id'); + $fieldId = (int) $input->get('field_id'); + $parentId = (int) $input->get('parent_id'); + $commentId = (int) $input->get('comment_id'); + } + + $page = $this->wire()->pages->get($pageId); + $field = $this->wire()->fields->get($fieldId); /** @var CommentField $field */ + + if(!$page->id) throw new WireException("Cannot find page $pageId"); + if(!$field) throw new WireException("Cannot find field $fieldId"); + if(!$page->hasField($field)) throw new WireException("Page $pageId does not have field $field->name"); + + if($commentId) { + // editing existing comment + $comment = $field->getCommentByID($page, $commentId); + if(!$comment) throw new WireException('Comment not found'); + if($comment->getField()->id != $field->id) throw new WireException('Invalid field'); + if($comment->getPage()->id != $page->id) throw new WireException('Invalid page'); + $this->headline(sprintf($this->_('Edit comment #%d'), $comment->id)); + + } else { + // adding new comment + $comment = new Comment(); + $this->wire($comment); + $comment->setPage($page); + $comment->setField($field); + $comment->cite = $user->get('title|name'); + $comment->email = $user->get('email'); + $comment->created = time(); + if($parentId) { + // new comment that is reply to existing comment + $parentComment = $field->getCommentByID($page, $parentId); + if(!$parentComment) throw new WireException("Cannot find parent comment $parentId"); + $comment->parent_id = $parentId; + $this->headline(sprintf($this->_('Comment #%d by %s'), $parentId, $comment->getFormatted('cite'))); + // show comment being replied to + $out .= '
'; + $out .= "' . $parentComment->getFormattedCommentText() . '
" . @@ -832,17 +1216,18 @@ class ProcessCommentsManager extends Process { " | " . "$pageTitle " . " " . - "$labels[view] / " . - "$labels[edit] / " . - "$labels[meta]" . + "$labels[view] / " . + "$labels[edit]" . "" . "$icons[changed]" . " | " . "||
---|---|---|---|
$labels[status] | " . - "$outs[status] | " . + "$labels[action] | " . + "" . + $outs['status'] . " " . + implode(' ', $statusLinks) . + " | " . "