From 4f9baad14067589e9ba1cd550ed843d4e367100e Mon Sep 17 00:00:00 2001 From: "JAM\\mallo" Date: Wed, 28 Sep 2022 15:09:39 -0400 Subject: [PATCH 01/35] no message --- .env.example | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 .env.example diff --git a/.env.example b/.env.example deleted file mode 100644 index d058c34ef2..0000000000 --- a/.env.example +++ /dev/null @@ -1,44 +0,0 @@ -APP_NAME=Laravel -APP_ENV=local -APP_KEY= -APP_DEBUG=true -APP_URL=http://localhost - -LOG_CHANNEL=stack - -DB_CONNECTION=mysql -DB_HOST=127.0.0.1 -DB_PORT=3306 -DB_DATABASE=homestead -DB_USERNAME=homestead -DB_PASSWORD=secret - -BROADCAST_DRIVER=log -CACHE_DRIVER=file -QUEUE_CONNECTION=sync -SESSION_DRIVER=file -SESSION_LIFETIME=120 - -REDIS_HOST=127.0.0.1 -REDIS_PASSWORD=null -REDIS_PORT=6379 - -MAIL_DRIVER=smtp -MAIL_HOST=smtp.mailtrap.io -MAIL_PORT=2525 -MAIL_USERNAME=null -MAIL_PASSWORD=null -MAIL_ENCRYPTION=null - -AWS_ACCESS_KEY_ID= -AWS_SECRET_ACCESS_KEY= -AWS_DEFAULT_REGION=us-east-1 -AWS_BUCKET= - -PUSHER_APP_ID= -PUSHER_APP_KEY= -PUSHER_APP_SECRET= -PUSHER_APP_CLUSTER=mt1 - -MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" -MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" From 90db87c5f9fbf90fd8fd9e4671d30299f96c52c4 Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Tue, 21 Jan 2025 22:57:14 +0000 Subject: [PATCH 02/35] feat: user mentions on tinymce (non functional) --- app/Http/Controllers/BrowseController.php | 17 ++++ app/Models/User/User.php | 10 +++ public/css/mentions.css | 90 +++++++++++++++++++ public/js/plugins/mention/plugin.min.js | 1 + resources/views/character/_image_js.blade.php | 7 +- .../admin/_edit_description_modal.blade.php | 6 +- .../admin/_edit_notes_modal.blade.php | 7 +- resources/views/comments/comments.blade.php | 7 +- .../comments/permalink_comment.blade.php | 7 +- resources/views/js/_modal_wysiwyg.blade.php | 38 ++++---- resources/views/layouts/app.blade.php | 26 +++++- routes/lorekeeper/browse.php | 7 +- 12 files changed, 182 insertions(+), 41 deletions(-) create mode 100644 public/css/mentions.css create mode 100644 public/js/plugins/mention/plugin.min.js diff --git a/app/Http/Controllers/BrowseController.php b/app/Http/Controllers/BrowseController.php index da2c5ffd16..a0de8ea35d 100644 --- a/app/Http/Controllers/BrowseController.php +++ b/app/Http/Controllers/BrowseController.php @@ -79,6 +79,23 @@ public function getUsers(Request $request) { ]); } + /** + * Shows user name list matching the search query. + * + * @return \Illuminate\Contracts\Support\Renderable + */ + public function getUsersSearch(Request $request) { + $username = $request->get('username'); + $users = User::visible()->where('name', 'LIKE', "%$username%")->orderBy('name')->get()->map(function ($user) { + return [ + 'name' => $user->name, + 'avatar' => $user->avatarUrl, + 'mention_display_name' => $user->mentionDisplayName + ]; + }); + return response()->json($users); + } + /** * Shows the user deactivated. * diff --git a/app/Models/User/User.php b/app/Models/User/User.php index d247021dcd..4c451f90ce 100644 --- a/app/Models/User/User.php +++ b/app/Models/User/User.php @@ -348,6 +348,16 @@ public function getDisplayNameAttribute() { return ($this->is_banned ? '' : '').''.$this->name.''.($this->is_banned ? '' : ''); } + /** + * Displays the user's name, but with specific classes to identify mentions + * + * @return string + */ + public function getMentionDisplayNameAttribute() { + return ($this->is_banned ? '' : '').'@'.$this->name.''.($this->is_banned ? '' : ''); + } + /** * Gets the user's last username change. * diff --git a/public/css/mentions.css b/public/css/mentions.css new file mode 100644 index 0000000000..d3935c1d37 --- /dev/null +++ b/public/css/mentions.css @@ -0,0 +1,90 @@ +.rte-autocomplete { + position: absolute; + top: 0px; + left: 0px; + display: block; + z-index: 1000; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0,0,0,0.2); + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0,0,0,0.2); + -moz-box-shadow: 0 5px 10px rgba(0,0,0,0.2); + box-shadow: 0 5px 10px rgba(0,0,0,0.2); + -webkit-background-clip: padding-box; + -moz-background-clip: padding; + background-clip: padding-box; + font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; + font-size: 14px; +} + +.rte-autocomplete:before { + content: ''; + display: inline-block; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + border-bottom: 7px solid #ccc; + border-bottom-color: rgba(0, 0, 0, 0.2); + position: absolute; + top: -7px; + left: 9px; +} + +.rte-autocomplete:after { + content: ''; + display: inline-block; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid white; + position: absolute; + top: -6px; + left: 10px; +} + +.rte-autocomplete > li.loading { + background: url(../images/loading.gif) no-repeat center center; + height: 16px; +} + +.rte-autocomplete > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 20px; + color: #1a1919; + white-space: nowrap; + text-decoration: none; +} + +.rte-autocomplete >li > a:hover, .rte-autocomplete > li > a:focus, .rte-autocomplete:hover > a, .rte-autocomplete:focus > a { + color: #fff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top,#08c,#0077b3); + background-image: -webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3)); + background-image: -webkit-linear-gradient(top,#08c,#0077b3); + background-image: -o-linear-gradient(top,#08c,#0077b3); + background-image: linear-gradient(to bottom,#08c,#0077b3); + background-repeat: repeat-x; +} + +.rte-autocomplete >.active > a, .rte-autocomplete > .active > a:hover, .rte-autocomplete > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #0081c2; + background-image: -moz-linear-gradient(top,#08c,#0077b3); + background-image: -webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3)); + background-image: -webkit-linear-gradient(top,#08c,#0077b3); + background-image: -o-linear-gradient(top,#08c,#0077b3); + background-image: linear-gradient(to bottom,#08c,#0077b3); + background-repeat: repeat-x; + outline: 0; +} diff --git a/public/js/plugins/mention/plugin.min.js b/public/js/plugins/mention/plugin.min.js new file mode 100644 index 0000000000..61d0e884e8 --- /dev/null +++ b/public/js/plugins/mention/plugin.min.js @@ -0,0 +1 @@ +!function(t){"use strict";if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t(require("jquery"));else if("function"==typeof define&&define.amd)define(["jquery"],t);else{t(("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).jQuery)}}(function(t){"use strict";var e=function(e,i){this.editor=e,this.options=t.extend({},{source:[],delay:500,queryBy:"name",items:10},i),this.options.insertFrom=this.options.insertFrom||this.options.queryBy,this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.renderDropdown=this.options.renderDropdown||this.renderDropdown,this.render=this.options.render||this.render,this.insert=this.options.insert||this.insert,this.highlighter=this.options.highlighter||this.highlighter,this.query="",this.hasFocus=!0,this.renderInput(),this.bindEvents()};e.prototype={constructor:e,renderInput:function(){var t=''+this.options.delimiter+'\ufeff';this.editor.execCommand("mceInsertContent",!1,t),this.editor.focus(),this.editor.selection.select(this.editor.selection.dom.select("span#autocomplete-searchtext span")[0]),this.editor.selection.collapse(0)},bindEvents:function(){this.editor.on("keyup",this.editorKeyUpProxy=t.proxy(this.rteKeyUp,this)),this.editor.on("keydown",this.editorKeyDownProxy=t.proxy(this.rteKeyDown,this),!0),this.editor.on("click",this.editorClickProxy=t.proxy(this.rteClicked,this)),t("body").on("click",this.bodyClickProxy=t.proxy(this.rteLostFocus,this)),t(this.editor.getWin()).on("scroll",this.rteScroll=t.proxy(function(){this.cleanUp(!0)},this))},unbindEvents:function(){this.editor.off("keyup",this.editorKeyUpProxy),this.editor.off("keydown",this.editorKeyDownProxy),this.editor.off("click",this.editorClickProxy),t("body").off("click",this.bodyClickProxy),t(this.editor.getWin()).off("scroll",this.rteScroll)},rteKeyUp:function(t){switch(t.which||t.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 8:""===this.query?this.cleanUp(!0):this.lookup();break;case 9:case 13:var e=void 0!==this.$dropdown?this.$dropdown.find("li.active"):[];e.length?(this.select(e.data()),this.cleanUp(!1)):this.cleanUp(!0);break;case 27:this.cleanUp(!0);break;default:this.lookup()}},rteKeyDown:function(t){switch(t.which||t.keyCode){case 9:case 13:case 27:t.preventDefault();break;case 38:t.preventDefault(),void 0!==this.$dropdown&&this.highlightPreviousResult();break;case 40:t.preventDefault(),void 0!==this.$dropdown&&this.highlightNextResult()}t.stopPropagation()},rteClicked:function(e){var i=t(e.target);this.hasFocus&&"autocomplete-searchtext"!==i.parent().attr("id")&&this.cleanUp(!0)},rteLostFocus:function(){this.hasFocus&&this.cleanUp(!0)},lookup:function(){this.query=t.trim(t(this.editor.getBody()).find("#autocomplete-searchtext").text()).replace("\ufeff",""),void 0===this.$dropdown&&this.show(),clearTimeout(this.searchTimeout),this.searchTimeout=setTimeout(t.proxy(function(){var e=t.isFunction(this.options.source)?this.options.source(this.query,t.proxy(this.process,this),this.options.delimiter):this.options.source;e&&this.process(e)},this),this.options.delay)},matcher:function(t){return~t[this.options.queryBy].toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(t){for(var e,i=[],o=[],s=[];void 0!==(e=t.shift());)e[this.options.queryBy].toLowerCase().indexOf(this.query.toLowerCase())?~e[this.options.queryBy].indexOf(this.query)?o.push(e):s.push(e):i.push(e);return i.concat(o,s)},highlighter:function(t){return t.replace(new RegExp("("+this.query.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")+")","ig"),function(t,e){return""+e+""})},show:function(){var e=this.editor.inline?this.offsetInline():this.offset();this.$dropdown=t(this.renderDropdown()).css({top:e.top,left:e.left}),t("body").append(this.$dropdown),this.$dropdown.on("click",t.proxy(this.autoCompleteClick,this))},process:function(e){if(this.hasFocus){var i=this,o=[],s=t.grep(e,function(t){return i.matcher(t)});s=i.sorter(s),s=s.slice(0,this.options.items),t.each(s,function(e,n){var r=t(i.render(n,e));r.html(r.html().replace(r.text(),i.highlighter(r.text()))),t.each(s[e],function(t,e){r.attr("data-"+t,e)}),o.push(r[0].outerHTML)}),o.length?this.$dropdown.html(o.join("")).show():this.$dropdown.hide()}},renderDropdown:function(){return''},render:function(t,e){return'
  • '+t[this.options.queryBy]+"
  • "},autoCompleteClick:function(e){var i=t(e.target).closest("li").data();t.isEmptyObject(i)||(this.select(i),this.cleanUp(!1)),e.stopPropagation(),e.preventDefault()},highlightPreviousResult:function(){var t=this.$dropdown.find("li.active").index(),e=0===t?this.$dropdown.find("li").length-1:--t;this.$dropdown.find("li").removeClass("active").eq(e).addClass("active")},highlightNextResult:function(){var t=this.$dropdown.find("li.active").index(),e=t===this.$dropdown.find("li").length-1?0:++t;this.$dropdown.find("li").removeClass("active").eq(e).addClass("active")},select:function(t){this.editor.focus();var e=this.editor.dom.select("span#autocomplete")[0];this.editor.dom.remove(e),this.editor.execCommand("mceInsertContent",!1,this.insert(t))},insert:function(t){return""+t[this.options.insertFrom]+" "},cleanUp:function(e){if(this.unbindEvents(),this.hasFocus=!1,void 0!==this.$dropdown&&(this.$dropdown.remove(),delete this.$dropdown),e){var i=this.query,o=t(this.editor.dom.select("span#autocomplete"));if(!o.length)return;var s=t("

    "+this.options.delimiter+i+"

    ")[0].firstChild,n=t(this.editor.selection.getNode()).offset().top===o.offset().top+(o.outerHeight()-o.height())/2;this.editor.dom.replace(s,o[0]),n&&(this.editor.selection.select(s),this.editor.selection.collapse())}},offset:function(){var e=t(this.editor.getContainer()).offset(),i=t(this.editor.getContentAreaContainer()).position(),o=t(this.editor.dom.select("span#autocomplete")).position();return{top:e.top+i.top+o.top+t(this.editor.selection.getNode()).innerHeight()-t(this.editor.getDoc()).scrollTop()+5,left:e.left+i.left+o.left}},offsetInline:function(){var e=t(this.editor.dom.select("span#autocomplete")).offset();return{top:e.top+t(this.editor.selection.getNode()).innerHeight()+5,left:e.left}}},tinymce.create("tinymce.plugins.Mention",{init:function(i){function o(){var e=i.selection.getRng(!0).startOffset,o=(i.selection.getRng(!0).startContainer.data||"").substr(e>0?e-1:0,1);return!t.trim(o).length}var s,n=i.getParam("mentions");n.delimiter=void 0!==n.delimiter?t.isArray(n.delimiter)?n.delimiter:[n.delimiter]:["@"],i.on("keypress",function(r){var h=t.inArray(String.fromCharCode(r.which||r.keyCode),n.delimiter);h>-1&&o()&&(void 0===s||void 0!==s.hasFocus&&!s.hasFocus)&&(r.preventDefault(),s=new e(i,t.extend({},n,{delimiter:n.delimiter[h]})))})},getInfo:function(){return{longname:"mention",author:"Steven Devooght",version:tinymce.majorVersion+"."+tinymce.minorVersion}}}),tinymce.PluginManager.add("mention",tinymce.plugins.Mention)}); diff --git a/resources/views/character/_image_js.blade.php b/resources/views/character/_image_js.blade.php index af2d0a989d..fefa868a6d 100644 --- a/resources/views/character/_image_js.blade.php +++ b/resources/views/character/_image_js.blade.php @@ -59,15 +59,16 @@ plugins: [ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen spoiler', - 'insertdatetime media table paste code help wordcount' + 'insertdatetime media table paste code help wordcount toc', ], - toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | code', + toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | toc bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | code', content_css: [ '{{ asset('css/app.css') }}', '{{ asset('css/lorekeeper.css') }}' ], spoiler_caption: 'Toggle Spoiler', - target_list: false + target_list: false, + toc_class: 'container', }); }); $(".edit-description").remove(); diff --git a/resources/views/character/admin/_edit_description_modal.blade.php b/resources/views/character/admin/_edit_description_modal.blade.php index bc55f8c960..17c0dedf06 100644 --- a/resources/views/character/admin/_edit_description_modal.blade.php +++ b/resources/views/character/admin/_edit_description_modal.blade.php @@ -9,8 +9,4 @@ {!! Form::close() !!} - +@include('js._modal_wysiwyg') diff --git a/resources/views/character/admin/_edit_notes_modal.blade.php b/resources/views/character/admin/_edit_notes_modal.blade.php index 6f29ca73cf..ee1c43c8d1 100644 --- a/resources/views/character/admin/_edit_notes_modal.blade.php +++ b/resources/views/character/admin/_edit_notes_modal.blade.php @@ -9,8 +9,5 @@ {!! Form::close() !!} - + +@include('js._modal_wysiwyg') diff --git a/resources/views/comments/comments.blade.php b/resources/views/comments/comments.blade.php index 0cba774825..c1a0e696dc 100644 --- a/resources/views/comments/comments.blade.php +++ b/resources/views/comments/comments.blade.php @@ -113,15 +113,16 @@ function sortComments() { plugins: [ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen spoiler', - 'insertdatetime media table paste code help wordcount' + 'insertdatetime media table paste code help wordcount toc', ], - toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | code', + toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | toc bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | code', content_css: [ '{{ asset('css/app.css') }}', '{{ asset('css/lorekeeper.css') }}' ], spoiler_caption: 'Toggle Spoiler', - target_list: false + target_list: false, + toc_class: 'container', }); } }); diff --git a/resources/views/comments/permalink_comment.blade.php b/resources/views/comments/permalink_comment.blade.php index 5719e171e3..644172b843 100644 --- a/resources/views/comments/permalink_comment.blade.php +++ b/resources/views/comments/permalink_comment.blade.php @@ -36,15 +36,16 @@ plugins: [ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen spoiler', - 'insertdatetime media table paste code help wordcount' + 'insertdatetime media table paste code help wordcount toc' ], - toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | code', + toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | toc bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | code', content_css: [ '{{ asset('css/app.css') }}', '{{ asset('css/lorekeeper.css') }}' ], spoiler_caption: 'Toggle Spoiler', - target_list: false + target_list: false, + toc_class: 'container', }); }); diff --git a/resources/views/js/_modal_wysiwyg.blade.php b/resources/views/js/_modal_wysiwyg.blade.php index 91dcad20f9..c0e7fa6512 100644 --- a/resources/views/js/_modal_wysiwyg.blade.php +++ b/resources/views/js/_modal_wysiwyg.blade.php @@ -1,16 +1,22 @@ -tinymce.init({ -selector: '#modal .wysiwyg', -height: 500, -menubar: false, -plugins: [ -'advlist autolink lists link image charmap print preview anchor', -'searchreplace visualblocks code fullscreen', -'insertdatetime media table paste code help wordcount' -], -toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | code', -content_css: [ -'//www.tiny.cloud/css/codepen.min.css', -'{{ asset('css/app.css') }}', -'{{ asset('css/lorekeeper.css') }}' -] -}); + + diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index cdc7af6bda..db5b205d35 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -156,15 +156,35 @@ plugins: [ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen spoiler', - 'insertdatetime media table paste code help wordcount' + 'insertdatetime media table paste code help wordcount toc mention', ], - toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | code', + toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | toc bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | code', content_css: [ '{{ asset('css/app.css') }}', '{{ asset('css/lorekeeper.css') }}' + ], spoiler_caption: 'Toggle Spoiler', - target_list: false + target_list: false, + toc_class: 'container', + mentions: { + source: function (query, process, delimiter) { + $.getJSON('{{ url('users/search') }}', function(data) { + process(data); + }); + }, + insert: function(item) { + return '' + item.mention_display_name + ''; + }, + render: function(item) { + return '
  • ' + + '' + + '' + + '' + item.name + '' + + '' + + '
  • '; + }, + }, }); bsCustomFileInput.init(); var $mobileMenuButton = $('#mobileMenuButton'); diff --git a/routes/lorekeeper/browse.php b/routes/lorekeeper/browse.php index cc27a2aaec..f9b7aba831 100644 --- a/routes/lorekeeper/browse.php +++ b/routes/lorekeeper/browse.php @@ -42,9 +42,10 @@ /************************************************************************************************** Users **************************************************************************************************/ -Route::get('/users', 'BrowseController@getUsers'); -Route::get('/blacklist', 'BrowseController@getBlacklist'); -Route::get('/deactivated-list', 'BrowseController@getDeactivated'); +Route::get('users', 'BrowseController@getUsers'); +Route::get('users/search', 'BrowseController@getUsersSearch')->name('user.search'); +Route::get('blacklist', 'BrowseController@getBlacklist'); +Route::get('deactivated-list', 'BrowseController@getDeactivated'); // PROFILES Route::group(['prefix' => 'user', 'namespace' => 'Users'], function () { From 2793418499eaa02932a24c8181d4ab4e834350ab Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Wed, 22 Jan 2025 11:20:38 +0000 Subject: [PATCH 03/35] feat(emotes): extension, squashed commit of the following: commit 96e152422cd992255f9ffaf49d8c90d33e378e18 Author: JAM\mallo Date: Sat Apr 29 02:14:24 2023 -0400 fix item entry collapsible commit c4b2ae164dbb79ea8736e0dd1b7ac4e4b53e3bba Author: JAM\mallo Date: Wed Apr 19 22:19:29 2023 -0400 add item "emotes" AND ext tracker commit 07ee272db534d47ae5b716173f1d7d0faf4e32b9 Author: JAM\mallo Date: Fri Mar 31 19:50:48 2023 -0400 no message commit d1a875321580901b5a577895b2ba52f8fb31698e Author: JAM\mallo Date: Fri Mar 31 13:16:00 2023 -0400 no message commit 1793229b9855b45c03912cd893f0083f19efd149 Author: JAM\mallo Date: Fri Mar 31 12:51:44 2023 -0400 no message --- app/Helpers/Helpers.php | 84 +++++++++++++ .../Controllers/Admin/EmoteController.php | 102 ++++++++++++++++ app/Http/Controllers/WorldController.php | 18 +++ app/Models/Emote.php | 110 +++++++++++++++++ app/Services/EmoteService.php | 115 ++++++++++++++++++ config/lorekeeper/admin_sidebar.php | 4 + config/lorekeeper/extension_tracker.php | 9 +- .../2023_03_31_142746_add_emotes.php | 32 +++++ .../admin/emotes/_delete_emote.blade.php | 13 ++ .../admin/emotes/create_edit_emote.blade.php | 94 ++++++++++++++ resources/views/admin/emotes/emotes.blade.php | 48 ++++++++ resources/views/world/_item_entry.blade.php | 14 +++ resources/views/world/_sidebar.blade.php | 1 + resources/views/world/emotes.blade.php | 61 ++++++++++ routes/lorekeeper/admin.php | 12 ++ routes/lorekeeper/browse.php | 1 + 16 files changed, 717 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/Admin/EmoteController.php create mode 100644 app/Models/Emote.php create mode 100644 app/Services/EmoteService.php create mode 100644 database/migrations/2023_03_31_142746_add_emotes.php create mode 100644 resources/views/admin/emotes/_delete_emote.blade.php create mode 100644 resources/views/admin/emotes/create_edit_emote.blade.php create mode 100644 resources/views/admin/emotes/emotes.blade.php create mode 100644 resources/views/world/emotes.blade.php diff --git a/app/Helpers/Helpers.php b/app/Helpers/Helpers.php index 302c9bbd38..b71b5b3b2e 100644 --- a/app/Helpers/Helpers.php +++ b/app/Helpers/Helpers.php @@ -118,6 +118,9 @@ function parse($text, &$pings = null) { $text = parseUsers($text, $users); $text = parseCharacters($text, $characters); $text = parseGalleryThumbs($text, $submissions); + $text = parseEmoteIDs($text, $users); + $text = parseEmoteNames($text, $users); + $text = parseItemIDs($text, $users); if($pings) $pings = ['users' => $users, 'characters' => $characters]; return $text; @@ -293,3 +296,84 @@ function prettyProfileName($url) if(isset($name) && isset($site)) return $name.'@'.(Config::get('lorekeeper.sites.'.$site.'.display_name') != null ? Config::get('lorekeeper.sites.'.$site.'.display_name') : $site); else return $url; } + +/** + * Parses a piece of user-entered text to match userid mentions + * and replace with a link. + * + * @param string $text + * @param mixed $users + * + * @return string + */ +function parseEmoteIDs($text, &$users) { + $matches = null; + $users = []; + $count = preg_match_all('/\[emote=([^\[\]&<>?"\']+)\]/', $text, $matches); + if ($count) { + $matches = array_unique($matches[1]); + foreach ($matches as $match) { + $emote = \App\Models\Emote::active()->where('id', $match)->first(); + if ($emote) { + $users[] = $emote; + $text = preg_replace('/\[emote='.$match.'\]/', '', $text); + } + } + } + + return $text; +} + +/** + * Parses a piece of user-entered text to match userid mentions + * and replace with a link. + * + * @param string $text + * @param mixed $users + * + * @return string + */ +function parseEmoteNames($text, &$users) { + $matches = null; + $users = []; + $count = preg_match_all('/\[emote=([A-Za-z0-9_-]+)/', $text, $matches); + if ($count) { + $matches = array_unique($matches[1]); + foreach ($matches as $match) { + $emote = \App\Models\Emote::active()->where('name', $match)->first(); + if ($emote) { + $users[] = $emote; + $text = preg_replace('/\[emote='.$match.'\]/', '', $text); + } + } + } + + return $text; +} + +/** + * Parses a piece of user-entered text to match an item id + * and replace with an image. + * + * @param string $text + * @param mixed $users + * + * @return string + */ +function parseItemIDs($text, &$users) { + $matches = null; + $users = []; + $count = preg_match_all('/\[item=([^\[\]&<>?"\']+)\]/', $text, $matches); + if ($count) { + $matches = array_unique($matches[1]); + foreach ($matches as $match) { + $item = \App\Models\Item\Item::released()->where('id', $match)->first(); + if ($item) { + $users[] = $item; + $text = preg_replace('/\[item='.$match.'\]/', ' ', $text); + } + } + } + + return $text; +} \ No newline at end of file diff --git a/app/Http/Controllers/Admin/EmoteController.php b/app/Http/Controllers/Admin/EmoteController.php new file mode 100644 index 0000000000..1d06c1bf34 --- /dev/null +++ b/app/Http/Controllers/Admin/EmoteController.php @@ -0,0 +1,102 @@ + Emote::all() + ]); + } + + /** + * Shows the create emote page. + * + * @return \Illuminate\Contracts\Support\Renderable + */ + public function getCreateEmote() + { + return view('admin.emotes.create_edit_emote', [ + 'emote' => new Emote, + ]); + } + + /** + * Shows the edit emote page. + * + * @return \Illuminate\Contracts\Support\Renderable + */ + public function getEditEmote($id) + { + return view('admin.emotes.create_edit_emote', [ + 'emote' => Emote::findOrFail($id), + ]); + } + + /** + * Creates or edits an emote. + * + * @param \Illuminate\Http\Request $request + * @param App\Services\EmoteService $service + * @param int|null $id + * @return \Illuminate\Http\RedirectResponse + */ + public function postCreateEditEmote(Request $request, EmoteService $service, $id = null) + { + $id ? $request->validate(Emote::$updateRules) : $request->validate(Emote::$createRules); + $data = $request->only([ + 'name','image', 'is_active' + ]); + if($id && $service->updateEmote(Emote::find($id), $data, Auth::user())) { + flash('Emote updated successfully.')->success(); + } + else if (!$id && $emote = $service->createEmote($data, Auth::user())) { + flash('Emote created successfully.')->success(); + return redirect()->to('admin/emotes/edit/'.$emote->id); + } + else { + foreach($service->errors()->getMessages()['error'] as $error) flash($error)->error(); + } + return redirect()->back(); + } + + /** + * Deletes a emote. + */ + public function getDeleteEmote($id) + { + $emote = Emote::findOrFail($id); + return view('admin.emotes._delete_emote', [ + 'emote' => $emote, + ]); + } + + /** + * Deletes a emote. + */ + public function postDeleteEmote(Request $request, EmoteService $service, $id) + { + if($service->deleteEmote(Emote::find($id))) { + flash('Emote deleted successfully.')->success(); + } + else { + foreach($service->errors()->getMessages()['error'] as $error) flash($error)->error(); + } + return redirect()->to('admin/emotes'); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/WorldController.php b/app/Http/Controllers/WorldController.php index 27741d0401..395aca82b9 100644 --- a/app/Http/Controllers/WorldController.php +++ b/app/Http/Controllers/WorldController.php @@ -19,6 +19,7 @@ use App\Models\Shop\Shop; use App\Models\Shop\ShopStock; use App\Models\User\User; +use App\Models\Emote; class WorldController extends Controller { @@ -390,4 +391,21 @@ public function getPrompts(Request $request) 'categories' => ['none' => 'Any Category'] + PromptCategory::orderBy('sort', 'DESC')->pluck('name', 'id')->toArray() ]); } + + /** + * Shows the emotes page. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Contracts\Support\Renderable + */ + public function getEmotes(Request $request) + { + $query = Emote::active(); + $data = $request->only(['name']); + if(isset($data['name'])) + $query->where('name', 'LIKE', '%'.$data['name'].'%'); + return view('world.emotes', [ + 'emotes' => $query->orderBy('name', 'DESC')->paginate(20)->appends($request->query()), + ]); + } } diff --git a/app/Models/Emote.php b/app/Models/Emote.php new file mode 100644 index 0000000000..6f81e9b683 --- /dev/null +++ b/app/Models/Emote.php @@ -0,0 +1,110 @@ + 'required|unique:items|between:3,100', + 'image' => 'required|mimes:png,jpg,jpeg,gif', + ]; + + /** + * Validation rules for updating. + * + * @var array + */ + public static $updateRules = [ + 'name' => 'required|between:3,100', + 'image' => 'mimes:png,jpg,jpeg,gif', + ]; + + + + /********************************************************************************************** + + SCOPES + **********************************************************************************************/ + + /** + * Scope a query to retrieve only active emotes. + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeActive($query) + { + return $query->where('is_active', 1); + } + + /********************************************************************************************** + + ACCESSORS + **********************************************************************************************/ + + /** + * Gets the file directory containing the model's image. + * + * @return string + */ + public function getImageDirectoryAttribute() + { + return 'images/data/emotes'; + } + + /** + * Gets the file name of the model's image. + * + * @return string + */ + public function getImageFileNameAttribute() + { + return $this->id . '-image.png'; + } + + /** + * Gets the path to the file directory containing the model's image. + * + * @return string + */ + public function getImagePathAttribute() + { + return public_path($this->imageDirectory); + } + + /** + * Gets the URL of the model's image. + * + * @return string + */ + public function getImageUrlAttribute() + { + return asset($this->imageDirectory . '/' . $this->imageFileName); + } + +} \ No newline at end of file diff --git a/app/Services/EmoteService.php b/app/Services/EmoteService.php new file mode 100644 index 0000000000..959d9cfdfd --- /dev/null +++ b/app/Services/EmoteService.php @@ -0,0 +1,115 @@ +handleImage($image, $emote->imagePath, $emote->imageFileName); + + return $this->commitReturn($emote); + } catch(\Exception $e) { + $this->setError('error', $e->getMessage()); + } + return $this->rollbackReturn(false); + } + + /** + * Updates an emote. + * + * @param \App\Models\Emote $emote + * @param array $data + * @param \App\Models\User\User $user + * @return bool|\App\Models\Emote + */ + public function updateEmote($emote, $data, $user) + { + DB::beginTransaction(); + + try { + + // More specific validation + if(Emote::where('name', $data['name'])->where('id', '!=', $emote->id)->exists()) throw new \Exception("The name has already been taken."); + + $image = null; + if(isset($data['image']) && $data['image']) { + $image = $data['image']; + unset($data['image']); + } + $data['is_active'] = isset($data['is_active']); + + $emote->update($data); + + if ($emote) $this->handleImage($image, $emote->imagePath, $emote->imageFileName); + + return $this->commitReturn($emote); + } catch(\Exception $e) { + $this->setError('error', $e->getMessage()); + } + return $this->rollbackReturn(false); + } + + /** + * Deletes an emote. + * + * @param \App\Models\Emote\Emote $emote + * @return bool + */ + public function deleteEmote($emote) + { + DB::beginTransaction(); + + try { + + if (file_exists($emote->imagePath . '/' . $emote->imageFileName)) $this->deleteImage($emote->imagePath, $emote->imageFileName); + $emote->delete(); + + return $this->commitReturn(true); + } catch(\Exception $e) { + $this->setError('error', $e->getMessage()); + } + return $this->rollbackReturn(false); + } + +} \ No newline at end of file diff --git a/config/lorekeeper/admin_sidebar.php b/config/lorekeeper/admin_sidebar.php index ec2dfc7fa1..09fc54e44b 100644 --- a/config/lorekeeper/admin_sidebar.php +++ b/config/lorekeeper/admin_sidebar.php @@ -46,6 +46,10 @@ [ 'name' => 'Pages', 'url' => 'admin/pages' + ], + [ + 'name' => 'Emotes', + 'url' => 'admin/emotes' ] ] ], diff --git a/config/lorekeeper/extension_tracker.php b/config/lorekeeper/extension_tracker.php index 13e053ec9c..01b69c567a 100644 --- a/config/lorekeeper/extension_tracker.php +++ b/config/lorekeeper/extension_tracker.php @@ -12,5 +12,12 @@ // 'version' => '1.0.0', // ], - + 'Emotes' => [ + 'key' => 'Emotes', + 'wiki_key' => 'Emotes', + 'creators' => json_encode([ + 'CH3RVB' => 'https://github.com/CH3RVB/', + ]), + 'version' => '1.1.0', + ], ]; \ No newline at end of file diff --git a/database/migrations/2023_03_31_142746_add_emotes.php b/database/migrations/2023_03_31_142746_add_emotes.php new file mode 100644 index 0000000000..ef43554ed2 --- /dev/null +++ b/database/migrations/2023_03_31_142746_add_emotes.php @@ -0,0 +1,32 @@ +id(); + $table->string('name'); + $table->boolean('is_active')->default(true); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('emotes'); + } +} diff --git a/resources/views/admin/emotes/_delete_emote.blade.php b/resources/views/admin/emotes/_delete_emote.blade.php new file mode 100644 index 0000000000..706b80de98 --- /dev/null +++ b/resources/views/admin/emotes/_delete_emote.blade.php @@ -0,0 +1,13 @@ +@if($emote) + {!! Form::open(['url' => 'admin/emotes/delete/'.$emote->id]) !!} + +

    Are you sure you want to delete {{ $emote->name }}?

    + +
    + {!! Form::submit('Delete Emote', ['class' => 'btn btn-danger']) !!} +
    + + {!! Form::close() !!} +@else + Invalid emote selected. +@endif \ No newline at end of file diff --git a/resources/views/admin/emotes/create_edit_emote.blade.php b/resources/views/admin/emotes/create_edit_emote.blade.php new file mode 100644 index 0000000000..7830624c71 --- /dev/null +++ b/resources/views/admin/emotes/create_edit_emote.blade.php @@ -0,0 +1,94 @@ +@extends('admin.layout') + +@section('admin-title') Emotes @endsection + +@section('admin-content') +{!! breadcrumbs(['Admin Panel' => 'admin', 'Emotes' => 'admin/emotes', ($emote->id ? 'Edit' : 'Create').' Emote' => $emote->id ? 'admin/emotes/edit/'.$emote->id : 'admin/emotes/create']) !!} + +

    {{ $emote->id ? 'Edit' : 'Create' }} Emote + @if($emote->id) + Delete Emote + @endif +

    + +{!! Form::open(['url' => $emote->id ? 'admin/emotes/edit/'.$emote->id : 'admin/emotes/create', 'files' => true]) !!} + +

    Basic Information

    + +
    + {!! Form::label('Name') !!} {!! add_help('NOTE: Names with spaces don\'t play well with the emote generator, so try to use underscores if you have to') !!} + {!! Form::text('name', $emote->name, ['class' => 'form-control']) !!} +
    + +
    + {!! Form::label('Image (Required)') !!} +
    {!! Form::file('image') !!}
    + @if($emote->has_image) +
    + {!! Form::checkbox('remove_image', 1, false, ['class' => 'form-check-input']) !!} + {!! Form::label('remove_image', 'Remove current image', ['class' => 'form-check-label']) !!} +
    + @endif +
    + +
    + {!! Form::checkbox('is_active', 1, $emote->id ? $emote->is_active : 1, ['class' => 'form-check-input', 'data-toggle' => 'toggle']) !!} + {!! Form::label('is_active', 'Set Active', ['class' => 'form-check-label ml-3']) !!} {!! add_help('If turned off, this emote will not be able to be used') !!} +
    + +
    + {!! Form::submit($emote->id ? 'Edit' : 'Create', ['class' => 'btn btn-primary']) !!} +
    + +{!! Form::close() !!} + +@if($emote->id && $emote->imageUrl) +

    Preview

    +
    +
    + @if(Auth::check() && Auth::user()->hasPower('edit_data')) + + @endif +
    + @isset($emote->imageUrl) + + @endisset +
    +

    {!! $emote->name !!}

    +
    +
    Use This Emote
    +
    +
    + In the rich text editor: +
    + [emote={{ $emote->id }}] +
    + or: +
    + [emote={{ $emote->name }}] +
    + In comments and forums: +
    + ![{{ $emote->name }}]({{ asset( $emote->imageUrl) }}) +
    +
    +
    + + +
    +@endif + +@endsection + +@section('scripts') +@parent + +@endsection \ No newline at end of file diff --git a/resources/views/admin/emotes/emotes.blade.php b/resources/views/admin/emotes/emotes.blade.php new file mode 100644 index 0000000000..3f9b1af56d --- /dev/null +++ b/resources/views/admin/emotes/emotes.blade.php @@ -0,0 +1,48 @@ +@extends('admin.layout') + +@section('admin-title') Emotes @endsection + +@section('admin-content') +{!! breadcrumbs(['Admin Panel' => 'admin', 'Emotes' => 'admin/emotes']) !!} + +

    Emotes

    + +

    This is a list of emotes players/admins can use in the tinymce editor (and in comments).

    + + + +@if(!count($emotes)) +

    No emotes found.

    +@else + + + + + + + + + + @foreach($emotes as $emote) + + + + + + @endforeach + + +
    NameIs Visible
    + {!! $emote->imageUrl ? '' : ''!!} {{ $emote->name }} + {{$emote->is_active ? 'Active' : ' '}} + Edit +
    +@endif + +@endsection + +@section('scripts') +@parent +@endsection \ No newline at end of file diff --git a/resources/views/world/_item_entry.blade.php b/resources/views/world/_item_entry.blade.php index 704612c155..4467f94e36 100644 --- a/resources/views/world/_item_entry.blade.php +++ b/resources/views/world/_item_entry.blade.php @@ -78,3 +78,17 @@ + +
    + Use as Emote
    + + diff --git a/resources/views/world/_sidebar.blade.php b/resources/views/world/_sidebar.blade.php index 9e077753ee..51e9c58e07 100644 --- a/resources/views/world/_sidebar.blade.php +++ b/resources/views/world/_sidebar.blade.php @@ -14,5 +14,6 @@ + \ No newline at end of file diff --git a/resources/views/world/emotes.blade.php b/resources/views/world/emotes.blade.php new file mode 100644 index 0000000000..9d0d7c08c5 --- /dev/null +++ b/resources/views/world/emotes.blade.php @@ -0,0 +1,61 @@ +@extends('world.layout') + +@section('title') Emotes @endsection + +@section('content') +{!! breadcrumbs(['World' => 'world', 'Emotes' => 'world/emotes']) !!} +

    Emotes

    + +
    + {!! Form::open(['method' => 'GET', 'class' => 'form-inline justify-content-end']) !!} +
    + {!! Form::text('name', Request::get('name'), ['class' => 'form-control']) !!} +
    + {!! Form::close() !!} +
    + +

    Emotes that you can use on world pages or the tinymce editor.

    + + +{!! $emotes->render() !!} +
    + @foreach($emotes as $emote) +
    +
    + @if(Auth::check() && Auth::user()->hasPower('edit_data')) + + @endif +
    + @isset($emote->imageUrl) + + @endisset +
    +

    {!! $emote->name !!}

    +
    +
    Use This Emote
    +
    +
    + In the rich text editor: +
    + [emote={{ $emote->id }}] +
    + or: +
    + [emote={{ $emote->name }}] +
    + In comments and forums: +
    + ![{{ $emote->name }}]({{ asset( $emote->imageUrl) }}) +
    +
    +
    + + +
    + @endforeach +
    +{!! $emotes->render() !!} + +
    {{ count($emotes) }} result{{ count($emotes) == 1 ? '' : 's' }} found.
    + +@endsection \ No newline at end of file diff --git a/routes/lorekeeper/admin.php b/routes/lorekeeper/admin.php index d0d89c83eb..c5356f127c 100644 --- a/routes/lorekeeper/admin.php +++ b/routes/lorekeeper/admin.php @@ -437,3 +437,15 @@ Route::post('vote/{id}/{action}', 'DesignController@postVote')->where('action', 'approve|reject'); }); Route::get('{type}/{status}', 'DesignController@getDesignIndex')->where('type', 'myo-approvals|design-approvals')->where('status', 'pending|approved|rejected'); + + + # Emotes + Route::group(['prefix' => 'emotes', 'middleware' => 'power:manage_data'], function() { + Route::get('/', 'EmoteController@getEmoteIndex'); + Route::get('create', 'EmoteController@getCreateEmote'); + Route::post('create', 'EmoteController@postCreateEditEmote'); + Route::get('edit/{id}', 'EmoteController@getEditEmote'); + Route::post('edit/{id}', 'EmoteController@postCreateEditEmote'); + Route::get('delete/{id}', 'EmoteController@getDeleteEmote'); + Route::post('delete/{id}', 'EmoteController@postDeleteEmote'); + }); \ No newline at end of file diff --git a/routes/lorekeeper/browse.php b/routes/lorekeeper/browse.php index 986b734751..2526fe4eb0 100644 --- a/routes/lorekeeper/browse.php +++ b/routes/lorekeeper/browse.php @@ -110,6 +110,7 @@ Route::get('trait-categories', 'WorldController@getFeatureCategories'); Route::get('traits', 'WorldController@getFeatures'); Route::get('character-categories', 'WorldController@getCharacterCategories'); + Route::get('emotes', 'WorldController@getEmotes'); }); Route::group(['prefix' => 'prompts'], function() { From 176bba0deaac28a1e3c040a3c7b7c21c783924de Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Wed, 22 Jan 2025 11:26:55 +0000 Subject: [PATCH 04/35] chore(deps): rebuild mix assets --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index d1f8b069d5..1aa4c9b9e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "lorekeeper", + "name": "LK-private", "lockfileVersion": 2, "requires": true, "packages": { From c1b20b17345726e5f1127d6a09ca349147aff705 Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Wed, 22 Jan 2025 11:29:56 +0000 Subject: [PATCH 05/35] refactor: fix blade formatting --- .../admin/emotes/_delete_emote.blade.php | 8 +- .../admin/emotes/create_edit_emote.blade.php | 145 +++++++++--------- resources/views/admin/emotes/emotes.blade.php | 78 +++++----- resources/views/world/_item_entry.blade.php | 18 +-- resources/views/world/emotes.blade.php | 101 ++++++------ 5 files changed, 179 insertions(+), 171 deletions(-) diff --git a/resources/views/admin/emotes/_delete_emote.blade.php b/resources/views/admin/emotes/_delete_emote.blade.php index 706b80de98..6f08dd1370 100644 --- a/resources/views/admin/emotes/_delete_emote.blade.php +++ b/resources/views/admin/emotes/_delete_emote.blade.php @@ -1,5 +1,5 @@ -@if($emote) - {!! Form::open(['url' => 'admin/emotes/delete/'.$emote->id]) !!} +@if ($emote) + {!! Form::open(['url' => 'admin/emotes/delete/' . $emote->id]) !!}

    Are you sure you want to delete {{ $emote->name }}?

    @@ -8,6 +8,6 @@ {!! Form::close() !!} -@else +@else Invalid emote selected. -@endif \ No newline at end of file +@endif diff --git a/resources/views/admin/emotes/create_edit_emote.blade.php b/resources/views/admin/emotes/create_edit_emote.blade.php index 7830624c71..65efb2bfcf 100644 --- a/resources/views/admin/emotes/create_edit_emote.blade.php +++ b/resources/views/admin/emotes/create_edit_emote.blade.php @@ -1,94 +1,97 @@ @extends('admin.layout') -@section('admin-title') Emotes @endsection +@section('admin-title') + Emotes +@endsection @section('admin-content') -{!! breadcrumbs(['Admin Panel' => 'admin', 'Emotes' => 'admin/emotes', ($emote->id ? 'Edit' : 'Create').' Emote' => $emote->id ? 'admin/emotes/edit/'.$emote->id : 'admin/emotes/create']) !!} + {!! breadcrumbs(['Admin Panel' => 'admin', 'Emotes' => 'admin/emotes', ($emote->id ? 'Edit' : 'Create') . ' Emote' => $emote->id ? 'admin/emotes/edit/' . $emote->id : 'admin/emotes/create']) !!} -

    {{ $emote->id ? 'Edit' : 'Create' }} Emote - @if($emote->id) - Delete Emote - @endif -

    +

    {{ $emote->id ? 'Edit' : 'Create' }} Emote + @if ($emote->id) + Delete Emote + @endif +

    -{!! Form::open(['url' => $emote->id ? 'admin/emotes/edit/'.$emote->id : 'admin/emotes/create', 'files' => true]) !!} + {!! Form::open(['url' => $emote->id ? 'admin/emotes/edit/' . $emote->id : 'admin/emotes/create', 'files' => true]) !!} -

    Basic Information

    +

    Basic Information

    -
    - {!! Form::label('Name') !!} {!! add_help('NOTE: Names with spaces don\'t play well with the emote generator, so try to use underscores if you have to') !!} - {!! Form::text('name', $emote->name, ['class' => 'form-control']) !!} -
    +
    + {!! Form::label('Name') !!} {!! add_help('NOTE: Names with spaces don\'t play well with the emote generator, so try to use underscores if you have to') !!} + {!! Form::text('name', $emote->name, ['class' => 'form-control']) !!} +
    -
    - {!! Form::label('Image (Required)') !!} -
    {!! Form::file('image') !!}
    - @if($emote->has_image) -
    - {!! Form::checkbox('remove_image', 1, false, ['class' => 'form-check-input']) !!} - {!! Form::label('remove_image', 'Remove current image', ['class' => 'form-check-label']) !!} -
    - @endif -
    +
    + {!! Form::label('Image (Required)') !!} +
    {!! Form::file('image') !!}
    + @if ($emote->has_image) +
    + {!! Form::checkbox('remove_image', 1, false, ['class' => 'form-check-input']) !!} + {!! Form::label('remove_image', 'Remove current image', ['class' => 'form-check-label']) !!} +
    + @endif +
    -
    - {!! Form::checkbox('is_active', 1, $emote->id ? $emote->is_active : 1, ['class' => 'form-check-input', 'data-toggle' => 'toggle']) !!} - {!! Form::label('is_active', 'Set Active', ['class' => 'form-check-label ml-3']) !!} {!! add_help('If turned off, this emote will not be able to be used') !!} -
    +
    + {!! Form::checkbox('is_active', 1, $emote->id ? $emote->is_active : 1, ['class' => 'form-check-input', 'data-toggle' => 'toggle']) !!} + {!! Form::label('is_active', 'Set Active', ['class' => 'form-check-label ml-3']) !!} {!! add_help('If turned off, this emote will not be able to be used') !!} +
    -
    - {!! Form::submit($emote->id ? 'Edit' : 'Create', ['class' => 'btn btn-primary']) !!} -
    +
    + {!! Form::submit($emote->id ? 'Edit' : 'Create', ['class' => 'btn btn-primary']) !!} +
    -{!! Form::close() !!} + {!! Form::close() !!} -@if($emote->id && $emote->imageUrl) -

    Preview

    -
    -
    - @if(Auth::check() && Auth::user()->hasPower('edit_data')) - - @endif -
    - @isset($emote->imageUrl) - - @endisset -
    -

    {!! $emote->name !!}

    + @if ($emote->id && $emote->imageUrl) +

    Preview

    +
    +
    -
    Use This Emote
    -
    -
    - In the rich text editor: -
    - [emote={{ $emote->id }}] + @if (Auth::check() && Auth::user()->hasPower('edit_data')) + + @endif +
    + @isset($emote->imageUrl) + + @endisset
    - or: -
    - [emote={{ $emote->name }}] +

    {!! $emote->name !!}

    +
    +
    Use This Emote
    - In comments and forums: -
    - ![{{ $emote->name }}]({{ asset( $emote->imageUrl) }}) +
    + In the rich text editor: +
    + [emote={{ $emote->id }}] +
    + or: +
    + [emote={{ $emote->name }}] +
    + In comments and forums: +
    + ![{{ $emote->name }}]({{ asset($emote->imageUrl) }}) +
    -
    - -
    -@endif +
    +
    + @endif @endsection @section('scripts') -@parent - -@endsection \ No newline at end of file + @parent + +@endsection diff --git a/resources/views/admin/emotes/emotes.blade.php b/resources/views/admin/emotes/emotes.blade.php index 3f9b1af56d..ef09c1ed96 100644 --- a/resources/views/admin/emotes/emotes.blade.php +++ b/resources/views/admin/emotes/emotes.blade.php @@ -1,48 +1,50 @@ @extends('admin.layout') -@section('admin-title') Emotes @endsection +@section('admin-title') + Emotes +@endsection @section('admin-content') -{!! breadcrumbs(['Admin Panel' => 'admin', 'Emotes' => 'admin/emotes']) !!} - -

    Emotes

    - -

    This is a list of emotes players/admins can use in the tinymce editor (and in comments).

    - - - -@if(!count($emotes)) -

    No emotes found.

    -@else - - - - - - - - - - @foreach($emotes as $emote) + {!! breadcrumbs(['Admin Panel' => 'admin', 'Emotes' => 'admin/emotes']) !!} + +

    Emotes

    + +

    This is a list of emotes players/admins can use in the tinymce editor (and in comments).

    + + + + @if (!count($emotes)) +

    No emotes found.

    + @else +
    NameIs Visible
    + - - - + + + - @endforeach - - -
    - {!! $emote->imageUrl ? '' : ''!!} {{ $emote->name }} - {{$emote->is_active ? 'Active' : ' '}} - Edit - NameIs Visible
    -@endif + + + @foreach ($emotes as $emote) + + + {!! $emote->imageUrl ? '' : '' !!} {{ $emote->name }} + + {{ $emote->is_active ? 'Active' : ' ' }} + + Edit + + + @endforeach + + + + @endif @endsection @section('scripts') -@parent -@endsection \ No newline at end of file + @parent +@endsection diff --git a/resources/views/world/_item_entry.blade.php b/resources/views/world/_item_entry.blade.php index 8c7b7e2f28..689e7e6fd6 100644 --- a/resources/views/world/_item_entry.blade.php +++ b/resources/views/world/_item_entry.blade.php @@ -136,13 +136,13 @@
    Use as Emote
    - +
    + {!! $emotes->render() !!} @endif @endsection diff --git a/resources/views/world/emotes.blade.php b/resources/views/world/emotes.blade.php index b9bd3912bd..bfe2039b4a 100644 --- a/resources/views/world/emotes.blade.php +++ b/resources/views/world/emotes.blade.php @@ -11,7 +11,7 @@
    {!! Form::open(['method' => 'GET', 'class' => 'form-inline justify-content-end']) !!}
    - {!! Form::text('name', Request::get('name'), ['class' => 'form-control']) !!} + {!! Form::text('name', Request::get('name'), ['class' => 'form-control', 'placeholder' => 'Search by Name']) !!}
    {!! Form::close() !!}
    @@ -29,11 +29,14 @@ @endif
    - @isset($emote->imageUrl) - - @endisset + {!! $emote->getImage() !!} +
    +

    + {!! $emote->name !!} +

    +
    + {!! $emote->description !!}
    -

    {!! $emote->name !!}

    Use This Emote
    From 146789ef79d571519d627e0a06aae9ee1c10da88 Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Wed, 22 Jan 2025 17:51:14 +0000 Subject: [PATCH 09/35] refactor: fix PHP styling --- app/Models/Emote.php | 2 +- .../2025_01_22_113431_add_description_to_emotes.php | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/app/Models/Emote.php b/app/Models/Emote.php index 90b6005f26..a268db9173 100644 --- a/app/Models/Emote.php +++ b/app/Models/Emote.php @@ -106,7 +106,7 @@ public function getImageUrlAttribute() { /** * Returns the emote's image as an HTML image element with alt text. - * + * * @return string */ public function getImage() { diff --git a/database/migrations/2025_01_22_113431_add_description_to_emotes.php b/database/migrations/2025_01_22_113431_add_description_to_emotes.php index 5c225645fd..4e0ef29dc1 100644 --- a/database/migrations/2025_01_22_113431_add_description_to_emotes.php +++ b/database/migrations/2025_01_22_113431_add_description_to_emotes.php @@ -4,13 +4,11 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -return new class extends Migration -{ +return new class extends Migration { /** * Run the migrations. */ - public function up(): void - { + public function up(): void { Schema::table('emotes', function (Blueprint $table) { // $table->text('description')->nullable()->default(null)->after('name'); @@ -21,8 +19,7 @@ public function up(): void /** * Reverse the migrations. */ - public function down(): void - { + public function down(): void { Schema::table('emotes', function (Blueprint $table) { // $table->dropColumn('description'); From 883880fad46358d5ede6099539dce63431bb3d17 Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Wed, 22 Jan 2025 18:01:58 +0000 Subject: [PATCH 10/35] refactor: fix blade formatting --- resources/views/js/_modal_wysiwyg.blade.php | 1 - resources/views/layouts/app.blade.php | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/resources/views/js/_modal_wysiwyg.blade.php b/resources/views/js/_modal_wysiwyg.blade.php index c0e7fa6512..2e8452bb57 100644 --- a/resources/views/js/_modal_wysiwyg.blade.php +++ b/resources/views/js/_modal_wysiwyg.blade.php @@ -1,4 +1,3 @@ - diff --git a/resources/views/galleries/submission.blade.php b/resources/views/galleries/submission.blade.php index e6576516e9..4dfea6e42c 100644 --- a/resources/views/galleries/submission.blade.php +++ b/resources/views/galleries/submission.blade.php @@ -221,17 +221,6 @@
    [thumb={{ $submission->id }}]
    - @if (!config('lorekeeper.settings.wysiwyg_comments')) - In a comment: -
    - @if (isset($submission->hash) && !isset($submission->content_warning)) - [![Image]({{ $submission->thumbnailUrl }})]({{ $submission->url }}) - @else - [{{ $submission->displayTitle }} by {{ $submission->creditsPlain }} - {{ isset($submission->hash) ? '(Art)' : '(Literature)' }}{{ isset($submission->content_warning) ? ' ・ **Content Warning:** ' . nl2br(htmlentities($submission->content_warning)) : '' }}]({{ $submission->url }}) - @endif -
    - @endif
    diff --git a/resources/views/js/_character_select_js.blade copy.php b/resources/views/js/_character_select_js.blade copy.php deleted file mode 100644 index a9c5f6e484..0000000000 --- a/resources/views/js/_character_select_js.blade copy.php +++ /dev/null @@ -1,109 +0,0 @@ - diff --git a/resources/views/js/_modal_wysiwyg.blade.php b/resources/views/js/_modal_wysiwyg.blade.php index c0e7fa6512..f8e83d7333 100644 --- a/resources/views/js/_modal_wysiwyg.blade.php +++ b/resources/views/js/_modal_wysiwyg.blade.php @@ -9,6 +9,7 @@ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen', 'insertdatetime media table paste code help wordcount toc' + 'textpattern', ], toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | toc bullist numlist outdent indent | removeformat | code', content_css: [ @@ -17,6 +18,24 @@ '{{ asset('css/lorekeeper.css') }}' ], toc_class: 'container', + textpattern_patterns: [ + {start: '# ', format: 'h1'}, + {start: '## ', format: 'h2'}, + {start: '### ', format: 'h3'}, + {start: '#### ', format: 'h4'}, + {start: '##### ', format: 'h5'}, + {start: '###### ', format: 'h6'}, + {start: '**', end: '**', format: 'bold'}, + {start: '__', end: '__', format: 'bold'}, + {start: '*', end: '*', format: 'italic'}, + {start: '_', end: '_', format: 'italic'}, + {start: '~~', end: '~~', format: 'strikethrough'}, + {start: '> ', format: 'blockquote'}, + {start: '* ', cmd: 'InsertUnorderedList'}, + {start: '- ', cmd: 'InsertUnorderedList'}, + {start: '+ ', cmd: 'InsertUnorderedList'}, + {start: '1. ', cmd: 'InsertOrderedList'}, + ], }); }); diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index db5b205d35..0143f2ffe4 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -157,6 +157,7 @@ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen spoiler', 'insertdatetime media table paste code help wordcount toc mention', + 'textpattern', ], toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | toc bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | code', content_css: [ @@ -166,6 +167,24 @@ ], spoiler_caption: 'Toggle Spoiler', target_list: false, + textpattern_patterns: [ + {start: '# ', format: 'h1'}, + {start: '## ', format: 'h2'}, + {start: '### ', format: 'h3'}, + {start: '#### ', format: 'h4'}, + {start: '##### ', format: 'h5'}, + {start: '###### ', format: 'h6'}, + {start: '**', end: '**', format: 'bold'}, + {start: '__', end: '__', format: 'bold'}, + {start: '*', end: '*', format: 'italic'}, + {start: '_', end: '_', format: 'italic'}, + {start: '~~', end: '~~', format: 'strikethrough'}, + {start: '> ', format: 'blockquote'}, + {start: '* ', cmd: 'InsertUnorderedList'}, + {start: '- ', cmd: 'InsertUnorderedList'}, + {start: '+ ', cmd: 'InsertUnorderedList'}, + {start: '1. ', cmd: 'InsertOrderedList'}, + ], toc_class: 'container', mentions: { source: function (query, process, delimiter) { diff --git a/resources/views/user/_profile_content.blade.php b/resources/views/user/_profile_content.blade.php index e32221bfac..8ca2aa23c8 100644 --- a/resources/views/user/_profile_content.blade.php +++ b/resources/views/user/_profile_content.blade.php @@ -171,24 +171,12 @@
    {{ '@' . $user->name }}
    - @if (!config('lorekeeper.settings.wysiwyg_comments')) - In a comment: -
    - [{{ $user->name }}]({{ $user->url }}) -
    - @endif
    For Names and Avatars:
    In the rich text editor:
    {{ '%' . $user->name }}
    - @if (!config('lorekeeper.settings.wysiwyg_comments')) - In a comment: -
    - [![{{ $user->name }}'s Avatar]({{ $user->avatarUrl }})]({{ $user->url }}) [{{ $user->name }}]({{ $user->url }}) -
    - @endif @if (Auth::check() && Auth::user()->isStaff) diff --git a/resources/views/world/_item_entry.blade.php b/resources/views/world/_item_entry.blade.php index 689e7e6fd6..be0560b121 100644 --- a/resources/views/world/_item_entry.blade.php +++ b/resources/views/world/_item_entry.blade.php @@ -131,18 +131,4 @@ @endif - - -
    - Use as Emote
    - - + \ No newline at end of file diff --git a/resources/views/world/emotes.blade.php b/resources/views/world/emotes.blade.php index bfe2039b4a..02156fbdb6 100644 --- a/resources/views/world/emotes.blade.php +++ b/resources/views/world/emotes.blade.php @@ -20,14 +20,12 @@ {!! $emotes->render() !!} -
    +
    @foreach ($emotes as $emote) -
    +
    -
    - @if (Auth::check() && Auth::user()->hasPower('edit_data')) - - @endif +
    +
    {!! $emote->getImage() !!}
    @@ -37,26 +35,18 @@
    {!! $emote->description !!}
    -
    -
    Use This Emote
    -
    -
    - In the rich text editor: -
    - [emote={{ $emote->id }}] -
    - or: -
    - [emote={{ $emote->name }}] +
    +
    +
    Use This Emote
    - In comments and forums: -
    - ![{{ $emote->name }}]({{ asset($emote->imageUrl) }}) +
    + In the rich text editor: +
    + :{{ $emote->name }} +
    - -
    @endforeach From efefd80f977d1a10512aaae21d48874adacdd17d Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Fri, 24 Jan 2025 20:33:34 +0000 Subject: [PATCH 21/35] chore(deps): rebuild mix assets --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 1aa4c9b9e3..d1f8b069d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "LK-private", + "name": "lorekeeper", "lockfileVersion": 2, "requires": true, "packages": { From 16b865e2c51823710736a424478fe85db85bf59d Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Fri, 24 Jan 2025 20:36:11 +0000 Subject: [PATCH 22/35] refactor: fix blade formatting --- resources/views/character/_image_info.blade.php | 2 +- resources/views/world/_item_entry.blade.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/character/_image_info.blade.php b/resources/views/character/_image_info.blade.php index bafc65b427..39343ae8ac 100644 --- a/resources/views/character/_image_info.blade.php +++ b/resources/views/character/_image_info.blade.php @@ -186,7 +186,7 @@
    In the rich text editor:
    - {{ '@'.$character->fullName }} + {{ '@' . $character->fullName }}

    diff --git a/resources/views/world/_item_entry.blade.php b/resources/views/world/_item_entry.blade.php index be0560b121..4199589aaa 100644 --- a/resources/views/world/_item_entry.blade.php +++ b/resources/views/world/_item_entry.blade.php @@ -131,4 +131,4 @@ @endif
    -
    \ No newline at end of file +
    From 4b01fbd907b2efdd1ab4b561d023f5ebbbaac11a Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Fri, 24 Jan 2025 20:42:10 +0000 Subject: [PATCH 23/35] feat: update all tinymce JS --- config/lorekeeper/extension_tracker.php | 8 -- resources/views/character/_image_js.blade.php | 74 +++++++++++++++++++ .../comments/permalink_comment.blade.php | 37 ++++++++++ resources/views/js/_modal_wysiwyg.blade.php | 33 +++++---- resources/views/layouts/app.blade.php | 19 ++++- resources/views/pages/credits.blade.php | 3 + 6 files changed, 148 insertions(+), 26 deletions(-) diff --git a/config/lorekeeper/extension_tracker.php b/config/lorekeeper/extension_tracker.php index 5c308def6f..c831fb8e01 100644 --- a/config/lorekeeper/extension_tracker.php +++ b/config/lorekeeper/extension_tracker.php @@ -13,12 +13,4 @@ // 'version' => '1.0.0', // ], - 'Emotes' => [ - 'key' => 'Emotes', - 'wiki_key' => 'Emotes', - 'creators' => json_encode([ - 'CH3RVB' => 'https://github.com/CH3RVB/', - ]), - 'version' => '1.1.0', - ], ]; diff --git a/resources/views/character/_image_js.blade.php b/resources/views/character/_image_js.blade.php index 74cb4e0d56..11bc5a77dd 100644 --- a/resources/views/character/_image_js.blade.php +++ b/resources/views/character/_image_js.blade.php @@ -95,6 +95,43 @@ cmd: 'InsertOrderedList' }, ], + mentions: { + delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions')) !!}'), + source: function(query, process, delimiter) { + $.get('{{ url('mentions') }}', { + query: query, + delimiter: delimiter + }, function(data) { + process(data); + }); + }, + highlighter: function(text) { + //make matched block strong (make case insensitive) + return text.replace(new RegExp('(' + this.query + ')', 'ig'), function($1, match) { + return '' + match + ''; + }); + }, + insert: function(item) { + let content = item.mention_display_name; + const editor = tinyMCE.activeEditor; + editor.insertContent(content + '​') + + const rng = editor.selection.getRng(); + rng.setStart(rng.endContainer, rng.endOffset); + rng.collapse(true); + editor.selection.setRng(rng); + + return ''; + }, + render: function(item) { + return '
  • ' + + '' + + (item.image ? '' : '') + + '' + item.name + '' + + '' + + '
  • '; + }, + }, }); }); $(".edit-notes").remove(); @@ -210,6 +247,43 @@ start: '1. ', cmd: 'InsertOrderedList' }, + mentions: { + delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions')) !!}'), + source: function(query, process, delimiter) { + $.get('{{ url('mentions') }}', { + query: query, + delimiter: delimiter + }, function(data) { + process(data); + }); + }, + highlighter: function(text) { + //make matched block strong (make case insensitive) + return text.replace(new RegExp('(' + this.query + ')', 'ig'), function($1, match) { + return '' + match + ''; + }); + }, + insert: function(item) { + let content = item.mention_display_name; + const editor = tinyMCE.activeEditor; + editor.insertContent(content + '​') + + const rng = editor.selection.getRng(); + rng.setStart(rng.endContainer, rng.endOffset); + rng.collapse(true); + editor.selection.setRng(rng); + + return ''; + }, + render: function(item) { + return '
  • ' + + '' + + (item.image ? '' : '') + + '' + item.name + '' + + '' + + '
  • '; + }, + }, ], }); }); diff --git a/resources/views/comments/permalink_comment.blade.php b/resources/views/comments/permalink_comment.blade.php index e3e050d763..80124f5220 100644 --- a/resources/views/comments/permalink_comment.blade.php +++ b/resources/views/comments/permalink_comment.blade.php @@ -117,6 +117,43 @@ cmd: 'InsertOrderedList' }, ], + mentions: { + delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions')) !!}'), + source: function(query, process, delimiter) { + $.get('{{ url('mentions') }}', { + query: query, + delimiter: delimiter + }, function(data) { + process(data); + }); + }, + highlighter: function(text) { + //make matched block strong (make case insensitive) + return text.replace(new RegExp('(' + this.query + ')', 'ig'), function($1, match) { + return '' + match + ''; + }); + }, + insert: function(item) { + let content = item.mention_display_name; + const editor = tinyMCE.activeEditor; + editor.insertContent(content + '​') + + const rng = editor.selection.getRng(); + rng.setStart(rng.endContainer, rng.endOffset); + rng.collapse(true); + editor.selection.setRng(rng); + + return ''; + }, + render: function(item) { + return '
  • ' + + '' + + (item.image ? '' : '') + + '' + item.name + '' + + '' + + '
  • '; + }, + }, }); }); diff --git a/resources/views/js/_modal_wysiwyg.blade.php b/resources/views/js/_modal_wysiwyg.blade.php index 2363c696a2..f7f2b7478f 100644 --- a/resources/views/js/_modal_wysiwyg.blade.php +++ b/resources/views/js/_modal_wysiwyg.blade.php @@ -97,27 +97,28 @@ process(data); }); }, + highlighter: function(text) { + //make matched block strong (make case insensitive) + return text.replace(new RegExp('(' + this.query + ')', 'ig'), function($1, match) { + return '' + match + ''; + }); + }, insert: function(item) { - switch (item.type) { - case '@': - case ':': - return item.mention_display_name; - break; - case '#': - return '
  • ' + - '' + - '' + item.name + '' + - '
  • '; - break; - default: - return item.mention_display_name; - break; - } + let content = item.mention_display_name; + const editor = tinyMCE.activeEditor; + editor.insertContent(content + '​') + + const rng = editor.selection.getRng(); + rng.setStart(rng.endContainer, rng.endOffset); + rng.collapse(true); + editor.selection.setRng(rng); + + return ''; }, render: function(item) { return '
  • ' + '' + - '' + + (item.image ? '' : '') + '' + item.name + '' + '' + '
  • '; diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 8c63a26762..05b331aabc 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -248,13 +248,28 @@ process(data); }); }, + highlighter: function(text) { + //make matched block strong (make case insensitive) + return text.replace(new RegExp('(' + this.query + ')', 'ig'), function($1, match) { + return '' + match + ''; + }); + }, insert: function(item) { - return 'temp'; + let content = item.mention_display_name; + const editor = tinyMCE.activeEditor; + editor.insertContent(content + '​') + + const rng = editor.selection.getRng(); + rng.setStart(rng.endContainer, rng.endOffset); + rng.collapse(true); + editor.selection.setRng(rng); + + return ''; }, render: function(item) { return '
  • ' + '' + - '' + + (item.image ? '' : '') + '' + item.name + '' + '' + '
  • '; diff --git a/resources/views/pages/credits.blade.php b/resources/views/pages/credits.blade.php index d7a0d75b18..35b9dbc714 100644 --- a/resources/views/pages/credits.blade.php +++ b/resources/views/pages/credits.blade.php @@ -88,6 +88,9 @@

    Dynamic Limits by ScuffedNewt

    +

    + Emotes by CH3RVB +

    Mentions by ScuffedNewt

    From d10a832e003d175dcb054c722df36584d054839b Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Fri, 24 Jan 2025 20:46:07 +0000 Subject: [PATCH 24/35] refactor: fix PHP styling --- app/Helpers/AssetHelpers.php | 2 +- app/Http/Controllers/BrowseController.php | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/Helpers/AssetHelpers.php b/app/Helpers/AssetHelpers.php index 1a0935e2be..4687718bec 100644 --- a/app/Helpers/AssetHelpers.php +++ b/app/Helpers/AssetHelpers.php @@ -160,7 +160,7 @@ function getAssetModelString($type, $namespaced = true) { return 'Emote'; } break; - + case 'gallery_submissions': case 'gallery_submission': if ($namespaced) { return '\App\Models\Gallery\GallerySubmission'; diff --git a/app/Http/Controllers/BrowseController.php b/app/Http/Controllers/BrowseController.php index 7ba797c227..ab6da38a49 100644 --- a/app/Http/Controllers/BrowseController.php +++ b/app/Http/Controllers/BrowseController.php @@ -7,9 +7,9 @@ use App\Models\Character\CharacterCategory; use App\Models\Character\CharacterImage; use App\Models\Character\Sublist; -use App\Models\Gallery\GallerySubmission; use App\Models\Emote; use App\Models\Feature\Feature; +use App\Models\Gallery\GallerySubmission; use App\Models\Item\Item; use App\Models\Prompt\Prompt; use App\Models\Rank\Rank; @@ -314,7 +314,7 @@ public function getSearchMentions(Request $request) { $emotes = Emote::where('name', 'LIKE', "%{$queryString}%")->orderBy('name')->get()->map(function ($emote) { return [ 'type' => ':', - 'name' => $emote->name . ' (Emote)', + 'name' => $emote->name.' (Emote)', 'image' => $emote->imageUrl, 'mention_display_name' => $emote->mentionImage, ]; @@ -323,7 +323,7 @@ public function getSearchMentions(Request $request) { $items = Item::released()->where('has_image', 1)->where('name', 'LIKE', "%{$queryString}%")->orderBy('name')->get()->map(function ($item) { return [ 'type' => ':', - 'name' => $item->name . ' (Item)', + 'name' => $item->name.' (Item)', 'image' => $item->imageUrl, 'mention_display_name' => $item->mentionImage, ]; @@ -335,7 +335,7 @@ public function getSearchMentions(Request $request) { $users = User::visible()->where('name', 'LIKE', "%{$queryString}%")->orderBy('name')->get()->map(function ($user) { return [ 'type' => '#', - 'name' => $user->name . ' (User)', + 'name' => $user->name.' (User)', 'image' => $user->avatarUrl, 'mention_display_name' => $user->mentionImage, ]; @@ -346,7 +346,7 @@ public function getSearchMentions(Request $request) { })->orderBy('name')->get()->map(function ($character) { return [ 'type' => '#', - 'name' => $character->fullName . ' (Character)', + 'name' => $character->fullName.' (Character)', 'image' => $character->image->thumbnailUrl, 'mention_display_name' => $character->mentionImage, ]; @@ -355,7 +355,7 @@ public function getSearchMentions(Request $request) { $items = Item::released()->where('name', 'LIKE', "%{$queryString}%")->orderBy('name')->get()->map(function ($item) { return [ 'type' => '#', - 'name' => $item->name . ' (Item)', + 'name' => $item->name.' (Item)', 'image' => $item->has_image ? $item->imageUrl : null, 'mention_display_name' => $item->has_image ? $item->mentionImage : $item->mentionDisplayName, ]; @@ -364,7 +364,7 @@ public function getSearchMentions(Request $request) { $prompts = Prompt::active()->where('name', 'LIKE', "%{$queryString}%")->orderBy('name')->get()->map(function ($prompt) { return [ 'type' => '#', - 'name' => $prompt->name . ' (Prompt)', + 'name' => $prompt->name.' (Prompt)', 'image' => $prompt->has_image ? $prompt->imageUrl : null, 'mention_display_name' => $prompt->has_image ? $prompt->mentionImage : $prompt->mentionDisplayName, ]; @@ -373,7 +373,7 @@ public function getSearchMentions(Request $request) { $traits = Feature::visible()->where('name', 'LIKE', "%{$queryString}%")->orderBy('name')->get()->map(function ($trait) { return [ 'type' => '#', - 'name' => $trait->name . ' (Trait)', + 'name' => $trait->name.' (Trait)', 'image' => $trait->has_image ? $trait->mentionImage : $trait->mentionDisplayName, 'mention_display_name' => $trait->mentionDisplayName, ]; @@ -382,7 +382,7 @@ public function getSearchMentions(Request $request) { $gallerySubmissions = GallerySubmission::visible()->where('title', 'LIKE', "%{$queryString}%")->orderBy('title')->get()->map(function ($submission) { return [ 'type' => '#', - 'name' => $submission->title . ' (Gallery Submission)', + 'name' => $submission->title.' (Gallery Submission)', 'image' => $submission->has_image ? $submission->imageUrl : null, 'mention_display_name' => $submission->has_image ? $submission->mentionImage : $submission->mentionDisplayName, ]; From dd4c91e0caa35687e07062f6bec44555b2f44c8e Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Fri, 24 Jan 2025 23:17:13 +0000 Subject: [PATCH 25/35] feat(mentions command): command to convert prior mentions to new format --- .../Commands/ConvertExtendedMentions.php | 115 ++++++++++++++++++ app/Models/Character/Character.php | 2 +- app/Models/Feature/Feature.php | 2 +- app/Models/Gallery/GallerySubmission.php | 4 +- app/Models/Prompt/Prompt.php | 2 +- app/Models/User/User.php | 2 +- config/lorekeeper/mentions.php | 7 +- resources/views/character/_image_js.blade.php | 4 +- resources/views/comments/comments.blade.php | 2 +- .../comments/permalink_comment.blade.php | 2 +- resources/views/js/_modal_wysiwyg.blade.php | 2 +- resources/views/layouts/app.blade.php | 2 +- 12 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 app/Console/Commands/ConvertExtendedMentions.php diff --git a/app/Console/Commands/ConvertExtendedMentions.php b/app/Console/Commands/ConvertExtendedMentions.php new file mode 100644 index 0000000000..1ce6bfd8a1 --- /dev/null +++ b/app/Console/Commands/ConvertExtendedMentions.php @@ -0,0 +1,115 @@ +info('Converting extended mentions...'); + $this->info('Converting News...'); + foreach (News::all() as $news) { + $newText = $this->convertText($news->text); + $news->text = $newText; + $news->parsed_text = parse($newText); + $news->save(); + } + + $this->info('Converting Site Pages...'); + foreach (SitePage::all() as $page) { + $newText = $this->convertText($page->text); + $page->text = $newText; + $page->parsed_text = parse($newText); + $page->save(); + } + + $this->info('Converting Sales...'); + foreach (Sales::all() as $sale) { + $newText = $this->convertText($sale->description); + $sale->description = $newText; + $sale->parsed_description = parse($newText); + $sale->save(); + } + + $this->info('Converting Character Profiles...'); + foreach (CharacterProfile::all() as $profile) { + $newText = $this->convertText($profile->description); + $profile->description = $newText; + $profile->parsed_description = parse($newText); + $profile->save(); + } + + $this->info('Converting User Profiles...'); + foreach (UserProfile::all() as $profile) { + $newText = $this->convertText($profile->bio); + $profile->bio = $newText; + $profile->parsed_bio = parse($newText); + $profile->save(); + } + + $this->info('Converting Gallery Submissions...'); + foreach (GallerySubmission::all() as $submission) { + $newText = $this->convertText($submission->description); + $submission->description = $newText; + $submission->parsed_description = parse($newText); + $submission->save(); + } + + $this->info('Conversion complete.'); + } + + private function convertText($text) { + $toMatch = [ + '/\B@([A-Za-z0-9_-]+)/', // matches @mentions + '/\B%([A-Za-z0-9_-]+)/', // matches %mentions + '/\[user=([^\[\]&<>?"\']+)\]/', // matches [user=username] + '/\[userav=([^\[\]&<>?"\']+)\]/', // matches [userav=username] + '/\[character=([^\[\]&<>?"\']+)\]/', // matches [character=name] + '/\[charthumb=([^\[\]&<>?"\']+)\]/', // matches [charthumb=name] + '/\[thumb=([^\[\]&<>?"\']+)\]/' // matches [thumb=name] + ]; + + $replacements = [ + '@$1', + '@$1', + '@$1', + '', + '@$1', + '', + '' + ]; + + foreach ($toMatch as $index => $pattern) { + $text = preg_replace($pattern, $replacements[$index], $text); + } + + return $text; + } +} diff --git a/app/Models/Character/Character.php b/app/Models/Character/Character.php index 5850b12bf2..3cbd7a11ec 100644 --- a/app/Models/Character/Character.php +++ b/app/Models/Character/Character.php @@ -330,7 +330,7 @@ public function getMentionDisplayNameAttribute() { * @return string */ public function getMentionImageAttribute() { - return ''.$this->name.''; + return ''.$this->name.''; } /** diff --git a/app/Models/Feature/Feature.php b/app/Models/Feature/Feature.php index a4362e2f90..a884da7b3d 100644 --- a/app/Models/Feature/Feature.php +++ b/app/Models/Feature/Feature.php @@ -227,7 +227,7 @@ public function getMentionDisplayNameAttribute() { * @return string */ public function getMentionImageAttribute() { - return ''.$this->name.''; + return ''.$this->name.''; } /** diff --git a/app/Models/Gallery/GallerySubmission.php b/app/Models/Gallery/GallerySubmission.php index ed7959ad7b..60ed9f6fdf 100644 --- a/app/Models/Gallery/GallerySubmission.php +++ b/app/Models/Gallery/GallerySubmission.php @@ -384,12 +384,12 @@ public function getMentionDisplayNameAttribute() { } /** - * Displays the prompt's image, but with specific classes to identify mentions. + * Displays the submission's image, but with specific classes to identify mentions. * * @return string */ public function getMentionImageAttribute() { - return ''.$this->name.''; + return ''.$this->name.''; } /** diff --git a/app/Models/Prompt/Prompt.php b/app/Models/Prompt/Prompt.php index f26a4c874b..474f79ec97 100644 --- a/app/Models/Prompt/Prompt.php +++ b/app/Models/Prompt/Prompt.php @@ -253,7 +253,7 @@ public function getMentionDisplayNameAttribute() { * @return string */ public function getMentionImageAttribute() { - return ''.$this->name.''; + return ''.$this->name.''; } /** diff --git a/app/Models/User/User.php b/app/Models/User/User.php index 2da32a6676..ba504f7f6e 100644 --- a/app/Models/User/User.php +++ b/app/Models/User/User.php @@ -366,7 +366,7 @@ public function getMentionDisplayNameAttribute() { */ public function getMentionImageAttribute() { return '' - .''.$this->name.'' + .''.$this->name.'' .''; } diff --git a/config/lorekeeper/mentions.php b/config/lorekeeper/mentions.php index 3b7ca88256..c83409309e 100644 --- a/config/lorekeeper/mentions.php +++ b/config/lorekeeper/mentions.php @@ -3,7 +3,8 @@ return [ // delimiters - '@', - ':', - '#', + 'delimiters' => ['@', ':', '#'], + + + ]; diff --git a/resources/views/character/_image_js.blade.php b/resources/views/character/_image_js.blade.php index 11bc5a77dd..effc82053e 100644 --- a/resources/views/character/_image_js.blade.php +++ b/resources/views/character/_image_js.blade.php @@ -96,7 +96,7 @@ }, ], mentions: { - delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions')) !!}'), + delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions.delimiters')) !!}'), source: function(query, process, delimiter) { $.get('{{ url('mentions') }}', { query: query, @@ -248,7 +248,7 @@ cmd: 'InsertOrderedList' }, mentions: { - delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions')) !!}'), + delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions.delimiters')) !!}'), source: function(query, process, delimiter) { $.get('{{ url('mentions') }}', { query: query, diff --git a/resources/views/comments/comments.blade.php b/resources/views/comments/comments.blade.php index 4463304a04..72aa5c7ed6 100644 --- a/resources/views/comments/comments.blade.php +++ b/resources/views/comments/comments.blade.php @@ -195,7 +195,7 @@ function sortComments() { }, ], mentions: { - delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions')) !!}'), + delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions.delimiters')) !!}'), source: function(query, process, delimiter) { $.get('{{ url('mentions') }}', { query: query, diff --git a/resources/views/comments/permalink_comment.blade.php b/resources/views/comments/permalink_comment.blade.php index 80124f5220..d7ed445a17 100644 --- a/resources/views/comments/permalink_comment.blade.php +++ b/resources/views/comments/permalink_comment.blade.php @@ -118,7 +118,7 @@ }, ], mentions: { - delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions')) !!}'), + delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions.delimiters')) !!}'), source: function(query, process, delimiter) { $.get('{{ url('mentions') }}', { query: query, diff --git a/resources/views/js/_modal_wysiwyg.blade.php b/resources/views/js/_modal_wysiwyg.blade.php index f7f2b7478f..1ba2efd285 100644 --- a/resources/views/js/_modal_wysiwyg.blade.php +++ b/resources/views/js/_modal_wysiwyg.blade.php @@ -88,7 +88,7 @@ }, ], mentions: { - delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions')) !!}'), + delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions.delimiters')) !!}'), source: function(query, process, delimiter) { $.get('{{ url('mentions') }}', { query: query, diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 05b331aabc..fc90861704 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -239,7 +239,7 @@ ], toc_class: 'container', mentions: { - delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions')) !!}'), + delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions.delimiters')) !!}'), source: function(query, process, delimiter) { $.get('{{ url('mentions') }}', { query: query, From 76a3c63f6a993df7169a409614415b0cbe1f8943 Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Fri, 24 Jan 2025 23:19:58 +0000 Subject: [PATCH 26/35] refactor: fix PHP styling --- .../Commands/ConvertExtendedMentions.php | 27 +++++++++---------- config/lorekeeper/mentions.php | 2 -- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/app/Console/Commands/ConvertExtendedMentions.php b/app/Console/Commands/ConvertExtendedMentions.php index 1ce6bfd8a1..307568b0d1 100644 --- a/app/Console/Commands/ConvertExtendedMentions.php +++ b/app/Console/Commands/ConvertExtendedMentions.php @@ -2,17 +2,15 @@ namespace App\Console\Commands; -use Illuminate\Console\Command; +use App\Models\Character\CharacterProfile; +use App\Models\Gallery\GallerySubmission; use App\Models\News; -use App\Models\SitePage; use App\Models\Sales\Sales; -use App\Models\Character\CharacterProfile; +use App\Models\SitePage; use App\Models\Users\UserProfile; -use App\Models\Gallery\GallerySubmission; - +use Illuminate\Console\Command; -class ConvertExtendedMentions extends Command -{ +class ConvertExtendedMentions extends Command { /** * The name and signature of the console command. * @@ -30,8 +28,7 @@ class ConvertExtendedMentions extends Command /** * Execute the console command. */ - public function handle() - { + public function handle() { // $this->info('Converting extended mentions...'); $this->info('Converting News...'); @@ -41,7 +38,7 @@ public function handle() $news->parsed_text = parse($newText); $news->save(); } - + $this->info('Converting Site Pages...'); foreach (SitePage::all() as $page) { $newText = $this->convertText($page->text); @@ -93,9 +90,9 @@ private function convertText($text) { '/\[userav=([^\[\]&<>?"\']+)\]/', // matches [userav=username] '/\[character=([^\[\]&<>?"\']+)\]/', // matches [character=name] '/\[charthumb=([^\[\]&<>?"\']+)\]/', // matches [charthumb=name] - '/\[thumb=([^\[\]&<>?"\']+)\]/' // matches [thumb=name] + '/\[thumb=([^\[\]&<>?"\']+)\]/', // matches [thumb=name] ]; - + $replacements = [ '@$1', '@$1', @@ -103,9 +100,9 @@ private function convertText($text) { '', '@$1', '', - '' - ]; - + '', + ]; + foreach ($toMatch as $index => $pattern) { $text = preg_replace($pattern, $replacements[$index], $text); } diff --git a/config/lorekeeper/mentions.php b/config/lorekeeper/mentions.php index c83409309e..3fe21fad7e 100644 --- a/config/lorekeeper/mentions.php +++ b/config/lorekeeper/mentions.php @@ -5,6 +5,4 @@ // delimiters 'delimiters' => ['@', ':', '#'], - - ]; From f6e89dd2b447168d4c7f756a22646e5b15ef23b8 Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Sat, 25 Jan 2025 00:07:04 +0000 Subject: [PATCH 27/35] fix: user av + name --- app/Console/Commands/ConvertExtendedMentions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Console/Commands/ConvertExtendedMentions.php b/app/Console/Commands/ConvertExtendedMentions.php index 307568b0d1..5ff01af82d 100644 --- a/app/Console/Commands/ConvertExtendedMentions.php +++ b/app/Console/Commands/ConvertExtendedMentions.php @@ -95,7 +95,7 @@ private function convertText($text) { $replacements = [ '@$1', - '@$1', + '@$1', '@$1', '', '@$1', From dc3b1140c1076f8c7defc8688f8b5795b02ea1b3 Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Fri, 4 Apr 2025 19:36:00 +0000 Subject: [PATCH 28/35] refactor: fix blade formatting --- resources/views/layouts/app.blade.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 423b4c8111..4f78ef75ac 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -155,8 +155,8 @@ $('[data-toggle="tooltip"]').tooltip({ html: true }); - $('.cp').colorpicker(); -<<<<<<< HEAD + $('.cp').colorpicker(); << + << << < HEAD tinymce.init({ selector: '.wysiwyg', height: 500, @@ -284,10 +284,11 @@ ''; }, }, - }); -======= + }); === + === = ->>>>>>> 84ef1f15fd172cdfceca45fdca80e0b158f320d4 + >>> + >>> > 84 ef1f15fd172cdfceca45fdca80e0b158f320d4 bsCustomFileInput.init(); var $mobileMenuButton = $('#mobileMenuButton'); var $sidebar = $('#sidebar'); From eda82642d9a8922ca96c5067e838e525f83a7543 Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Fri, 4 Apr 2025 21:06:13 +0100 Subject: [PATCH 29/35] fix: conflicts --- resources/views/layouts/app.blade.php | 134 +------------------------- 1 file changed, 1 insertion(+), 133 deletions(-) diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 4f78ef75ac..f60bcd8c4e 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -155,140 +155,8 @@ $('[data-toggle="tooltip"]').tooltip({ html: true }); - $('.cp').colorpicker(); << - << << < HEAD - tinymce.init({ - selector: '.wysiwyg', - height: 500, - menubar: false, - convert_urls: false, - plugins: [ - 'advlist autolink lists link image charmap print preview anchor', - 'searchreplace visualblocks code fullscreen spoiler', - 'insertdatetime media table paste code help wordcount toc mention', - 'textpattern', - ], - toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | toc bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | code', - content_css: [ - '{{ asset('css/app.css') }}', - '{{ asset('css/lorekeeper.css') }}' + $('.cp').colorpicker(); - ], - spoiler_caption: 'Toggle Spoiler', - target_list: false, - textpattern_patterns: [{ - start: '# ', - format: 'h1' - }, - { - start: '## ', - format: 'h2' - }, - { - start: '### ', - format: 'h3' - }, - { - start: '#### ', - format: 'h4' - }, - { - start: '##### ', - format: 'h5' - }, - { - start: '###### ', - format: 'h6' - }, - { - start: '**', - end: '**', - format: 'bold' - }, - { - start: '__', - end: '__', - format: 'bold' - }, - { - start: '*', - end: '*', - format: 'italic' - }, - { - start: '_', - end: '_', - format: 'italic' - }, - { - start: '~~', - end: '~~', - format: 'strikethrough' - }, - { - start: '> ', - format: 'blockquote' - }, - { - start: '* ', - cmd: 'InsertUnorderedList' - }, - { - start: '- ', - cmd: 'InsertUnorderedList' - }, - { - start: '+ ', - cmd: 'InsertUnorderedList' - }, - { - start: '1. ', - cmd: 'InsertOrderedList' - }, - ], - toc_class: 'container', - mentions: { - delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions.delimiters')) !!}'), - source: function(query, process, delimiter) { - $.get('{{ url('mentions') }}', { - query: query, - delimiter: delimiter - }, function(data) { - process(data); - }); - }, - highlighter: function(text) { - //make matched block strong (make case insensitive) - return text.replace(new RegExp('(' + this.query + ')', 'ig'), function($1, match) { - return '' + match + ''; - }); - }, - insert: function(item) { - let content = item.mention_display_name; - const editor = tinyMCE.activeEditor; - editor.insertContent(content + '​') - - const rng = editor.selection.getRng(); - rng.setStart(rng.endContainer, rng.endOffset); - rng.collapse(true); - editor.selection.setRng(rng); - - return ''; - }, - render: function(item) { - return '
  • ' + - '' + - (item.image ? '' : '') + - '' + item.name + '' + - '' + - '
  • '; - }, - }, - }); === - === = - - >>> - >>> > 84 ef1f15fd172cdfceca45fdca80e0b158f320d4 bsCustomFileInput.init(); var $mobileMenuButton = $('#mobileMenuButton'); var $sidebar = $('#sidebar'); From 31fd3ca11e2036afe75144f335e4d31981ecfb49 Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Mon, 26 May 2025 16:37:58 +0100 Subject: [PATCH 30/35] fix: fix tinymce init and change # delimiter to % --- app/Http/Controllers/BrowseController.php | 14 +++++++------- config/lorekeeper/mentions.php | 2 +- resources/views/comments/_form.blade.php | 4 ++++ resources/views/comments/comments.blade.php | 1 - resources/views/galleries/submission.blade.php | 2 +- resources/views/js/_tinymce_wysiwyg.blade.php | 4 +++- resources/views/user/_profile_content.blade.php | 2 +- 7 files changed, 17 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/BrowseController.php b/app/Http/Controllers/BrowseController.php index f14543f5c4..e2c8132357 100644 --- a/app/Http/Controllers/BrowseController.php +++ b/app/Http/Controllers/BrowseController.php @@ -331,10 +331,10 @@ public function getSearchMentions(Request $request) { $result = collect($emotes)->merge(collect($items)); break; - case '#': + case '%': $users = User::visible()->where('name', 'LIKE', "%{$queryString}%")->orderBy('name')->get()->map(function ($user) { return [ - 'type' => '#', + 'type' => '%', 'name' => $user->name.' (User)', 'image' => $user->avatarUrl, 'mention_display_name' => $user->mentionImage, @@ -345,7 +345,7 @@ public function getSearchMentions(Request $request) { $query->where('name', 'LIKE', "%{$queryString}%")->orWhere('slug', 'LIKE', "%{$queryString}%"); })->orderBy('name')->get()->map(function ($character) { return [ - 'type' => '#', + 'type' => '%', 'name' => $character->fullName.' (Character)', 'image' => $character->image->thumbnailUrl, 'mention_display_name' => $character->mentionImage, @@ -354,7 +354,7 @@ public function getSearchMentions(Request $request) { $items = Item::released()->where('name', 'LIKE', "%{$queryString}%")->orderBy('name')->get()->map(function ($item) { return [ - 'type' => '#', + 'type' => '%', 'name' => $item->name.' (Item)', 'image' => $item->has_image ? $item->imageUrl : null, 'mention_display_name' => $item->has_image ? $item->mentionImage : $item->mentionDisplayName, @@ -363,7 +363,7 @@ public function getSearchMentions(Request $request) { $prompts = Prompt::active()->where('name', 'LIKE', "%{$queryString}%")->orderBy('name')->get()->map(function ($prompt) { return [ - 'type' => '#', + 'type' => '%', 'name' => $prompt->name.' (Prompt)', 'image' => $prompt->has_image ? $prompt->imageUrl : null, 'mention_display_name' => $prompt->has_image ? $prompt->mentionImage : $prompt->mentionDisplayName, @@ -372,7 +372,7 @@ public function getSearchMentions(Request $request) { $traits = Feature::visible()->where('name', 'LIKE', "%{$queryString}%")->orderBy('name')->get()->map(function ($trait) { return [ - 'type' => '#', + 'type' => '%', 'name' => $trait->name.' (Trait)', 'image' => $trait->has_image ? $trait->mentionImage : $trait->mentionDisplayName, 'mention_display_name' => $trait->mentionDisplayName, @@ -381,7 +381,7 @@ public function getSearchMentions(Request $request) { $gallerySubmissions = GallerySubmission::visible()->where('title', 'LIKE', "%{$queryString}%")->orderBy('title')->get()->map(function ($submission) { return [ - 'type' => '#', + 'type' => '%', 'name' => $submission->title.' (Gallery Submission)', 'image' => $submission->has_image ? $submission->imageUrl : null, 'mention_display_name' => $submission->has_image ? $submission->mentionImage : $submission->mentionDisplayName, diff --git a/config/lorekeeper/mentions.php b/config/lorekeeper/mentions.php index 3fe21fad7e..65d6b14a25 100644 --- a/config/lorekeeper/mentions.php +++ b/config/lorekeeper/mentions.php @@ -3,6 +3,6 @@ return [ // delimiters - 'delimiters' => ['@', ':', '#'], + 'delimiters' => ['@', ':', '%'], ]; diff --git a/resources/views/comments/_form.blade.php b/resources/views/comments/_form.blade.php index d4ff3fb2c7..3fd2ff2232 100644 --- a/resources/views/comments/_form.blade.php +++ b/resources/views/comments/_form.blade.php @@ -13,3 +13,7 @@

    + +@section('scripts') + @include('js._tinymce_wysiwyg', ['tinymceSelector' => '.comment-wysiwyg', 'tinymceHeight' => '250']) +@endsection \ No newline at end of file diff --git a/resources/views/comments/comments.blade.php b/resources/views/comments/comments.blade.php index f7cddf781c..a696e17be7 100644 --- a/resources/views/comments/comments.blade.php +++ b/resources/views/comments/comments.blade.php @@ -105,7 +105,6 @@ function sortComments() { window.history.pushState({}, '', url); } $('#{{ $commentType }}-comments').fadeIn(); - @include('js._tinymce_wysiwyg', ['tinymceSelector' => '.comment-wysiwyg', 'tinymceHeight' => '250', 'tinymceScript' => false]) } }); } diff --git a/resources/views/galleries/submission.blade.php b/resources/views/galleries/submission.blade.php index 0999731057..7ed9abd4e1 100644 --- a/resources/views/galleries/submission.blade.php +++ b/resources/views/galleries/submission.blade.php @@ -219,7 +219,7 @@
    In the rich text editor:
    - {{ '#' . $submission->id }} + {{ '%' . $submission->id }}
    diff --git a/resources/views/js/_tinymce_wysiwyg.blade.php b/resources/views/js/_tinymce_wysiwyg.blade.php index dfe6554640..f1f9b8f909 100644 --- a/resources/views/js/_tinymce_wysiwyg.blade.php +++ b/resources/views/js/_tinymce_wysiwyg.blade.php @@ -10,7 +10,7 @@ plugins: [ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen spoiler', - 'insertdatetime media table paste {{ config('lorekeeper.extensions.tinymce_code_editor') ? 'codeeditor' : 'code' }} help wordcount toc', + 'insertdatetime media table paste code help wordcount toc mention', 'textpattern', ], toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | toc bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | {{ config('lorekeeper.extensions.tinymce_code_editor') ? 'codeeditor' : 'code' }}', @@ -91,7 +91,9 @@ cmd: 'InsertOrderedList' }, ], + toc_class: 'container', mentions: { + delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions')) !!}'), delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions.delimiters')) !!}'), source: function(query, process, delimiter) { $.get('{{ url('mentions') }}', { diff --git a/resources/views/user/_profile_content.blade.php b/resources/views/user/_profile_content.blade.php index 5e32c5c150..a38bdf0e07 100644 --- a/resources/views/user/_profile_content.blade.php +++ b/resources/views/user/_profile_content.blade.php @@ -175,7 +175,7 @@
    For Avatars:
    In the rich text editor:
    - {{ '#' . $user->name }} + {{ '%' . $user->name }}
    From e2a50d82fe6cefb66a1a12a4290f020687447cae Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Mon, 26 May 2025 15:38:33 +0000 Subject: [PATCH 31/35] refactor: fix blade formatting --- resources/views/comments/_form.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/comments/_form.blade.php b/resources/views/comments/_form.blade.php index 3fd2ff2232..9d44c29d15 100644 --- a/resources/views/comments/_form.blade.php +++ b/resources/views/comments/_form.blade.php @@ -16,4 +16,4 @@ @section('scripts') @include('js._tinymce_wysiwyg', ['tinymceSelector' => '.comment-wysiwyg', 'tinymceHeight' => '250']) -@endsection \ No newline at end of file +@endsection From d001cebd419f43a2318825b4e34d6dc2a13b6e9a Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Mon, 26 May 2025 16:43:18 +0100 Subject: [PATCH 32/35] fix: loading --- resources/views/comments/_form.blade.php | 4 ---- resources/views/comments/comments.blade.php | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/resources/views/comments/_form.blade.php b/resources/views/comments/_form.blade.php index 3fd2ff2232..d4ff3fb2c7 100644 --- a/resources/views/comments/_form.blade.php +++ b/resources/views/comments/_form.blade.php @@ -13,7 +13,3 @@
    - -@section('scripts') - @include('js._tinymce_wysiwyg', ['tinymceSelector' => '.comment-wysiwyg', 'tinymceHeight' => '250']) -@endsection \ No newline at end of file diff --git a/resources/views/comments/comments.blade.php b/resources/views/comments/comments.blade.php index a696e17be7..f7cddf781c 100644 --- a/resources/views/comments/comments.blade.php +++ b/resources/views/comments/comments.blade.php @@ -105,6 +105,7 @@ function sortComments() { window.history.pushState({}, '', url); } $('#{{ $commentType }}-comments').fadeIn(); + @include('js._tinymce_wysiwyg', ['tinymceSelector' => '.comment-wysiwyg', 'tinymceHeight' => '250', 'tinymceScript' => false]) } }); } From 3a11810605b0e9045a98e8a3a5ba26c0238ea501 Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Tue, 27 May 2025 01:02:35 +0100 Subject: [PATCH 33/35] fix: restore extension config --- resources/views/js/_tinymce_wysiwyg.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/js/_tinymce_wysiwyg.blade.php b/resources/views/js/_tinymce_wysiwyg.blade.php index f1f9b8f909..b6338fef81 100644 --- a/resources/views/js/_tinymce_wysiwyg.blade.php +++ b/resources/views/js/_tinymce_wysiwyg.blade.php @@ -10,7 +10,7 @@ plugins: [ 'advlist autolink lists link image charmap print preview anchor', 'searchreplace visualblocks code fullscreen spoiler', - 'insertdatetime media table paste code help wordcount toc mention', + 'insertdatetime media table paste {{ config('lorekeeper.extensions.tinymce_code_editor') ? 'codeeditor' : 'code' }} help wordcount toc mention', 'textpattern', ], toolbar: 'undo redo | formatselect | bold italic backcolor | alignleft aligncenter alignright alignjustify | toc bullist numlist outdent indent | link image | spoiler-add spoiler-remove | removeformat | {{ config('lorekeeper.extensions.tinymce_code_editor') ? 'codeeditor' : 'code' }}', From a46b303a45a70a11eb14012864433d4a482e6d30 Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Thu, 29 May 2025 21:56:28 +0100 Subject: [PATCH 34/35] fix: allow pings in comments --- app/Helpers/Helpers.php | 30 +++++++++---------- .../Middleware/ParsePostRequestFields.php | 2 +- app/Models/Character/Character.php | 2 +- app/Models/Feature/Feature.php | 2 +- app/Models/Gallery/GallerySubmission.php | 4 +-- app/Models/Item/Item.php | 8 +++-- app/Models/Prompt/Prompt.php | 4 +-- app/Models/User/User.php | 8 ++--- .../views/account/notifications.blade.php | 2 +- resources/views/js/_tinymce_wysiwyg.blade.php | 1 - 10 files changed, 31 insertions(+), 32 deletions(-) diff --git a/app/Helpers/Helpers.php b/app/Helpers/Helpers.php index 9ecda0762b..180beec0e4 100644 --- a/app/Helpers/Helpers.php +++ b/app/Helpers/Helpers.php @@ -290,11 +290,11 @@ function parse($text, &$pings = null) { } } + $text = parseMentions($text, $pings); + $purifier = new HTMLPurifier($config); $text = $purifier->purify($text); - $text = parseMentions($text, $pings); - return $text; } @@ -316,23 +316,21 @@ function parseMentions($text, &$pings) { PREG_SET_ORDER ); - if ($count) { - foreach ($matches as $match) { - $parentElement = $match[0]; - $type = $match[2]; - $id = $match[3]; + foreach ($matches as $match) { + $parentElement = $match[0]; + $type = $match[2]; + $id = $match[3]; - $model = getAssetModelString($type); - $object = $model::find($id); + $model = getAssetModelString($type); + $object = $model::find($id); - if (!$object) { - continue; - } - - $pings[$type][] = $object; - $hasImage = preg_match('/]+>/i', $parentElement); - $text = str_replace($parentElement, $hasImage ? $object->mentionImage : $object->mentionDisplayName, $text); + if (!$object) { + continue; } + + $pings[$type][] = $object; + $hasImage = preg_match('/]+>/i', $parentElement); + $text = str_replace($parentElement, $hasImage ? $object->mentionImage : $object->mentionDisplayName, $text); } return $text; diff --git a/app/Http/Middleware/ParsePostRequestFields.php b/app/Http/Middleware/ParsePostRequestFields.php index f108b5c7fe..ebd103eed3 100644 --- a/app/Http/Middleware/ParsePostRequestFields.php +++ b/app/Http/Middleware/ParsePostRequestFields.php @@ -15,7 +15,7 @@ class ParsePostRequestFields { */ public function handle(Request $request, Closure $next) { if ($request->isMethod('post')) { - $excludedFields = ['_token', 'password', 'email', 'description', 'text', 'evaluation', 'criteria']; + $excludedFields = ['_token', 'password', 'email', 'description', 'text', 'evaluation', 'criteria', 'message']; $strippedFields = ['name', 'title']; $parsedFields = []; diff --git a/app/Models/Character/Character.php b/app/Models/Character/Character.php index 3cbd7a11ec..ba41dafda3 100644 --- a/app/Models/Character/Character.php +++ b/app/Models/Character/Character.php @@ -330,7 +330,7 @@ public function getMentionDisplayNameAttribute() { * @return string */ public function getMentionImageAttribute() { - return ''.$this->name.''; + return ''.$this->name.''; } /** diff --git a/app/Models/Feature/Feature.php b/app/Models/Feature/Feature.php index 5841fbb318..ba15b91529 100644 --- a/app/Models/Feature/Feature.php +++ b/app/Models/Feature/Feature.php @@ -217,7 +217,7 @@ public function getMentionDisplayNameAttribute() { * @return string */ public function getMentionImageAttribute() { - return ''.$this->name.''; + return ''.$this->name.''; } /** diff --git a/app/Models/Gallery/GallerySubmission.php b/app/Models/Gallery/GallerySubmission.php index 2307aef5fd..cbb6c4522c 100644 --- a/app/Models/Gallery/GallerySubmission.php +++ b/app/Models/Gallery/GallerySubmission.php @@ -370,7 +370,7 @@ public function getDisplayNameAttribute() { * Displays the submission's name, but with specific classes to identify mentions. */ public function getMentionDisplayNameAttribute() { - return ''.$this->name.''; + return ''.$this->name.''; } /** @@ -379,7 +379,7 @@ public function getMentionDisplayNameAttribute() { * @return string */ public function getMentionImageAttribute() { - return ''.$this->name.''; + return ''.$this->name.''; } /** diff --git a/app/Models/Item/Item.php b/app/Models/Item/Item.php index 3d40df1a9b..0a65e2b766 100644 --- a/app/Models/Item/Item.php +++ b/app/Models/Item/Item.php @@ -205,10 +205,12 @@ public function getMentionDisplayNameAttribute() { } /** - * Displays the item's image, but with specific classes to identify mentions. + * Displays the item in the tinymce editor. + * + * @return string */ - public function getMentionDisplayImageAttribute() { - return ''.$this->name.''; + public function getMentionImageAttribute() { + return ''.$this->alt_text.''; } /** diff --git a/app/Models/Prompt/Prompt.php b/app/Models/Prompt/Prompt.php index 53ee1644fa..7aa5e954c2 100644 --- a/app/Models/Prompt/Prompt.php +++ b/app/Models/Prompt/Prompt.php @@ -234,7 +234,7 @@ public function getDisplayNameAttribute() { * Displays the prompts's name, but with specific classes to identify mentions. */ public function getMentionDisplayNameAttribute() { - return ''.$this->name.''; + return ''.$this->name.''; } /** @@ -243,7 +243,7 @@ public function getMentionDisplayNameAttribute() { * @return string */ public function getMentionImageAttribute() { - return ''.$this->name.''; + return ''.$this->name.''; } /** diff --git a/app/Models/User/User.php b/app/Models/User/User.php index 14b8d20a58..9de7f5cd87 100644 --- a/app/Models/User/User.php +++ b/app/Models/User/User.php @@ -367,7 +367,7 @@ public function getDisplayNameAttribute() { * @return string */ public function getMentionDisplayNameAttribute() { - return '' + return '' .($this->is_banned ? '' : '').'@'.$this->name.''.($this->is_banned ? '' : '') .''; } @@ -378,9 +378,9 @@ public function getMentionDisplayNameAttribute() { * @return string */ public function getMentionImageAttribute() { - return '' + return '' .''.$this->name.'' - .''; + .''; } /** @@ -420,7 +420,7 @@ public function getDisplayAliasAttribute() { return '(Unverified)'; } - return $this->primaryAlias->displayAlias; + return $this->primaryAlias?->displayAlias ?? '(No Alias)'; } /** diff --git a/resources/views/account/notifications.blade.php b/resources/views/account/notifications.blade.php index 16056bb3c6..a2f38ebb84 100644 --- a/resources/views/account/notifications.blade.php +++ b/resources/views/account/notifications.blade.php @@ -28,7 +28,7 @@ {!! Form::submit('x clear', ['class' => 'badge btn-primary', 'style' => 'display:inline; border: 0;']) !!} {!! Form::close() !!} - {{ config('lorekeeper.notifications.' . $type . '.name') }} + {{ config('lorekeeper.notifications.' . $type . '.name') ?? 'Unknown Notification' }}
    diff --git a/resources/views/js/_tinymce_wysiwyg.blade.php b/resources/views/js/_tinymce_wysiwyg.blade.php index b6338fef81..28bcb73d28 100644 --- a/resources/views/js/_tinymce_wysiwyg.blade.php +++ b/resources/views/js/_tinymce_wysiwyg.blade.php @@ -93,7 +93,6 @@ ], toc_class: 'container', mentions: { - delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions')) !!}'), delimiter: JSON.parse('{!! json_encode(config('lorekeeper.mentions.delimiters')) !!}'), source: function(query, process, delimiter) { $.get('{{ url('mentions') }}', { From aacac2c96da5bb972c47082baf25b8e859de058b Mon Sep 17 00:00:00 2001 From: ScuffedNewt Date: Thu, 29 May 2025 20:57:07 +0000 Subject: [PATCH 35/35] refactor: fix blade formatting --- resources/views/account/notifications.blade.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/views/account/notifications.blade.php b/resources/views/account/notifications.blade.php index a2f38ebb84..e833ebc61d 100644 --- a/resources/views/account/notifications.blade.php +++ b/resources/views/account/notifications.blade.php @@ -28,7 +28,8 @@ {!! Form::submit('x clear', ['class' => 'badge btn-primary', 'style' => 'display:inline; border: 0;']) !!} {!! Form::close() !!} - {{ config('lorekeeper.notifications.' . $type . '.name') ?? 'Unknown Notification' }} + {{ config('lorekeeper.notifications.' . $type . '.name') ?? 'Unknown Notification' }}