1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/pixelfed_ynh.git synced 2024-09-03 20:06:04 +02:00

Merge pull request #1500 from pixelfed/frontend-ui-refactor

Add Profile Sponsors
This commit is contained in:
daniel 2019-07-11 21:15:58 -06:00 committed by GitHub
commit d2d7f07c35
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 1945 additions and 1422 deletions

View file

@ -0,0 +1,16 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\ProfileSponsor;
use Auth;
class ProfileSponsorController extends Controller
{
public function get(Request $request, $id)
{
$res = ProfileSponsor::whereProfileId($id)->firstOrFail()->sponsors;
return response($res)->header('Content-Type', 'application/json');
}
}

View file

@ -4,11 +4,13 @@ namespace App\Http\Controllers;
use App\AccountLog; use App\AccountLog;
use App\Following; use App\Following;
use App\ProfileSponsor;
use App\Report; use App\Report;
use App\UserFilter; use App\UserFilter;
use Auth, Cookie, DB, Cache, Purify; use Auth, Cookie, DB, Cache, Purify;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Str;
use App\Http\Controllers\Settings\{ use App\Http\Controllers\Settings\{
ExportSettings, ExportSettings,
LabsSettings, LabsSettings,
@ -166,5 +168,49 @@ class SettingsController extends Controller
return response()->json([200])->cookie($cookie); return response()->json([200])->cookie($cookie);
} }
public function sponsor()
{
$default = [
'patreon' => null,
'liberapay' => null,
'opencollective' => null
];
$sponsors = ProfileSponsor::whereProfileId(Auth::user()->profile->id)->first();
$sponsors = $sponsors ? json_decode($sponsors->sponsors, true) : $default;
return view('settings.sponsor', compact('sponsors'));
}
public function sponsorStore(Request $request)
{
$this->validate($request, [
'patreon' => 'nullable|string',
'liberapay' => 'nullable|string',
'opencollective' => 'nullable|string'
]);
$patreon = Str::startsWith($request->input('patreon'), 'patreon.com/') ? e($request->input('patreon')) : null;
$liberapay = Str::startsWith($request->input('liberapay'), 'liberapay.com/') ? e($request->input('liberapay')) : null;
$opencollective = Str::startsWith($request->input('opencollective'), 'opencollective.com/') ? e($request->input('opencollective')) : null;
if(empty($patreon) && empty($liberapay) && empty($opencollective)) {
return redirect(route('settings'))->with('error', 'An error occured. Please try again later.');;
}
$res = [
'patreon' => $patreon,
'liberapay' => $liberapay,
'opencollective' => $opencollective
];
$sponsors = ProfileSponsor::firstOrCreate([
'profile_id' => Auth::user()->profile_id ?? Auth::user()->profile->id
]);
$sponsors->sponsors = json_encode($res);
$sponsors->save();
$sponsors = $res;
return redirect(route('settings'))->with('status', 'Sponsor settings successfully updated!');;
}
} }

15
app/ProfileSponsor.php Normal file
View file

@ -0,0 +1,15 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ProfileSponsor extends Model
{
public $fillable = ['profile_id'];
public function profile()
{
return $this->belongsTo(Profile::class);
}
}

View file

@ -0,0 +1,33 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateProfileSponsorsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('profile_sponsors', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('profile_id')->unsigned()->unique()->index();
$table->json('sponsors')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('profile_sponsors');
}
}

1069
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -15,26 +15,26 @@
"bootstrap": ">=4.3.1", "bootstrap": ">=4.3.1",
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"jquery": "^3.4.1", "jquery": "^3.4.1",
"lodash": "^4.17.11", "lodash": ">=4.17.13",
"popper.js": "^1.15.0", "popper.js": "^1.15.0",
"resolve-url-loader": "^2.3.2", "resolve-url-loader": "^2.3.2",
"sass": "^1.21.0", "sass": "^1.22.3",
"sass-loader": "^7.1.0", "sass-loader": "^7.1.0",
"vue": "^2.6.10", "vue": "^2.6.10",
"vue-template-compiler": "^2.6.10" "vue-template-compiler": "^2.6.10"
}, },
"dependencies": { "dependencies": {
"bootstrap-vue": "^2.0.0-rc.23", "bootstrap-vue": "^2.0.0-rc.26",
"emoji-mart-vue": "^2.6.6", "emoji-mart-vue": "^2.6.6",
"filesize": "^3.6.1", "filesize": "^3.6.1",
"howler": "^2.1.2", "howler": "^2.1.2",
"infinite-scroll": "^3.0.6", "infinite-scroll": "^3.0.6",
"laravel-echo": "^1.5.4", "laravel-echo": "^1.5.4",
"laravel-mix": "^4.0.16", "laravel-mix": "^4.1.2",
"node-sass": "^4.12.0", "node-sass": "^4.12.0",
"opencollective": "^1.0.3", "opencollective": "^1.0.3",
"opencollective-postinstall": "^2.0.2", "opencollective-postinstall": "^2.0.2",
"plyr": "^3.5.4", "plyr": "^3.5.6",
"promise-polyfill": "8.1.0", "promise-polyfill": "8.1.0",
"pusher-js": "^4.4.0", "pusher-js": "^4.4.0",
"quill": "^1.3.6", "quill": "^1.3.6",

4
public/css/app.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/ace.js vendored

File diff suppressed because one or more lines are too long

1
public/js/collectioncompose.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/loops.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/quill.js vendored

File diff suppressed because one or more lines are too long

2
public/js/search.js vendored

File diff suppressed because one or more lines are too long

2
public/js/status.js vendored

File diff suppressed because one or more lines are too long

View file

@ -1 +1 @@
(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{14:function(e,a,o){e.exports=o("YMO/")},"YMO/":function(e,a,o){(function(e){function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],function(e,a,o){a.isDark=!0,a.cssClass="ace-monokai",a.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}",e("../lib/dom").importCssString(a.cssText,a.cssClass)}),ace.require(["ace/theme/monokai"],function(c){"object"==o(e)&&"object"==o(a)&&e&&(e.exports=c)})}).call(this,o("YuTi")(e))},YuTi:function(e,a){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}},[[14,0]]]); (window.webpackJsonp=window.webpackJsonp||[]).push([[17],{14:function(e,a,o){e.exports=o("YMO/")},"YMO/":function(e,a,o){(function(e){function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],function(e,a,o){a.isDark=!0,a.cssClass="ace-monokai",a.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}",e("../lib/dom").importCssString(a.cssText,a.cssClass)}),ace.require(["ace/theme/monokai"],function(c){"object"==o(e)&&"object"==o(a)&&e&&(e.exports=c)})}).call(this,o("YuTi")(e))},YuTi:function(e,a){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}},[[14,0]]]);

File diff suppressed because one or more lines are too long

2
public/js/vendor.js vendored

File diff suppressed because one or more lines are too long

View file

@ -1,24 +1,25 @@
{ {
"/js/manifest.js": "/js/manifest.js?id=01c8731923a46c30aaed", "/js/manifest.js": "/js/manifest.js?id=01c8731923a46c30aaed",
"/js/vendor.js": "/js/vendor.js?id=8ea306403cb5cfa88c2b", "/js/vendor.js": "/js/vendor.js?id=6e7489157aac9e82dbbe",
"/js/ace.js": "/js/ace.js?id=72ae94b2a68487d22caf", "/js/ace.js": "/js/ace.js?id=4a28163d5fd63e64d6af",
"/js/activity.js": "/js/activity.js?id=7405cc1a22814a5b2a70", "/js/activity.js": "/js/activity.js?id=7405cc1a22814a5b2a70",
"/js/app.js": "/js/app.js?id=2f034c84c06dbb3e511d", "/js/app.js": "/js/app.js?id=2f034c84c06dbb3e511d",
"/css/app.css": "/css/app.css?id=461b8782fc167f734ffa", "/css/app.css": "/css/app.css?id=56642158bfe8b6469355",
"/css/appdark.css": "/css/appdark.css?id=34cd81dd9c8bc68cfd51", "/css/appdark.css": "/css/appdark.css?id=1b13fc163fa4deb9233f",
"/css/landing.css": "/css/landing.css?id=1ea686af4c64df5018fc", "/css/landing.css": "/css/landing.css?id=31de3e75de8690f7ece5",
"/css/quill.css": "/css/quill.css?id=81604d62610b0dbffad6", "/css/quill.css": "/css/quill.css?id=81604d62610b0dbffad6",
"/js/components.js": "/js/components.js?id=0b7b6f606e590f4df10f", "/js/collectioncompose.js": "/js/collectioncompose.js?id=ec48ebc94ae6b1ec70ea",
"/js/compose.js": "/js/compose.js?id=aca2cd178a7ca454713d", "/js/components.js": "/js/components.js?id=d64d41a2defb1a205865",
"/js/developers.js": "/js/developers.js?id=e4a227c87d1b09fc2dd9", "/js/compose.js": "/js/compose.js?id=488b24bf2f2168540449",
"/js/discover.js": "/js/discover.js?id=772fbc6c176aaa9039ec", "/js/developers.js": "/js/developers.js?id=ba029a560f0c30c5efc9",
"/js/hashtag.js": "/js/hashtag.js?id=32c3a6b1a04949d390ab", "/js/discover.js": "/js/discover.js?id=627f0a106fd359ae3b80",
"/js/loops.js": "/js/loops.js?id=cacf532da1e0d50ec014", "/js/hashtag.js": "/js/hashtag.js?id=0f7e529e8128cc17638b",
"/js/mode-dot.js": "/js/mode-dot.js?id=7d248d684a37f3eb88de", "/js/loops.js": "/js/loops.js?id=19112dc8663fc43db735",
"/js/profile.js": "/js/profile.js?id=8b6af927d424cb58203e", "/js/mode-dot.js": "/js/mode-dot.js?id=c7c83849e6bba99f1c33",
"/js/quill.js": "/js/quill.js?id=a8a0855cb59d6a2f7aee", "/js/profile.js": "/js/profile.js?id=273e21d1f85a097b18e4",
"/js/search.js": "/js/search.js?id=27506b08cf8c889e3f7f", "/js/quill.js": "/js/quill.js?id=c2b060eaf87ef63eb5c1",
"/js/status.js": "/js/status.js?id=665fb54127ca484a1692", "/js/search.js": "/js/search.js?id=3186ccb02c7fad43c701",
"/js/theme-monokai.js": "/js/theme-monokai.js?id=1bc564c4661eb0fa30b6", "/js/status.js": "/js/status.js?id=4b9a52b586880e264f05",
"/js/timeline.js": "/js/timeline.js?id=90a01cbe86e6dff2b5c3" "/js/theme-monokai.js": "/js/theme-monokai.js?id=a4da64fc6e2f406a616d",
"/js/timeline.js": "/js/timeline.js?id=a3c3e38470108fa5df42"
} }

View file

@ -1,5 +1,5 @@
<template> <template>
<div class="w-100 h-100"> <div class="w-100 h-100">
<div v-if="relationship && relationship.blocking && warning" class="bg-white pt-3 border-bottom"> <div v-if="relationship && relationship.blocking && warning" class="bg-white pt-3 border-bottom">
<div class="container"> <div class="container">
<p class="text-center font-weight-bold">You are blocking this account</p> <p class="text-center font-weight-bold">You are blocking this account</p>
@ -19,7 +19,12 @@
<div class="d-block d-md-none"> <div class="d-block d-md-none">
<div class="row"> <div class="row">
<div class="col-5"> <div class="col-5">
<img class="rounded-circle box-shadow mr-5" :src="profile.avatar" width="77px" height="77px"> <img class="rounded-circle box-shadow mr-2" :src="profile.avatar" width="77px" height="77px">
<p v-if="sponsorList.patreon || sponsorList.liberapay || sponsorList.opencollective" class="text-center mt-1 mr-2">
<button type="button" @click="showSponsorModal" class="btn btn-sm btn-outline-secondary font-weight-bold py-0">
Sponsor
</button>
</p>
</div> </div>
<div class="col-7 pl-2"> <div class="col-7 pl-2">
<p class="align-middle"> <p class="align-middle">
@ -45,6 +50,12 @@
</div> </div>
<div class="d-none d-md-block"> <div class="d-none d-md-block">
<img class="rounded-circle box-shadow" :src="profile.avatar" width="172px" height="172px"> <img class="rounded-circle box-shadow" :src="profile.avatar" width="172px" height="172px">
<p v-if="sponsorList.patreon || sponsorList.liberapay || sponsorList.opencollective" class="text-center mt-3">
<button type="button" @click="showSponsorModal" class="btn btn-outline-secondary font-weight-bold py-0">
<i class="fas fa-heart text-danger"></i>
Sponsor
</button>
</p>
</div> </div>
</div> </div>
</div> </div>
@ -97,7 +108,7 @@
<span class="font-weight-bold pr-3">{{profile.display_name}}</span> <span class="font-weight-bold pr-3">{{profile.display_name}}</span>
</p> </p>
<div v-if="profile.note" class="mb-0 lead" v-html="profile.note"></div> <div v-if="profile.note" class="mb-0 lead" v-html="profile.note"></div>
<p v-if="profile.website" class="mb-0"><a :href="profile.website" class="font-weight-bold" rel="me external nofollow noopener" target="_blank">{{profile.website}}</a></p> <p v-if="profile.website" class=""><a :href="profile.website" class="font-weight-bold" rel="me external nofollow noopener" target="_blank">{{profile.website}}</a></p>
</div> </div>
</div> </div>
</div> </div>
@ -133,7 +144,7 @@
</div> </div>
<div class="bg-white"> <div class="bg-white">
<ul class="nav nav-topbar d-flex justify-content-center border-0"> <ul class="nav nav-topbar d-flex justify-content-center border-0">
<!-- <li class="nav-item"> <!-- <li class="nav-item">
<a class="nav-link active font-weight-bold text-uppercase" :href="profile.url">Posts</a> <a class="nav-link active font-weight-bold text-uppercase" :href="profile.url">Posts</a>
</li> </li>
--> -->
@ -141,21 +152,21 @@
<a :class="this.mode == 'grid' ? 'nav-link font-weight-bold text-uppercase text-primary' : 'nav-link font-weight-bold text-uppercase'" href="#" v-on:click.prevent="switchMode('grid')"><i class="fas fa-th fa-lg"></i></a> <a :class="this.mode == 'grid' ? 'nav-link font-weight-bold text-uppercase text-primary' : 'nav-link font-weight-bold text-uppercase'" href="#" v-on:click.prevent="switchMode('grid')"><i class="fas fa-th fa-lg"></i></a>
</li> </li>
<!-- <li class="nav-item"> <!-- <li class="nav-item">
<a :class="this.mode == 'masonry' ? 'nav-link font-weight-bold text-uppercase active' : 'nav-link font-weight-bold text-uppercase'" href="#" v-on:click.prevent="switchMode('masonry')"><i class="fas fa-th-large"></i></a> <a :class="this.mode == 'masonry' ? 'nav-link font-weight-bold text-uppercase active' : 'nav-link font-weight-bold text-uppercase'" href="#" v-on:click.prevent="switchMode('masonry')"><i class="fas fa-th-large"></i></a>
</li> --> </li> -->
<li class="nav-item px-3"> <li class="nav-item px-3">
<a :class="this.mode == 'list' ? 'nav-link font-weight-bold text-uppercase text-primary' : 'nav-link font-weight-bold text-uppercase'" href="#" v-on:click.prevent="switchMode('list')"><i class="fas fa-th-list fa-lg"></i></a> <a :class="this.mode == 'list' ? 'nav-link font-weight-bold text-uppercase text-primary' : 'nav-link font-weight-bold text-uppercase'" href="#" v-on:click.prevent="switchMode('list')"><i class="fas fa-th-list fa-lg"></i></a>
</li> </li>
<li class="nav-item" v-if="owner"> <li class="nav-item" v-if="owner">
<a class="nav-link font-weight-bold text-uppercase" :href="profile.url + '/saved'">Saved</a> <a class="nav-link font-weight-bold text-uppercase" :href="profile.url + '/saved'">Saved</a>
</li> </li>
</ul> </ul>
</div> </div>
<div class="container"> <div class="container">
<div class="profile-timeline mt-md-4"> <div class="profile-timeline mt-md-4">
<div class="row" v-if="mode == 'grid'"> <div class="row" v-if="mode == 'grid'">
<div class="col-4 p-0 p-sm-2 p-md-3 p-xs-1" v-for="(s, index) in timeline"> <div class="col-4 p-0 p-sm-2 p-md-3 p-xs-1" v-for="(s, index) in timeline">
@ -290,10 +301,10 @@
</infinite-loading> </infinite-loading>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div v-if="profileLayout == 'moment'"> <div v-if="profileLayout == 'moment'">
<div :class="momentBackground()" style="width:100%;min-height:274px;"> <div :class="momentBackground()" style="width:100%;min-height:274px;">
</div> </div>
<div class="bg-white border-bottom"> <div class="bg-white border-bottom">
@ -370,18 +381,18 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- <b-modal id="statusModal" ref="statusModalRef" hide-footer hide-header v-if="modalStatus" size="lg" v-on:hide.native="closeModal()" lazy class="border-0"> <!-- <b-modal id="statusModal" ref="statusModalRef" hide-footer hide-header v-if="modalStatus" size="lg" v-on:hide.native="closeModal()" lazy class="border-0">
<post-component v-bind:status-template="modalStatus.pf_type" v-bind:status-id="modalStatus.id" v-bind:status-username="modalStatus.account.username" v-bind:status-url="modalStatus.url" v-bind:status-profile-url="modalStatus.account.url" v-bind:status-avatar="modalStatus.account.avatar"></post-component> <post-component v-bind:status-template="modalStatus.pf_type" v-bind:status-id="modalStatus.id" v-bind:status-username="modalStatus.account.username" v-bind:status-url="modalStatus.url" v-bind:status-profile-url="modalStatus.account.url" v-bind:status-avatar="modalStatus.account.avatar"></post-component>
</b-modal> --> </b-modal> -->
<b-modal ref="followingModal" <b-modal ref="followingModal"
id="following-modal" id="following-modal"
hide-footer hide-footer
centered centered
title="Following" title="Following"
body-class="list-group-flush p-0"> body-class="list-group-flush p-0">
<div class="list-group"> <div class="list-group">
<div class="list-group-item border-0" v-for="(user, index) in following" :key="'following_'+index"> <div class="list-group-item border-0" v-for="(user, index) in following" :key="'following_'+index">
<div class="media"> <div class="media">
<a :href="user.url"> <a :href="user.url">
@ -410,15 +421,15 @@
<div v-if="followingMore" class="list-group-item text-center" v-on:click="followingLoadMore()"> <div v-if="followingMore" class="list-group-item text-center" v-on:click="followingLoadMore()">
<p class="mb-0 small text-muted font-weight-light cursor-pointer">Load more</p> <p class="mb-0 small text-muted font-weight-light cursor-pointer">Load more</p>
</div> </div>
</div> </div>
</b-modal> </b-modal>
<b-modal ref="followerModal" <b-modal ref="followerModal"
id="follower-modal" id="follower-modal"
hide-footer hide-footer
centered centered
title="Followers" title="Followers"
body-class="list-group-flush p-0"> body-class="list-group-flush p-0">
<div class="list-group"> <div class="list-group">
<div class="list-group-item border-0" v-for="(user, index) in followers" :key="'follower_'+index"> <div class="list-group-item border-0" v-for="(user, index) in followers" :key="'follower_'+index">
<div class="media"> <div class="media">
<a :href="user.url"> <a :href="user.url">
@ -439,16 +450,16 @@
<div v-if="followerMore" class="list-group-item text-center" v-on:click="followersLoadMore()"> <div v-if="followerMore" class="list-group-item text-center" v-on:click="followersLoadMore()">
<p class="mb-0 small text-muted font-weight-light cursor-pointer">Load more</p> <p class="mb-0 small text-muted font-weight-light cursor-pointer">Load more</p>
</div> </div>
</div> </div>
</b-modal> </b-modal>
<b-modal ref="visitorContextMenu" <b-modal ref="visitorContextMenu"
id="visitor-context-menu" id="visitor-context-menu"
hide-footer hide-footer
hide-header hide-header
centered centered
size="sm" size="sm"
body-class="list-group-flush p-0"> body-class="list-group-flush p-0">
<div class="list-group" v-if="relationship"> <div class="list-group" v-if="relationship">
<div v-if="!owner && !relationship.following" class="list-group-item cursor-pointer text-center font-weight-bold lead rounded text-primary" @click="followProfile"> <div v-if="!owner && !relationship.following" class="list-group-item cursor-pointer text-center font-weight-bold lead rounded text-primary" @click="followProfile">
Follow Follow
</div> </div>
@ -473,42 +484,62 @@
<div class="list-group-item cursor-pointer text-center font-weight-bold lead rounded text-muted" @click="$refs.visitorContextMenu.hide()"> <div class="list-group-item cursor-pointer text-center font-weight-bold lead rounded text-muted" @click="$refs.visitorContextMenu.hide()">
Close Close
</div> </div>
</div> </div>
</b-modal> </b-modal>
<b-modal ref="sponsorModal"
id="sponsor-modal"
hide-footer
:title="'Sponsor ' + profileUsername"
centered
size="md"
body-class="px-5">
<div>
<p class="font-weight-bold">External Links</p>
<p v-if="sponsorList.patreon" class="pt-2">
<a :href="'https://' + sponsorList.patreon" rel="nofollow" class="font-weight-bold">{{sponsorList.patreon}}</a>
</p>
<p v-if="sponsorList.liberapay" class="pt-2">
<a :href="'https://' + sponsorList.liberapay" rel="nofollow" class="font-weight-bold">{{sponsorList.liberapay}}</a>
</p>
<p v-if="sponsorList.opencollective" class="pt-2">
<a :href="'https://' + sponsorList.opencollective" rel="nofollow" class="font-weight-bold">{{sponsorList.opencollective}}</a>
</p>
</div>
</b-modal>
</div> </div>
</template> </template>
<!-- <style type="text/css" scoped=""> <!-- <style type="text/css" scoped="">
.modal-body { .modal-body {
padding: 0; padding: 0;
margin: 0; margin: 0;
} }
@media (min-width: 992px) { @media (min-width: 992px) {
.modal-lg, .modal-xl { .modal-lg, .modal-xl {
max-width: 900px; max-width: 900px;
} }
} }
</style> --> </style> -->
<style type="text/css" scoped> <style type="text/css" scoped>
.o-square { .o-square {
max-width: 320px; max-width: 320px;
} }
.o-portrait { .o-portrait {
max-width: 320px; max-width: 320px;
} }
.o-landscape { .o-landscape {
max-width: 320px; max-width: 320px;
} }
.post-icon { .post-icon {
color: #fff; color: #fff;
position:relative; position:relative;
margin-top: 10px; margin-top: 10px;
z-index: 9; z-index: 9;
opacity: 0.6; opacity: 0.6;
text-shadow: 3px 3px 16px #272634; text-shadow: 3px 3px 16px #272634;
} }
</style> </style>
<script type="text/javascript"> <script type="text/javascript">
export default { export default {
props: [ props: [
'profile-id', 'profile-id',
'profile-layout', 'profile-layout',
@ -536,7 +567,8 @@ export default {
following: [], following: [],
followingCursor: 1, followingCursor: 1,
followingMore: true, followingMore: true,
warning: false warning: false,
sponsorList: [],
} }
}, },
beforeMount() { beforeMount() {
@ -588,6 +620,7 @@ export default {
this.timeline = data; this.timeline = data;
this.ownerCheck(); this.ownerCheck();
this.loading = false; this.loading = false;
this.loadSponsor();
}).catch(err => { }).catch(err => {
swal( swal(
'Oops, something went wrong', 'Oops, something went wrong',
@ -1085,7 +1118,18 @@ export default {
c += 'bg-pixelfed'; c += 'bg-pixelfed';
} }
return c; return c;
},
loadSponsor() {
axios.get('/api/local/profile/sponsor/' + this.profileId)
.then(res => {
this.sponsorList = res.data;
});
},
showSponsorModal() {
this.$refs.sponsorModal.show();
}
} }
} }
}
</script> </script>

View file

@ -33,6 +33,9 @@
<li class="nav-item pl-3 {{request()->is('settings/security*')?'active':''}}"> <li class="nav-item pl-3 {{request()->is('settings/security*')?'active':''}}">
<a class="nav-link font-weight-light text-muted" href="{{route('settings.security')}}">Security</a> <a class="nav-link font-weight-light text-muted" href="{{route('settings.security')}}">Security</a>
</li> </li>
<li class="nav-item pl-3 {{request()->is('settings/sponsor*')?'active':''}}">
<a class="nav-link font-weight-light text-muted" href="{{route('settings.sponsor')}}">Sponsor</a>
</li>
<li class="nav-item"> <li class="nav-item">
<hr> <hr>
</li> </li>

View file

@ -0,0 +1,48 @@
@extends('settings.template')
@section('section')
<div class="title">
<h3 class="font-weight-bold">Sponsor</h3>
<p class="lead">Add crowdfunding links to your profile.</p>
</div>
<hr>
<form method="post" action="{{route('settings.sponsor')}}">
@csrf
<div class="form-group row">
<label for="patreon" class="col-sm-3 col-form-label font-weight-bold text-right">Patreon</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="patreon" name="patreon" placeholder="patreon.com/dansup" value="{{$sponsors['patreon']}}">
<p class="help-text small text-muted font-weight-bold">
Example: patreon.com/dansup
</p>
</div>
</div>
<div class="form-group row">
<label for="liberapay" class="col-sm-3 col-form-label font-weight-bold text-right">Liberapay</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="liberapay" name="liberapay" placeholder="liberapay.com/pixelfed" value="{{$sponsors['liberapay']}}">
<p class="help-text small text-muted font-weight-bold">
Example: liberapay.com/pixelfed
</p>
</div>
</div>
<div class="form-group row">
<label for="opencollective" class="col-sm-3 col-form-label font-weight-bold text-right">OpenCollective</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="opencollective" name="opencollective" placeholder="opencollective.com/pixelfed" value="{{$sponsors['opencollective']}}">
<p class="help-text small text-muted font-weight-bold">
Example: opencollective.com/pixelfed
</p>
</div>
</div>
<hr>
<div class="form-group row">
<div class="col-12 text-right">
<button type="submit" class="btn btn-primary font-weight-bold float-right">Submit</button>
</div>
</div>
</form>
@endsection

View file

@ -114,6 +114,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
Route::get('exp/rec', 'ApiController@userRecommendations'); Route::get('exp/rec', 'ApiController@userRecommendations');
Route::post('discover/tag/subscribe', 'HashtagFollowController@store')->middleware('throttle:maxHashtagFollowsPerHour,60')->middleware('throttle:maxHashtagFollowsPerDay,1440');; Route::post('discover/tag/subscribe', 'HashtagFollowController@store')->middleware('throttle:maxHashtagFollowsPerHour,60')->middleware('throttle:maxHashtagFollowsPerDay,1440');;
Route::get('discover/tag/list', 'HashtagFollowController@getTags'); Route::get('discover/tag/list', 'HashtagFollowController@getTags');
Route::get('profile/sponsor/{id}', 'ProfileSponsorController@get');
}); });
}); });
@ -261,6 +262,8 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
Route::get('invites/create', 'UserInviteController@create')->name('settings.invites.create'); Route::get('invites/create', 'UserInviteController@create')->name('settings.invites.create');
Route::post('invites/create', 'UserInviteController@store'); Route::post('invites/create', 'UserInviteController@store');
Route::get('invites', 'UserInviteController@show')->name('settings.invites'); Route::get('invites', 'UserInviteController@show')->name('settings.invites');
Route::get('sponsor', 'SettingsController@sponsor')->name('settings.sponsor');
Route::post('sponsor', 'SettingsController@sponsorStore');
}); });
Route::group(['prefix' => 'site'], function () { Route::group(['prefix' => 'site'], function () {