Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • benhayward.ben/mobile-native
  • minds/mobile-native
  • msantang78/mobile-native
  • edgebal/mobile-native
  • msantang78_test/mobile-native
  • duyquoc/mobile-native
  • priestd09/mobile-native
  • eiennohi/mobile-native
  • omadrid/mobile-native
  • sieuhuflit/mobile-native
  • juanmsolaro/mobile-native
  • ascenderking/mobile-native
  • jim-toth/mobile-native
  • thinnakrit/mobile-native-lang
  • project_connection/mobile-native
  • AaronTheBruce/mobile-native
  • cormac.kantargis.hack/mobile-native
  • xthread/mobile-native
  • Paulnguyenun/mobile-native
  • lustigdev/mobile-native
  • GubbenOlsson/mobile-native
  • calvinoea/mobile-native
  • namesty/mobile-native
  • mrrobot16/mobile-native
  • eliobricenov/mobile-native
  • bedriguler/mobile-native
  • m994/mobile-native
  • threetoes/mobile-native
  • liangel/mobile-native
  • hosituan/mobile-native
  • nacef.otay/mobile-native
  • madibaa/mobile-native
  • valentin129/mobile-native
  • manishoo/mobile-native1
34 results
Show changes
Commits on Source (16)
Showing
with 222 additions and 14 deletions
......@@ -18,6 +18,7 @@ exports[`Activity component renders correctly 1`] = `
entity={
ActivityModel {
"__list": null,
"allow_comments": true,
"attachment_guid": false,
"blurb": false,
"comments:count": undefined,
......@@ -74,6 +75,7 @@ exports[`Activity component renders correctly 1`] = `
entity={
ActivityModel {
"__list": null,
"allow_comments": true,
"attachment_guid": false,
"blurb": false,
"comments:count": undefined,
......@@ -146,6 +148,7 @@ exports[`Activity component renders correctly 1`] = `
entity={
ActivityModel {
"__list": null,
"allow_comments": true,
"attachment_guid": false,
"blurb": false,
"comments:count": undefined,
......@@ -246,6 +249,7 @@ exports[`Activity component renders correctly 1`] = `
entity={
ActivityModel {
"__list": null,
"allow_comments": true,
"attachment_guid": false,
"blurb": false,
"comments:count": undefined,
......@@ -313,6 +317,7 @@ exports[`Activity component renders correctly 1`] = `
entity={
ActivityModel {
"__list": null,
"allow_comments": true,
"attachment_guid": false,
"blurb": false,
"comments:count": undefined,
......@@ -376,6 +381,7 @@ exports[`Activity component renders correctly 1`] = `
entity={
ActivityModel {
"__list": null,
"allow_comments": true,
"attachment_guid": false,
"blurb": false,
"comments:count": undefined,
......@@ -445,6 +451,7 @@ exports[`Activity component renders correctly 1`] = `
entity={
ActivityModel {
"__list": null,
"allow_comments": true,
"attachment_guid": false,
"blurb": false,
"comments:count": undefined,
......@@ -507,6 +514,7 @@ exports[`Activity component renders correctly 1`] = `
entity={
ActivityModel {
"__list": null,
"allow_comments": true,
"attachment_guid": false,
"blurb": false,
"comments:count": undefined,
......
......@@ -17,7 +17,7 @@ exports[`Comment action component renders correctly 1`] = `
>
<Icon
color="rgb(96, 125, 139)"
name="chat-bubble"
name="speaker-notes-off"
raised={false}
reverse={false}
reverseColor="white"
......
......@@ -18,6 +18,7 @@ exports[`blog view screen component should renders correctly 1`] = `
BlogModel {
"__list": null,
"access_id": "2",
"allow_comments": true,
"boost_rejection_reason": -1,
"categories": Array [],
"category": "education",
......@@ -44,6 +45,7 @@ exports[`blog view screen component should renders correctly 1`] = `
"ownerObj": UserModel {
"__list": null,
"access_id": "2",
"allow_comments": true,
"banned": "no",
"blocked": false,
"boostProPlus": false,
......@@ -204,6 +206,7 @@ exports[`blog view screen component should renders correctly 1`] = `
BlogModel {
"__list": null,
"access_id": "2",
"allow_comments": true,
"boost_rejection_reason": -1,
"categories": Array [],
"category": "education",
......@@ -230,6 +233,7 @@ exports[`blog view screen component should renders correctly 1`] = `
"ownerObj": UserModel {
"__list": null,
"access_id": "2",
"allow_comments": true,
"banned": "no",
"blocked": false,
"boostProPlus": false,
......@@ -372,6 +376,7 @@ exports[`blog view screen component should renders correctly 1`] = `
BlogModel {
"__list": null,
"access_id": "2",
"allow_comments": true,
"boost_rejection_reason": -1,
"categories": Array [],
"category": "education",
......@@ -398,6 +403,7 @@ exports[`blog view screen component should renders correctly 1`] = `
"ownerObj": UserModel {
"__list": null,
"access_id": "2",
"allow_comments": true,
"banned": "no",
"blocked": false,
"boostProPlus": false,
......@@ -520,6 +526,7 @@ exports[`blog view screen component should renders correctly 1`] = `
BlogModel {
"__list": null,
"access_id": "2",
"allow_comments": true,
"boost_rejection_reason": -1,
"categories": Array [],
"category": "education",
......@@ -546,6 +553,7 @@ exports[`blog view screen component should renders correctly 1`] = `
"ownerObj": UserModel {
"__list": null,
"access_id": "2",
"allow_comments": true,
"banned": "no",
"blocked": false,
"boostProPlus": false,
......@@ -664,6 +672,7 @@ exports[`blog view screen component should renders correctly 1`] = `
BlogModel {
"__list": null,
"access_id": "2",
"allow_comments": true,
"boost_rejection_reason": -1,
"categories": Array [],
"category": "education",
......@@ -690,6 +699,7 @@ exports[`blog view screen component should renders correctly 1`] = `
"ownerObj": UserModel {
"__list": null,
"access_id": "2",
"allow_comments": true,
"banned": "no",
"blocked": false,
"boostProPlus": false,
......
......@@ -234,7 +234,9 @@
"removeOwner":"Remove as Owner",
"makeModerator":"Make Moderator",
"removeModerator":"Remove as Moderator",
"listMembersCount":"Members {{count}}"
"listMembersCount":"Members {{count}}",
"disableConversations":"Disable conversations",
"enableConversations":"Enable conversations"
},
"keychain": {
"unlockMessage": "Unlock {{keychain}} keychain",
......@@ -725,6 +727,8 @@
"wantToUpdate":"Do you want to update the app?",
"updateAvailable":"Update available",
"rememberTomorrow":"Remind me later",
"enableComments": "Enable comments",
"disableComments": "Disable comments",
"noInternet":"No Internet Connection",
"offline":"Offline",
"cantReachServer":"Can't reach the server",
......
......@@ -217,7 +217,9 @@
"banConfirm": "Estás seguro? Quieres suspender a este usuario?",
"errorLoading": "Error cargando grupos",
"confirmKick": "Estás seguro? Quieres expulsar a este usuario?",
"listMembersCount": "Miembros {{count}}"
"listMembersCount": "Miembros",
"disableConversations":"Inhabilitar conversaciones",
"enableConversations":"Habilitar conversaciones"
},
"keychain": {
"unlockMessage": "Desbloquear {{keychain}} keychain",
......@@ -746,6 +748,8 @@
"wantToUpdate": "Quieres actualizar la aplicación? ",
"updateAvailable": "Actualización disponible",
"rememberTomorrow": "Recuerdame más tarde",
"enableComments": "Habilitar comentarios",
"disableComments": "Inhabilitar comentarios",
"noInternet": "Sin conexión a internet",
"offline": "Fuera de línea",
"cantReachServer": "No puedo conectarme al servidor",
......
......@@ -21,6 +21,8 @@ import {
Alert,
} from 'react-native';
import ActionSheet from 'react-native-actionsheet';
import { Header } from 'react-navigation';
import { inject, observer } from 'mobx-react/native';
......@@ -44,6 +46,7 @@ import CommentList from '../comments/CommentList';
import CenteredLoading from '../common/components/CenteredLoading';
import logService from '../common/services/log.service';
import i18n from '../common/services/i18n.service';
import featuresService from '../common/services/features.service';
/**
* Blog View Screen
......@@ -142,10 +145,18 @@ export default class BlogsViewScreen extends Component {
</View>
)
const image = blog.getBannerSource();
const actionSheet = this.getActionSheet();
const optMenu = featuresService.has('allow-comments-toggle') ?
(<View style={styles.rightToolbar}>
<Icon name="more-vert" onPress={() => this.showActionSheet()} size={26} style={styles.icon}/>
{actionSheet}
</View>) : (null);
return (
<View style={styles.screen}>
<FastImage source={image} resizeMode={FastImage.resizeMode.cover} style={styles.image} />
<Text style={styles.title}>{blog.title}</Text>
{optMenu}
<View style={styles.ownerBlockContainer}>
<OwnerBlock entity={blog} navigation={this.props.navigation} rightToolbar={actions}>
<Text style={styles.timestamp}>{formatDate(blog.time_created)}</Text>
......@@ -170,6 +181,51 @@ export default class BlogsViewScreen extends Component {
)
}
getActionSheet() {
let options = [ i18n.t('cancel') ];
options.push(this.props.blogsView.blog.allow_comments ? i18n.t('disableComments') : i18n.t('enableComments'));
return (
<ActionSheet
ref={o => this.ActionSheet = o}
options={options}
onPress={ (i) => { this.handleActionSheetSelection(options[i]) }}
cancelButtonIndex={0}
/>
)
}
async showActionSheet() {
this.ActionSheet.show();
}
async handleActionSheetSelection(option) {
switch(option) {
case i18n.t('disableComments'):
case i18n.t('enableComments'):
try {
await this.props.blogsView.blog.toggleAllowComments();
} catch (err) {
console.error(err);
this.showError();
}
}
}
/**
* Show an error message
*/
showError() {
Alert.alert(
i18n.t('sorry'),
i18n.t('errorMessage') + '\n' + i18n.t('activity.tryAgain'),
[
{text: i18n.t('ok'), onPress: () => {}},
],
{ cancelable: false }
);
}
/**
* Render
*/
......@@ -314,4 +370,12 @@ const styles = StyleSheet.create({
color: '#888',
fontSize: 10,
},
rightToolbar: {
alignSelf: 'flex-end',
bottom: 35,
right: 10
},
icon: {
color: '#888',
},
});
......@@ -313,7 +313,7 @@ export default class CommentList extends React.Component<Props, State> {
* Render poster
*/
renderPoster() {
if (this.state.hideInput) return null;
if (this.state.hideInput || (!this.props.entity.allow_comments && this.props.entity.type !== "group")) return null;
const attachment = this.props.store.attachment;
......
......@@ -112,4 +112,15 @@ export function updateComment(guid, description) {
return api.post(`api/v1/comments/update/${guid}`, {
description: description
});
}
/**
* Enable/Disable comments
* @param {string} guid
* @param {boolean} state
*/
export function toggleAllowComments(guid, state) {
return api.post(`api/v2/permissions/comments/${guid}`,{
allowed: state
});
}
\ No newline at end of file
......@@ -14,11 +14,18 @@ import logService from './services/log.service';
import channelService from '../channel/ChannelService';
import { revokeBoost, acceptBoost, rejectBoost } from '../boost/BoostService';
import { toggleAllowComments as toggleAllow } from '../comments/CommentsService';
/**
* Base model
*/
export default class BaseModel {
/**
* Enable/Disable comments
*/
@observable allow_comments = true;
/**
* List reference (if the entity belongs to one)
* @var {OffsetListStore}
......@@ -261,4 +268,10 @@ export default class BaseModel {
throw err;
}
}
@action
async toggleAllowComments() {
const data = await toggleAllow(this.guid, !this.allow_comments);
this.allow_comments = !this.allow_comments;
}
}
\ No newline at end of file
import { observable, decorate } from 'mobx';
import { observable, decorate, action } from 'mobx';
import BaseModel from '../common/BaseModel';
import groupsService from './GroupsService';
/**
* Group model
*/
export default class GroupModel extends BaseModel {
@observable conversationDisabled = false;
@action
async toggleConversationDisabled() {
await groupsService.toggleConversationDisabled(this.guid, !this.conversationDisabled);
this.conversationDisabled = !this.conversationDisabled;
}
}
/**
......
......@@ -366,7 +366,7 @@ class GroupViewStore {
*/
@action
setGroup(group) {
this.group = group;
this.group = GroupModel.checkOrCreate(group);
this.setGuid(group.guid);
}
......
......@@ -201,6 +201,10 @@ class GroupsService {
revokeModerator(group_guid, user_guid) {
return api.delete(`api/v1/groups/management/${group_guid}/${user_guid}/moderator`);
}
toggleConversationDisabled(group_guid, state) {
return api.post(`api/v1/groups/group/${group_guid}`, { conversationDisabled: state });
}
}
export default new GroupsService();
......@@ -8,6 +8,7 @@ import {
View,
TouchableHighlight,
ActivityIndicator,
StyleSheet
} from 'react-native';
import {
......@@ -17,6 +18,7 @@ import {debounce} from 'lodash';
import FastImage from 'react-native-fast-image';
import Icon from 'react-native-vector-icons/MaterialIcons';
import ActionSheet from 'react-native-actionsheet';
import { MINDS_CDN_URI } from '../../config/Config';
import abbrev from '../../common/helpers/abbrev';
......@@ -28,6 +30,7 @@ import SearchView from '../../common/components/SearchView';
import gathering from '../../common/services/gathering.service';
import colors from '../../styles/Colors';
import i18n from '../../common/services/i18n.service';
import featuresService from '../../common/services/features.service';
/**
* Group Header
......@@ -129,14 +132,17 @@ export default class GroupHeader extends Component {
*/
renderToolbar() {
const group = this.props.store.group;
const conversation = { text: i18n.t('conversation').toUpperCase(), icon: 'ios-chatboxes', iconType: 'ion', value: 'conversation' };
const typeOptions = [
{ text: i18n.t('feed').toUpperCase(), icon: 'list', value: 'feed' },
{ text: i18n.t('description').toUpperCase(), icon: 'short-text', value: 'desc' },
{ text: i18n.t('members').toUpperCase(), badge: abbrev(group['members:count'], 0), value: 'members' },
{ text: i18n.t('conversation').toUpperCase(), icon: 'ios-chatboxes', iconType: 'ion', value: 'conversation' },
{ text: i18n.t('members').toUpperCase(), badge: abbrev(group['members:count'], 0), value: 'members' }
]
if (!featuresService.has('allow-disabling-groups-conversations') || group.conversationDisabled !== 1) {
typeOptions.push(conversation);
}
const searchBar = this.props.store.tab == 'members' ?
<SearchView
containerStyle={[CommonStyle.flexContainer, CommonStyle.hairLineBottom]}
......@@ -174,6 +180,8 @@ export default class GroupHeader extends Component {
this.props.store.loadMembers();
break;
case 'conversation':
if (group.conversationDisabled) return;
this.props.groupsBar.markAsRead(group, 'conversation');
break;
default:
......@@ -194,6 +202,53 @@ export default class GroupHeader extends Component {
}
}
getActionSheet() {
let options = [ i18n.t('cancel') ];
options.push(this.props.store.group.conversationDisabled ? i18n.t('groups.enableConversations') : i18n.t('groups.disableConversations'));
return (
<View style={stylesheet.rightToolbar}>
<Icon name="more-vert" onPress={() => this.showActionSheet()} size={26} style={stylesheet.icon}/>
<ActionSheet
ref={o => this.ActionSheet = o}
options={options}
onPress={ (i) => { this.handleActionSheetSelection(options[i]) }}
cancelButtonIndex={0}
/>
</View>
)
}
async showActionSheet() {
this.ActionSheet.show();
}
async handleActionSheetSelection(option) {
switch(option) {
case i18n.t('groups.disableConversations'):
case i18n.t('groups.enableConversations'):
try{
await this.props.store.group.toggleConversationDisabled();
} catch (err) {
console.error(err);
this.showError();
}
}
}
/**
* Show an error message
*/
showError() {
Alert.alert(
i18n.t('sorry'),
i18n.t('errorMessage') + '\n' + i18n.t('activity.tryAgain'),
[
{text: i18n.t('ok'), onPress: () => {}},
],
{ cancelable: false }
);
}
/**
* Render Header
*/
......@@ -203,10 +258,11 @@ export default class GroupHeader extends Component {
const styles = this.props.styles;
const avatar = { uri: this.getAvatar() };
const iurl = { uri: this.getBannerFromGroup() };
const actionSheet = group['is:owner'] ? this.getActionSheet() : (null);
return (
<View >
<FastImage source={iurl} style={styles.banner} resizeMode={FastImage.resizeMode.cover} />
{actionSheet}
<View style={styles.headertextcontainer}>
<View style={styles.avatarContainer}>
<View style={[CommonStyle.rowJustifyStart, CommonStyle.flexContainer]}>
......@@ -229,3 +285,14 @@ export default class GroupHeader extends Component {
)
}
}
const stylesheet = StyleSheet.create({
rightToolbar: {
alignSelf: 'flex-end',
bottom: 126,
right: 10
},
icon: {
color: '#888',
}
})
......@@ -26,6 +26,7 @@ import ActionSheet from 'react-native-actionsheet';
import { MINDS_URI } from '../../config/Config';
import testID from '../../common/helpers/testID';
import i18n from '../../common/services/i18n.service';
import featuresService from '../../common/services/features.service';
/**
* Activity Actions
......@@ -83,6 +84,10 @@ export default class ActivityActions extends Component {
}
}
if (featuresService.has('allow-comments-toggle')) {
options.push( this.props.entity.allow_comments ? i18n.t('disableComments') : i18n.t('enableComments'));
}
} else {
if (this.props.user.isAdmin()) {
......@@ -116,7 +121,6 @@ export default class ActivityActions extends Component {
options.push( i18n.t('unfollow') );
}
return options;
}
......@@ -136,7 +140,7 @@ export default class ActivityActions extends Component {
{ cancelable: false }
);
if (this.props.navigation.state.routeName == 'Activity'){
if (this.props.navigation.state.routeName == 'Activity') {
this.props.navigation.goBack();
}
} catch (err) {
......@@ -227,6 +231,15 @@ export default class ActivityActions extends Component {
case i18n.t('report'):
this.props.navigation.navigate('Report', { entity: this.props.entity });
break;
case i18n.t('enableComments'):
case i18n.t('disableComments'):
try {
await this.props.entity.toggleAllowComments();
} catch (err) {
console.error(err);
this.showError();
}
break;
}
}
......
......@@ -33,9 +33,11 @@ export default class CommentsAction extends Component {
* Render
*/
render() {
const icon = this.props.entity.allow_comments ? 'chat-bubble' : 'speaker-notes-off';
return (
<TouchableOpacityCustom style={[CommonStyle.flexContainer, CommonStyle.rowJustifyCenter]} onPress={this.openComments}>
<Icon color={this.props.entity['comments:count'] > 0 ? 'rgb(70, 144, 214)' : 'rgb(96, 125, 139)'} name='chat-bubble' size={this.props.size} />
<Icon color={this.props.entity['comments:count'] > 0 ? 'rgb(70, 144, 214)' : 'rgb(96, 125, 139)'} name={icon} size={this.props.size} />
<Counter size={this.props.size * 0.75} count={this.props.entity['comments:count']} />
</TouchableOpacityCustom>
);
......@@ -45,8 +47,9 @@ export default class CommentsAction extends Component {
* Open comments screen
*/
openComments = () => {
const cantOpen = !this.props.entity.allow_comments && this.props.entity['comments:count'] == 0;
// TODO: fix
if (this.props.navigation.state.routeName == 'Activity' ){
if (this.props.navigation.state.routeName == 'Activity' || cantOpen) {
return;
}
this.props.navigation.push('Activity', {
......