From c9f4af7e585113c2be5192327c62ec107e09db8c Mon Sep 17 00:00:00 2001 From: isUnknown Date: Tue, 10 Sep 2024 17:14:38 +0200 Subject: [PATCH] add front-comments --- site/plugins/front-comments | 1 - site/plugins/front-comments/.editorconfig | 20 + site/plugins/front-comments/LICENSE.md | 21 ++ site/plugins/front-comments/README.md | 98 +++++ site/plugins/front-comments/SECURITY.md | 18 + .../front-comments/assets/icons/accept.svg | 17 + .../assets/icons/chat-box-empty.svg | 14 + .../assets/icons/chat-box-plus.svg | 20 + .../assets/icons/chat-box-text-select.svg | 15 + .../front-comments/assets/icons/code.svg | 1 + .../front-comments/assets/icons/decline.svg | 17 + .../front-comments/assets/icons/delete.svg | 14 + .../front-comments/assets/icons/gitlab.svg | 1 + .../front-comments/assets/icons/palette.svg | 1 + .../front-comments/assets/icons/pen.svg | 1 + site/plugins/front-comments/assets/index.css | 1 + site/plugins/front-comments/assets/index.js | 35 ++ site/plugins/front-comments/assets/style.css | 336 +++++++++++++++++ .../front-comments/blueprints/fields/team.yml | 14 + .../front-comments/classes/Comment.php | 201 ++++++++++ site/plugins/front-comments/composer.json | 26 ++ site/plugins/front-comments/composer.lock | 66 ++++ .../front-comments/dialogs/create-issue.php | 45 +++ .../front-comments/dialogs/delete-comment.php | 19 + site/plugins/front-comments/doc/cover.jpg | Bin 0 -> 168983 bytes .../front-comments/dropdowns/comment.php | 43 +++ site/plugins/front-comments/index.css | 1 + site/plugins/front-comments/index.js | 1 + site/plugins/front-comments/index.php | 89 +++++ site/plugins/front-comments/lib/functions.php | 120 ++++++ site/plugins/front-comments/package-lock.json | 355 ++++++++++++++++++ site/plugins/front-comments/package.json | 23 ++ .../front-comments/routes/delete-comment.php | 22 ++ .../front-comments/routes/store-comment.php | 32 ++ .../snippets/front-comments-field.php | 7 + .../snippets/front-comments-script.php | 35 ++ .../snippets/front-comments-style.php | 6 + .../snippets/front-comments.php | 21 ++ .../src/front/classes/AddBtn.js | 89 +++++ .../src/front/classes/Suggestion.js | 224 +++++++++++ .../src/front/classes/comments/Comment.js | 163 ++++++++ .../front/classes/comments/CommentBuilder.js | 95 +++++ .../classes/edition-panels/CommentPanel.js | 52 +++ .../src/front/classes/edition-panels/Panel.js | 90 +++++ .../classes/edition-panels/SuggestionPanel.js | 74 ++++ .../src/front/composables/helpers.js | 30 ++ .../plugins/front-comments/src/front/index.js | 73 ++++ .../plugins/front-comments/src/front/store.js | 40 ++ .../src/panel/components/KCommentsView.vue | 177 +++++++++ .../plugins/front-comments/src/panel/index.js | 11 + site/plugins/front-comments/test.php | 14 + .../front-comments/translations/en.php | 16 + .../front-comments/translations/fr.php | 17 + 53 files changed, 2921 insertions(+), 1 deletion(-) delete mode 160000 site/plugins/front-comments create mode 100644 site/plugins/front-comments/.editorconfig create mode 100755 site/plugins/front-comments/LICENSE.md create mode 100755 site/plugins/front-comments/README.md create mode 100644 site/plugins/front-comments/SECURITY.md create mode 100644 site/plugins/front-comments/assets/icons/accept.svg create mode 100644 site/plugins/front-comments/assets/icons/chat-box-empty.svg create mode 100644 site/plugins/front-comments/assets/icons/chat-box-plus.svg create mode 100644 site/plugins/front-comments/assets/icons/chat-box-text-select.svg create mode 100644 site/plugins/front-comments/assets/icons/code.svg create mode 100644 site/plugins/front-comments/assets/icons/decline.svg create mode 100644 site/plugins/front-comments/assets/icons/delete.svg create mode 100644 site/plugins/front-comments/assets/icons/gitlab.svg create mode 100644 site/plugins/front-comments/assets/icons/palette.svg create mode 100644 site/plugins/front-comments/assets/icons/pen.svg create mode 100644 site/plugins/front-comments/assets/index.css create mode 100644 site/plugins/front-comments/assets/index.js create mode 100644 site/plugins/front-comments/assets/style.css create mode 100644 site/plugins/front-comments/blueprints/fields/team.yml create mode 100644 site/plugins/front-comments/classes/Comment.php create mode 100755 site/plugins/front-comments/composer.json create mode 100644 site/plugins/front-comments/composer.lock create mode 100644 site/plugins/front-comments/dialogs/create-issue.php create mode 100644 site/plugins/front-comments/dialogs/delete-comment.php create mode 100644 site/plugins/front-comments/doc/cover.jpg create mode 100644 site/plugins/front-comments/dropdowns/comment.php create mode 100644 site/plugins/front-comments/index.css create mode 100644 site/plugins/front-comments/index.js create mode 100755 site/plugins/front-comments/index.php create mode 100644 site/plugins/front-comments/lib/functions.php create mode 100644 site/plugins/front-comments/package-lock.json create mode 100644 site/plugins/front-comments/package.json create mode 100644 site/plugins/front-comments/routes/delete-comment.php create mode 100644 site/plugins/front-comments/routes/store-comment.php create mode 100644 site/plugins/front-comments/snippets/front-comments-field.php create mode 100644 site/plugins/front-comments/snippets/front-comments-script.php create mode 100644 site/plugins/front-comments/snippets/front-comments-style.php create mode 100644 site/plugins/front-comments/snippets/front-comments.php create mode 100644 site/plugins/front-comments/src/front/classes/AddBtn.js create mode 100644 site/plugins/front-comments/src/front/classes/Suggestion.js create mode 100644 site/plugins/front-comments/src/front/classes/comments/Comment.js create mode 100644 site/plugins/front-comments/src/front/classes/comments/CommentBuilder.js create mode 100644 site/plugins/front-comments/src/front/classes/edition-panels/CommentPanel.js create mode 100644 site/plugins/front-comments/src/front/classes/edition-panels/Panel.js create mode 100644 site/plugins/front-comments/src/front/classes/edition-panels/SuggestionPanel.js create mode 100644 site/plugins/front-comments/src/front/composables/helpers.js create mode 100644 site/plugins/front-comments/src/front/index.js create mode 100644 site/plugins/front-comments/src/front/store.js create mode 100644 site/plugins/front-comments/src/panel/components/KCommentsView.vue create mode 100644 site/plugins/front-comments/src/panel/index.js create mode 100644 site/plugins/front-comments/test.php create mode 100644 site/plugins/front-comments/translations/en.php create mode 100644 site/plugins/front-comments/translations/fr.php diff --git a/site/plugins/front-comments b/site/plugins/front-comments deleted file mode 160000 index a20a49f..0000000 --- a/site/plugins/front-comments +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a20a49fe8be9300cca38e95e7d84db47497a646f diff --git a/site/plugins/front-comments/.editorconfig b/site/plugins/front-comments/.editorconfig new file mode 100644 index 0000000..3b762c9 --- /dev/null +++ b/site/plugins/front-comments/.editorconfig @@ -0,0 +1,20 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.php] +indent_size = 4 + +[*.md,*.txt] +trim_trailing_whitespace = false +insert_final_newline = false + +[composer.json] +indent_size = 4 diff --git a/site/plugins/front-comments/LICENSE.md b/site/plugins/front-comments/LICENSE.md new file mode 100755 index 0000000..8e663d7 --- /dev/null +++ b/site/plugins/front-comments/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/site/plugins/front-comments/README.md b/site/plugins/front-comments/README.md new file mode 100755 index 0000000..bf0da4d --- /dev/null +++ b/site/plugins/front-comments/README.md @@ -0,0 +1,98 @@ +![Kirby Front Comments plugin cover](./doc/cover.jpg) + +# Kirby front comments plugin + +The Kirby Front Comments plugin allows you to add comments anywhere in the front-end of your Kirby website, making it easy for admins, developers, designers and other collaborators to communicate and collaborate directly on the site. It automatically integrate contextual information to each comment, such as user agent, window width, date and time, making it a valuable tool for debugging and troubleshooting. + +In addition, the plugin can be connected to your GitHub, GitLab (including Framagit) account, allowing you to create and close issues directly from your website. This makes it easy to track and manage issues, and to keep all your collaboration in one place. + +## Setup + +### Install + +**Composer is the recommended way to install the plugin.** Run the following command in your terminal: + +``` +composer require adrienpayet/front-comments +``` + +Alternatively, you can download this repository and add it to the /site/plugins directory of your project. + +### Include the snippet + +Add the snippet anywhere inside the `` of your header: ``. + +### Connect with GitHub or GitLab repository (optional) + +To create issues directly from comments on the website, add the repository informations to the plugin `repo` option : + +`/site/config/config.php`: + +```php +return [ + 'adrienpayet.front-comments.repo.service' => 'github', // REQUIRED - 'github' | 'gitlab' | 'framagit' (case insensive) + 'adrienpayet.front-comments.repo.token' => 'glpat-xxxxxxxxxxxxxxxxxxxx', // REQUIRED - access token (see below) + 'adrienpayet.front-comments.repo.owner' => 'username', // REQUIRED + 'adrienpayet.front-comments.repo.name' => 'repository name', // REQUIRED - 'Your Plugin Name' | 'your-plugin-name' + 'adrienpayet.front-comments.repo.labels' => ['bug', 'front-end'], // OPTIONAL - ['label 1', 'label 2'] (Default value is set to ['front-comments']). +] +``` + +**Use the string notation to set each option individually. Setting the plugins options as an array would overwrite some necessary default options.** + +_Learn how to create and manage personnal access tokens on [GitHub](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) and [GitLab](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token)._ + +## Use + +### Add new comments + +Logged in users can add comments directly in the front-end by clicking the button located by default in the bottom right corner of the screen. See below how to [change its position](#customize). + +### Manage comments though the panel + +To view and manage all comments, visit `your-website.com/panel/comments`, also is accessible from the default panel menu. To add the comments global view to your custom panel menu, call 'comments' in your `/site/config/config.php` : + +```php +'panel' => [ + 'menu' => [ + 'custom-menu-item' => [...], + '-', + + 'comments' + + 'users', + ] +] +``` + +From this section, you can create and delete comments, as well as create or visit linked issues. + +Please note that **issues can only be created through this section**. However, deleting a comment, whether from the front-end or the panel, will automatically close any linked issues. This ensures that your comments and issues are always synchronized and up-to-date. + +## Customize + +### Change the add button position + +The default position of the add button is set to bottom right. You can change it by passing a `position` property to the snippet : + +```php + 'bottom-right' // default position + // alternatives : + 'position' => 'bottom-left' + 'position' => 'top-left' + 'position' => 'top-right' +]) ?> +``` + +## Troubleshooting + +### Fix 403 error (rare) + +In rare cases, the plugin files may not load due to 403 errors (check the JavaScript console). Fix it by passing a `'location' => 'assets'` property to the snippet: + +```php + 'assets']) ?> +``` + +This will copy the files into `/assets/front-comments`, which should resolve the issue. diff --git a/site/plugins/front-comments/SECURITY.md b/site/plugins/front-comments/SECURITY.md new file mode 100644 index 0000000..3726336 --- /dev/null +++ b/site/plugins/front-comments/SECURITY.md @@ -0,0 +1,18 @@ +# Security Policy + +## Supported Versions + +*Use this section to tell people about which versions of your project are currently being supported with security updates.* + +| Version | Supported | +| ------- | ------------------ | +| 5.1.x | :white_check_mark: | +| 5.0.x | :x: | +| 4.0.x | :white_check_mark: | +| < 4.0 | :x: | + +## Reporting a Vulnerability + +*Use this section to tell people how to report a vulnerability.* + +*Tell them where to go, how often they can expect to get an update on a reported vulnerability, what to expect if the vulnerability is accepted or declined, etc.* diff --git a/site/plugins/front-comments/assets/icons/accept.svg b/site/plugins/front-comments/assets/icons/accept.svg new file mode 100644 index 0000000..76352cb --- /dev/null +++ b/site/plugins/front-comments/assets/icons/accept.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/site/plugins/front-comments/assets/icons/chat-box-empty.svg b/site/plugins/front-comments/assets/icons/chat-box-empty.svg new file mode 100644 index 0000000..34b364d --- /dev/null +++ b/site/plugins/front-comments/assets/icons/chat-box-empty.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/site/plugins/front-comments/assets/icons/chat-box-plus.svg b/site/plugins/front-comments/assets/icons/chat-box-plus.svg new file mode 100644 index 0000000..ec99631 --- /dev/null +++ b/site/plugins/front-comments/assets/icons/chat-box-plus.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/site/plugins/front-comments/assets/icons/chat-box-text-select.svg b/site/plugins/front-comments/assets/icons/chat-box-text-select.svg new file mode 100644 index 0000000..7326afc --- /dev/null +++ b/site/plugins/front-comments/assets/icons/chat-box-text-select.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/site/plugins/front-comments/assets/icons/code.svg b/site/plugins/front-comments/assets/icons/code.svg new file mode 100644 index 0000000..b8d8005 --- /dev/null +++ b/site/plugins/front-comments/assets/icons/code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/plugins/front-comments/assets/icons/decline.svg b/site/plugins/front-comments/assets/icons/decline.svg new file mode 100644 index 0000000..cd5a56d --- /dev/null +++ b/site/plugins/front-comments/assets/icons/decline.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/site/plugins/front-comments/assets/icons/delete.svg b/site/plugins/front-comments/assets/icons/delete.svg new file mode 100644 index 0000000..a18c05e --- /dev/null +++ b/site/plugins/front-comments/assets/icons/delete.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/site/plugins/front-comments/assets/icons/gitlab.svg b/site/plugins/front-comments/assets/icons/gitlab.svg new file mode 100644 index 0000000..b4ae72b --- /dev/null +++ b/site/plugins/front-comments/assets/icons/gitlab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/plugins/front-comments/assets/icons/palette.svg b/site/plugins/front-comments/assets/icons/palette.svg new file mode 100644 index 0000000..8115984 --- /dev/null +++ b/site/plugins/front-comments/assets/icons/palette.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/plugins/front-comments/assets/icons/pen.svg b/site/plugins/front-comments/assets/icons/pen.svg new file mode 100644 index 0000000..a8b4ba1 --- /dev/null +++ b/site/plugins/front-comments/assets/icons/pen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/site/plugins/front-comments/assets/index.css b/site/plugins/front-comments/assets/index.css new file mode 100644 index 0000000..1afa00c --- /dev/null +++ b/site/plugins/front-comments/assets/index.css @@ -0,0 +1 @@ +h2[data-v-019dfc9e]{margin-bottom:1rem}.k-table .k-table-index-column[data-v-019dfc9e]{width:6rem} diff --git a/site/plugins/front-comments/assets/index.js b/site/plugins/front-comments/assets/index.js new file mode 100644 index 0000000..f145fcd --- /dev/null +++ b/site/plugins/front-comments/assets/index.js @@ -0,0 +1,35 @@ +(function(){"use strict";const m={comments:[],suggestions:[],author:null,page:{id:null,uri:null},csrf:null,save(u){const t={};t[u]=this[u];const d={method:"PATCH",headers:{"X-CSRF":this.csrf},body:JSON.stringify(t).replaceAll("_","")};return fetch("/api/pages/"+this.page.id,d).then(c=>c.ok?c.json():Promise.reject("Front comments plugin - can't add comment: "+c.statusText)).then(c=>{console.log(c),console.log("Front comments plugin - comment successfully added.")}).catch(c=>Promise.reject(c))}};var R=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function G(u){return u&&u.__esModule&&Object.prototype.hasOwnProperty.call(u,"default")?u.default:u}var U={exports:{}};(function(u,t){(function(d,c){u.exports=c()})(R,function(){var d=1e3,c=6e4,b=36e5,P="millisecond",w="second",C="minute",D="hour",M="day",j="week",y="month",J="quarter",x="year",T="date",Z="Invalid Date",it=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,rt=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,ot={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(r){var s=["th","st","nd","rd"],e=r%100;return"["+r+(s[(e-20)%10]||s[e]||s[0])+"]"}},I=function(r,s,e){var i=String(r);return!i||i.length>=s?r:""+Array(s+1-i.length).join(e)+r},at={s:I,z:function(r){var s=-r.utcOffset(),e=Math.abs(s),i=Math.floor(e/60),n=e%60;return(s<=0?"+":"-")+I(i,2,"0")+":"+I(n,2,"0")},m:function r(s,e){if(s.date()1)return r(a[0])}else{var l=s.name;L[l]=s,n=l}return!i&&n&&(k=n),n||!i&&k},_=function(r,s){if(N(r))return r.clone();var e=typeof s=="object"?s:{};return e.date=r,e.args=arguments,new H(e)},h=at;h.l=F,h.i=N,h.w=function(r,s){return _(r,{locale:s.$L,utc:s.$u,x:s.$x,$offset:s.$offset})};var H=function(){function r(e){this.$L=F(e.locale,null,!0),this.parse(e),this.$x=this.$x||e.x||{},this[K]=!0}var s=r.prototype;return s.parse=function(e){this.$d=function(i){var n=i.date,o=i.utc;if(n===null)return new Date(NaN);if(h.u(n))return new Date;if(n instanceof Date)return new Date(n);if(typeof n=="string"&&!/Z$/i.test(n)){var a=n.match(it);if(a){var l=a[2]-1||0,f=(a[7]||"0").substring(0,3);return o?new Date(Date.UTC(a[1],l,a[3]||1,a[4]||0,a[5]||0,a[6]||0,f)):new Date(a[1],l,a[3]||1,a[4]||0,a[5]||0,a[6]||0,f)}}return new Date(n)}(e),this.init()},s.init=function(){var e=this.$d;this.$y=e.getFullYear(),this.$M=e.getMonth(),this.$D=e.getDate(),this.$W=e.getDay(),this.$H=e.getHours(),this.$m=e.getMinutes(),this.$s=e.getSeconds(),this.$ms=e.getMilliseconds()},s.$utils=function(){return h},s.isValid=function(){return this.$d.toString()!==Z},s.isSame=function(e,i){var n=_(e);return this.startOf(i)<=n&&n<=this.endOf(i)},s.isAfter=function(e,i){return _(e) + ${this.author.slice(0,1).toUpperCase()} + `);return this.team&&(t.classList.add("fc__team-icon"),t.classList.add(`fc__team-icon--${this.team}`)),t.addEventListener("mouseenter",()=>{setTimeout(()=>{this.expand()},10)}),this.node=t,t}expand(){const t=this.windowWidth?`
  • + Largeur fenêtre : ${this.windowWidth}px +
  • `:"",d=this.userAgent?`
  • + Agent utilisateur :
    + ${this.userAgent} +
  • `:"",c=this.userAgent||this.windowWidth?` +
    + + +
    +
      + ${t} + ${d} +
    +
    +
    + `:"",b=this._injectNode(`
    + + ${this.author}
    ${this.date} à ${this.time}
    + +

    ${this.message}

    + ${c} +
    `);q.fixOffscreen(b),b.querySelector(".fc__comment-delete").addEventListener("click",()=>{this.remove()});const w=document.querySelector(".fc__open-window");return w&&w.addEventListener("click",()=>{window.open(window.location.href,"",`width=${this.windowWidth}, height=800`)}),b.addEventListener("mouseleave",()=>{setTimeout(()=>{this.toBubble()},10)}),this.node=b,b}_injectNode(t){this.node&&document.body.removeChild(this.node);const d=document.createElement("div");d.innerHTML=t;const c=d.firstChild;return document.body.appendChild(c),c}async remove(){const t={method:"PATCH"};fetch(`/comments/delete/${this.id}/${m.page.uri}.json`,t).then(d=>d.json()).then(d=>{m.comments=m.comments.filter(c=>c.id!=this.id),document.body.removeChild(this.node)}).catch(d=>{console.log(d)})}}class et{constructor(){this._panel,this._textArea}create(){this._panel=this._createPanel(),this._textArea=this._createTextArea();const t=this._createBtns();this._panel.appendChild(this._textArea),this._panel.appendChild(t),document.body.appendChild(this._panel),this._textArea.focus(),q.fixOffscreen(this._panel),document.querySelector(".fc__edition-panel__remove-btn").addEventListener("click",()=>{document.body.removeChild(this._panel)})}_createPanel(){const t=document.createElement("div");return t.classList.add("fc__edition-panel"),t.style.left=this._getMousePos().x+"px",t.style.top=this._getMousePos().y+window.scrollY+"px",t}_createBtns(){const t=document.createElement("div");t.classList.add("fc__edition-panel__btns");const d=document.createElement("button");d.classList.add("fc__edition-panel__remove-btn"),d.textContent="supprimer";const c=document.createElement("button");return c.classList.add("fc__edition-panel__save-btn"),c.textContent="enregistrer",t.appendChild(d),t.appendChild(c),t}_getMousePos(){return{x:event.clientX,y:event.clientY}}_createTextArea(){const t=document.createElement("textarea");return t.classList.add("fc__text"),t}_getPos(){const t=this._panel.offsetLeft/((window.innerWidth+window.pageXOffset)/100);return{top:this._panel.style.top,left:t+"vw"}}}class z{constructor(){this.position={},this.author="",this.team="",this.message="",this.id=Date.now(),this.date=X().format("DD/MM/YY"),this.time=X().format("HH:mm"),this.windowWidth=window.innerWidth,this.userAgent=navigator.userAgent}setPosition(t){return this.position=t,this}setAuthor(t){return this.author=t,this}setTeam(t){return this.team=t,this}setMessage(t){return this.message=t,this}setId(t){return this.id=t,this}setDate(t){return this.date=t,this}setTime(t){return this.time=t,this}setWindowWidth(t){return this.windowWidth=t,this}setUserAgent(t){return this.userAgent=t,this}build(){return!this.position||!this.author||!this.message?(console.error("Missing required parameters for Comment: position, author, message",this),null):new tt(this.position,this.author,this.message,this.id,this.date,this.time,this.windowWidth,this.userAgent,this.team)}}class nt extends et{create(){super.create(),document.querySelector(".fc__edition-panel__save-btn").addEventListener("click",()=>{this._createComment()}),this._textArea.addEventListener("keydown",t=>{t.key==="Enter"&&!t.shiftKey&&this._createComment(),t.key==="Escape"&&document.body.removeChild(this._panel)})}async _createComment(){const t=new z().setAuthor(m.author).setTeam(m.team).setMessage(this._textArea.value).setPosition({top:this._getPos().top,left:this._getPos().left}).build();try{m.comments.push(t),await m.save("comments"),t.toBubble(),document.body.removeChild(this._panel)}catch(d){m.comments=m.comments.filter(c=>c.id!==t.id),document.body.removeChild(t.node),console.error("Create comment failed:",d)}return t}}class st{constructor(t){this._button=this._createButton(t),this._initEventListeners()}_createButton(t){const d=document.createElement("div");d.innerHTML=``;const c=d.firstChild;return document.body.appendChild(c),c}_initEventListeners(){this._button.addEventListener("click",this._handleClick.bind(this)),window.addEventListener("mousemove",this._handleMouseMove.bind(this)),window.addEventListener("keydown",this._handleKeyDown.bind(this))}_handleClick(t){this._button.classList.contains("fc__btn-add--move")&&(new nt().create(),this._resetPosition()),this._button.classList.toggle("fc__btn-add--move")}_handleMouseMove(t){this._button.classList.contains("fc__btn-add--move")&&(this._button.style.left=t.clientX-48/2+"px",this._button.style.top=t.clientY+window.scrollY-48/2+"px")}_handleKeyDown(t){t.key==="Escape"&&(this._button.classList.remove("fc__btn-add--move"),this._resetPosition())}_resetPosition(){this._button.style.left="",this._button.style.top=""}}document.addEventListener("DOMContentLoaded",()=>{m.author=FCAuthor,m.team=FCTeam.length>0?FCTeam:void 0,m.page.id=FCPageId,m.page.uri=FCPageUri,m.csrf=FCCsrf,m.filesPath=FCFilesPath;try{FCComments.forEach(u=>{try{const t=new z().setPosition(u.position).setAuthor(u.author).setMessage(u.message).setId(u.id).setDate(u.date).setTime(u.time).setWindowWidth(u.windowWidth).setUserAgent(u.userAgent).setTeam(u==null?void 0:u.team).build();t.toBubble(),m.comments.push(t)}catch(t){console.error("Plugin Front Comments : can't parse comments : ",t),console.log("Comments : ",FCComments)}})}catch(u){console.error("Can't parse comments : ",u),console.log("Comments : ",FCComments)}new st(FCPosition)})})(); diff --git a/site/plugins/front-comments/assets/style.css b/site/plugins/front-comments/assets/style.css new file mode 100644 index 0000000..086d608 --- /dev/null +++ b/site/plugins/front-comments/assets/style.css @@ -0,0 +1,336 @@ +:root { + --fc-border: 2px solid #000; + --fc-border-light: 1px solid #999; + --fc-font-size-m: 1.1rem; + --fc-font-size-s: calc(var(--fc-font-size-m) / 1.3); +} + +button { + transition: all 0.2s ease-in-out; +} + +.fc__btn { + all: initial; + border: none !important; + background-color: transparent !important; + padding: 0 !important; + cursor: pointer !important; +} +.fc__btn:not(.fc__bubble):hover, +.fc__btn-add.fc__btn-add--move { + filter: invert(100%); +} +.fc__icon { + width: 100%; +} + +.fc__bubble, +.fc__btn-add { + z-index: 999; +} +.fc__btn-add:focus { + outline: none !important; +} + +.fc__edition-panel, +.fc__btn-add, +.fc__bubble { + z-index: 999; +} + +.fc__btn-add { + position: fixed; + width: 3rem; + height: 2.5rem; + cursor: pointer; +} +.fc__btn-add--bottom-right { + bottom: 1rem; + right: 1rem; +} +.fc__btn-add--bottom-left { + bottom: 1rem; + left: 1rem; +} +.fc__btn-add--top-left { + top: 1rem; + left: 1rem; +} +.fc__btn-add--top-right { + top: 1rem; + right: 1rem; +} + +.fc__btn-add .fc__plus { + width: 3rem; + height: 3rem; + display: inline-block; + transform: translateY(-2px); +} +.fc__btn-add:not(.fc__btn-add--move) { + top: auto !important; + left: auto !important; +} +.fc__btn-add.fc__btn-add--move { + position: absolute; + cursor: none !important; +} + +.fc__btn-add--field { + right: 5rem; +} + +.fc__edition-panel { + --panel-width: 15rem; + position: absolute; + padding-bottom: 0; +} + +.fc__edition-panel--left { + transform: translateX(calc(0rem - var(--panel-width))); +} +.fc__edition-panel--top { + transform: translateY(calc(0rem - 150px)); +} + +.fc__edition-panel textarea { + position: relative !important; + resize: none !important; + color: #000 !important; + font-family: sans-serif !important; + font-weight: 100 !important; + + width: var(--panel-width) !important; + height: 7rem !important; + outline: none !important; + border: var(--fc-border) !important; + padding: 0.5rem !important; +} + +.fc__edition-panel textarea:focus { + outline: none !important; +} + +.fc__edition-panel__btns { + display: flex; + background-color: #fff; + color: #000; + margin-top: 0.5rem; +} + +.fc__edition-panel__btns button { + all: initial; + + color: #000 !important; + font-family: sans-serif; + font-weight: 100; + text-align: center; + font-size: 1rem; + + width: 100%; + padding: 0.5rem; + border: var(--fc-border) !important; + background-color: #fff; + cursor: pointer; +} +.fc__edition-panel__btns button:first-child { + border-right: none !important; +} + +.fc__edition-panel__btns button:hover { + background-color: #000 !important; + color: #fff !important; +} + +.fc__bubble { + position: absolute !important; + display: flex !important; + justify-content: center !important; + align-items: center !important; + + width: 3rem !important; + height: 2.9rem !important; + scroll-margin-top: 6rem !important; + + color: #000 !important; + font-family: sans-serif !important; + font-size: var(--fc-font-size-m) !important; + font-weight: 500 !important; + + background-image: var(--fc-icon-chat-box-empty) !important; + background-size: 3rem 2.5rem !important; + background-position: -2px 4px !important; + background-repeat: no-repeat !important; +} + +.fc__comment { + position: absolute !important; + z-index: 999 !important; + + width: 20rem !important; + padding: 1rem !important; + background-color: #fff !important; + color: #000 !important; + border: var(--fc-border) !important !important; +} + +.fc__comment * { + color: #000 !important; + font-family: sans-serif !important; + font-weight: 100 !important; +} + +.fc__comment p { + font-size: 1rem !important; + margin: 1rem 0 !important; +} + +.fc__comment-delete { + position: absolute; + right: 1rem; + top: 1rem; +} + +.fc__icon { + width: 1.5rem; + height: 1.5rem; +} + +.fc__comment, +.fc__edition-panel { + font-family: sans-serif; + font-size: var(--fc-font-size-m); + font-weight: 100; +} + +/* ================= CONTEXT ================= */ +#collapsible { + display: none; +} + +.fc__label-toggle { + display: block; + font-size: var(--fc-font-size-s); + cursor: pointer; +} + +.fc__label-toggle::before { + content: " "; + display: inline-block; + + border-top: 5px solid transparent; + border-bottom: 5px solid transparent; + border-left: 5px solid currentColor; + + vertical-align: middle; + margin-right: 0.7rem; + transform: translateY(-2px); + + transition: transform 0.2s ease-out; +} + +.fc__collapsible-content { + max-height: 0px; + overflow: hidden; + + transition: max-height 0.25s ease-in-out; +} + +.fc__toggle:checked + .fc__label-toggle + .fc__collapsible-content { + max-height: 100vh; +} +.fc__toggle:checked + .fc__label-toggle::before { + transform: rotate(90deg) translateX(-3px); +} + +.fc__content-inner { + margin: 0; + margin-top: 1rem; + padding-left: 0; +} + +.fc__context-item { + list-style-type: none; + font-size: var(--fc-font-size-s); + line-height: 1.3; +} +.fc__context-item:not(:last-child) { + padding-bottom: 0.5rem; + margin-bottom: 0.5rem; + border-bottom: 1px dotted #000; +} + +.fc__open-window { + all: initial; + background-color: transparent !important; + border: 1px solid #000 !important; + border-radius: 0 !important; + cursor: pointer !important; + margin-left: 1rem !important; + padding: 0.1rem 0.3rem !important; +} + +.fc__open-window:hover { + background-color: #000 !important; + color: #fff !important; +} +/* ================= END CONTEXT ================= */ + +.fc__author { + font-weight: 400; +} + +.fc__datetime { + font-size: var(--fc-font-size-s); +} + +.fc__suggestion { + position: relative; + padding: 0.1rem 0.2rem; + margin: 0 0.2rem; + background-color: inherit; + border: var(--fc-border); +} +.fc__suggestion:hover { + color: #fff; + background-color: #000; +} +.fc__suggestion--edit { + background-color: rgba(0, 0, 0, 0.1) !important; +} + +.fc__suggestion-bubble { + position: absolute; + z-index: 999; + width: 20vw; + background-color: #fff; + color: #000; + border: var(--fc-border); + padding: 1rem; + left: -0.1rem; + bottom: -5.5rem; +} + +.fc__suggestion-bubble__btns { + position: absolute; + top: 1rem; + right: 1rem; + display: flex; + column-gap: 0.5rem; +} + +.fc__team-icon::before { + width: 1rem; + height: 1rem; + margin-right: 0.2rem; + transform: translateY(-0.1rem); +} +.fc__team-icon--code::before { + content: url("/media/plugins/adrienpayet/front-comments/icons/code.svg"); +} +.fc__team-icon--design::before { + content: url("/media/plugins/adrienpayet/front-comments/icons/palette.svg"); +} +.fc__team-icon--content::before { + content: url("/media/plugins/adrienpayet/front-comments/icons/pen.svg"); +} diff --git a/site/plugins/front-comments/blueprints/fields/team.yml b/site/plugins/front-comments/blueprints/fields/team.yml new file mode 100644 index 0000000..30a0126 --- /dev/null +++ b/site/plugins/front-comments/blueprints/fields/team.yml @@ -0,0 +1,14 @@ +label: Équipe +type: toggles +grow: false +options: + - value: content + text: Contenu + icon: pen + - value: design + text: Design + icon: palette + - value: code + text: Code + icon: code +help: Pour identifier vos commentaires. diff --git a/site/plugins/front-comments/classes/Comment.php b/site/plugins/front-comments/classes/Comment.php new file mode 100644 index 0000000..44af57d --- /dev/null +++ b/site/plugins/front-comments/classes/Comment.php @@ -0,0 +1,201 @@ +page = $page; + $this->data = $commentData; + $this->options = option('adrienpayet.front-comments'); + + if ($this->options['repo.service']) { + $this->options['repo.service'] = strtolower($this->options['repo.service']); + $this->options['repo.name'] = strtolower($this->options['repo.name']); + $this->options['repo.name'] = str_replace(' ', '-', $this->options['repo.name']); + } + } + + + private function _getCreateIssueRequestUrl() + { + $id = urlencode($this->options['repo.owner'] . '/' . $this->options['repo.name']); + + $baseUrl = null; + if ($this->options['repo.service'] === 'github') { + $baseUrl = "https://api.github.com/repos/"; + } elseif ($this->options['repo.service'] === 'framagit') { + $baseUrl = "https://framagit.org/api/v4/projects/"; + } elseif ($this->options['repo.service'] === 'gitlab') { + $baseUrl = "https://gitlab.com/api/v4/projects/"; + } + + $url = null; + if ($this->options['repo.service'] === 'github') { + $url = $baseUrl . $id . "/issues?access_token=" . $this->options['repo.token']; + } else { + $url = $baseUrl . $id . "/issues?private_token=" . $this->options['repo.token']; + } + + return $url; + } + + private function _formatData() + { + $description = $this->_createDescription(); + + $data = array( + 'title' => $this->data['message'], + 'labels' => option('adrienpayet.front-comments.labels') + ); + + if ($this->options['repo.service'] === 'github') { + $data['body'] = $description; + } else { + $data['description'] = $description; + } + + return $data; + } + + private function _createDescription() + { + $description = 'Comment created by **' . $this->data['author'] . '** '; + $description .= 'the **' . $this->data['date'] . '** at ' . $this->data['time'] . ' '; + $description .= ' in a window of **' . $this->data['windowWidth'] . 'px width**. '; + $description .= 'User agent: ' . $this->data['userAgent'] . ' . '; + $description .= '[**SEE THE COMMENT**](' . site()->url() . '/' . $this->page->uri() . '/#' . $this->data['id'] .')'; + return $description; + } + + public function createIssue() + { + $requestUrl = $this->_getCreateIssueRequestUrl(); + $data = $this->_formatData(); + + $curl = curl_init(); + + curl_setopt_array($curl, [ + CURLOPT_URL => $requestUrl, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => 'POST', + CURLOPT_POSTFIELDS => json_encode($data), + CURLOPT_HTTPHEADER => [ + 'Content-Type: application/json', + ], + ]); + + $response = curl_exec($curl); + $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + + if ($httpCode != 201) { + throw new Exception("Failed to create issue: {$httpCode}", 1); + } + + curl_close($curl); + + $responseData = json_decode($response); + + if (isset($responseData->id)) { + $this->data['issue-id'] = $responseData->iid; + $this->data['issue-url'] = $this->options['repo.service'] === 'github' ? $responseData->html_url : $responseData->web_url; + } else { + throw new Exception("Invalid response format", 1); + } + } + + + public function closeIssue() + { + $requestUrl = $this->_getCloseIssueRequestUrl(); + + $data = null; + if ($this->options['repo.service'] === 'github') { + $data = json_encode([ + 'state' => 'closed' + ]); + } else { + $data = json_encode([ + 'state_event' => 'close' + ]); + } + + $curl = curl_init(); + + curl_setopt_array($curl, [ + CURLOPT_URL => $requestUrl, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_ENCODING => '', + CURLOPT_MAXREDIRS => 10, + CURLOPT_TIMEOUT => 0, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, + CURLOPT_CUSTOMREQUEST => $this->options['repo.service'] === 'github' ? 'PATCH' : 'PUT', + CURLOPT_POSTFIELDS => $data, + CURLOPT_HTTPHEADER => [ + 'Content-Type: application/json', + ], + ]); + + $response = curl_exec($curl); + $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + + if ($httpCode != 200) { + throw new Exception("Failed to close issue: {$httpCode}", 1); + } + + curl_close($curl); + } + + private function _getCloseIssueRequestUrl() + { + $id = urlencode($this->options['repo.owner'] . '/' . $this->options['repo.name']); + + $baseUrl = null; + if ($this->options['repo.service'] === 'github') { + $baseUrl = "https://api.github.com/repos/"; + } elseif ($this->options['repo.service'] === 'framagit') { + $baseUrl = "https://framagit.org/api/v4/projects/"; + } elseif ($this->options['repo.service'] === 'gitlab') { + $baseUrl = "https://gitlab.com/api/v4/projects/"; + } + + $issueId = $this->data['issue-id']; + + $url = null; + if ($this->options['repo.service'] === 'github') { + $url = $baseUrl . $id . "/issues/" . $issueId . "?access_token=" . $this->options['repo.token']; + } else { + $url = $baseUrl . $id . "/issues/" . $issueId . "?private_token=" . $this->options['repo.token']; + } + + return $url; + } + + + public function id() + { + return $this->data['id']; + } + + public function data() + { + return $this->data; + } + + public function hasIssue() + { + return isset($this->data['issue-id']) && strlen($this->data['issue-id']) > 0; + } + +} diff --git a/site/plugins/front-comments/composer.json b/site/plugins/front-comments/composer.json new file mode 100755 index 0000000..9621d25 --- /dev/null +++ b/site/plugins/front-comments/composer.json @@ -0,0 +1,26 @@ +{ + "name": "adrienpayet/front-comments", + "description": "Kirby plugin for adding comments anywhere in front-end pages.", + "license": "MIT", + "type": "kirby-plugin", + "version": "0.11.2", + "homepage": "https://framagit.org/isUnknown/kirby-front-comments", + "authors": [ + { + "name": "Adrien Payet", + "email": "adrien.payet@outlook.com" + } + ], + "require": { + "getkirby/composer-installer": "^1.1" + }, + "config": { + "allow-plugins": { + "getkirby/composer-installer": true + }, + "preferred-install": "dist" + }, + "extra": { + "installer-name": "front-comments" + } +} diff --git a/site/plugins/front-comments/composer.lock b/site/plugins/front-comments/composer.lock new file mode 100644 index 0000000..ec1ddb0 --- /dev/null +++ b/site/plugins/front-comments/composer.lock @@ -0,0 +1,66 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "2898e83ce5a2a538f1eea79c257844d2", + "packages": [ + { + "name": "getkirby/composer-installer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/getkirby/composer-installer.git", + "reference": "c98ece30bfba45be7ce457e1102d1b169d922f3d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/getkirby/composer-installer/zipball/c98ece30bfba45be7ce457e1102d1b169d922f3d", + "reference": "c98ece30bfba45be7ce457e1102d1b169d922f3d", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0" + }, + "require-dev": { + "composer/composer": "^1.8 || ^2.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Kirby\\ComposerInstaller\\Plugin" + }, + "autoload": { + "psr-4": { + "Kirby\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Kirby's custom Composer installer for the Kirby CMS and for Kirby plugins", + "homepage": "https://getkirby.com", + "support": { + "issues": "https://github.com/getkirby/composer-installer/issues", + "source": "https://github.com/getkirby/composer-installer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://getkirby.com/buy", + "type": "custom" + } + ], + "time": "2020-12-28T12:54:39+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.6.0" +} diff --git a/site/plugins/front-comments/dialogs/create-issue.php b/site/plugins/front-comments/dialogs/create-issue.php new file mode 100644 index 0000000..ff321ef --- /dev/null +++ b/site/plugins/front-comments/dialogs/create-issue.php @@ -0,0 +1,45 @@ + 'comments/create-issue/(:any)/(:all)', + 'load' => function (string $commentId, string $pageUri) { + return [ + 'component' => 'k-text-dialog', + 'props' => [ + 'text' => t('adrienpayet.front-comments.confirm-create-issue') + ] + ]; + }, + 'submit' => function (string $commentId, string $pageUri) { + + $page = Find::page($pageUri); + $comments = $page->comments()->toData('yaml'); + + $commentData = getCommentData($comments, $commentId); + + $comment = new Comment($commentData, $page); + + try { + $comment->createIssue(); + $comments = array_map( + function ($item) use ($comment) { + if ($item['id'] == $comment->id()) { + return $comment->data(); + } + return $item; + }, + $comments + ); + $page->update( + [ + 'comments' => $comments + ] + ); + return true; + } catch (\Throwable $th) { + throw new Exception($th->getMessage(), 1); + } + } +]; diff --git a/site/plugins/front-comments/dialogs/delete-comment.php b/site/plugins/front-comments/dialogs/delete-comment.php new file mode 100644 index 0000000..b417725 --- /dev/null +++ b/site/plugins/front-comments/dialogs/delete-comment.php @@ -0,0 +1,19 @@ + 'comments/delete/(:any)/(:all)', + 'load' => function (string $commentId, string $pageUri) { + return [ + 'component' => 'k-remove-dialog', + 'props' => [ + 'text' => t('adrienpayet.front-comments.confirm-delete-comment') + ] + ]; + }, + 'submit' => function (string $commentId, string $pageUri) { + deleteComment($pageUri, $commentId); + return true; + } +]; diff --git a/site/plugins/front-comments/doc/cover.jpg b/site/plugins/front-comments/doc/cover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a68bf4f5c6a73b04c329c153280064c8e0fa6a50 GIT binary patch literal 168983 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 literal 0 HcmV?d00001 diff --git a/site/plugins/front-comments/dropdowns/comment.php b/site/plugins/front-comments/dropdowns/comment.php new file mode 100644 index 0000000..a5285c5 --- /dev/null +++ b/site/plugins/front-comments/dropdowns/comment.php @@ -0,0 +1,43 @@ + 'comments/(:any)/(:all)', + 'action' => function (string $commentId, string $pageUri) { + $options = [ + [ + 'text' => t('adrienpayet.front-comments.see'), + 'icon' => 'preview', + 'link' => site()->url() . '/' . $pageUri . '/#' . $commentId, + ], + [ + 'text' => t('adrienpayet.front-comments.remove'), + 'icon' => 'remove', + 'dialog' => 'comments/delete/' . $commentId . '/' . $pageUri + ] + ]; + + if (option('adrienpayet.front-comments.repo.name')) { + $page = Find::page($pageUri); + $comments = $page->comments()->toData('yaml'); + + $commentData = getCommentData($comments, $commentId); + $service = strtolower(option('adrienpayet.front-comments.repo.service')); + + if (isset($commentData['issue-id']) && strlen($commentData['issue-id']) > 0) { + $options[] = [ + 'text' => t('adrienpayet.front-comments.see-issue'), + 'icon' => $service === 'github' ? 'github' : 'gitlab', + 'link' => $commentData['issue-url'], + ]; + } else { + $options[] = [ + 'text' => t('adrienpayet.front-comments.create-issue'), + 'icon' => $service === 'github' ? 'github' : 'gitlab', + 'dialog' => 'comments/create-issue/' . $commentId . '/' . $pageUri + ]; + } + } + + return $options; + } +]; diff --git a/site/plugins/front-comments/index.css b/site/plugins/front-comments/index.css new file mode 100644 index 0000000..5ef05eb --- /dev/null +++ b/site/plugins/front-comments/index.css @@ -0,0 +1 @@ +h2[data-v-15db4f00]{margin-bottom:1rem}.k-comment-author .k-icon[data-v-15db4f00]{display:inline-block;margin-right:1rem}.k-table .k-table-index-column[data-v-15db4f00]{width:6rem}section[data-v-15db4f00]{margin-bottom:2rem}.k-table td[data-v-15db4f00]{padding:.5rem;height:100%}.k-comment-author[data-v-15db4f00]{width:15rem}.author-wrapper[data-v-15db4f00]{display:flex}.k-comment-message[data-v-15db4f00]{width:100%}.k-comment-date[data-v-15db4f00]{width:6rem}.k-comment-time[data-v-15db4f00]{width:5rem}.k-comment-actions[data-v-15db4f00]{width:2rem} diff --git a/site/plugins/front-comments/index.js b/site/plugins/front-comments/index.js new file mode 100644 index 0000000..a5013a0 --- /dev/null +++ b/site/plugins/front-comments/index.js @@ -0,0 +1 @@ +(function(){"use strict";const g="";function C(l,t,e,d,n,m,r,c){var s=typeof l=="function"?l.options:l;t&&(s.render=t,s.staticRenderFns=e,s._compiled=!0),d&&(s.functional=!0),m&&(s._scopeId="data-v-"+m);var o;if(r?(o=function(i){i=i||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,!i&&typeof __VUE_SSR_CONTEXT__<"u"&&(i=__VUE_SSR_CONTEXT__),n&&n.call(this,i),i&&i._registeredComponents&&i._registeredComponents.add(r)},s._ssrRegister=o):n&&(o=c?function(){n.call(this,(s.functional?this.parent:this).$root.$options.shadowRoot)}:n),o)if(s.functional){s._injectStyles=o;var _=s.render;s.render=function(y,f){return o.call(f),_(y,f)}}else{var a=s.beforeCreate;s.beforeCreate=a?[].concat(a,o):[o]}return{exports:l,options:s}}const u={__name:"KCommentsView",props:{pages:Array,csrf:String},setup(l){const{pages:t,csrf:e}=l;n();function d(r,c){const[s,o,_]=r.split("/"),[a,i]=c.split(":");return new Date(`20${_}-${o}-${s}T${a}:${i}:00`)}function n(){const r=c=>d(c.date,c.time);t.forEach(c=>{c.comments.sort((s,o)=>{const _=r(s);return r(o)-_})}),t.sort((c,s)=>{const o=c.comments[c.comments.length-1],_=s.comments[s.comments.length-1],a=r(o);return r(_)-a})}function m(r,c){const s=t.findIndex(a=>a.comments.some(i=>i.id===r));t[s].comments.findIndex(a=>a.id===r);const o=t[s].comments.filter(a=>a.id!==r);t[s].comments=o;const _={method:"PATCH",headers:{"X-CSRF":e},body:JSON.stringify({comments:o})};fetch("/api/pages/"+c.replace("/","+"),_).then(a=>a.json()).then(a=>{console.log(a),console.log("Page successfully updated.")}).catch(a=>{console.log(a)})}return{__sfc:!0,convertToDate:d,sortByDate:n,remove:m}}};var p=function(){var t=this,e=t._self._c;return t._self._setupProxy,e("k-inside",[t.pages.length>0?[e("h1",{staticClass:"k-header-title"},[t._v("Pages")]),t._l(t.pages,function(d){return e("section",{key:d.uri},[e("h2",{staticClass:"k-label"},[t._v(t._s(d.title))]),e("div",{staticClass:"k-table"},[e("table",[e("thead",[e("tr",[e("th",{staticClass:"k-comment-author"},[t._v(" "+t._s(t.$t("adrienpayet.front-comments.author"))+" ")]),e("th",{staticClass:"k-comment-message"},[t._v(" "+t._s(t.$t("adrienpayet.front-comments.message"))+" ")]),e("th",{staticClass:"k-comment-date"},[t._v(" "+t._s(t.$t("adrienpayet.front-comments.date"))+" ")]),e("th",{staticClass:"k-comment-time"},[t._v(" "+t._s(t.$t("adrienpayet.front-comments.time"))+" ")]),e("th",{staticClass:"k-comment-actions"})])]),e("tbody",t._l(d.comments,function(n){return e("tr",{key:n.id},[e("td",{staticClass:"k-comment-author"},[e("div",{staticClass:"author-wrapper"},[(n==null?void 0:n.team)==="code"?e("k-icon",{attrs:{type:"code"}}):t._e(),(n==null?void 0:n.team)==="design"?e("k-icon",{attrs:{type:"palette"}}):t._e(),(n==null?void 0:n.team)==="content"?e("k-icon",{attrs:{type:"pen"}}):t._e(),t._v(" "+t._s(n.author)+" ")],1)]),e("td",{staticClass:"k-comment-message",domProps:{innerHTML:t._s(n.message)}}),e("td",{staticClass:"k-comment-date"},[t._v(" "+t._s(n.date)+" ")]),e("td",{staticClass:"k-comment-time"},[t._v(" "+t._s(n.time)+" ")]),e("td",{staticClass:"k-comment-actions"},[e("k-options-dropdown",{attrs:{options:"comments/"+n.id+"/"+d.uri}})],1)])}),0)])])])})]:e("h1",{staticClass:"k-header-title"},[t._v(" "+t._s(t.$t("adrienpayet.front-comments.no-comment"))+" ")])],2)},h=[],v=C(u,p,h,!1,null,"15db4f00",null,null);const k=v.exports;panel.plugin("adrienpayet/front-comments",{icons:{gitlab:''},components:{"k-comments-view":k}})})(); diff --git a/site/plugins/front-comments/index.php b/site/plugins/front-comments/index.php new file mode 100755 index 0000000..0781df6 --- /dev/null +++ b/site/plugins/front-comments/index.php @@ -0,0 +1,89 @@ + 'classes/Comment.php' +], __DIR__); + +require_once __DIR__ . '/lib/functions.php'; + +Kirby::plugin('adrienpayet/front-comments', [ + 'translations' => [ + 'en' => require_once(__DIR__ . '/translations/en.php'), + 'fr' => require_once(__DIR__ . '/translations/fr.php') + ], + 'options' => [ + 'cache' => true, + 'repo.service' => null, + 'repo.token' => null, + 'repo.owner' => null, + 'repo.name' => null, + 'repo.labels' => ['front-comments'] + ], + 'blueprints' => [ + 'fields/front-comments/team' => __DIR__ . '/blueprints/fields/team.yml' + ], + 'icons' => [], + 'areas' => [ + 'comments' => function ($kirby) { + return [ + 'label' => t('adrienpayet.front-comments.comments'), + 'icon' => 'chat', + 'menu' => true, + 'link' => 'comments', + 'dropdowns' => [ + require __DIR__ . '/dropdowns/comment.php' + ], + 'dialogs' => [ + require __DIR__ . '/dialogs/delete-comment.php', + require __DIR__ . '/dialogs/create-issue.php' + ], + 'views' => [ + [ + 'pattern' => 'comments', + 'action' => function () { + return [ + 'component' => 'k-comments-view', + 'title' => t('adrienpayet.front-comments.comments'), + 'props' => [ + 'pages' => function () { + $pages = array_values(kirby()->cache('adrienpayet.front-comments')->getOrSet('commented-pages', function () { return [] ;})); + return $pages; + }, + 'csrf' => csrf() + ], + ]; + } + ] + ], + ]; + } + ], + 'snippets' => [ + 'front-comments' => __DIR__ . '/snippets/front-comments.php', + 'front-comments-script' => __DIR__ . '/snippets/front-comments-script.php', + 'front-comments-style' => __DIR__ . '/snippets/front-comments-style.php', + 'front-comments-field' => __DIR__ . '/snippets/front-comments-field.php', + ], + 'routes' => [ + [ + 'pattern' => '/store-comment.json', + 'method' => 'POST', + 'action' => function () { + include_once __DIR__ . '/routes/store-comment.php'; + return storeComment(); + } + ], + [ + 'pattern' => '/comments/delete/(:any)/(:all).json', + 'method' => 'PATCH', + 'action' => function ($commentId, $pageUri) { + return json_encode(deleteComment($pageUri, $commentId)); + } + ] + ], + 'hooks' => [ + 'page.update:after' => function ($newPage) { + cacheFrontComments($newPage); + } + ] +]); diff --git a/site/plugins/front-comments/lib/functions.php b/site/plugins/front-comments/lib/functions.php new file mode 100644 index 0000000..cd01756 --- /dev/null +++ b/site/plugins/front-comments/lib/functions.php @@ -0,0 +1,120 @@ +getMessage(), 1); + } + } +} + +function deleteDir(string $dirPath): void +{ + if (!is_dir($dirPath)) { + throw new InvalidArgumentException("$dirPath must be a directory"); + } + if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') { + $dirPath .= '/'; + } + $files = glob($dirPath . '*', GLOB_MARK); + foreach ($files as $file) { + if (is_dir($file)) { + deleteDir($file); + } else { + unlink($file); + } + } + rmdir($dirPath); +} + +function setFiles($location) +{ + $destination = __DIR__ . '/../../../../assets/front-comments'; + + if ($location === 'media') { + if (is_dir($destination)) { + deleteDir($destination); + } + } else { + $source = __DIR__ . '/../assets'; + if (!is_dir($destination)) { + mkdir($destination, 0755, true); + } + + rec_copy($source, $destination); + } +} + +function getCommentData($comments, $commentId) +{ + + $comment = array_filter( + $comments, + function ($item) use ($commentId) { + return $item['id'] == $commentId; + } + ); + + $comment = current($comment); + + return $comment; + +} + +function deleteComment($pageUri, $commentId) +{ + $page = Find::page($pageUri); + + $comments = $page->comments()->toData('yaml'); + + $newComments = []; + foreach ($comments as $item) { + $comment = new Comment($item, $page); + if ($comment->id() == $commentId) { + if ($comment->hasIssue()) { + $comment->closeIssue(); + } + } else { + $newComments[] = $comment->data(); + } + } + + $newPage = $page->update( + [ + 'comments' => $newComments + ] + ); + + return $newPage->comments()->toData('yaml'); +} + +function cacheFrontComments($newPage) +{ + if ($newPage->comments()->exists() && $newPage->comments()->isNotEmpty()) { + $cache = kirby()->cache('adrienpayet.front-comments'); + $comments = $cache->getOrSet('commented-pages', function () { return []; }); + $comments[$newPage->uuid()->id()] = [ + 'uri' => $newPage->uri(), + 'title' => $newPage->title()->value(), + 'url' => $newPage->url(), + 'comments' => $newPage->comments()->yaml(), + ]; + + $cache->set('commented-pages', $comments); + } +} diff --git a/site/plugins/front-comments/package-lock.json b/site/plugins/front-comments/package-lock.json new file mode 100644 index 0000000..febfce0 --- /dev/null +++ b/site/plugins/front-comments/package-lock.json @@ -0,0 +1,355 @@ +{ + "name": "front-comments", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "dayjs": "^1.11.10" + }, + "devDependencies": { + "concurrently": "^8.2.2" + } + }, + "node_modules/@babel/runtime": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz", + "integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/concurrently": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz", + "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "date-fns": "^2.30.0", + "lodash": "^4.17.21", + "rxjs": "^7.8.1", + "shell-quote": "^1.8.1", + "spawn-command": "0.0.2", + "supports-color": "^8.1.1", + "tree-kill": "^1.2.2", + "yargs": "^17.7.2" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" + } + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/spawn-command": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + } + } +} diff --git a/site/plugins/front-comments/package.json b/site/plugins/front-comments/package.json new file mode 100644 index 0000000..3a32912 --- /dev/null +++ b/site/plugins/front-comments/package.json @@ -0,0 +1,23 @@ +{ + "scripts": { + "dev": "concurrently \"npm run dev:front\" \"npm run dev:panel\"", + "dev:front": "npx -y kirbyup src/front/index.js --out-dir assets/ --watch", + "dev:panel": "npx -y kirbyup src/panel/index.js --watch", + "build": "npm run build:front && npm run build:panel", + "build:front": "npx -y kirbyup src/front/index.js --out-dir assets/", + "build:panel": "npx -y kirbyup src/panel/index.js" + }, + "dependencies": { + "dayjs": "^1.11.10" + }, + "devDependencies": { + "concurrently": "^8.2.2" + }, + "archive": { + "exclude": [ + ".git", + ".gitignore", + ".gitattributes" + ] + } +} diff --git a/site/plugins/front-comments/routes/delete-comment.php b/site/plugins/front-comments/routes/delete-comment.php new file mode 100644 index 0000000..5182ea2 --- /dev/null +++ b/site/plugins/front-comments/routes/delete-comment.php @@ -0,0 +1,22 @@ + $item) { + if ($item['id'] === $request['id']) { + array_splice($data, $index, 1); + break; + } + } + + file_put_contents($dataFile, json_encode($data)); + + return json_encode($data); +} diff --git a/site/plugins/front-comments/routes/store-comment.php b/site/plugins/front-comments/routes/store-comment.php new file mode 100644 index 0000000..dc60ea6 --- /dev/null +++ b/site/plugins/front-comments/routes/store-comment.php @@ -0,0 +1,32 @@ + $item) { + if ($item['id'] === $request['id']) { + $foundIndex = $index; + break; + } + } + + if (is_null($foundIndex)) { + $jsonData[] = $request; + } else { + $jsonData[$foundIndex] = $request; + } + + file_put_contents($dataFile, json_encode($jsonData)); + return $jsonData; +} diff --git a/site/plugins/front-comments/snippets/front-comments-field.php b/site/plugins/front-comments/snippets/front-comments-field.php new file mode 100644 index 0000000..f5d4604 --- /dev/null +++ b/site/plugins/front-comments/snippets/front-comments-field.php @@ -0,0 +1,7 @@ +user()): ?> +

    + +
    + + + \ No newline at end of file diff --git a/site/plugins/front-comments/snippets/front-comments-script.php b/site/plugins/front-comments/snippets/front-comments-script.php new file mode 100644 index 0000000..eae8227 --- /dev/null +++ b/site/plugins/front-comments/snippets/front-comments-script.php @@ -0,0 +1,35 @@ +comments()->exists() && $page->comments()->isNotEmpty() + ? $page->comments()->toData('yaml') + : []; + +$suggestions = $page->suggestions()->exists() && $page->suggestions()->isNotEmpty() + ? $page->suggestions()->toData('yaml') + : []; + +foreach ($comments as &$comment) { + $comment['message'] = nl2br($comment['message']); +} + +foreach ($suggestions as &$suggestion) { + $suggestion['message'] = nl2br($suggestion['message']); +} + + +$commentsJson = json_encode($comments, JSON_HEX_APOS); +$suggestionsJson = json_encode($suggestions, JSON_HEX_APOS); +?> + + + :root { + --fc-icon-chat-box-empty: url(/icons/chat-box-empty.svg); + } + +user()) { + $position = isset($position) ? $position : 'bottom-right'; + $location = isset($location) ? $location : 'media'; + + $filesPath = $location === 'media' ? + '/media/plugins/adrienpayet/front-comments' + : '/assets/front-comments'; + setFiles($location); + + + echo snippet('front-comments-style', ['filesPath' => $filesPath]); + echo snippet( + 'front-comments-script', + [ + 'filesPath' => $filesPath, + 'position' => $position + ] + ); +} diff --git a/site/plugins/front-comments/src/front/classes/AddBtn.js b/site/plugins/front-comments/src/front/classes/AddBtn.js new file mode 100644 index 0000000..f4b2d24 --- /dev/null +++ b/site/plugins/front-comments/src/front/classes/AddBtn.js @@ -0,0 +1,89 @@ +import CommentPanel from "./edition-panels/CommentPanel.js"; +import Store from "../store.js"; + +/** + * Class representing the Add Button. + */ +class AddButton { + /** + * Create an AddButton. + * @param {string} selector - The CSS selector for the button. + */ + constructor(position) { + this._button = this._createButton(position); + this._initEventListeners(); + } + + /** + * Create and return a new button element with the specified HTML content. + * @return {HTMLButtonElement} The created button element. + * @private + */ + _createButton(position) { + const div = document.createElement("div"); + div.innerHTML = ``; + const button = div.firstChild; + document.body.appendChild(button); + return button; + } + + /** + * Initialize the event listeners for the button. + * @private + */ + _initEventListeners() { + this._button.addEventListener("click", this._handleClick.bind(this)); + window.addEventListener("mousemove", this._handleMouseMove.bind(this)); + window.addEventListener("keydown", this._handleKeyDown.bind(this)); + } + + /** + * Handle the click event on the button. + * @private + */ + _handleClick(event) { + if (this._button.classList.contains("fc__btn-add--move")) { + const commentPanel = new CommentPanel(); + commentPanel.create(); + this._resetPosition(); + } + this._button.classList.toggle("fc__btn-add--move"); + } + + /** + * Handle the mousemove event on the window. + * @private + */ + _handleMouseMove(event) { + if (this._button.classList.contains("fc__btn-add--move")) { + const iconSize = 48; + this._button.style.left = event.clientX - iconSize / 2 + "px"; + this._button.style.top = + event.clientY + window.scrollY - iconSize / 2 + "px"; + } + } + + /** + * Handle the keydown event on the window. + * @private + */ + _handleKeyDown(event) { + if (event.key === "Escape") { + this._button.classList.remove("fc__btn-add--move"); + this._resetPosition(); + } + } + + /** + * Reset the position of the button. + * @private + */ + _resetPosition() { + this._button.style.left = ""; + this._button.style.top = ""; + } +} + +export default AddButton; diff --git a/site/plugins/front-comments/src/front/classes/Suggestion.js b/site/plugins/front-comments/src/front/classes/Suggestion.js new file mode 100644 index 0000000..47dbf4b --- /dev/null +++ b/site/plugins/front-comments/src/front/classes/Suggestion.js @@ -0,0 +1,224 @@ +import dayjs from "dayjs"; +import Store from "../store.js"; + +class Suggestion { + constructor( + author, + context, + target, + suggestion, + fieldName, + id = Date.now(), + date = dayjs().format("DD/MM/YY"), + time = dayjs().format("HH:mm") + ) { + this.author = author; + this.context = context; + this.target = target; + this.suggestion = suggestion; + this.fieldName = fieldName; + this.id = id; + this.date = date; + this.time = time; + this.node; + this.highlightTargetInField(); + } + + highlightTargetInField() { + const highlight = document.querySelector(".fc__suggestion--edit"); + if (highlight) { + this.node = highlight; + highlight.classList.remove("fc__suggestion--edit"); + highlight.classList.add("fc__suggestion"); + } else { + const { target, fieldName } = this; + const fieldElement = this.getFieldElement(fieldName); + const textNodes = this.getTextNodes(fieldElement); + this.highlightTarget(textNodes, target); + } + + if (this.node) { + this.node.addEventListener("mouseenter", () => { + this._bubble = this.createBubble(); + this.node.appendChild(this._bubble); + }); + this.node.addEventListener("mouseleave", () => { + this.node.removeChild(this._bubble); + }); + } else { + this.remove(); + } + } + + getFieldElement(fieldName) { + return document.querySelector(`[data-field-name="${fieldName}"]`); + } + + getTextNodes(fieldElement) { + const textNodes = []; + const childNodes = Array.from(fieldElement.childNodes); + + childNodes.forEach((node) => { + if (node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== "") { + textNodes.push(node); + } else if (node.hasChildNodes()) { + textNodes.push(...this.getChildTextNodes(node)); + } + }); + + return textNodes; + } + + highlightTarget(textNodes, target) { + textNodes.forEach((textNode) => { + const targetIndex = textNode.textContent.indexOf(target); + + if ( + targetIndex >= 0 && + this.matchContext(textNode, target, targetIndex) + ) { + this.node = this.insertHighlightedTarget(textNode, target, targetIndex); + } else { + // this.remove(); + } + }); + } + + matchContext(textNode, target, targetIndex) { + const beforeMatch = textNode.textContent.slice( + Math.max(0, targetIndex - 30), + targetIndex + ); + const afterMatch = textNode.textContent.slice( + targetIndex + target.length, + targetIndex + target.length + 30 + ); + + return ( + beforeMatch === this.context.before && afterMatch === this.context.after + ); + } + + insertHighlightedTarget(textNode, target, targetIndex) { + const highlightedTarget = this.createHighlightedTarget(target); + const beforeTarget = this.createTextNode( + textNode.textContent.slice(0, targetIndex) + ); + const afterTarget = this.createTextNode( + textNode.textContent.slice(targetIndex + target.length) + ); + + textNode.parentNode.insertBefore(beforeTarget, textNode); + textNode.parentNode.insertBefore(highlightedTarget, textNode); + textNode.parentNode.insertBefore(afterTarget, textNode); + textNode.remove(); + return highlightedTarget; + } + + createHighlightedTarget(target) { + const highlightedTarget = document.createElement("span"); + highlightedTarget.classList.add("fc__suggestion"); + highlightedTarget.textContent = target; + return highlightedTarget; + } + + createTextNode(text) { + return document.createTextNode(text); + } + + getChildTextNodes(node) { + const textNodes = []; + const childNodes = Array.from(node.childNodes); + + childNodes.forEach((childNode) => { + if ( + childNode.nodeType === Node.TEXT_NODE && + childNode.textContent.trim() !== "" + ) { + textNodes.push(childNode); + } else if (childNode.hasChildNodes()) { + textNodes.push(...this.getChildTextNodes(childNode)); + } + }); + + return textNodes; + } + + createBubble() { + const bubble = document.createElement("div"); + bubble.className = "fc__suggestion-bubble"; + bubble.innerHTML = `

    ${this.suggestion}

    `; + + bubble.appendChild(this.createBtns()); + return bubble; + } + + createBtns() { + const btns = document.createElement("div"); + btns.classList.add("fc__suggestion-bubble__btns"); + const decline = document.createElement("button"); + decline.classList.add("fc__btn"); + decline.innerHTML = ``; + + const accept = document.createElement("button"); + accept.classList.add("fc__btn"); + accept.innerHTML = ``; + + decline.addEventListener("click", () => { + this.remove(); + }); + + accept.addEventListener("click", () => { + this.push(); + }); + + btns.appendChild(decline); + btns.appendChild(accept); + return btns; + } + + remove() { + Store.suggestions = Store.suggestions.filter( + (suggestion) => suggestion.id != this.id + ); + if (this.node !== undefined) { + this.node.parentNode.removeChild(this.node); + } + Store.save("suggestions"); + } + + push() { + const field = this.getFieldElement(this.fieldName); + + const data = {}; + data[this.fieldName] = field.dataset.content.replace( + this.target, + this.suggestion + ); + + const init = { + method: "PATCH", + headers: { + "X-CSRF": Store.csrf, + }, + body: JSON.stringify(data).replaceAll("_", ""), + }; + fetch("/api/pages/" + Store.page, init) + .then((response) => response.json()) + .then((response) => { + console.log(response); + console.log("Page comments successfully updated."); + }) + .catch((error) => { + console.log(error); + }); + + Store.suggestions = Store.suggestions.filter( + (suggestion) => suggestion.id != this.id + ); + Store.save("suggestions"); + this.node.outerHTML = this.suggestion; + } +} + +export default Suggestion; diff --git a/site/plugins/front-comments/src/front/classes/comments/Comment.js b/site/plugins/front-comments/src/front/classes/comments/Comment.js new file mode 100644 index 0000000..f0cde11 --- /dev/null +++ b/site/plugins/front-comments/src/front/classes/comments/Comment.js @@ -0,0 +1,163 @@ +import Store from "../../store.js"; +import dayjs from "dayjs"; +import Helpers from "../../composables/helpers.js"; + +/** + * Represents a comment on a webpage. + */ +class Comment { + /** + * Create a Comment. + * @param {Object} position - The positions where the comment should be displayed. + */ + constructor( + position, + author, + message, + id, + date, + time, + windowWidth, + userAgent, + team + ) { + this.position = position; + this.author = author; + this.message = message; + this.id = id; + this.date = date; + this.time = time; + this.windowWidth = windowWidth; + this.userAgent = userAgent; + this.team = team; + this.node; + } + + toBubble() { + const bubble = this._injectNode(``); + + if (this.team) { + bubble.classList.add("fc__team-icon"); + bubble.classList.add(`fc__team-icon--${this.team}`); + } + + bubble.addEventListener("mouseenter", () => { + setTimeout(() => { + this.expand(); + }, 10); + }); + + this.node = bubble; + return bubble; + } + + /** + * Show the comment message. + */ + expand() { + const windowWidthInfoElement = this.windowWidth + ? `
  • + Largeur fenêtre : ${this.windowWidth}px +
  • ` + : ""; + const userAgentInfoElement = this.userAgent + ? `
  • + Agent utilisateur :
    + ${this.userAgent} +
  • ` + : ""; + const contextInfoElement = + this.userAgent || this.windowWidth + ? ` +
    + + +
    +
      + ${windowWidthInfoElement} + ${userAgentInfoElement} +
    +
    +
    + ` + : ""; + + const comment = this._injectNode(`
    + + ${this.author}
    ${this.date} à ${this.time}
    + +

    ${this.message}

    + ${contextInfoElement} +
    `); + + Helpers.fixOffscreen(comment); + + const deleteBtn = comment.querySelector(".fc__comment-delete"); + + deleteBtn.addEventListener("click", () => { + this.remove(); + }); + + const openWindowBtn = document.querySelector(".fc__open-window"); + + if (openWindowBtn) { + openWindowBtn.addEventListener("click", () => { + window.open( + window.location.href, + "", + `width=${this.windowWidth}, height=800` + ); + }); + } + + comment.addEventListener("mouseleave", () => { + setTimeout(() => { + this.toBubble(); + }, 10); + }); + + this.node = comment; + return comment; + } + + _injectNode(htmlString) { + if (this.node) { + document.body.removeChild(this.node); + } + const div = document.createElement("div"); + div.innerHTML = htmlString; + const node = div.firstChild; + document.body.appendChild(node); + return node; + } + + /** + * Hide the comment message. + */ + async remove() { + const init = { + method: "PATCH", + }; + fetch(`/comments/delete/${this.id}/${Store.page.uri}.json`, init) + .then((res) => res.json()) + .then((json) => { + Store.comments = Store.comments.filter((item) => item.id != this.id); + document.body.removeChild(this.node); + }) + .catch((error) => { + console.log(error); + }); + } +} + +export default Comment; diff --git a/site/plugins/front-comments/src/front/classes/comments/CommentBuilder.js b/site/plugins/front-comments/src/front/classes/comments/CommentBuilder.js new file mode 100644 index 0000000..45b1b52 --- /dev/null +++ b/site/plugins/front-comments/src/front/classes/comments/CommentBuilder.js @@ -0,0 +1,95 @@ +import Store from "../../store.js"; +import dayjs from "dayjs"; +import Helpers from "../../composables/helpers.js"; +import Comment from "./Comment.js"; + +class CommentBuilder { + constructor() { + this.position = {}; + this.author = ""; + this.team = ""; + this.message = ""; + this.id = Date.now(); + this.date = dayjs().format("DD/MM/YY"); + this.time = dayjs().format("HH:mm"); + this.windowWidth = window.innerWidth; + this.userAgent = navigator.userAgent; + } + + /** + * + * @param {Object} position - An object with two properties: top and left. + * @param {string} position.top - The vertical position of the comment in CSS format (e.g. "10px", "50%"). + * @param {string} position.left - The horizontal position of the comment in CSS format (e.g. "10px", "50%"). + * @returns {CommentBuilder} The CommentBuilder instance for method chaining. + */ + setPosition(position) { + this.position = position; + return this; + } + + setAuthor(author) { + this.author = author; + return this; + } + + setTeam(team) { + this.team = team; + return this; + } + + setMessage(message) { + this.message = message; + return this; + } + + setId(id) { + this.id = id; + return this; + } + + setDate(date) { + this.date = date; + return this; + } + + setTime(time) { + this.time = time; + return this; + } + + setWindowWidth(windowWidth) { + this.windowWidth = windowWidth; + return this; + } + + setUserAgent(userAgent) { + this.userAgent = userAgent; + return this; + } + + build() { + if (!this.position || !this.author || !this.message) { + console.error( + "Missing required parameters for Comment: position, author, message", + this + ); + return null; + } + const comment = new Comment( + this.position, + this.author, + this.message, + this.id, + this.date, + this.time, + this.windowWidth, + this.userAgent, + this.team + ); + + return comment; + } +} + +export default CommentBuilder; diff --git a/site/plugins/front-comments/src/front/classes/edition-panels/CommentPanel.js b/site/plugins/front-comments/src/front/classes/edition-panels/CommentPanel.js new file mode 100644 index 0000000..907a1e8 --- /dev/null +++ b/site/plugins/front-comments/src/front/classes/edition-panels/CommentPanel.js @@ -0,0 +1,52 @@ +import Panel from "./Panel.js"; +import Store from "../../store.js"; +import Comment from "../comments/Comment.js"; +import CommentBuilder from "../comments/CommentBuilder.js"; + +class CommentPanel extends Panel { + create() { + super.create(); + document + .querySelector(".fc__edition-panel__save-btn") + .addEventListener("click", () => { + this._createComment(); + }); + this._textArea.addEventListener("keydown", (event) => { + if (event.key === "Enter" && !event.shiftKey) { + this._createComment(); + } + if (event.key === "Escape") { + document.body.removeChild(this._panel); + } + }); + } + + async _createComment() { + const comment = new CommentBuilder() + .setAuthor(Store.author) + .setTeam(Store.team) + .setMessage(this._textArea.value) + .setPosition({ + top: this._getPos().top, + left: this._getPos().left, + }) + .build(); + + try { + Store.comments.push(comment); + await Store.save("comments"); + comment.toBubble(); + document.body.removeChild(this._panel); + } catch (error) { + Store.comments = Store.comments.filter( + (storedComment) => storedComment.id !== comment.id + ); + document.body.removeChild(comment.node); + console.error("Create comment failed:", error); + } + + return comment; + } +} + +export default CommentPanel; diff --git a/site/plugins/front-comments/src/front/classes/edition-panels/Panel.js b/site/plugins/front-comments/src/front/classes/edition-panels/Panel.js new file mode 100644 index 0000000..d89e2f4 --- /dev/null +++ b/site/plugins/front-comments/src/front/classes/edition-panels/Panel.js @@ -0,0 +1,90 @@ +import Comment from "../comments/Comment.js"; +import Store from "../../store.js"; +import Helpers from "../../composables/helpers.js"; + +class Panel { + constructor() { + this._panel; + this._textArea; + } + + create() { + this._panel = this._createPanel(); + this._textArea = this._createTextArea(); + const btns = this._createBtns(); + this._panel.appendChild(this._textArea); + this._panel.appendChild(btns); + document.body.appendChild(this._panel); + this._textArea.focus(); + + Helpers.fixOffscreen(this._panel); + + document + .querySelector(".fc__edition-panel__remove-btn") + .addEventListener("click", () => { + document.body.removeChild(this._panel); + }); + } + + _createPanel() { + const panel = document.createElement("div"); + panel.classList.add("fc__edition-panel"); + + const panelWidth = 240; + const panelHeight = 300; + + panel.style.left = this._getMousePos().x + "px"; + panel.style.top = this._getMousePos().y + window.scrollY + "px"; + + return panel; + } + + _createBtns() { + const btns = document.createElement("div"); + btns.classList.add("fc__edition-panel__btns"); + + const removeBtn = document.createElement("button"); + removeBtn.classList.add("fc__edition-panel__remove-btn"); + removeBtn.textContent = "supprimer"; + + const saveBtn = document.createElement("button"); + saveBtn.classList.add("fc__edition-panel__save-btn"); + saveBtn.textContent = "enregistrer"; + + btns.appendChild(removeBtn); + btns.appendChild(saveBtn); + + return btns; + } + + _getMousePos() { + return { + x: event.clientX, + y: event.clientY, + }; + } + + _createTextArea() { + const textArea = document.createElement("textarea"); + textArea.classList.add("fc__text"); + return textArea; + } + + /** + * Get the position of the panel relative to the viewport. + * @returns {Object} An object containing the top and left position. + * @property {string} top - The vertical position of the comment in pixels (px). + * @property {string} left - The horizontal position of the comment in viewport width units (vw). + */ + _getPos() { + const relativeLeft = + this._panel.offsetLeft / ((window.innerWidth + window.pageXOffset) / 100); + + return { + top: this._panel.style.top, + left: relativeLeft + "vw", + }; + } +} + +export default Panel; diff --git a/site/plugins/front-comments/src/front/classes/edition-panels/SuggestionPanel.js b/site/plugins/front-comments/src/front/classes/edition-panels/SuggestionPanel.js new file mode 100644 index 0000000..fa884e3 --- /dev/null +++ b/site/plugins/front-comments/src/front/classes/edition-panels/SuggestionPanel.js @@ -0,0 +1,74 @@ +import Panel from "./Panel.js"; +import Store from "../../store.js"; +import Suggestion from "../Suggestion.js"; + +class SuggestionPanel extends Panel { + constructor(field) { + super(); + this._field = field; + this._selection = window.getSelection(); + this._target = this._selection.toString(); + } + create() { + this._highlight(); + this._context = this._getContext(); + super.create(); + document + .querySelector(".fc__edition-panel__save-btn") + .addEventListener("click", () => { + this._createSuggestion(); + }); + this._textArea.addEventListener("keydown", (event) => { + if (event.key === "Enter") { + this._createSuggestion(); + } + if (event.key === "Escape") { + document.body.removeChild(this._panel); + } + }); + } + + _createSuggestion() { + const suggestion = new Suggestion( + Store.author, + this._context, + this._target, + this._textArea.value, + this._field.dataset.fieldName + ); + Store.suggestions.push(suggestion); + Store.save("suggestions"); + document.body.removeChild(this._panel); + return suggestion; + } + + _highlight() { + if (this._selection.toString() !== "") { + const range = this._selection.getRangeAt(0); + const span = document.createElement("span"); + span.className = "fc__suggestion--edit"; + range.surroundContents(span); + } + } + + _getContext() { + if (this._selection.toString() !== "") { + const textNode = this._selection.anchorNode; + const textContent = textNode.textContent; + const selectedText = this._selection.toString(); + const index = textContent.indexOf(selectedText); + const before = textContent.slice(Math.max(0, index - 30), index); + const after = textContent.slice( + index + selectedText.length, + index + selectedText.length + 30 + ); + const context = { + before: before, + after: after, + }; + return context; + } + } +} + +export default SuggestionPanel; diff --git a/site/plugins/front-comments/src/front/composables/helpers.js b/site/plugins/front-comments/src/front/composables/helpers.js new file mode 100644 index 0000000..c44f1d2 --- /dev/null +++ b/site/plugins/front-comments/src/front/composables/helpers.js @@ -0,0 +1,30 @@ +class Helpers { + static fixOffscreen(node) { + const margin = 16; + + if (!node) { + console.error("fixOffscreen: node does not exist"); + return; + } + + const XDiff = + window.innerWidth + + window.pageXOffset - + (node.offsetLeft + node.offsetWidth + window.pageXOffset); + + const YDiff = + window.innerHeight + + window.pageYOffset - + (node.offsetTop + node.offsetHeight); + + if (XDiff <= 0) { + node.style.transform = `translateX(${XDiff - margin}px)`; + } + + if (YDiff <= 0) { + node.style.transform += `translateY(${YDiff - margin}px)`; + } + } +} + +export default Helpers; diff --git a/site/plugins/front-comments/src/front/index.js b/site/plugins/front-comments/src/front/index.js new file mode 100644 index 0000000..9fccb03 --- /dev/null +++ b/site/plugins/front-comments/src/front/index.js @@ -0,0 +1,73 @@ +import Comment from "./classes/comments/Comment.js"; +import Panel from "./classes/edition-panels/Panel.js"; +import Store from "./store.js"; +import AddBtn from "./classes/AddBtn.js"; +import SuggestionPanel from "./classes/edition-panels/SuggestionPanel.js"; +import Suggestion from "./classes/Suggestion.js"; +import CommentBuilder from "./classes/comments/CommentBuilder.js"; + +document.addEventListener("DOMContentLoaded", () => { + Store.author = FCAuthor; + Store.team = FCTeam.length > 0 ? FCTeam : undefined; + Store.page.id = FCPageId; + Store.page.uri = FCPageUri; + Store.csrf = FCCsrf; + Store.filesPath = FCFilesPath; + + try { + FCComments.forEach((item) => { + try { + const comment = new CommentBuilder() + .setPosition(item.position) + .setAuthor(item.author) + .setMessage(item.message) + .setId(item.id) + .setDate(item.date) + .setTime(item.time) + .setWindowWidth(item.windowWidth) + .setUserAgent(item.userAgent) + .setTeam(item?.team) + .build(); + + comment.toBubble(); + + Store.comments.push(comment); + } catch (error) { + console.error("Plugin Front Comments : can't parse comments : ", error); + console.log("Comments : ", FCComments); + } + }); + } catch (error) { + console.error("Can't parse comments : ", error); + console.log("Comments : ", FCComments); + } + + const addBtn = new AddBtn(FCPosition); + + // const suggestions = JSON.parse(FCSuggestions); + // suggestions.forEach((item) => { + // const suggestion = new Suggestion( + // item.author, + // item.context, + // item.target, + // item.suggestion, + // item.fieldName, + // item.id, + // item.date, + // item.time + // ); + // Store.suggestions.push(suggestion); + // }); + // document.querySelectorAll(".fc__field").forEach((field) => { + // field.addEventListener("mouseup", (event) => { + // const selection = window.getSelection().toString(); + // if ( + // selection.length > 0 && + // !event.target.classList.contains("fc__suggestion-bubble") + // ) { + // const suggestionPanel = new SuggestionPanel(field); + // suggestionPanel.create(); + // } + // }); + // }); +}); diff --git a/site/plugins/front-comments/src/front/store.js b/site/plugins/front-comments/src/front/store.js new file mode 100644 index 0000000..dfffb86 --- /dev/null +++ b/site/plugins/front-comments/src/front/store.js @@ -0,0 +1,40 @@ +const Store = { + comments: [], + suggestions: [], + author: null, + page: { + id: null, + uri: null, + }, + csrf: null, + save(key) { + const data = {}; + data[key] = this[key]; + const init = { + method: "PATCH", + headers: { + "X-CSRF": this.csrf, + }, + body: JSON.stringify(data).replaceAll("_", ""), + }; + + return fetch("/api/pages/" + this.page.id, init) + .then((response) => { + if (!response.ok) { + return Promise.reject( + "Front comments plugin - can't add comment: " + response.statusText + ); + } + return response.json(); + }) + .then((response) => { + console.log(response); + console.log("Front comments plugin - comment successfully added."); + }) + .catch((error) => { + return Promise.reject(error); + }); + }, +}; + +export default Store; diff --git a/site/plugins/front-comments/src/panel/components/KCommentsView.vue b/site/plugins/front-comments/src/panel/components/KCommentsView.vue new file mode 100644 index 0000000..dccf7e6 --- /dev/null +++ b/site/plugins/front-comments/src/panel/components/KCommentsView.vue @@ -0,0 +1,177 @@ + + + + + diff --git a/site/plugins/front-comments/src/panel/index.js b/site/plugins/front-comments/src/panel/index.js new file mode 100644 index 0000000..44d0196 --- /dev/null +++ b/site/plugins/front-comments/src/panel/index.js @@ -0,0 +1,11 @@ +import KCommentsView from "./components/KCommentsView.vue"; + +panel.plugin("adrienpayet/front-comments", { + icons: { + gitlab: + '', + }, + components: { + "k-comments-view": KCommentsView, + }, +}); diff --git a/site/plugins/front-comments/test.php b/site/plugins/front-comments/test.php new file mode 100644 index 0000000..378cef6 --- /dev/null +++ b/site/plugins/front-comments/test.php @@ -0,0 +1,14 @@ + [ + 'cache' => true, + ], + 'hooks' => [ + 'page.update:after' => function ($newPage) { + kirby() + ->cache('adrienpayet.front-comments') + ->set('foo', 'bar'); + } + ] +]); diff --git a/site/plugins/front-comments/translations/en.php b/site/plugins/front-comments/translations/en.php new file mode 100644 index 0000000..f5bed21 --- /dev/null +++ b/site/plugins/front-comments/translations/en.php @@ -0,0 +1,16 @@ + 'Comments', + 'adrienpayet.front-comments.remove' => 'Remove', + 'adrienpayet.front-comments.see' => 'See', + 'adrienpayet.front-comments.see-issue' => 'Go to the issue', + 'adrienpayet.front-comments.create-issue' => 'Create an issue', + 'adrienpayet.front-comments.confirm-create-issue' => 'Do you really want to create an issue ?', + 'adrienpayet.front-comments.confirm-delete-comment' => 'Do you really want to remove this comment ?', + 'adrienpayet.front-comments.author' => 'Author', + 'adrienpayet.front-comments.message' => 'Message', + 'adrienpayet.front-comments.date' => 'Date', + 'adrienpayet.front-comments.time' => 'Time', + 'adrienpayet.front-comments.add-comment' => 'Add a comment', +]; diff --git a/site/plugins/front-comments/translations/fr.php b/site/plugins/front-comments/translations/fr.php new file mode 100644 index 0000000..2fdc444 --- /dev/null +++ b/site/plugins/front-comments/translations/fr.php @@ -0,0 +1,17 @@ + 'Commentaires', + 'adrienpayet.front-comments.remove' => 'Supprimer', + 'adrienpayet.front-comments.see' => 'Voir', + 'adrienpayet.front-comments.see-issue' => 'Voir le ticket', + 'adrienpayet.front-comments.create-issue' => 'Créer un ticket', + 'adrienpayet.front-comments.confirm-create-issue' => 'Voulez-vous vraiment créer un ticket ?', + 'adrienpayet.front-comments.confirm-delete-comment' => 'Voulez-vous vraiment supprimer ce commentaire ?', + 'adrienpayet.front-comments.author' => 'Auteur', + 'adrienpayet.front-comments.message' => 'Message', + 'adrienpayet.front-comments.date' => 'Date', + 'adrienpayet.front-comments.time' => 'Heure', + 'adrienpayet.front-comments.no-comment' => 'Aucun commentaire', + 'adrienpayet.front-comments.add-comment' => 'Ajouter un commentaire', +];