├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── extend.php ├── js ├── admin.js ├── dist │ ├── admin.js │ ├── admin.js.map │ ├── forum.js │ └── forum.js.map ├── forum.js ├── package-lock.json ├── package.json ├── src │ ├── admin │ │ ├── components │ │ │ └── LevelRanksSettingsModal.js │ │ └── index.js │ └── forum │ │ ├── components │ │ └── LevelBar.js │ │ └── index.js └── webpack.config.js ├── resources ├── less │ └── forum.less └── locale │ ├── en.yml │ └── pl.yml └── src └── Listeners └── LoadSettingsFromDatabase.php /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | .DS_Store 61 | 62 | # flarum webpack 63 | v8-compile-cache-0 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Shahiem Seymor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Level ranks by ReFlar 3 | 4 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/ReFlar/level-ranks/blob/master/LICENSE) [![Latest Stable Version](https://img.shields.io/packagist/v/reflar/level-ranks.svg)](https://github.com/ReFlar/level-ranks) 5 | 6 | Add a level/expierence bar to your flarum Forum. 7 | 8 | ### Installation :balloon: 9 | 10 | Install it with composer: 11 | 12 | ```sh 13 | composer require reflar/level-ranks 14 | ``` 15 | 16 | ### Issues 🐛 17 | 18 | [Open an issue on Github](https://github.com/ReFlar/level-ranks/issues) 19 | 20 | Suggestions? Please feel free to give me some suggestions 21 | 22 | ### Links 🔗 23 | 24 | - [Github](https://github.com/ReFlar/level-ranks) 25 | - [Packagist](https://packagist.org/packages/reflar/level-ranks) 26 | - [Buy me a house with $1 💰](https://paypal.me/shahiemseymor) 27 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reflar/level-ranks", 3 | "description": "Add a level/experience bar to your flarum Forum.", 4 | "keywords": [ 5 | "extension", 6 | "flarum", 7 | "experience", 8 | "level", 9 | "xp" 10 | ], 11 | "type": "flarum-extension", 12 | "authors": [ 13 | { 14 | "name": "Shahiem Seymor", 15 | "email": "s.seymor@live.nl", 16 | "homepage": "http://shahiemseymor.com/" 17 | } 18 | ], 19 | "support": { 20 | "issues": "https://github.com/ReFlar/level-ranks/issues", 21 | "source": "https://github.com/ReFlar/level-ranks" 22 | }, 23 | "require": { 24 | "flarum/core": "^0.1.0-beta.8" 25 | }, 26 | "extra": { 27 | "flarum-extension": { 28 | "title": "ReFlar Level Ranks", 29 | "icon": { 30 | "name": "fas fa-percent", 31 | "backgroundColor": "#263238", 32 | "color": "#fff" 33 | } 34 | } 35 | }, 36 | "autoload": { 37 | "psr-4": { 38 | "Reflar\\LevelRanks\\": "src/" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /extend.php: -------------------------------------------------------------------------------- 1 | js(__DIR__.'/js/dist/forum.js') 22 | ->css(__DIR__.'/resources/less/forum.less'), 23 | (new Extend\Frontend('admin')) 24 | ->js(__DIR__.'/js/dist/admin.js'), 25 | new Extend\Locales(__DIR__.'/resources/locale'), 26 | function (Dispatcher $events) { 27 | $events->subscribe(Listeners\LoadSettingsFromDatabase::class); 28 | }, 29 | ]; 30 | -------------------------------------------------------------------------------- /js/admin.js: -------------------------------------------------------------------------------- 1 | export * from './src/admin'; -------------------------------------------------------------------------------- /js/dist/admin.js: -------------------------------------------------------------------------------- 1 | module.exports=function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=7)}([function(e,t){e.exports=flarum.core.compat.app},function(e,t,r){"use strict";function n(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}r.d(t,"a",function(){return n})},,,,function(e,t){e.exports=flarum.core.compat["components/SettingsModal"]},,function(e,t,r){"use strict";r.r(t);var n=r(0),o=r.n(n),a=r(1),l=r(5),u=function(e){function t(){return e.apply(this,arguments)||this}Object(a.a)(t,e);var r=t.prototype;return r.className=function(){return"LevelRanksSettingsModal Modal--medium"},r.title=function(){return app.translator.trans("reflar-level-ranks.admin.settings.title")},r.form=function(){return[m("div",{className:"Form-group"},m("div",{className:"Form-group"},m("label",null,app.translator.trans("reflar-level-ranks.admin.settings.levelText")),m("input",{placeholder:app.translator.trans("reflar-level-ranks.lib.defaults.level"),className:"FormControl",bidi:this.setting("reflar-level-ranks.pointsText")})))]},t}(r.n(l).a);o.a.initializers.add("reflar-level-ranks",function(){o.a.extensionSettings["reflar-level-ranks"]=function(){return o.a.modal.show(new u)}})}]); 2 | //# sourceMappingURL=admin.js.map -------------------------------------------------------------------------------- /js/dist/admin.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack://@reflar/level-ranks/webpack/bootstrap","webpack://@reflar/level-ranks/external \"flarum.core.compat['app']\"","webpack://@reflar/level-ranks/./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js","webpack://@reflar/level-ranks/external \"flarum.core.compat['components/SettingsModal']\"","webpack://@reflar/level-ranks/./src/admin/components/LevelRanksSettingsModal.js","webpack://@reflar/level-ranks/./src/admin/index.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","flarum","core","compat","_inheritsLoose","subClass","superClass","constructor","__proto__","__webpack_exports__","LevelRanksSettingsModal","className","title","app","translator","trans","form","placeholder","bidi","this","setting","SettingsModal","initializers","add","extensionSettings","modal","show"],"mappings":"2BACA,IAAAA,EAAA,GAGA,SAAAC,EAAAC,GAGA,GAAAF,EAAAE,GACA,OAAAF,EAAAE,GAAAC,QAGA,IAAAC,EAAAJ,EAAAE,GAAA,CACAG,EAAAH,EACAI,GAAA,EACAH,QAAA,IAUA,OANAI,EAAAL,GAAAM,KAAAJ,EAAAD,QAAAC,IAAAD,QAAAF,GAGAG,EAAAE,GAAA,EAGAF,EAAAD,QA0DA,OArDAF,EAAAQ,EAAAF,EAGAN,EAAAS,EAAAV,EAGAC,EAAAU,EAAA,SAAAR,EAAAS,EAAAC,GACAZ,EAAAa,EAAAX,EAAAS,IACAG,OAAAC,eAAAb,EAAAS,EAAA,CAA0CK,YAAA,EAAAC,IAAAL,KAK1CZ,EAAAkB,EAAA,SAAAhB,GACA,oBAAAiB,eAAAC,aACAN,OAAAC,eAAAb,EAAAiB,OAAAC,YAAA,CAAwDC,MAAA,WAExDP,OAAAC,eAAAb,EAAA,cAAiDmB,OAAA,KAQjDrB,EAAAsB,EAAA,SAAAD,EAAAE,GAEA,GADA,EAAAA,IAAAF,EAAArB,EAAAqB,IACA,EAAAE,EAAA,OAAAF,EACA,KAAAE,GAAA,iBAAAF,QAAAG,WAAA,OAAAH,EACA,IAAAI,EAAAX,OAAAY,OAAA,MAGA,GAFA1B,EAAAkB,EAAAO,GACAX,OAAAC,eAAAU,EAAA,WAAyCT,YAAA,EAAAK,UACzC,EAAAE,GAAA,iBAAAF,EAAA,QAAAM,KAAAN,EAAArB,EAAAU,EAAAe,EAAAE,EAAA,SAAAA,GAAgH,OAAAN,EAAAM,IAAqBC,KAAA,KAAAD,IACrI,OAAAF,GAIAzB,EAAA6B,EAAA,SAAA1B,GACA,IAAAS,EAAAT,KAAAqB,WACA,WAA2B,OAAArB,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAH,EAAAU,EAAAE,EAAA,IAAAA,GACAA,GAIAZ,EAAAa,EAAA,SAAAiB,EAAAC,GAAsD,OAAAjB,OAAAkB,UAAAC,eAAA1B,KAAAuB,EAAAC,IAGtD/B,EAAAkC,EAAA,GAIAlC,IAAAmC,EAAA,mBClFAhC,EAAAD,QAAAkC,OAAAC,KAAAC,OAAA,kCCAe,SAAAC,EAAAC,EAAAC,GACfD,EAAAR,UAAAlB,OAAAY,OAAAe,EAAAT,WACAQ,EAAAR,UAAAU,YAAAF,EACAA,EAAAG,UAAAF,EAHAzC,EAAAU,EAAAkC,EAAA,sBAAAL,sBCAApC,EAAAD,QAAAkC,OAAAC,KAAAC,OAAA,oGCEqBO,4GACjBC,qBACI,MAAO,2CAGXC,iBACI,OAAOC,IAAIC,WAAWC,MAAM,8CAGhCC,gBACI,MAAO,CACH3C,EAAA,OAAKsC,UAAU,cACXtC,EAAA,OAAKsC,UAAU,cACXtC,EAAA,aAAQwC,IAAIC,WAAWC,MAAM,gDAC7B1C,EAAA,SAAO4C,YAAaJ,IAAIC,WAAWC,MAAM,yCAA0CJ,UAAU,cAAcO,KAAMC,KAAKC,QAAQ,iDAd7FC,GCCrDR,IAAIS,aAAaC,IAAI,qBAAsB,WACvCV,IAAIW,kBAAkB,sBAAwB,kBAAMX,IAAIY,MAAMC,KAAK,IAAIhB","file":"admin.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 7);\n","module.exports = flarum.core.compat['app'];","export default function _inheritsLoose(subClass, superClass) {\n subClass.prototype = Object.create(superClass.prototype);\n subClass.prototype.constructor = subClass;\n subClass.__proto__ = superClass;\n}","module.exports = flarum.core.compat['components/SettingsModal'];","import SettingsModal from 'flarum/components/SettingsModal';\r\n\r\nexport default class LevelRanksSettingsModal extends SettingsModal {\r\n className() {\r\n return 'LevelRanksSettingsModal Modal--medium';\r\n }\r\n\r\n title() {\r\n return app.translator.trans('reflar-level-ranks.admin.settings.title');\r\n }\r\n\r\n form() {\r\n return [\r\n
\r\n
\r\n \r\n \r\n
\r\n
\r\n ];\r\n }\r\n}","import app from 'flarum/app';\r\nimport LevelRanksSettingsModal from './components/LevelRanksSettingsModal';\r\n\r\napp.initializers.add('reflar-level-ranks', () => {\r\n app.extensionSettings['reflar-level-ranks'] = () => app.modal.show(new LevelRanksSettingsModal());\r\n});"],"sourceRoot":""} -------------------------------------------------------------------------------- /js/dist/forum.js: -------------------------------------------------------------------------------- 1 | module.exports=function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=6)}([function(t,e){t.exports=flarum.core.compat.app},function(t,e,r){"use strict";function n(t,e){t.prototype=Object.create(e.prototype),t.prototype.constructor=t,t.__proto__=e}r.d(e,"a",function(){return n})},function(t,e){t.exports=flarum.core.compat.extend},function(t,e){t.exports=flarum.core.compat["components/PostUser"]},function(t,e){t.exports=flarum.core.compat.Component},,function(t,e,r){"use strict";r.r(e);var n=r(0),o=r.n(n),s=r(2),a=r(3),u=r.n(a),i=r(1),c=r(4),l=function(t){function e(){return t.apply(this,arguments)||this}Object(i.a)(e,t);var r=e.prototype;return r.config=function(){this.$().tooltip({container:"body"})},r.view=function(){var t=this.props.user,e=o.a.forum.attribute("reflar-level-ranks.pointsText")||o.a.translator.trans("reflar-level-ranks.lib.defaults.level"),r=21*(t.commentCount()-t.discussionCount())+33*t.discussionCount(),n=Math.floor(r/135),s=100/135*(r-135*n);return m("div",{class:"PostUser-level",title:r+" "+o.a.translator.trans("reflar-level-ranks.forum.desc.expText")},m("span",{class:"PostUser-text"},m("span",{class:"PostUser-levelText"},e)," ",m("span",{class:"PostUser-levelPoints"},n)),m("div",{class:"PostUser-bar PostUser-bar--empty"}),m("div",{class:"PostUser-bar",style:"width: "+s+"%;"}))},e}(r.n(c).a);o.a.initializers.add("reflar-level-ranks",function(t){Object(s.extend)(u.a.prototype,"view",function(t){var e=this.props.post.user();e&&t.children.push(l.component({user:e}))})})}]); 2 | //# sourceMappingURL=forum.js.map -------------------------------------------------------------------------------- /js/dist/forum.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack://@reflar/level-ranks/webpack/bootstrap","webpack://@reflar/level-ranks/external \"flarum.core.compat['app']\"","webpack://@reflar/level-ranks/./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js","webpack://@reflar/level-ranks/external \"flarum.core.compat['extend']\"","webpack://@reflar/level-ranks/external \"flarum.core.compat['components/PostUser']\"","webpack://@reflar/level-ranks/external \"flarum.core.compat['Component']\"","webpack://@reflar/level-ranks/./src/forum/components/LevelBar.js","webpack://@reflar/level-ranks/./src/forum/index.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","flarum","core","compat","_inheritsLoose","subClass","superClass","constructor","__proto__","__webpack_exports__","LevelBar","config","this","$","tooltip","container","view","user","props","pointsText","app","forum","attribute","translator","trans","expTotal","commentCount","discussionCount","expLevel","Math","floor","expPercent","class","title","style","Component","initializers","add","extend","PostUser","post","children","push","component"],"mappings":"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","file":"forum.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 6);\n","module.exports = flarum.core.compat['app'];","export default function _inheritsLoose(subClass, superClass) {\n subClass.prototype = Object.create(superClass.prototype);\n subClass.prototype.constructor = subClass;\n subClass.__proto__ = superClass;\n}","module.exports = flarum.core.compat['extend'];","module.exports = flarum.core.compat['components/PostUser'];","module.exports = flarum.core.compat['Component'];","import Component from 'flarum/Component';\nimport app from 'flarum/app';\n\nexport default class LevelBar extends Component {\n config() {\n this.$().tooltip({ container: 'body' });\n }\n\n view() {\n const user = this.props.user;\n const pointsText = app.forum.attribute('reflar-level-ranks.pointsText') || app.translator.trans('reflar-level-ranks.lib.defaults.level');\n\n let expComments = (user.commentCount() - user.discussionCount()) * 21,\n expDiscussions = user.discussionCount() * 33;\n\n let expTotal = expComments + expDiscussions,\n expLevel = Math.floor(expTotal / 135),\n expPercent = (100 / 135) * ((expTotal) - (expLevel * 135));\n\n return (\n
\n \n {pointsText}\n  \n {expLevel}\n \n
\n
\n
\n );\n }\n}\n","import app from 'flarum/app';\nimport { extend } from 'flarum/extend';\nimport PostUser from 'flarum/components/PostUser';\nimport LevelBar from './components/LevelBar';\n\napp.initializers.add('reflar-level-ranks', app => {\n\textend(PostUser.prototype, 'view', function (view) {\n const user = this.props.post.user();\n\n if (!user) return;\n\n\t\tview.children.push(LevelBar.component({ user }))\n\t});\n});\n"],"sourceRoot":""} -------------------------------------------------------------------------------- /js/forum.js: -------------------------------------------------------------------------------- 1 | export * from './src/forum'; -------------------------------------------------------------------------------- /js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@reflar/level-ranks", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "flarum-webpack-config": "^0.1.0-beta.8", 6 | "webpack": "^4.0.0", 7 | "webpack-cli": "^3.0.7" 8 | }, 9 | "scripts": { 10 | "build": "webpack --mode production", 11 | "watch": "webpack --mode development --watch" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /js/src/admin/components/LevelRanksSettingsModal.js: -------------------------------------------------------------------------------- 1 | import SettingsModal from 'flarum/components/SettingsModal'; 2 | 3 | export default class LevelRanksSettingsModal extends SettingsModal { 4 | className() { 5 | return 'LevelRanksSettingsModal Modal--medium'; 6 | } 7 | 8 | title() { 9 | return app.translator.trans('reflar-level-ranks.admin.settings.title'); 10 | } 11 | 12 | form() { 13 | return [ 14 |
15 |
16 | 17 | 18 |
19 |
20 | ]; 21 | } 22 | } -------------------------------------------------------------------------------- /js/src/admin/index.js: -------------------------------------------------------------------------------- 1 | import app from 'flarum/app'; 2 | import LevelRanksSettingsModal from './components/LevelRanksSettingsModal'; 3 | 4 | app.initializers.add('reflar-level-ranks', () => { 5 | app.extensionSettings['reflar-level-ranks'] = () => app.modal.show(new LevelRanksSettingsModal()); 6 | }); -------------------------------------------------------------------------------- /js/src/forum/components/LevelBar.js: -------------------------------------------------------------------------------- 1 | import Component from 'flarum/Component'; 2 | import app from 'flarum/app'; 3 | 4 | export default class LevelBar extends Component { 5 | config() { 6 | this.$().tooltip({ container: 'body' }); 7 | } 8 | 9 | view() { 10 | const user = this.props.user; 11 | const pointsText = app.forum.attribute('reflar-level-ranks.pointsText') || app.translator.trans('reflar-level-ranks.lib.defaults.level'); 12 | 13 | let expComments = (user.commentCount() - user.discussionCount()) * 21, 14 | expDiscussions = user.discussionCount() * 33; 15 | 16 | let expTotal = expComments + expDiscussions, 17 | expLevel = Math.floor(expTotal / 135), 18 | expPercent = (100 / 135) * ((expTotal) - (expLevel * 135)); 19 | 20 | return ( 21 |
22 | 23 | {pointsText} 24 |   25 | {expLevel} 26 | 27 |
28 |
29 |
30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /js/src/forum/index.js: -------------------------------------------------------------------------------- 1 | import app from 'flarum/app'; 2 | import { extend } from 'flarum/extend'; 3 | import PostUser from 'flarum/components/PostUser'; 4 | import LevelBar from './components/LevelBar'; 5 | 6 | app.initializers.add('reflar-level-ranks', app => { 7 | extend(PostUser.prototype, 'view', function (view) { 8 | const user = this.props.post.user(); 9 | 10 | if (!user) return; 11 | 12 | view.children.push(LevelBar.component({ user })) 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /js/webpack.config.js: -------------------------------------------------------------------------------- 1 | const config = require('flarum-webpack-config'); 2 | 3 | module.exports = config(); -------------------------------------------------------------------------------- /resources/less/forum.less: -------------------------------------------------------------------------------- 1 | .PostUser-level { 2 | float: left; 3 | position: relative; 4 | margin-left: -80px; 5 | margin-top: 75px; 6 | width: 64px; 7 | text-align: center; 8 | } 9 | 10 | div.PostUser-bar--empty { 11 | background: @control-bg; 12 | } 13 | 14 | .PostUser-bar { 15 | background: @primary-color; 16 | border-radius: 10px; 17 | width: 100%; 18 | height: 10px; 19 | position: absolute; 20 | top: 25px; 21 | } 22 | 23 | .PostUser-levelNumber { 24 | position: relative; 25 | } 26 | 27 | .Post--hidden .PostUser-level { 28 | display: none; 29 | } 30 | 31 | .Post--hidden.revealContent .PostUser-level { 32 | display: block; 33 | } 34 | -------------------------------------------------------------------------------- /resources/locale/en.yml: -------------------------------------------------------------------------------- 1 | reflar-level-ranks: 2 | admin: 3 | settings: 4 | title: Level Ranks Settings 5 | levelText: Enter the text to be displayed for the points (e.g. Rank, Level) 6 | forum: 7 | desc: 8 | expText: EXP 9 | lib: 10 | defaults: 11 | level: Level -------------------------------------------------------------------------------- /resources/locale/pl.yml: -------------------------------------------------------------------------------- 1 | reflar-level-ranks: 2 | admin: 3 | settings: 4 | title: Ustawienia Rangi 5 | levelText: Wprowadź tekst, który będzie wyświetlany dla punktów (np. Ranga, Poziom) 6 | forum: 7 | desc: 8 | expText: EXP 9 | lib: 10 | defaults: 11 | level: ranga 12 | -------------------------------------------------------------------------------- /src/Listeners/LoadSettingsFromDatabase.php: -------------------------------------------------------------------------------- 1 | settings = $settings; 36 | } 37 | 38 | /** 39 | * @param Dispatcher $events 40 | */ 41 | public function subscribe(Dispatcher $events) 42 | { 43 | $events->listen(Serializing::class, [$this, 'prepareApiAttributes']); 44 | } 45 | 46 | /** 47 | * @param Serializing $event 48 | */ 49 | public function prepareApiAttributes(Serializing $event) 50 | { 51 | if ($event->isSerializer(ForumSerializer::class)) { 52 | $key = 'reflar-level-ranks.pointsText'; 53 | $event->attributes[$key] = $this->settings->get($key); 54 | } 55 | } 56 | } 57 | --------------------------------------------------------------------------------