BotFramework-WebChat Replace chat avatar with placeholder - javascript

I want to change the chat avatar, and the avatar of the bot, but setting the backgroundImage doesn't work
var styleSet = window.WebChat.createStyleSet({
backgroundColor: '#f3f3f3',
bubbleBackground: '#FFFFFF',
bubbleBorderRadius: 5,
bubbleTextColor: 'Black',
bubbleFromUserBackground: '#3a8dde',
bubbleFromUserBorderRadius: 5,
bubbleFromUserTextColor: 'White',
});
styleSet.avatar = {
alignItems: 'center',
borderRadius: '50%',
color: 'white',
backgroundColor: 'gray',
display: 'flex',
height: "50px",
justifyContent: 'center',
overflow: 'hidden',
width: "50px"
};
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({token: 'My.Secret.token'}),
//styles
styleSet: styleSet,
botAvatarInitials: 'BF',
userAvatarInitials: 'WC'
}, document.getElementById('webchat'));

There is currently no solution for setting background images, but there is a workaround you can use with idiosyncratic styling, originally shared here on GitHub.
import { createStyleSet } from 'botframework-webchat;
const styleSet = createStyleSet({});
styleSet.avatar = {
...styleSet.avatar,
'&.from-user': {
backgroundImage:'url(\'https://github.com/compulim.png?size=64\')'
},
'&:not(.from-user)': {
backgroundImage:'url(\'https://learn.microsoft.com/en-us/azure/bot-service/v4sdk/media/logo_bot.svg?view=azure-bot-service-4.0\')' }
};
};
<ReactWebChat
botAvatarInitials= ' '
userAvatarInitials= ' '
styleSet={styleSet}`
/>
In JavaScript, you can do the following:
const styleSet = window.WebChat.createStyleSet();
styleSet.avatar = {
...styleSet.avatar,
'&.from-user': {
backgroundImage:'url(\'https://github.com/compulim.png?size=64\')'
},
'&:not(.from-user)': {
backgroundImage:'url(\'https://learn.microsoft.com/en-us/azure/bot-service/v4sdk/media/logo_bot.svg?view=azure-bot-service-4.0\')' }
};
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
styleSet,
botAvatarInitials: ' ',
userAvatarInitials: ' '
}, document.getElementById('webchat'));

Related

Pushing into an array object in react but not rendering on the screen

Im using react and displaying some labels via the array object of labels. Now, I want to do this dynamically. So if a user clicks a button, the object updates and the user interface should update accordingly as well. The issue here is that I got the array to update after clicking on the button, as evidenced by a console log line that I wrote in the onclick handler. But the user interface does not update accordingly. Just the array shows the values. Here is what the inital array looks like:
const labelsArray = [
{ label: 'Hey There', sublabel1: 'How are you?' },
{
label: 'Greetings', sublabel1: 'Fellows'
},
{ label: 'Awesome', sublabel1: 'Youre doing great', sublabel2: 'cool' }
];
I want to append a warningLabel, and errorLabel to the 2nd object of this array. So since arrays are 0 indexed, I did the following in the onclick handler:
const appendLabel = async () => {
labelsArray[1].warningLabel = "Hello";
labelsArray[1].errorLabel = "Hello";
console.log(labelsArray)
};
The array updates, but not the user interface. Which is really weird.
Also, this is not related to react state mutation, which I know because of my research of this topic when I was trying to figure it out. So just to be clear, its not about state mutation, which might have someone put this as a duplicate question. Its more of a react/object structure question. But I could be wrong! Anyways, any help is appreciated. Thanks!
Here is my whole component for reference
import React, { useState } from 'react';
import { Button, Typography } from '#material-ui/core';
import { withStyles } from '#material-ui/core/styles/';
import Stepper from '#material-ui/core/Stepper';
import Step from '#material-ui/core/Step';
import StepLabel from '#material-ui/core/StepLabel';
import StepConnector from '#material-ui/core/StepConnector';
import PropTypes from 'prop-types';
const styles = theme => ({
stepLabelRoot: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center'
},
checklistHeader: {
fontWeight: 'bold',
marginTop: '80px'
},
connectorIcon: {
color: theme.palette.text.secondary
},
stepper: {
background: 'none',
fontWeight: 'bold'
},
checkListImageContainer: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center'
},
connector: {
},
activeConnector: {
border: 'solid 1px #6fef71'
},
stepIcon: {
height: '35px',
width: '35px',
'&:hover': {
backgroundColor: 'rgba(134, 141, 150, 0.37)',
borderRadius: '50%'
},
},
activeStepIcon: {
backgroundColor: 'yellow'
},
label: {
fontWeight: 'bold',
display: 'flex',
fontSize: '15px'
},
sublabel: {
fontWeight: 'normal',
fontSize: '13px'
},
errorLabel: {
color: 'red'
},
warningLabel: {
color: 'yellow'
},
step: {
'&$completed': {
color: 'lightgreen'
},
'&$active': {
color: 'pink'
},
'&$disabled': {
color: 'red'
},
},
alternativeLabel: {},
active: {
}, // needed so that the &$active tag works
completed: {
},
disabled: {
},
labelContainer: {
'&$alternativeLabel': {
marginTop: 0
},
},
});
const labelsArray = [
{ label: 'Random text?', sublabel1: 'Lorem Ipsum' },
{
label: 'Another random text', sublabel1: 'Hello World'
},
{ label: 'Cool', sublabel1: 'cool', sublabel2: 'ayo' }
];
const Checklist = ({ classes,activeStep }) => {
return (
<React.Fragment>
<Stepper alternativeLabel activeStep={2} connector={<StepConnector />} className={classes.stepper}>
{labelsArray.map(label => (
<Step key={label} completed>
<StepLabel active
completed
StepIconProps={{
classes: {
root: classes.step,
completed: classes.completed,
active: classes.active,
disabled: classes.disabled
}
}}>
<div className={classes.stepLabelRoot}>
<span className={classes.label}>
{label.label}
</span>
<span className={classes.sublabel}>
{label.sublabel1}
</span>
<span className={classes.sublabel}>
{label.sublabel2}
</span>
<span className={classes.sublabel}>
{label.sublabel3}
</span>
<span className={classes.errorLabel}>
{label.errorLabel && <img src="/static/images/lock-material.png" alt="img" style={{ height: '15px', width: '15px' }} />}
{label.errorLabel}
</span>
<span className={classes.warningLabel}>
{label.warningLabel && <img src="/static/images/warning-sign.png" alt="img" style={{ height: '15px', width: '15px' }} />}
{label.warningLabel}
</span>
</div>
</StepLabel>
</Step>
))}
</Stepper>
<Button onClick={() => appendLabel()}>Hello</Button>
</React.Fragment>
);
};
Checklist.defaultProps = {
activeStep: -1
};
Checklist.propTypes = {
classes: PropTypes.object.isRequired,
form: PropTypes.bool.isRequired,
activeStep: PropTypes.number
};
export default withStyles(styles, { withTheme: true })(Checklist);
You need to set the labelsArray in the state and update it accordingly in order to re-render the component when the user clicks the button
Edited:
A way of doing that with a state would be:
const LABELS =[
{ label: 'Hey There', sublabel1: 'How are you?' },
{ label: 'Greetings', sublabel1: 'Fellows' },
{ label: 'Awesome', sublabel1: 'Youre doing great', sublabel2: 'cool' }
];
const [labelsArray, setLabelsArray] = useState(LABELS);
const appendLabel = () => {
let editedLabels = [...labelsArray];
editedLabels[1].warningLabel = "Hello";
editedLabels[1].errorLabel = "Hello";
setLabelsArray(editedLabels);
};

convert class components to functional components react native

as i am new in react native. i have no much knowledge of class component. i was stuck in code as class components are used in this code but i want to convert them into functional components. anyone please help me to convert this given code into functional component. this is a code of a swipeable card in react native all the given code in class component and use of constructor and this. i want to just convert it into functional component.
//This is an example of Tinder like Swipeable Card//
import React, { Component } from 'react';
//import react in our code.
import {
Platform, StyleSheet, View, Text,
Dimensions, Animated, PanResponder,
} from 'react-native';
//import all the components we are going to use.
const SCREEN_WIDTH = Dimensions.get('window').width;
class SwipeableCard extends React.Component {
constructor() {
super();
this.panResponder;
this.state = {
Xposition: new Animated.Value(0),
RightText: false,
LeftText: false,
};
this.Card_Opacity = new Animated.Value(1);
this.panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => false,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderMove: (evt, gestureState) => {
this.state.Xposition.setValue(gestureState.dx);
if (gestureState.dx > SCREEN_WIDTH - 250) {
this.setState({
RightText: true,
LeftText: false,
});
} else if (gestureState.dx < -SCREEN_WIDTH + 250) {
this.setState({
LeftText: true,
RightText: false,
});
}
},
onPanResponderRelease: (evt, gestureState) => {
if (
gestureState.dx < SCREEN_WIDTH - 150 &&
gestureState.dx > -SCREEN_WIDTH + 150
) {
this.setState({
LeftText: false,
RightText: false,
});
Animated.spring(
this.state.Xposition,
{
toValue: 0,
speed: 5,
bounciness: 10,
},
{ useNativeDriver: true }
).start();
} else if (gestureState.dx > SCREEN_WIDTH - 150) {
Animated.parallel(
[
Animated.timing(this.state.Xposition, {
toValue: SCREEN_WIDTH,
duration: 200,
}),
Animated.timing(this.Card_Opacity, {
toValue: 0,
duration: 200,
}),
],
{ useNativeDriver: true }
).start(() => {
this.setState({ LeftText: false, RightText: false }, () => {
this.props.removeCard();
});
});
} else if (gestureState.dx < -SCREEN_WIDTH + 150) {
Animated.parallel(
[
Animated.timing(this.state.Xposition, {
toValue: -SCREEN_WIDTH,
duration: 200,
}),
Animated.timing(this.Card_Opacity, {
toValue: 0,
duration: 200,
}),
],
{ useNativeDriver: true }
).start(() => {
this.setState({ LeftText: false, RightText: false }, () => {
this.props.removeCard();
});
});
}
},
});
}
render() {
const rotateCard = this.state.Xposition.interpolate({
inputRange: [-200, 0, 200],
outputRange: ['-20deg', '0deg', '20deg'],
});
return (
<Animated.View
{...this.panResponder.panHandlers}
style={[
styles.card_Style,
{
backgroundColor: this.props.item.backgroundColor,
opacity: this.Card_Opacity,
transform: [
{ translateX: this.state.Xposition },
{ rotate: rotateCard },
],
},
]}>
<Text style={styles.Card_Title}> {this.props.item.card_Title} </Text>
{this.state.LeftText ? (
<Text style={styles.Left_Text_Style}> Left Swipe </Text>
) : null}
{this.state.RightText ? (
<Text style={styles.Right_Text_Style}> Right Swipe </Text>
) : null}
</Animated.View>
);
}
}
export default class App extends React.Component {
constructor() {
super();
this.state = {
Sample_Card_Array: [{
id: '1', card_Title: 'Card 1', backgroundColor: '#FFC107',
}, {
id: '2', card_Title: 'Card 2', backgroundColor: '#ED2525',
}, {
id: '3', card_Title: 'Card 3', backgroundColor: '#E7088E',
}, {
id: '4', card_Title: 'Card 4', backgroundColor: '#00BCD4',
}, {
id: '5', card_Title: 'Card 5', backgroundColor: '#FFFB14',
}],
No_More_Card: false,
};
}
componentDidMount() {
this.setState({
Sample_Card_Array: this.state.Sample_Card_Array.reverse(),
});
if (this.state.Sample_Card_Array.length == 0) {
this.setState({ No_More_Card: true });
}
}
removeCard = id => {
this.state.Sample_Card_Array.splice(
this.state.Sample_Card_Array.findIndex(x => x.id == id),
1
);
this.setState({ Sample_Card_Array: this.state.Sample_Card_Array }, () => {
if (this.state.Sample_Card_Array.length == 0) {
this.setState({ No_More_Card: true });
}
});
};
render() {
return (
<View style={styles.MainContainer}>
{this.state.Sample_Card_Array.map((item, key) => (
<SwipeableCard
key={key}
item={item}
removeCard={this.removeCard.bind(this, item.id)}
/>
))}
{this.state.No_More_Card ? (
<Text style={{ fontSize: 22, color: '#000' }}>No Cards Found.</Text>
) : null}
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
paddingTop: Platform.OS === 'ios' ? 20 : 0,
},
card_Style: {
width: '75%',
height: '45%',
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
borderRadius: 7,
},
Card_Title: {
color: '#fff',
fontSize: 24,
},
Left_Text_Style: {
top: 22,
right: 32,
position: 'absolute',
color: '#fff',
fontSize: 20,
fontWeight: 'bold',
backgroundColor: 'transparent',
},
Right_Text_Style: {
top: 22,
left: 32,
position: 'absolute',
color: '#fff',
fontSize: 20,
fontWeight: 'bold',
backgroundColor: 'transparent',
},
});
the part in the render method is what you return.
to create stateObjects in functional components you will need to use the useState method
const functionalComponent = (props)=>{//props are passed in via props arg...
const defaultState = Xposition: new Animated.Value(0),
RightText: false,
LeftText: false
}
const [state,setState] = useState(defaultState);
... // more stuff
return (
<Animated.View
{...this.panResponder.panHandlers}
style={[
styles.card_Style,
{
backgroundColor: props.item.backgroundColor,
opacity: Card_Opacity,
transform: [
{ translateX: state.Xposition },
{ rotate: rotateCard },
],
},
]}>
<Text style={styles.Card_Title}> {props.item.card_Title} </Text>
{this.state.LeftText ? (
<Text style={styles.Left_Text_Style}> Left Swipe </Text>
) : null}
{this.state.RightText ? (
<Text style={styles.Right_Text_Style}> Right Swipe </Text>
) : null}
</Animated.View>
);
}
you should really go watch some videos on useState, you can be much more granular
to set the state you will need to use the setState method returned from the useState call : setState({..state,{XPosition:55}) or something ... you do the ...state to include the old state values, as the state variable will be overwritten with exactly what you pass in... it wont "update" the existing state it will overwrite it
the next bit is hooking into the functionality in componentDidMount you can do this with useEffect
useEffect(()=>{ // this is setup
// do the stuff from componentDidMount
return ()=>{
// any required teardown can be done here
},[] //[] signifies only do this when component mounts... not every update
);// end useEffect componentDidMount
again there is alot more to useEffect, if you want to do stuff when specific state or props are updated

How to avoid data from other tab to be visible in current tab

I am using createMaterialTopTabNavigator to display Top Tabs in react native but the data from other tab is visible on the current tab
I have tried to set the container style to flex 1 and the flexWrap : 'wrap' but still the problem persists
const NotificationTabs = createMaterialTopTabNavigator(
{
MobileNotification: {
screen: MobileNotificationScreen,
navigationOptions: {
title: Languages.Notifications.Mobile,
},
},
EmailNotification: {
screen: EmailNotificationScreen,
navigationOptions: {
title: Languages.Notifications.Email,
},
},
},
{
initialRouteName: 'MobileNotification',
tabBarComponent: TopTabBarComponent,
tabBarOptions: {
style: {
backgroundColor: Colors.SAWhite,
},
labelStyle: {
color: Colors.SAPrimary,
...Fonts.Style.normal,
},
activeTintColor: Colors.SAPrimary,
inactiveTintColor: Colors.SASecondary,
upperCaseLabel: false,
},
}
);
<View style={styles.flat}>
<NotificationTabs navigation={navigation} />
</View>
styles
flat: {
flex:1
borderRadius:10
marginTop: '10%',
padding: 4,
backgroundColor: Colors.SAWhite,
},
I fixed it by adding overflow: 'hidden' to the styles
flat: {
flex:1
borderRadius:10
marginTop: '10%',
padding: 4,
backgroundColor: Colors.SAWhite,
overflow: 'hidden'
}

Placeholder won't ellipsize using react-native-picker-select

I am using RNPickerSelect with custom styling (using styled-components/native). However, since the property useNativeAndroidPickerStyle is set to false, texts that are too long do not ellipsize, but move to the right.
After setting useNativeAndroidPickerStyle to true, the text does ellipsize, but the styling is lost. Adding textInputProps={{numberOfLines: 1}} doesn't seem to solve the problem, either, as it is just ignored. Adding the numberOfLines property to the styled component, but it throws an error, as this is not a styling property.
The pickdr is coded as follows
<RNPickerSelect
placeholder={{
label: `${i18n.t('selectABoard')}`,
value: null,
}}
items={items}
onValueChange={
value => {
if (value != null && value !== selected) {
if (boards.find(board => board.name === value.name)) {
onBoardSelected(value);
} else {
onCommitteeSelected(value);
}
}
}
}
value={selected}
style={stylesPicker}
Icon={() => (
<IconContainer>
<Entypo
name="chevron-down"
color={colors.PRIMARY_BLUE}
size={20}
/>
</IconContainer>
)}
useNativeAndroidPickerStyle={false}
textInputProps={{numberOfLines: 1}}
/>
const stylesPicker = StyleSheet.create({
placeholder: {
color: colors.PRIMARY_BLUE,
},
inputIOS: {
color: colors.PRIMARY_BLUE,
height: NAVBAR_HEIGHT,
paddingLeft: 16,
paddingRight: 16,
},
inputAndroid: {
color: colors.PRIMARY_BLUE,
height: NAVBAR_HEIGHT,
paddingLeft: 16,
paddingRight: 16,
},
iconContainer: {
alignItems: 'center',
height: NAVBAR_HEIGHT,
justifyContent: 'center',
paddingRight: 16,
}
});
The whole text is "Nahual Prueba NGO - Finance Committee", the expected placeholder should be something like "Nahual Prueba NG..."

fetch is not work in IOS simulator with React Native 0.44

Fetch is not working in IOS simulator with React Native 0.44.
I'm trying to create a login form in react native using fetch.
This is my code,
login.ios.js
import React, { Component } from 'react';
import { StyleSheet,TextInput,ActivityIndicatorIOS,TouchableHighlight, Text, View } from 'react-native';
class Login extends Component {
constructor(){
super();
this.state = {
reg_mob_no: "",
password: "",
error: "",
showProgress: false,
}
}
async onLoginPressed() {
this.setState({showProgress: true})
try {
let response = await fetch('http://example.in/api/premiumuser/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
reg_mob_no: this.state.reg_mob_no,
password: this.state.password,
})
});
let res = await response.text();
console.log("res is:" + res );
} catch(error) {
}
}
render() {
return (
<View style={styles.container}>
<Text style={styles.heading}>
Login Form!
</Text>
<TextInput
onChangeText={ (text)=> this.setState({reg_mob_no: text}) }
style={styles.input} placeholder="Registered Mobile No">
</TextInput>
<TextInput
onChangeText={ (text)=> this.setState({password: text}) }
style={styles.input}
placeholder="Password"
secureTextEntry={true}>
</TextInput>
<TouchableHighlight onPress={this.onLoginPressed.bind(this)} style={styles.button}>
<Text style={styles.buttonText}>
Login
</Text>
</TouchableHighlight>
<Text style={styles.error}>
{this.state.error}
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
backgroundColor: '#F5FCFF',
padding: 10,
paddingTop: 80
},
input: {
height: 50,
marginTop: 10,
padding: 4,
fontSize: 18,
borderWidth: 1,
borderColor: '#48bbec'
},
button: {
height: 50,
backgroundColor: '#48BBEC',
alignSelf: 'stretch',
marginTop: 10,
justifyContent: 'center'
},
buttonText: {
fontSize: 22,
color: '#FFF',
alignSelf: 'center'
},
heading: {
fontSize: 30,
},
error: {
color: 'red',
paddingTop: 10
},
success: {
color: 'green',
paddingTop: 10
},
loader: {
marginTop: 20
}
});
module.exports = Login;
I am not getting any response from server when clicked on registerbutton.
This same source in working with expo but not working in ios simulator. Developer tool showing nothing.
How to solve this issue..
Please help!!!
React Native version: 0.44
Platform: IOS
Development Operating System: mac os 10.12
Build tools: Xcode 9
Try to include the key-value pair credentials: 'include' in fetch options.
RN 0.44 introduced withCredentials XHR flag, as you can see here.

Categories

Resources