Browse Source

Merge pull request #2144 from pixelfed/staging

Update Timeline component, fix mod tools
daniel 5 năm trước cách đây
mục cha
commit
ce9b5b7ff8

+ 1 - 0
CHANGELOG.md

@@ -13,6 +13,7 @@
 - Updated RemotePost component, fix missing like button on comments ([7ef90565](https://github.com/pixelfed/pixelfed/commit/7ef90565))
 - Updated PublicApiControllers, fix block/mutes filtering on public timeline ([08383dd4](https://github.com/pixelfed/pixelfed/commit/08383dd4))
 - Updated FixUsernames command, fixes remote username search ([0f943f67](https://github.com/pixelfed/pixelfed/commit/0f943f67))
+- Updated Timeline component, fix mod tools ([b1d5eb05](https://github.com/pixelfed/pixelfed/commit/b1d5eb05))
 
 
 ## [v0.10.9 (2020-04-17)](https://github.com/pixelfed/pixelfed/compare/v0.10.8...v0.10.9)

+ 57 - 43
app/Http/Controllers/InternalApiController.php

@@ -30,6 +30,8 @@ use League\Fractal\Serializer\ArraySerializer;
 use League\Fractal\Pagination\IlluminatePaginatorAdapter;
 use Illuminate\Validation\Rule;
 use Illuminate\Support\Str;
+use App\Services\ModLogService;
+use App\Services\PublicTimelineService;
 
 class InternalApiController extends Controller
 {
@@ -161,24 +163,23 @@ class InternalApiController extends Controller
 
     public function modAction(Request $request)
     {
-        abort_unless(Auth::user()->is_admin, 403);
+        abort_unless(Auth::user()->is_admin, 400);
         $this->validate($request, [
             'action' => [
                 'required',
                 'string',
                 Rule::in([
-                    'autocw',
-                    'noautolink',
-                    'unlisted',
-                    'disable',
-                    'suspend'
+                    'addcw',
+                    'remcw',
+                    'unlist'
+                    
                 ])
             ],
             'item_id' => 'required|integer|min:1',
             'item_type' => [
                 'required',
                 'string',
-                Rule::in(['status'])
+                Rule::in(['profile', 'status'])
             ]
         ]);
 
@@ -187,48 +188,61 @@ class InternalApiController extends Controller
         $item_type = $request->input('item_type');
 
         switch($action) {
-            case 'autocw':
-                $profile = $item_type == 'status' ? Status::findOrFail($item_id)->profile : null;
-                $profile->cw = true;
-                $profile->save();
+            case 'addcw':
+                $status = Status::findOrFail($item_id);
+                $status->is_nsfw = true;
+                $status->save();
+                ModLogService::boot()
+                    ->user(Auth::user())
+                    ->objectUid($status->profile->user_id)
+                    ->objectId($status->id)
+                    ->objectType('App\Status::class')
+                    ->action('admin.status.moderate')
+                    ->metadata([
+                        'action' => 'cw',
+                        'message' => 'Success!'
+                    ])
+                    ->accessLevel('admin')
+                    ->save();
             break;
 
-            case 'noautolink':
-                $profile = $item_type == 'status' ? Status::findOrFail($item_id)->profile : null;
-                $profile->no_autolink = true;
-                $profile->save();
+            case 'remcw':
+                $status = Status::findOrFail($item_id);
+                $status->is_nsfw = false;
+                $status->save();
+                ModLogService::boot()
+                    ->user(Auth::user())
+                    ->objectUid($status->profile->user_id)
+                    ->objectId($status->id)
+                    ->objectType('App\Status::class')
+                    ->action('admin.status.moderate')
+                    ->metadata([
+                        'action' => 'remove_cw',
+                        'message' => 'Success!'
+                    ])
+                    ->accessLevel('admin')
+                    ->save();
             break;
 
-            case 'unlisted':
-                $profile = $item_type == 'status' ? Status::findOrFail($item_id)->profile : null;
-                $profile->unlisted = true;
-                $profile->save();
+            case 'unlist':
+                $status = Status::whereScope('public')->findOrFail($item_id);
+                $status->scope = $status->visibility = 'unlisted';
+                $status->save();
+                PublicTimelineService::del($status->id);
+                ModLogService::boot()
+                    ->user(Auth::user())
+                    ->objectUid($status->profile->user_id)
+                    ->objectId($status->id)
+                    ->objectType('App\Status::class')
+                    ->action('admin.status.moderate')
+                    ->metadata([
+                        'action' => 'unlist',
+                        'message' => 'Success!'
+                    ])
+                    ->accessLevel('admin')
+                    ->save();
             break;
-
-            case 'disable':
-                $profile = $item_type == 'status' ? Status::findOrFail($item_id)->profile : null;
-                $user = $profile->user;
-                $profile->status = 'disabled';
-                $user->status = 'disabled';
-                $profile->save();
-                $user->save();
-            break;
-
-
-            case 'suspend':
-                $profile = $item_type == 'status' ? Status::findOrFail($item_id)->profile : null;
-                $user = $profile->user;
-                $profile->status = 'suspended';
-                $user->status = 'suspended';
-                $profile->save();
-                $user->save();
-            break;
-            
-            default:
-                # code...
-                break;
         }
-        Cache::forget('profiles:private');
         return ['msg' => 200];
     }
 

BIN
public/js/timeline.js


BIN
public/mix-manifest.json


+ 64 - 104
resources/assets/js/components/Timeline.vue

@@ -399,55 +399,56 @@
 	body-class="list-group-flush p-0 rounded">
 	<div class="list-group text-center">
 		<div class="list-group-item rounded cursor-pointer" @click="moderatePost(ctxMenuStatus, 'unlist')">Unlist from Timelines</div>
-		<div class="list-group-item rounded cursor-pointer" @click="">Add Content Warning</div>
+		<div v-if="ctxMenuStatus.sensitive" class="list-group-item rounded cursor-pointer" @click="moderatePost(ctxMenuStatus, 'remcw')">Remove Content Warning</div>
+		<div v-else class="list-group-item rounded cursor-pointer" @click="moderatePost(ctxMenuStatus, 'addcw')">Add Content Warning</div>
 		<div class="list-group-item rounded cursor-pointer text-lighter" @click="ctxModMenuClose()">Cancel</div>
 	</div>
- </b-modal>
- <b-modal ref="ctxShareModal"
-    id="ctx-share-modal"
-    title="Share"
-    hide-footer
-    centered
-    rounded
-    size="sm"
-    body-class="list-group-flush p-0 rounded text-center">
-      <div class="list-group-item rounded cursor-pointer border-top-0">Email</div>
-      <div class="list-group-item rounded cursor-pointer">Facebook</div>
-      <div class="list-group-item rounded cursor-pointer">Mastodon</div>
-      <div class="list-group-item rounded cursor-pointer">Pinterest</div>
-      <div class="list-group-item rounded cursor-pointer">Pixelfed</div>
-      <div class="list-group-item rounded cursor-pointer">Twitter</div>
-      <div class="list-group-item rounded cursor-pointer">VK</div>
-      <div class="list-group-item rounded cursor-pointer text-lighter" @click="closeCtxShareMenu()">Cancel</div>
- </b-modal>
- <b-modal ref="ctxEmbedModal"
-    id="ctx-embed-modal"
-    hide-header
-    hide-footer
-    centered
-    rounded
-    size="md"
-    body-class="p-2 rounded">
+</b-modal>
+<b-modal ref="ctxShareModal"
+	id="ctx-share-modal"
+	title="Share"
+	hide-footer
+	centered
+	rounded
+	size="sm"
+	body-class="list-group-flush p-0 rounded text-center">
+		<div class="list-group-item rounded cursor-pointer border-top-0">Email</div>
+		<div class="list-group-item rounded cursor-pointer">Facebook</div>
+		<div class="list-group-item rounded cursor-pointer">Mastodon</div>
+		<div class="list-group-item rounded cursor-pointer">Pinterest</div>
+		<div class="list-group-item rounded cursor-pointer">Pixelfed</div>
+		<div class="list-group-item rounded cursor-pointer">Twitter</div>
+		<div class="list-group-item rounded cursor-pointer">VK</div>
+		<div class="list-group-item rounded cursor-pointer text-lighter" @click="closeCtxShareMenu()">Cancel</div>
+</b-modal>
+<b-modal ref="ctxEmbedModal"
+	id="ctx-embed-modal"
+	hide-header
+	hide-footer
+	centered
+	rounded
+	size="md"
+	body-class="p-2 rounded">
 	<div>
 		<textarea class="form-control disabled" rows="1" style="border: 1px solid #efefef; font-size: 14px; line-height: 12px; height: 37px; margin: 0 0 7px; resize: none; white-space: nowrap;" v-model="ctxEmbedPayload"></textarea>
 		<hr>
 		<button :class="copiedEmbed ? 'btn btn-primary btn-block btn-sm py-1 font-weight-bold disabed': 'btn btn-primary btn-block btn-sm py-1 font-weight-bold'" @click="ctxCopyEmbed" :disabled="copiedEmbed">{{copiedEmbed ? 'Embed Code Copied!' : 'Copy Embed Code'}}</button>
 		<p class="mb-0 px-2 small text-muted">By using this embed, you agree to our <a href="/site/terms">Terms of Use</a></p>
 	</div>
-  </b-modal>
-  <b-modal
-  	id="lightbox"
-  	ref="lightboxModal"
-  	hide-header
-  	hide-footer
-  	centered
-  	size="lg"
-  	body-class="p-0"
-  	>
-  	<div v-if="lightboxMedia" :class="lightboxMedia.filter_class" class="w-100 h-100">
-  		<img :src="lightboxMedia.url" style="max-height: 100%; max-width: 100%">
-  	</div>
-  </b-modal>
+</b-modal>
+<b-modal
+	id="lightbox"
+	ref="lightboxModal"
+	hide-header
+	hide-footer
+	centered
+	size="lg"
+	body-class="p-0"
+	>
+	<div v-if="lightboxMedia" :class="lightboxMedia.filter_class" class="w-100 h-100">
+		<img :src="lightboxMedia.url" style="max-height: 100%; max-width: 100%">
+	</div>
+ </b-modal>
 <b-modal ref="replyModal"
 	id="ctx-reply-modal"
 	hide-footer
@@ -929,63 +930,11 @@
 
 			moderatePost(status, action, $event) {
 				let username = status.account.username;
+				let msg = '';
+				let self = this;
 				switch(action) {
-					case 'autocw':
-						let msg = 'Are you sure you want to enforce CW for ' + username + ' ?';
-						swal({
-							title: 'Confirm',
-							text: msg,
-							icon: 'warning',
-							buttons: true,
-							dangerMode: true
-						}).then(res =>  {
-							if(res) {
-								axios.post('/api/v2/moderator/action', {
-									action: action,
-									item_id: status.id,
-									item_type: 'status'
-								}).then(res => {
-									swal('Success', 'Successfully enforced CW for ' + username, 'success');
-								}).catch(err => {
-									swal(
-										'Error',
-										'Something went wrong, please try again later.',
-										'error'
-									);
-								});
-							}
-						});
-					break;
-
-					case 'noautolink':
-						msg = 'Are you sure you want to disable auto linking for ' + username + ' ?';
-						swal({
-							title: 'Confirm',
-							text: msg,
-							icon: 'warning',
-							buttons: true,
-							dangerMode: true
-						}).then(res =>  {
-							if(res) {
-								axios.post('/api/v2/moderator/action', {
-									action: action,
-									item_id: status.id,
-									item_type: 'status'
-								}).then(res => {
-									swal('Success', 'Successfully disabled autolinking for ' + username, 'success');
-								}).catch(err => {
-									swal(
-										'Error',
-										'Something went wrong, please try again later.',
-										'error'
-									);
-								});
-							}
-						});
-					break;
-
-					case 'unlisted':
-						msg = 'Are you sure you want to unlist from timelines for ' + username + ' ?';
+					case 'addcw':
+						msg = 'Are you sure you want to add a content warning to this post?';
 						swal({
 							title: 'Confirm',
 							text: msg,
@@ -999,20 +948,23 @@
 									item_id: status.id,
 									item_type: 'status'
 								}).then(res => {
-									swal('Success', 'Successfully unlisted for ' + username, 'success');
+									swal('Success', 'Successfully added content warning', 'success');
+									status.sensitive = true;
+									self.ctxModMenuClose();
 								}).catch(err => {
 									swal(
 										'Error',
 										'Something went wrong, please try again later.',
 										'error'
 									);
+									self.ctxModMenuClose();
 								});
 							}
 						});
 					break;
 
-					case 'disable':
-						msg = 'Are you sure you want to disable ' + username + '’s account ?';
+					case 'remcw':
+						msg = 'Are you sure you want to remove the content warning on this post?';
 						swal({
 							title: 'Confirm',
 							text: msg,
@@ -1026,20 +978,23 @@
 									item_id: status.id,
 									item_type: 'status'
 								}).then(res => {
-									swal('Success', 'Successfully disabled ' + username + '’s account', 'success');
+									swal('Success', 'Successfully added content warning', 'success');
+									status.sensitive = false;
+									self.ctxModMenuClose();
 								}).catch(err => {
 									swal(
 										'Error',
 										'Something went wrong, please try again later.',
 										'error'
 									);
+									self.ctxModMenuClose();
 								});
 							}
 						});
 					break;
 
-					case 'suspend':
-						msg = 'Are you sure you want to suspend ' + username + '’s account ?';
+					case 'unlist':
+						msg = 'Are you sure you want to unlist this post?';
 						swal({
 							title: 'Confirm',
 							text: msg,
@@ -1053,8 +1008,13 @@
 									item_id: status.id,
 									item_type: 'status'
 								}).then(res => {
-									swal('Success', 'Successfully suspend ' + username + '’s account', 'success');
+									this.feed = this.feed.filter(f => {
+										return f.id != status.id;
+									});
+									swal('Success', 'Successfully unlisted post', 'success');
+									self.ctxModMenuClose();
 								}).catch(err => {
+									self.ctxModMenuClose();
 									swal(
 										'Error',
 										'Something went wrong, please try again later.',