mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-22 06:21:27 +00:00
Update Settings, add default license and enforced media descriptions
This commit is contained in:
parent
27778e00c9
commit
67e3f6048f
9 changed files with 252 additions and 35 deletions
|
@ -15,7 +15,8 @@ use App\{
|
|||
Profile,
|
||||
Place,
|
||||
Status,
|
||||
UserFilter
|
||||
UserFilter,
|
||||
UserSetting
|
||||
};
|
||||
use App\Transformer\Api\{
|
||||
MediaTransformer,
|
||||
|
@ -661,4 +662,25 @@ class ComposeController extends Controller
|
|||
'finished' => $finished
|
||||
];
|
||||
}
|
||||
|
||||
public function composeSettings(Request $request)
|
||||
{
|
||||
$uid = $request->user()->id;
|
||||
|
||||
return Cache::remember('profile:compose:settings:' . $uid, now()->addHours(12), function() use($uid) {
|
||||
$res = UserSetting::whereUserId($uid)->first();
|
||||
|
||||
if(!$res) {
|
||||
return [
|
||||
'default_license' => null,
|
||||
'media_descriptions' => false
|
||||
];
|
||||
}
|
||||
|
||||
return json_decode($res->compose_settings, true) ?? [
|
||||
'default_license' => null,
|
||||
'media_descriptions' => false
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use App\Following;
|
|||
use App\ProfileSponsor;
|
||||
use App\Report;
|
||||
use App\UserFilter;
|
||||
use App\UserSetting;
|
||||
use Auth, Cookie, DB, Cache, Purify;
|
||||
use Illuminate\Support\Facades\Redis;
|
||||
use Carbon\Carbon;
|
||||
|
@ -221,7 +222,7 @@ class SettingsController extends Controller
|
|||
$sponsors->sponsors = json_encode($res);
|
||||
$sponsors->save();
|
||||
$sponsors = $res;
|
||||
return redirect(route('settings'))->with('status', 'Sponsor settings successfully updated!');;
|
||||
return redirect(route('settings'))->with('status', 'Sponsor settings successfully updated!');
|
||||
}
|
||||
|
||||
public function timelineSettings(Request $request)
|
||||
|
@ -249,7 +250,52 @@ class SettingsController extends Controller
|
|||
} else {
|
||||
Redis::zrem('pf:tl:replies', $pid);
|
||||
}
|
||||
return redirect(route('settings.timeline'));
|
||||
return redirect(route('settings'))->with('status', 'Timeline settings successfully updated!');;
|
||||
}
|
||||
|
||||
public function mediaSettings(Request $request)
|
||||
{
|
||||
$setting = UserSetting::whereUserId($request->user()->id)->firstOrFail();
|
||||
$compose = $setting->compose_settings ? json_decode($setting->compose_settings, true) : [
|
||||
'default_license' => null,
|
||||
'media_descriptions' => false
|
||||
];
|
||||
return view('settings.media', compact('compose'));
|
||||
}
|
||||
|
||||
public function updateMediaSettings(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'default' => 'required|int|min:1|max:16',
|
||||
'sync' => 'nullable',
|
||||
'media_descriptions' => 'nullable'
|
||||
]);
|
||||
|
||||
$license = $request->input('default');
|
||||
$sync = $request->input('sync') == 'on';
|
||||
$media_descriptions = $request->input('media_descriptions') == 'on';
|
||||
|
||||
$setting = UserSetting::whereUserId($request->user()->id)->firstOrFail();
|
||||
$compose = json_decode($setting->compose_settings, true);
|
||||
$changed = false;
|
||||
|
||||
if(!isset($compose['default_license']) || $compose['default_license'] !== $license) {
|
||||
$compose['default_license'] = (int) $license;
|
||||
$changed = true;
|
||||
}
|
||||
|
||||
if(!isset($compose['media_descriptions']) || $compose['media_descriptions'] !== $media_descriptions) {
|
||||
$compose['media_descriptions'] = $media_descriptions;
|
||||
$changed = true;
|
||||
}
|
||||
|
||||
if($changed) {
|
||||
$setting->compose_settings = json_encode($compose);
|
||||
$setting->save();
|
||||
Cache::forget('profile:compose:settings:' . $request->user()->id);
|
||||
}
|
||||
|
||||
return redirect(route('settings'))->with('status', 'Media settings successfully updated!');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddComposeSettingsToUserSettingsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('user_settings', function (Blueprint $table) {
|
||||
$table->json('compose_settings')->nullable();
|
||||
});
|
||||
|
||||
Schema::table('media', function (Blueprint $table) {
|
||||
$table->text('caption')->change();
|
||||
$table->index('profile_id');
|
||||
$table->index('mime');
|
||||
$table->index('license');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('user_settings', function (Blueprint $table) {
|
||||
$table->dropColumn('compose_settings');
|
||||
});
|
||||
|
||||
Schema::table('media', function (Blueprint $table) {
|
||||
$table->string('caption')->change();
|
||||
$table->dropIndex('profile_id');
|
||||
$table->dropIndex('mime');
|
||||
$table->dropIndex('license');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -134,20 +134,16 @@ export default {
|
|||
window._sharedData.curUser = res.data;
|
||||
window.App.util.navatar();
|
||||
});
|
||||
axios.get('/api/pixelfed/v1/notifications', {
|
||||
params: {
|
||||
pg: true
|
||||
}
|
||||
})
|
||||
axios.get('/api/pixelfed/v1/notifications?pg=true')
|
||||
.then(res => {
|
||||
let data = res.data.filter(n => {
|
||||
if(n.type == 'share' && !status) {
|
||||
if(n.type == 'share' && !n.status) {
|
||||
return false;
|
||||
}
|
||||
if(n.type == 'comment' && !status) {
|
||||
if(n.type == 'comment' && !n.status) {
|
||||
return false;
|
||||
}
|
||||
if(n.type == 'mention' && !status) {
|
||||
if(n.type == 'mention' && !n.status) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -167,8 +163,7 @@ export default {
|
|||
}
|
||||
axios.get('/api/pixelfed/v1/notifications', {
|
||||
params: {
|
||||
pg: true,
|
||||
page: this.notificationCursor
|
||||
max_id: this.notificationMaxId
|
||||
}
|
||||
}).then(res => {
|
||||
if(res.data.length) {
|
||||
|
|
|
@ -100,10 +100,10 @@
|
|||
v-for="(item, index) in availableLicenses"
|
||||
class="list-group-item cursor-pointer"
|
||||
:class="{
|
||||
'text-primary': licenseIndex === index,
|
||||
'font-weight-bold': licenseIndex === index
|
||||
'text-primary': licenseId === item.id,
|
||||
'font-weight-bold': licenseId === item.id
|
||||
}"
|
||||
@click="toggleLicense(index)">
|
||||
@click="toggleLicense(item)">
|
||||
{{item.name}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -336,7 +336,13 @@
|
|||
<p class="px-4 mb-0 py-2 cursor-pointer" @click="showTagCard()">Tag people</p>
|
||||
</div>
|
||||
<div class="border-bottom">
|
||||
<p class="px-4 mb-0 py-2 cursor-pointer" @click="showLicenseCard()">Add license <span class="ml-2 badge badge-primary">NEW</span></p>
|
||||
<p class="px-4 mb-0 py-2 cursor-pointer" @click="showLicenseCard()">
|
||||
<span>Add license <span class="ml-2 badge badge-primary">NEW</span></span>
|
||||
<span class="float-right">
|
||||
<a v-if="licenseTitle" href="#" @click.prevent="showLicenseCard()" class="btn btn-outline-secondary btn-sm small mr-3 mt-n1 disabled" style="font-size:10px;padding:3px;text-transform: uppercase" disabled>{{licenseTitle}}</a>
|
||||
<a href="#" @click.prevent="showLicenseCard()" class="text-decoration-none"><i class="fas fa-chevron-right fa-lg text-lighter"></i></a>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="border-bottom">
|
||||
<p class="px-4 mb-0 py-2 cursor-pointer" @click="showLocationCard()" v-if="!place">Add location</p>
|
||||
|
@ -591,11 +597,11 @@
|
|||
<span></span>
|
||||
<span>{{media[carouselCursor].license ? media[carouselCursor].license.length : 0}}/140</span>
|
||||
</p> -->
|
||||
<select class="form-control" v-model="licenseIndex">
|
||||
<select class="form-control" v-model="licenseId">
|
||||
<option
|
||||
v-for="(item, index) in availableLicenses"
|
||||
:value="index"
|
||||
:selected="index === licenseIndex">
|
||||
:value="item.id"
|
||||
:selected="item.id == licenseId">
|
||||
{{item.name}}
|
||||
</option>
|
||||
</select>
|
||||
|
@ -845,52 +851,79 @@ export default {
|
|||
availableLicenses: [
|
||||
{
|
||||
id: 1,
|
||||
name: "All Rights Reserved"
|
||||
name: "All Rights Reserved",
|
||||
title: ""
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "Public Domain Work"
|
||||
name: "Public Domain Work",
|
||||
title: ""
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "Public Domain Dedication (CC0)"
|
||||
name: "Public Domain Dedication (CC0)",
|
||||
title: "CC0"
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
name: "Attribution"
|
||||
name: "Attribution",
|
||||
title: "CC BY"
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
name: "Attribution-ShareAlike"
|
||||
name: "Attribution-ShareAlike",
|
||||
title: "CC BY-SA"
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
name: "Attribution-NonCommercial"
|
||||
name: "Attribution-NonCommercial",
|
||||
title: "CC BY-NC"
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
name: "Attribution-NonCommercial-ShareAlike"
|
||||
name: "Attribution-NonCommercial-ShareAlike",
|
||||
title: "CC BY-NC-SA"
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
name: "Attribution-NoDerivs"
|
||||
name: "Attribution-NoDerivs",
|
||||
title: "CC BY-ND"
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
name: "Attribution-NonCommercial-NoDerivs"
|
||||
name: "Attribution-NonCommercial-NoDerivs",
|
||||
title: "CC BY-NC-ND"
|
||||
}
|
||||
],
|
||||
licenseIndex: 0,
|
||||
video: {
|
||||
title: '',
|
||||
description: ''
|
||||
}
|
||||
},
|
||||
composeSettings: {
|
||||
default_license: null,
|
||||
media_descriptions: false
|
||||
},
|
||||
licenseId: null,
|
||||
licenseTitle: null
|
||||
}
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
this.fetchProfile();
|
||||
this.filters = window.App.util.filters;
|
||||
axios.get('/api/compose/v0/settings')
|
||||
.then(res => {
|
||||
this.composeSettings = res.data;
|
||||
this.licenseId = this.composeSettings.default_license;
|
||||
if(this.licenseId > 10) {
|
||||
this.licenseTitle = this.availableLicenses.filter(l => {
|
||||
return l.id == this.licenseId;
|
||||
}).map(l => {
|
||||
return l.title;
|
||||
})[0];
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
@ -1064,6 +1097,16 @@ export default {
|
|||
|
||||
switch(state) {
|
||||
case 'publish' :
|
||||
if(this.composeSettings.media_descriptions === true) {
|
||||
let count = this.media.filter(m => {
|
||||
return !m.hasOwnProperty('alt') || m.alt.length < 2;
|
||||
});
|
||||
|
||||
if(count.length) {
|
||||
swal('Missing media descriptions', 'You have enabled mandatory media descriptions. Please add media descriptions under Advanced settings to proceed. For more information, please see the media settings page.', 'warning');
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(this.media.length == 0) {
|
||||
swal('Whoops!', 'You need to add media before you can save this!', 'warning');
|
||||
return;
|
||||
|
@ -1080,7 +1123,7 @@ export default {
|
|||
place: this.place,
|
||||
tagged: this.taggedUsernames,
|
||||
optimize_media: this.optimizeMedia,
|
||||
license: this.availableLicenses[this.licenseIndex].id,
|
||||
license: this.licenseId,
|
||||
video: this.video
|
||||
};
|
||||
axios.post('/api/compose/v0/publish', data)
|
||||
|
@ -1515,8 +1558,18 @@ export default {
|
|||
this.page = 'licensePicker';
|
||||
},
|
||||
|
||||
toggleLicense(index) {
|
||||
this.licenseIndex = index;
|
||||
toggleLicense(license) {
|
||||
this.licenseId = license.id;
|
||||
|
||||
if(this.licenseId > 10) {
|
||||
this.licenseTitle = this.availableLicenses.filter(l => {
|
||||
return l.id == this.licenseId;
|
||||
}).map(l => {
|
||||
return l.title;
|
||||
})[0];
|
||||
} else {
|
||||
this.licenseTitle = null;
|
||||
}
|
||||
|
||||
switch(this.mode) {
|
||||
case 'photo':
|
||||
|
|
|
@ -120,7 +120,7 @@
|
|||
setTimeout(function() {
|
||||
self.profile = window._sharedData.curUser;
|
||||
self.fetchFollowRequests();
|
||||
}, 500);
|
||||
}, 1500);
|
||||
},
|
||||
|
||||
updated() {
|
||||
|
@ -157,7 +157,7 @@
|
|||
}
|
||||
axios.get('/api/pixelfed/v1/notifications', {
|
||||
params: {
|
||||
page: this.notificationCursor
|
||||
max_id: this.notificationMaxId
|
||||
}
|
||||
}).then(res => {
|
||||
if(res.data.length) {
|
||||
|
|
49
resources/views/settings/media.blade.php
Normal file
49
resources/views/settings/media.blade.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
@extends('settings.template')
|
||||
|
||||
@section('section')
|
||||
|
||||
<div class="title">
|
||||
<h3 class="font-weight-bold">Media</h3>
|
||||
</div>
|
||||
<hr>
|
||||
<form method="post">
|
||||
@csrf
|
||||
<div class="form-group pb-3">
|
||||
<label class="form-check-label font-weight-bold" for="">Default License</label>
|
||||
<select class="form-control" name="default">
|
||||
@foreach(App\Util\Media\License::get() as $license)
|
||||
<option value="{{$license['id']}}" {{$compose['default_license'] == $license['id'] ? 'selected':''}}>
|
||||
{{$license['name']}}
|
||||
@if($license['id'] > 10)
|
||||
({{$license['title']}})
|
||||
@endif
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<p class="text-muted small help-text">Set a default license for new posts.</p>
|
||||
</div>
|
||||
|
||||
<div class="form-check pb-3">
|
||||
<input class="form-check-input" type="checkbox" name="sync">
|
||||
<label class="form-check-label font-weight-bold" for="">Sync Licenses</label>
|
||||
<p class="text-muted small help-text">Update existing posts with your new default license. You can sync once every 24 hours.</p>
|
||||
</div>
|
||||
|
||||
<div class="form-check pb-3">
|
||||
<input class="form-check-input" type="checkbox" name="media_descriptions" {{$compose['media_descriptions'] == $license['id'] ? 'checked':''}}>
|
||||
<label class="form-check-label font-weight-bold" for="">Require Media Descriptions</label>
|
||||
<p class="text-muted small help-text">
|
||||
Briefly describe your media to improve accessibility for vision impaired people. <br />
|
||||
<span class="font-weight-bold">Not available for mobile or 3rd party apps at this time.</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group row mt-5 pt-5">
|
||||
<div class="col-12 text-right">
|
||||
<hr>
|
||||
<button type="submit" class="btn btn-primary font-weight-bold py-0 px-5">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@endsection
|
|
@ -14,6 +14,9 @@
|
|||
<a class="nav-link font-weight-light text-muted" href="{{route('settings.invites')}}">Invites</a>
|
||||
</li>
|
||||
@endif
|
||||
<li class="nav-item pl-3 {{request()->is('settings/media*')?'active':''}}">
|
||||
<a class="nav-link font-weight-light text-muted" href="{{route('settings.media')}}">Media</a>
|
||||
</li>
|
||||
<li class="nav-item pl-3 {{request()->is('settings/notifications')?'active':''}}">
|
||||
<a class="nav-link font-weight-light text-muted" href="{{route('settings.notifications')}}">Notifications</a>
|
||||
</li>
|
||||
|
|
|
@ -119,6 +119,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
|||
Route::post('/publish', 'ComposeController@store');
|
||||
Route::post('/publish/text', 'ComposeController@storeText');
|
||||
Route::get('/media/processing', 'ComposeController@mediaProcessingCheck');
|
||||
Route::get('/settings', 'ComposeController@composeSettings');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -429,6 +430,8 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
|||
|
||||
Route::get('timeline', 'SettingsController@timelineSettings')->name('settings.timeline');
|
||||
Route::post('timeline', 'SettingsController@updateTimelineSettings');
|
||||
Route::get('media', 'SettingsController@mediaSettings')->name('settings.media');
|
||||
Route::post('media', 'SettingsController@updateMediaSettings');
|
||||
});
|
||||
|
||||
Route::group(['prefix' => 'site'], function () {
|
||||
|
|
Loading…
Reference in a new issue