...
 
Commits (13)
......@@ -16,11 +16,7 @@
</li>
<li
class="mdl-menu__item"
*ngIf="
(options.indexOf('edit') !== -1 &&
entity.owner_guid == session.getLoggedInUser().guid) ||
session.isAdmin()
"
*ngIf="options.indexOf('edit') !== -1 && checkEditPermissions()"
(click)="selectOption('edit')"
i18n="@@M__ACTION__EDIT"
>
......@@ -116,12 +112,7 @@
<!-- DELETE -->
<li
class="mdl-menu__item"
*ngIf="
(options.indexOf('delete') !== -1 &&
entity.owner_guid == session.getLoggedInUser().guid) ||
session.isAdmin() ||
canDelete
"
*ngIf="options.indexOf('delete') !== -1 && checkDeletePermissions()"
(click)="deleteToggle = true"
i18n="@@M__ACTION__DELETE"
>
......
......@@ -5,18 +5,17 @@ import {
EventEmitter,
Input,
Output,
OnInit,
} from '@angular/core';
import { Session } from '../../../services/session';
import { OverlayModalService } from '../../../services/ux/overlay-modal';
import { Client } from '../../../services/api/client';
import { ReportCreatorComponent } from '../../../modules/report/creator/creator.component';
import { MindsUser } from '../../../interfaces/entities';
import { SignupModalService } from '../../../modules/modals/signup/service';
import { BlockListService } from '../../services/block-list.service';
import { ActivityService } from '../../../common/services/activity.service';
import { FeaturesService } from '../../../services/features.service';
import { ShareModalComponent } from '../../../modules/modals/share/share';
import { PermissionsService } from '../../services/permissions.service';
type Option =
| 'edit'
......@@ -45,15 +44,16 @@ type Option =
templateUrl: 'post-menu.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class PostMenuComponent implements OnInit {
export class PostMenuComponent {
@Input() entity: any;
@Input() options: Array<Option>;
@Output() optionSelected: EventEmitter<Option> = new EventEmitter<Option>();
@Input() canDelete: boolean = false;
@Input() isTranslatable: boolean = false;
@Input() askForCategoriesWhenFeaturing: boolean = false;
@Input() user: any;
@Output() optionSelected: EventEmitter<Option> = new EventEmitter<Option>();
featuredCategory: string = 'not-selected';
asyncFollow: boolean = false;
......@@ -76,13 +76,12 @@ export class PostMenuComponent implements OnInit {
public signupModal: SignupModalService,
protected blockListService: BlockListService,
protected activityService: ActivityService,
public featuresService: FeaturesService
public featuresService: FeaturesService,
private permissionsService: PermissionsService
) {
this.initCategories();
}
ngOnInit() {}
initCategories() {
for (let category in window.Minds.categories) {
this.categories.push({
......@@ -370,4 +369,27 @@ export class PostMenuComponent implements OnInit {
this.selectOption('share');
}
checkEditPermissions() {
if (this.featuresService.has('permissions')) {
return this.permissionsService.canInteract(this.entity, 'edit_post');
}
return (
this.entity.owner_guid == this.session.getLoggedInUser().guid ||
this.session.isAdmin()
);
}
checkDeletePermissions() {
if (this.featuresService.has('permissions')) {
return this.permissionsService.canInteract(this.entity, 'delete_post');
}
return (
this.entity.owner_guid == this.session.getLoggedInUser().guid ||
this.session.isAdmin() ||
this.canDelete
);
}
}
export type Permissions = {
name: string;
permissions: string[];
};
export class PermissionsService {
canInteract(entity: any, permission: string) {
let permissions: Permissions = entity.permissions;
return (
permissions &&
permissions.permissions.findIndex(item => item === permission) !== -1
);
}
}
<div class="m--spam-notice" *ngIf="user?.spam">
<ng-container *ngIf="user?.spam" i18n="@@MINDS__CHANNELS__FLAGGED_AS_SPAM"
>This user was flagged as spam.</ng-container
>
<ng-container *ngIf="user?.spam" i18n="@@MINDS__CHANNELS__FLAGGED_AS_SPAM">
This user was flagged as spam.
</ng-container>
<ng-container
*ngIf="user?.deleted"
i18n="@@MINDS__CHANNELS__FLAGGED_AS_DELETED"
>This user was flagged as deleted.</ng-container
>
This user was flagged as deleted.
</ng-container>
<ng-container *ngIf="!session.isAdmin()" i18n="@@M__ACTION__APPEAL_MARK">
If you wish to appeal, please check your
......@@ -21,14 +22,16 @@
style="margin: 16px auto;"
></div>
</div>
<div class="m-error-splash" *ngIf="error && !user">
<img [src]="minds.cdn_assets_url + 'assets/logos/logo.svg'" />
<h3 class="mdl-color-text--red-300">{{ error }}</h3>
<span
class="mdl-color-text--blue-grey-300"
i18n="@@MINDS__CHANNELS__ERROR_CHECK_USERNAME"
>Please check the username</span
>
Please check the username
</span>
</div>
<header [hidden]="!isLocked"></header>
......@@ -42,6 +45,29 @@
></m-channel--carousel>
</header>
<!-- IF A CLOSE / MODERATED CHANNEL AND NOT A MEMBER -->
<div
class="mdl-grid channel-grid m-channel--closed"
style="max-width:900px"
*ngIf="user && !user.blocked && !user.subscribed && user.mode !== 0"
>
<div class="m-groupSplash__avatar">
<minds-avatar [object]="user"></minds-avatar>
</div>
<h3
class="mdl-color-text--blue-grey-300"
i18n="@@MINDS__CHANNELS__THIS_IS_A_CLOSED_CHANNEL"
>
This is a closed channel
</h3>
<minds-button-subscribe
[user]="user"
(subscribed)="onSubscribed()"
[request]="true"
></minds-button-subscribe>
</div>
<div
class="mdl-grid channel-grid m-channel--blocked"
style="max-width:900px"
......@@ -53,15 +79,15 @@
>
You have blocked @{{ user.username }}
</h3>
<a (click)="unBlock()" i18n="@@MINDS__CHANNELS__UNBLOCK_ACTION"
>Click to Unblock</a
>
<a (click)="unBlock()" i18n="@@MINDS__CHANNELS__UNBLOCK_ACTION">
Click to Unblock
</a>
</div>
<div
class="mdl-grid channel-grid"
style="max-width:990px"
*ngIf="user && !user?.blocked"
*ngIf="user && !user?.blocked && (user.mode === 0 || user.subscribed)"
>
<section class="mdl-cell mdl-cell--4-col m-channel-sidebar">
<m-channel--sidebar
......@@ -108,22 +134,26 @@
class="mdl-tabs__tab"
[ngClass]="{ 'is-active': filter === 'subscribers' }"
i18n="@@MINDS__CHANNELS__SUBSCRIBERS_WITH_COUNT"
>Subscribers ({{ user.subscribers_count }})</a
>
Subscribers ({{ user.subscribers_count }})
</a>
<a
[routerLink]="['/', user.username, 'subscriptions']"
class="mdl-tabs__tab"
[ngClass]="{ 'is-active': filter === 'subscriptions' }"
i18n="@@MINDS__CHANNELS__SUBSCRIPTIONS_WITH_COUNT"
>Subscriptions ({{ user.subscriptions_count }})</a
>
Subscriptions ({{ user.subscriptions_count }})
</a>
<a
[routerLink]="['/', user.username, 'requests']"
*ngIf="user.mode === 2 && user.guid == session.getLoggedInUser().guid"
class="mdl-tabs__tab"
[ngClass]="{ 'is-active': filter === 'requests' }"
>Requests</a
>
Requests
</a>
</div>
</div>
......@@ -142,22 +172,26 @@
class="mdl-tabs__tab"
[ngClass]="{ 'is-active': filter === 'subscribers' }"
i18n="@@MINDS__CHANNELS__SUBSCRIBERS_WITH_COUNT"
>Subscribers ({{ user.subscribers_count }})</a
>
Subscribers ({{ user.subscribers_count }})
</a>
<a
[routerLink]="['/', user.username, 'subscriptions']"
class="mdl-tabs__tab"
[ngClass]="{ 'is-active': filter === 'subscriptions' }"
i18n="@@MINDS__CHANNELS__SUBSCRIPTIONS_WITH_COUNT"
>Subscriptions ({{ user.subscriptions_count }})</a
>
Subscriptions ({{ user.subscriptions_count }})
</a>
<a
[routerLink]="['/', user.username, 'requests']"
*ngIf="user.mode === 2 && user.guid == session.getLoggedInUser().guid"
class="mdl-tabs__tab"
[ngClass]="{ 'is-active': filter === 'requests' }"
>Requests</a
>
Requests
</a>
</div>
</div>
......
......@@ -100,8 +100,39 @@ m-channel {
}
}
.m-channel--blocked {
.m-channel--closed {
display: flex;
justify-content: center;
& > * {
margin: $minds-margin 0;
}
}
.m-channel--blocked,
.m-channel--closed {
margin: 100px auto;
minds-avatar {
margin: -75px auto 0;
.minds-avatar {
margin: auto;
border-radius: 50%;
width: 150px;
height: 150px;
display: flex;
flex-direction: row;
align-items: center;
background-size: cover;
background-position: center center;
img {
display: none;
}
}
}
h3 {
font-size: 26px;
text-align: center;
......
......@@ -17,6 +17,7 @@ import { Observable } from 'rxjs';
import { DialogService } from '../../common/services/confirm-leave-dialog.service';
import { BlockListService } from '../../common/services/block-list.service';
import { ChannelSortedComponent } from './sorted/sorted.component';
import { PermissionsService } from '../../common/services/permissions.service';
import { ClientMetaService } from '../../common/services/client-meta.service';
@Component({
......@@ -56,6 +57,7 @@ export class ChannelComponent {
private context: ContextService,
private dialogService: DialogService,
private blockListService: BlockListService,
private permissions: PermissionsService,
private clientMetaService: ClientMetaService,
@SkipSelf() injector: Injector
) {
......@@ -154,6 +156,10 @@ export class ChannelComponent {
});
}
onSubscribed() {
// TODO do something here
}
isOwner() {
return this.session.getLoggedInUser().guid === this.user.guid;
}
......
......@@ -60,11 +60,7 @@
<ul class="m-comment__ribbon" [hidden]="!toggle.value" #toggle>
<li
class="m-commentRibbon__item"
*ngIf="
comment.owner_guid == session.getLoggedInUser()?.guid ||
session.isAdmin() ||
canEdit
"
*ngIf="checkEditPermissions()"
(click)="editing = !editing; toggle.value = false"
title="Edit"
i18n-title="@@M__ACTION__EDIT"
......@@ -82,12 +78,7 @@
</li>
<li
class="m-commentRibbon__item"
*ngIf="
comment.owner_guid == session.getLoggedInUser()?.guid ||
session.isAdmin() ||
parent.owner_guid == session.getLoggedInUser()?.guid ||
canDelete
"
*ngIf="checkDeletePermissions()"
(click)="delete(); toggle.value = false"
title="Delete"
i18n-title="@@M__ACTION__DELETE"
......
......@@ -32,6 +32,7 @@ import { FeaturesService } from '../../../services/features.service';
import { MindsVideoComponent } from '../../media/components/video/video.component';
import { MediaModalComponent } from '../../media/modal/modal.component';
import isMobile from '../../../helpers/is-mobile';
import { PermissionsService } from '../../../common/services/permissions.service';
@Component({
selector: 'm-comment',
......@@ -105,7 +106,8 @@ export class CommentComponentV2
private el: ElementRef,
private router: Router,
protected activityService: ActivityService,
protected featuresService: FeaturesService
protected featuresService: FeaturesService,
protected permissionsService: PermissionsService
) {}
ngOnInit() {
......@@ -380,4 +382,32 @@ export class CommentComponentV2
})
.present();
}
checkEditPermissions() {
if (this.featuresService.has('permissions')) {
return this.permissionsService.canInteract(this.comment, 'edit_comment');
}
return (
this.comment.owner_guid == this.session.getLoggedInUser().guid ||
this.session.isAdmin() ||
this.canEdit
);
}
checkDeletePermissions() {
if (this.featuresService.has('permissions')) {
return this.permissionsService.canInteract(
this.comment,
'delete_comment'
);
}
return (
this.comment.owner_guid == this.session.getLoggedInUser().guid ||
this.session.isAdmin() ||
this.parent.owner_guid == this.session.getLoggedInUser().guid ||
this.canDelete
);
}
}
......@@ -113,7 +113,7 @@
</div>
<m-comment__poster
*ngIf="activityService.allowComment$ | async"
*ngIf="canPost && activityService.allowComment$ | async"
[guid]="guid"
[parent]="parent"
[entity]="entity"
......
......@@ -23,6 +23,8 @@ import { BlockListService } from '../../../common/services/block-list.service';
import { ActivityService } from '../../../common/services/activity.service';
import { Subscription } from 'rxjs';
import { TouchSequence } from 'selenium-webdriver';
import { FeaturesService } from '../../../services/features.service';
import { PermissionsService } from '../../../common/services/permissions.service';
@Component({
selector: 'm-comments__thread',
......@@ -33,7 +35,12 @@ import { TouchSequence } from 'selenium-webdriver';
export class CommentsThreadComponent implements OnInit {
minds;
@Input() parent;
@Input() entity;
@Input('entity') set _entity(value: any) {
this.entity = value;
this.checkPermissions();
}
entity;
@Input() entityGuid;
@Input() canEdit: boolean = false;
@Input() canDelete: boolean = false;
......@@ -66,18 +73,32 @@ export class CommentsThreadComponent implements OnInit {
comment: null,
};
canPost: boolean = true;
constructor(
public session: Session,
private commentsService: CommentsService,
public sockets: SocketsService,
private renderer: Renderer,
protected blockListService: BlockListService,
private featuresService: FeaturesService,
protected permissionsService: PermissionsService,
private cd: ChangeDetectorRef,
public activityService: ActivityService
) {
this.minds = window.Minds;
}
private async checkPermissions() {
if (this.featuresService.has('permissions')) {
// TODO: maybe there should be a "view comment" flag?
this.canPost = await this.permissionsService.canInteract(
this.entity,
'create_comment'
);
}
}
ngOnInit() {
this.load(true);
this.listen();
......
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Router } from '@angular/router';
import { GroupsService } from '../groups-service';
......@@ -6,6 +6,8 @@ import { ReportCreatorComponent } from '../../report/creator/creator.component';
import { OverlayModalService } from '../../../services/ux/overlay-modal';
import { Client } from '../../../services/api/client';
import { Session } from '../../../services/session';
import { FeaturesService } from '../../../services/features.service';
import { PermissionsService } from '../../../common/services/permissions.service';
@Component({
selector: 'minds-groups-settings-button',
......@@ -15,8 +17,9 @@ import { Session } from '../../../services/session';
<i
*ngIf="group['is:muted']"
class="minds-groups-button-badge material-icons"
>notifications_off</i
>
notifications_off
</i>
</button>
<ul class="minds-dropdown-menu" [hidden]="!showMenu">
......@@ -171,12 +174,12 @@ import { Session } from '../../../services/session';
<m-modal [open]="featureModalOpen" (closed)="onFeatureModalClose($event)">
<div class="m-button-feature-modal">
<select [(ngModel)]="category">
<option value="not-selected" i18n="@@M__COMMON__SELECT_A_CATEGORY"
>-- SELECT A CATEGORY --</option
>
<option *ngFor="let category of categories" [value]="category.id">{{
category.label
}}</option>
<option value="not-selected" i18n="@@M__COMMON__SELECT_A_CATEGORY">
-- SELECT A CATEGORY --
</option>
<option *ngFor="let category of categories" [value]="category.id">
{{ category.label }}
</option>
</select>
<button
......@@ -222,7 +225,9 @@ export class GroupsSettingsButton {
public client: Client,
public session: Session,
public overlayService: OverlayModalService,
public router: Router
public router: Router,
private featuresService: FeaturesService,
private permissionsService: PermissionsService
) {}
ngOnInit() {
......@@ -304,11 +309,22 @@ export class GroupsSettingsButton {
this.overlayService.create(ReportCreatorComponent, this.group).present();
}
checkDeletePermissions() {
if (this.featuresService.has('permissions')) {
return this.permissionsService.canInteract(this.group, 'delete_group');
}
return true;
}
/**
* deletePrompt
* Displays the delete prompt if deletion is possible
*/
async deletePrompt() {
if (!this.checkDeletePermissions()) {
alert(`You don't have permissions to delete a group`);
}
if ((await this.service.countMembers(this.group.guid)) !== 1) {
alert('You cannot delete a group that has members.');
return;
......
......@@ -132,7 +132,7 @@ minds-button-remind a {
}
minds-button-comment > a,
minds-button-remind > a {
&:hover {
&:not(.disabled):hover {
@include m-theme() {
color: themed($m-blue-grey-800);
}
......
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Component, ChangeDetectionStrategy, Input } from '@angular/core';
import { Session } from '../../../../services/session';
import { Client } from '../../../../services/api';
import { SignupModalService } from '../../../../modules/modals/signup/service';
import { PermissionsService } from '../../../../common/services/permissions.service';
import { FeaturesService } from '../../../../services/features.service';
// had forwardRef(() => RemindComposerModal)
@Component({
selector: 'minds-button-remind',
inputs: ['_object: object'],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<a (click)="remind()" [ngClass]="{ selected: object.reminded }">
<a
(click)="remind()"
[ngClass]="{ selected: object.reminded, disabled: !enabled }"
>
<i class="material-icons">repeat</i>
<span class="minds-counter" *ngIf="object.reminds > 0">{{
object.reminds | number
......@@ -36,15 +40,31 @@ export class RemindButton {
constructor(
public session: Session,
public client: Client,
private modal: SignupModalService
private modal: SignupModalService,
private permissionsService: PermissionsService,
private featuresService: FeaturesService
) {}
set _object(value: any) {
@Input('object') set _object(value: any) {
this.object = value;
this.checkPermissions();
}
enabled: boolean = true;
private checkPermissions() {
if (this.featuresService.has('permissions')) {
this.enabled = this.permissionsService.canInteract(this.object, 'remind');
} else {
this.enabled = true;
}
}
remind() {
var self = this;
if (!this.enabled) {
return;
}
if (this.object.reminded) return false;
......
......@@ -14,7 +14,15 @@ import { SignupModalService } from '../../../../modules/modals/signup/service';
>
<i class="material-icons">person_add</i>
<span>
<ng-container i18n="@@M__ACTION__SUBSCRIBE">Subscribe</ng-container>
<ng-container i18n="@@M__ACTION__SUBSCRIBE" *ngIf="!request">
Subscribe
</ng-container>
<ng-container
i18n="@@M__ACTION__SEND_SUBSCRIPTION_REQUEST"
*ngIf="request"
>
Send Subscription Request
</ng-container>
</span>
</button>
<button
......@@ -36,9 +44,9 @@ import { SignupModalService } from '../../../../modules/modals/signup/service';
>
<i class="material-icons">close</i>
<span>
<ng-container i18n="@@MINDS__BUTTONS__UNSUBSCRIBE__SUBSCRIBED_LABEL"
>Unsubscribe</ng-container
>
<ng-container i18n="@@MINDS__BUTTONS__UNSUBSCRIBE__SUBSCRIBED_LABEL">
Unsubscribe
</ng-container>
</span>
</button>
`,
......@@ -51,6 +59,7 @@ export class SubscribeButton {
_content: any;
_listener: Function;
showModal: boolean = false;
@Input() request: boolean = false;
@Output('subscribed') onSubscribed: EventEmitter<any> = new EventEmitter();
constructor(
......
......@@ -46,6 +46,7 @@ import { AuthService } from './auth.service';
import { SiteService } from '../common/services/site.service';
import { SessionsStorageService } from './session-storage.service';
import { DiagnosticsService } from './diagnostics.service';
import { PermissionsService } from '../common/services/permissions.service';
export const MINDS_PROVIDERS: any[] = [
SiteService,
......@@ -69,6 +70,7 @@ export const MINDS_PROVIDERS: any[] = [
useFactory: Client._,
deps: [HttpClient, Location, SiteService],
},
PermissionsService,
{
provide: Upload,
useFactory: Upload._,
......