Giter VIP home page Giter VIP logo

Comments (8)

iwalker7 avatar iwalker7 commented on July 22, 2024 1

Hi, try to run the ONLY Board component no menu or other screens, if it does fix the problem its probably caused by wrong styles of Board parent container (try to add height/ flex it )

same issue here. i think its not solved.

from react-native-draganddrop-board.

AiTranXuan avatar AiTranXuan commented on July 22, 2024

same issues with u @@

from react-native-draganddrop-board.

ariesbrylle-bms avatar ariesbrylle-bms commented on July 22, 2024

same issue here. Have you fix it?

from react-native-draganddrop-board.

TacticCoder avatar TacticCoder commented on July 22, 2024

Hi, try to run the ONLY Board component no menu or other screens, if it does fix the problem its probably caused by wrong styles of Board parent container (try to add height/ flex it )

from react-native-draganddrop-board.

TacticCoder avatar TacticCoder commented on July 22, 2024

same issue here. Have you fix it?

Solved?

from react-native-draganddrop-board.

AiTranXuan avatar AiTranXuan commented on July 22, 2024

Hi, try to run the ONLY Board component no menu or other screens, if it does fix the problem its probably caused by wrong styles of Board parent container (try to add height/ flex it )

same issue here. i think its not solved.

I agree with u.

from react-native-draganddrop-board.

TacticCoder avatar TacticCoder commented on July 22, 2024

In my end its works great, If one of you guys can upload his project or at least his tech stack with the board code it will be great.

from react-native-draganddrop-board.

AiTranXuan avatar AiTranXuan commented on July 22, 2024

@TacticCoder
`// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {intlShape} from 'react-intl';
import {Alert, Animated, Keyboard, StyleSheet, TouchableOpacity, View, Text, Dimensions} from 'react-native';
import {General} from '@mm-redux/constants';
import EventEmitter from '@mm-redux/utils/event_emitter';
import {goToThreadScreen, showModal, showModalOverCurrentContext} from '@actions/navigation';
import LocalConfig from '@assets/config';
import {UPDATE_NATIVE_SCROLLVIEW, TYPING_VISIBLE} from '@constants/post_draft';
import CompassIcon from '@components/compass_icon';
import EphemeralStore from '@store/ephemeral_store';
import {unsupportedServer} from '@utils/supported_server';
import {preventDoubleTap} from '@utils/tap';
import {setNavigatorStyles} from '@utils/theme';
import tracker from '@utils/time_tracker';

import PushNotifications from '@init/push_notifications';
import telemetry from 'app/telemetry';
import {map, get, size, findIndex, find, noop} from 'lodash';
import {PluginType} from 'app/constants/plugin';
import {COOKIE_RESPONSE} from 'app/keycloak/index';
import AsyncStorage from '@react-native-community/async-storage';
import FastImage from 'react-native-fast-image';
import {BoardRepository, Board} from 'react-native-draganddrop-board';
import {KanbanTypes, KanbanUIStatus} from '@constants/';
import {genAssignUsers, getStateOfKanbanChannel, tagToColor} from 'app/utils/kanban';
import {getCookies} from 'app/utils/url';

export let ClientUpgradeListener;
const {height} = Dimensions.get('window');

export default class ChannelBase extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
getChannelStats: PropTypes.func.isRequired,
loadChannelsForTeam: PropTypes.func.isRequired,
selectDefaultTeam: PropTypes.func.isRequired,
selectInitialChannel: PropTypes.func.isRequired,
recordLoadTime: PropTypes.func.isRequired,
getListUnreadMessage: PropTypes.func.isRequired,
handleHideKanban: PropTypes.func.isRequired,
handleOffKanban: PropTypes.func.isRequired,
handleOnKanban: PropTypes.func.isRequired,
handleShowKanban: PropTypes.func.isRequired,
getPostThread: PropTypes.func.isRequired,
selectPost: PropTypes.func.isRequired,
}).isRequired,
componentId: PropTypes.string.isRequired,
currentChannelId: PropTypes.string,
currentTeamId: PropTypes.string,
members: PropTypes.array,
currentUserId: PropTypes.string,
disableTermsModal: PropTypes.bool,
isSupportedServer: PropTypes.bool,
isSystemAdmin: PropTypes.bool,
teamName: PropTypes.string,
theme: PropTypes.object.isRequired,
showTermsOfService: PropTypes.bool,
skipMetrics: PropTypes.bool,
serverURL: PropTypes.string,
kanbanStatus: PropTypes.string,
};

static contextTypes = {
    intl: intlShape.isRequired,
};

static defaultProps = {
    disableTermsModal: false,
};

constructor(props) {
    super(props);

    this.postDraft = React.createRef();

    this.state = {
        channelsRequestFailed: false,
        dataKanban: [],
        modalKanbanVisible: false,
        modalChooseLaneVisible: false,
        isAddCard: false,
        card: null,
        lane_id: null,
        cookie: null,
    };

    if (LocalConfig.EnableMobileClientUpgrade && !ClientUpgradeListener) {
        ClientUpgradeListener = require('app/components/client_upgrade_listener').default;
    }

    this.typingAnimations = [];
}

handleOnKanban = async () => {
    const {currentChannelId} = this.props;
    await getStateOfKanbanChannel(currentChannelId, (kanbanStatus) => {
        if (kanbanStatus) {
            switch (kanbanStatus) {
            case KanbanUIStatus.ON:
                // Nếu Kanban đang ở trạng thái On [default =Hide]=> hide
                this.props.actions.handleHideKanban();
                break;
            case KanbanUIStatus.SHOW:
                // Nếu Kanban đang ở trạng thái show => SHOW
                this.props.actions.handleShowKanban();
                break;
            case KanbanUIStatus.HIDE:
                // Nếu Kanban đang ở trạng thái Hide [default =Hide]=> Hide
                this.props.actions.handleHideKanban();
                break;
            default:
                this.props.actions.handleHideKanban();
                break;
            }
        }
    });
}

handleOffKanban = () => {
    this.props.actions.handleOffKanban();
}

convertDataAndArrange = async (data) => {
    const result = [];

    map(data?.lanes, async (lane) => {
        // indexLane is the position of the Lane on the Board
        const indexLane = findIndex(data?.ordered_lanes, (o) => {
            return o === lane?.id;
        });
        const laneResult = {
            id: indexLane + 1,
            lane_id: lane?.id,
            name: lane?.title,
            creator: lane?.creator,
            rows: [],
        };
        const rowsNow = [];

        map(lane?.cards, async (card) => {
            // eslint-disable-next-line max-nested-callbacks
            const indexCard = findIndex(lane?.ordered_cards, (obj) => {
                return obj === card?.id;
            });

            const assignUsersFull = await genAssignUsers(card?.data?.assignUsers, this.props.members);

            // const assignUsersFull = [];
            // if (size(card?.data?.assignUsers) > 0) {
            //     forEach(card?.data?.assignUsers, async (user) => {
            //         if (size(this.props.members) > 0) {
            //             const resultMember = find(this.props.members, (member) => {
            //                 return member?.username === user;
            //             });
            //             assignUsersFull.push({username: user, avatar: resultMember?.avatar || null});
            //         }
            //     });
            // }
            rowsNow[indexCard] = {
                id: (indexCard + 1),
                card_id: card?.id,
                lane_id: card?.lane_id,
                name: card?.title,
                description: card?.description,
                tags: card?.data?.tags,
                assignUsers: card?.data?.assignUsers || [],
                assignUsersFull,
                thread_id: card?.thread_id,
                creator: card?.creator,
            };
        });
        laneResult.rows = rowsNow;
        result[indexLane] = laneResult;
    });

    return result;
}

updateDataKanban = (dataKanban) => {
    this.setState({dataKanban});
    if (this.state.card) {
        map(dataKanban, async (lane) => {
            const cardResult = find(lane?.rows, (obj) => {
                return obj?.card_id === this.state.card?.card_id;
            });
            if (cardResult) {
                this.setState({card: cardResult});
            }
        });

        // update data card
    }
}

getBoardContent = (callback = null) => {
    const {serverURL, currentChannelId} = this.props;
    AsyncStorage.getItem(COOKIE_RESPONSE).then(async (cookies) => {
        if (cookies) {
            const cookie = getCookies(JSON.parse(cookies));
            this.setState({cookie});
            const url_get_board = encodeURI(serverURL + `/plugins/${PluginType.CHATOPS_KANBAN_PLUGIN}/c-${currentChannelId}`);
            // eslint-disable-next-line no-console
            console.log('url_get_board ', url_get_board, ' \n-cookie: ', cookie);
            fetch(url_get_board, {
                method: 'GET',
                credentials: 'include',
                headers: {
                    Accept: 'application/json',
                    'x-requested-with': 'XMLHttpRequest',
                    cookie,
                },
            }).
                then((res) => {
                    return res.json();
                }).
                then(async (json) => {
                    // eslint-disable-next-line no-console
                    // console.log('Dữ liệu kanban: ', JSON.stringify(json));
                    if (size(json) > 0) {
                        // eslint-disable-next-line no-console
                        console.log('getBoardContent data: ', JSON.stringify(json), ' member: ', this.props.members);
                        if (size(get(json, 'lanes', [])) > 0) {
                            const dataKanban = await this.convertDataAndArrange(json);
                            this.updateDataKanban(dataKanban);
                        } else {
                            this.setState({
                                dataKanban: [],
                                card: null,
                                lane_id: null,
                            });
                        }
                        // eslint-disable-next-line no-unused-expressions
                        callback && callback(true);
                    } else {
                        // Không có dữ liệu kanban = disable
                        this.handleOffKanban();
                        // eslint-disable-next-line no-unused-expressions
                        callback && callback(false);
                    }
                }).
                catch((e) => {
                    // Chạy vào đây tức là plugin kanban bị disable hoặc ko được cài plugin kanban
                    this.handleOffKanban();
                    // eslint-disable-next-line no-unused-expressions
                    callback && callback(false);
                    // eslint-disable-next-line no-console
                    console.log(
                        '[Keycloak] Call API get_board_channel FAIL',
                        e,
                    );
                });
        } else {
            // eslint-disable-next-line no-console
            console.log('[COOKIE_RESPONSE] not found => Ko gọi đc api get plugin');
            this.handleOffKanban();
        }
    });
}

// nếu đang ở board
getBoardKanban = async () => {
    this.getBoardContent((statusBoard) => {
        if (statusBoard) {
            this.handleOnKanban();
        }
    });
}

// Get board khi nhận đc socket
getBoardCurrent = async (channelIdSocket) => {
    const {currentChannelId} = this.props;
    if (channelIdSocket === currentChannelId) {
        this.getBoardContent((statusCurrent) => {
            if (statusCurrent) {
                if (this.props.kanbanStatus !== KanbanUIStatus.SHOW) {
                    this.handleOnKanban();
                }
            }
        });

        // this.props.actions.getPostThread(rootId);
        // this.props.actions.selectPost(rootId);
    } else {
        // eslint-disable-next-line no-console
        console.log('Không phải channel đang mở nên ko cần update data kanban');
    }
}

deleteLane = (lane) => {
    const {serverURL, currentChannelId} = this.props;
    AsyncStorage.getItem(COOKIE_RESPONSE).then(async (cookies) => {
        if (cookies) {
            const cookie = getCookies(JSON.parse(cookies));
            this.setState({cookie});
            const url_delete_card = encodeURI(serverURL + `/plugins/${PluginType.CHATOPS_KANBAN_PLUGIN}/channel/${currentChannelId}/lane/${lane?.lane_id}`);
            // eslint-disable-next-line no-console
            fetch(url_delete_card, {
                method: 'DELETE',
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                    'x-requested-with': 'XMLHttpRequest',
                    cookie,
                },
                credentials: 'include',
                body: null,
            }).
                // eslint-disable-next-line @typescript-eslint/no-unused-vars
                then((res) => {
                    // return res.json();
                }).

                // then(async (json) => {
                //     console.log('[Done] Du lieu delete card; ', json);
                //     this.hideCardDetail();
                // }).
                catch((e) => {
                    // eslint-disable-next-line no-console
                    console.log(
                        '[Keycloak] Call API delete lane FAIL',
                        e,
                    );
                });
        } else {
            // eslint-disable-next-line no-console
            console.log('[COOKIE_RESPONSE] not found => Ko gọi đc api delete lane');

            // this.handleOffKanban();
        }
    });
}

deleteCard = (item) => {
    const {serverURL, currentChannelId} = this.props;
    AsyncStorage.getItem(COOKIE_RESPONSE).then(async (cookies) => {
        if (cookies) {
            const cookie = getCookies(JSON.parse(cookies));
            this.setState({cookie});
            const url_delete_card = encodeURI(serverURL + `/plugins/${PluginType.CHATOPS_KANBAN_PLUGIN}/channel/${currentChannelId}/card/${item?.lane_id}/${item?.card_id}`);
            // eslint-disable-next-line no-console
            fetch(url_delete_card, {
                method: 'DELETE',
                headers: {
                    Accept: 'application/json',
                    'Content-Type': 'application/json',
                    'x-requested-with': 'XMLHttpRequest',
                    cookie,
                },
                credentials: 'include',
                body: null,
            }).
                // eslint-disable-next-line @typescript-eslint/no-unused-vars
                then((res) => {
                    // return res.json();
                }).

                // then(async (json) => {
                //     console.log('[Done] Du lieu delete card; ', json);
                //     this.hideCardDetail();
                // }).
                catch((e) => {
                    // eslint-disable-next-line no-console
                    console.log(
                        '[Keycloak] Call API delete card FAIL',
                        e,
                    );
                });
        } else {
            // eslint-disable-next-line no-console
            console.log('[COOKIE_RESPONSE] not found => Ko gọi đc api create card');

            // this.handleOffKanban();
        }
    });
}

clickDeleteLane = (item) => () => {
    const {intl} = this.context;

    Alert.alert(
        intl.formatMessage({
            id: 'kanban.deleteLane',
            defaultMessage: 'Delete Lane',
        }),
        intl.formatMessage({
            id: 'kanban.confirmDeleteLane',
            defaultMessage: 'Are you sure you want to delete this lane?',
        }),
        [{
            text: intl.formatMessage({
                id: 'mobile.channel_list.alertNo',
                defaultMessage: 'No',
            }),
            onPress: noop,
        }, {
            text: intl.formatMessage({
                id: 'mobile.channel_list.alertYes',
                defaultMessage: 'Yes',
            }),
            onPress: () => {
                this.deleteLane(item);
            },
        }],
    );
}

clickDeleteCard = (item) => () => {
    const {intl} = this.context;

    Alert.alert(
        intl.formatMessage({
            id: 'kanban.deleteCard',
            defaultMessage: 'Delete Card',
        }),
        intl.formatMessage({
            id: 'kanban.confirmDeleteCard',
            defaultMessage: 'Are you sure you want to delete this card?',
        }),
        [{
            text: intl.formatMessage({
                id: 'mobile.channel_list.alertNo',
                defaultMessage: 'No',
            }),
            onPress: noop,
        }, {
            text: intl.formatMessage({
                id: 'mobile.channel_list.alertYes',
                defaultMessage: 'Yes',
            }),
            onPress: () => {
                this.deleteCard(item);
            },
        }],
    );
}

clickMoveCard = (card) => () => {
    this.setState({
        lane_id: card?.lane_id,
        card,
    });
    setTimeout(() => {
        this.showChooseLane();
    }, 350);
}

componentDidMount = async () => {
    const {
        actions,
        currentChannelId,
        currentTeamId,
        disableTermsModal,
        isSupportedServer,
        isSystemAdmin,
        showTermsOfService,
        skipMetrics,
    } = this.props;

    AsyncStorage.getItem(COOKIE_RESPONSE).then(async (cookies) => {
        if (cookies) {
            const cookie = getCookies(JSON.parse(cookies));
            this.setState({cookie});
        }
    });
    EventEmitter.on('leave_team', this.handleLeaveTeam);
    EventEmitter.on(TYPING_VISIBLE, this.runTypingAnimations);
    EventEmitter.on(General.REMOVED_FROM_CHANNEL, this.handleRemovedFromChannel);
    EventEmitter.on(KanbanTypes.GET_DATA_CHANNEL_KANBAN, this.getBoardCurrent);

    if (currentTeamId) {
        this.loadChannels(currentTeamId);
    } else {
        actions.selectDefaultTeam();
    }

    if (currentChannelId) {
        PushNotifications.clearChannelNotifications(currentChannelId);
        requestAnimationFrame(() => {
            actions.getChannelStats(currentChannelId);
        });
    }

    if (tracker.initialLoad && !skipMetrics) {
        actions.recordLoadTime('Start time', 'initialLoad');
    }

    if (showTermsOfService && !disableTermsModal) {
        this.showTermsOfServiceModal();
    } else if (!isSupportedServer) {
        // Only display the Alert if the TOS does not need to show first
        unsupportedServer(isSystemAdmin, this.context.intl.formatMessage);
    }

    if (!skipMetrics) {
        telemetry.end(['start:channel_screen']);
    }

    this.getBoardKanban();
}

componentDidUpdate(prevProps) {
    if (tracker.teamSwitch) {
        this.props.actions.recordLoadTime('Switch Team', 'teamSwitch');
    }

    if (prevProps.isSupportedServer && !this.props.isSupportedServer) {
        unsupportedServer(this.props.isSystemAdmin, this.context.intl.formatMessage);
    }

    if (this.props.theme !== prevProps.theme) {
        setNavigatorStyles(this.props.componentId, this.props.theme);
        EphemeralStore.allNavigationComponentIds.forEach((componentId) => {
            if (this.props.componentId !== componentId) {
                setNavigatorStyles(componentId, this.props.theme);
            }
        });
    }

    if (this.props.currentTeamId &&
        (!this.props.currentChannelId || this.props.currentTeamId !== prevProps.currentTeamId)) {
        this.loadChannels(this.props.currentTeamId);
    }

    if (this.props.currentChannelId && this.props.currentChannelId !== prevProps.currentChannelId) {
        // Thay đổi channel thì get lại dữ liệu
        this.getBoardKanban();
        PushNotifications.clearChannelNotifications(this.props.currentChannelId);

        requestAnimationFrame(() => {
            this.props.actions.getChannelStats(this.props.currentChannelId);
            this.updateNativeScrollView();
        });
    }

    if (LocalConfig.EnableMobileClientUpgrade && !ClientUpgradeListener) {
        ClientUpgradeListener = require('app/components/client_upgrade_listener').default;
    }
}

componentWillUnmount() {
    EventEmitter.off('leave_team', this.handleLeaveTeam);
    EventEmitter.off(TYPING_VISIBLE, this.runTypingAnimations);
    EventEmitter.off(General.REMOVED_FROM_CHANNEL, this.handleRemovedFromChannel);
    EventEmitter.off(KanbanTypes.GET_DATA_CHANNEL_KANBAN, this.getBoardCurrent);
}

registerTypingAnimation = (animation) => {
    const length = this.typingAnimations.push(animation);
    const removeAnimation = () => {
        const animationIndex = length - 1;
        this.typingAnimations = this.typingAnimations.filter((a, index) => index !== animationIndex);
    };

    return removeAnimation;
}

runTypingAnimations = (typingVisible) => {
    Animated.parallel(
        this.typingAnimations.map((animation) => animation(typingVisible)),
    ).start();
}

goToChannelInfo = preventDoubleTap(() => {
    const {intl} = this.context;
    const {theme} = this.props;
    const screen = 'ChannelInfo';
    const title = intl.formatMessage({id: 'mobile.routes.channelInfo', defaultMessage: 'Info'});
    CompassIcon.getImageSource('close', 24, theme.sidebarHeaderTextColor).then((source) => {
        const options = {
            topBar: {
                leftButtons: [{
                    id: 'close-info',
                    icon: source,
                    testID: 'close.channel_info.button',
                }],
            },
        };

        Keyboard.dismiss();

        showModal(screen, title, null, options);
    });
}, 1000);

handleLeaveTeam = () => {
    this.props.actions.selectDefaultTeam();
};

handleRemovedFromChannel = (channelName) => {
    const {formatMessage} = this.context.intl;

    Alert.alert(
        formatMessage({
            id: 'mobile.user_removed.title',
            defaultMessage: 'Removed from {channelName}',
        }, {channelName}),
        formatMessage({
            id: 'mobile.user_removed.message',
            defaultMessage: 'You were removed from the channel.',
        }),
    );
};

loadChannels = (teamId) => {
    const {loadChannelsForTeam, selectInitialChannel} = this.props.actions;
    if (EphemeralStore.getStartFromNotification()) {
        // eslint-disable-next-line no-console
        console.log('Switch to channel from a push notification');
        EphemeralStore.setStartFromNotification(false);
    } else {
        loadChannelsForTeam(teamId).then((result) => {
            if (result?.error) {
                this.setState({channelsRequestFailed: true});
                return;
            }

            this.setState({channelsRequestFailed: false});
            selectInitialChannel(teamId);
        });
    }
};

retryLoad = () => {
    const {currentTeamId, actions} = this.props;
    if (currentTeamId) {
        this.loadChannels(currentTeamId);
    } else {
        actions.selectDefaultTeam();
    }
}

retryLoadChannels = () => {
    this.loadChannels(this.props.currentTeamId);
};

renderLoadingOrFailedChannel() {
    const {formatMessage} = this.context.intl;
    const {
        currentChannelId,
        teamName,
        theme,
    } = this.props;

    const {channelsRequestFailed} = this.state;
    if (!currentChannelId) {
        if (channelsRequestFailed) {
            const FailedNetworkAction = require('app/components/failed_network_action').default;
            const title = formatMessage({id: 'mobile.failed_network_action.teams_title', defaultMessage: 'Something went wrong'});
            const message = formatMessage({
                id: 'mobile.failed_network_action.teams_channel_description',
                defaultMessage: 'Channels could not be loaded for {teamName}.',
            }, {teamName});

            return (
                <FailedNetworkAction
                    errorMessage={message}
                    errorTitle={title}
                    onRetry={this.retryLoadChannels}
                    theme={theme}
                />
            );
        }

        const Loading = require('app/components/channel_loader').default;
        return (
            <Loading
                channelIsLoading={true}
                color={theme.centerChannelColor}
                retryLoad={this.retryLoad}
            />
        );
    }

    return null;
}

showTermsOfServiceModal = async () => {
    const {intl} = this.context;
    const {isSupportedServer, isSystemAdmin, theme} = this.props;
    const screen = 'TermsOfService';
    const title = intl.formatMessage({id: 'mobile.tos_link', defaultMessage: 'Terms of Service'});
    CompassIcon.getImageSource('close', 24, theme.sidebarHeaderTextColor).then((closeButton) => {
        const passProps = {
            closeButton,
            isSupportedServer,
            isSystemAdmin,
        };
        const options = {
            layout: {
                componentBackgroundColor: theme.centerChannelBg,
            },
            topBar: {
                visible: true,
                height: null,
                title: {
                    color: theme.sidebarHeaderTextColor,
                    text: title,
                },
            },
        };

        showModalOverCurrentContext(screen, passProps, options);
    });
};

updateNativeScrollView = () => {
    EventEmitter.emit(UPDATE_NATIVE_SCROLLVIEW, this.props.currentChannelId);
};

goToThread = (card) => {
    // console.log('post138; ', JSON.stringify(post));
    telemetry.start(['post_list:thread']);
    const {actions, currentChannelId} = this.props;

    const channelId = currentChannelId;
    const rootId = (card?.thread_id || card?.root_id);
    const title = '';
    const passProps = {
        card,
        channelId,
        rootId,
    };

    // eslint-disable-next-line no-console
    console.log('passProps:goToThread ', passProps);
    Keyboard.dismiss();
    actions.getPostThread(rootId);
    actions.selectPost(rootId);

    requestAnimationFrame(() => {
        goToThreadScreen(title, passProps);
    });
};

clickItem = (card) => () => {
    this.setState({
        card,
        lane_id: card?.lane_id,

        // modalKanbanVisible: true,
    });
    this.goToThread(card);

    // this.showCardDetail();
}

showChooseLane = () => {
    this.setState({modalChooseLaneVisible: true});
}

hideChooseLane = () => {
    this.setState({modalChooseLaneVisible: false});
}

showCardDetail = () => {
    this.setState({modalKanbanVisible: true});
}

hideCardDetail = () => {
    this.setState({modalKanbanVisible: false, isAddCard: false});
}

showModalAddCard = (lane) => () => {
    // eslint-disable-next-line no-console
    console.log('lane add card: ', JSON.stringify(lane));
    this.setState({
        lane_id: lane?.lane_id, isAddCard: true,
    });
    setTimeout(() => {
        this.setState({modalKanbanVisible: true});
    }, 350);
}

hideModalAddCard = () => {
    this.setState({modalKanbanVisible: false, isAddCard: false});
}

renderEmptyComponent = (lane) => {
    const {intl} = this.context;
    return (<View style={style.ev1}>
        <FastImage
            tintColor={'#1b2c3e'}
            style={style.icon}
            source={require('@assets/images/emptyBox.png')}
        />
        <TouchableOpacity
            onPress={this.showModalAddCard(lane)}
            style={style.ev2}
        >
            <Text style={style.ev3}>{intl.formatMessage({id: 'kanban.emptyText', defaultMessage: 'Does not exist any card!'})}</Text>
            <Text style={style.ev4}>{intl.formatMessage({id: 'kanban.addCardNow', defaultMessage: 'Add card now'})}</Text>
        </TouchableOpacity>
    </View>);
}

renderAvatarUser = (member, idx) => {
    return (member?.avatar ? <FastImage
        key={idx}
        source={{
            uri: member?.avatar,
            headers: {cookie: this.state.cookie},
        }}
        resizeMode='contain'
        style={style.v15}
    /> :
        (<View
            key={idx}
            style={style.v14}
        >
            <Text style={style.v13}>{member.username[0]}</Text>
        </View>)
    );
}

renderAssignUsers = (item) => {
    // eslint-disable-next-line no-console
    // console.log('item?.assignUsersFull: ', item?.assignUsersFull, ' member: ', this.props.members);
    return (
        size(item?.assignUsersFull) > 0 ?
            <View style={style.v12}>
                {
                    // eslint-disable-next-line react/jsx-closing-bracket-location
                    map(item?.assignUsersFull, ((member, idx) => {
                        if (idx <= 4) {
                            return (this.renderAvatarUser(member, idx));
                        }
                        if (idx === 5) {
                            return (<View
                                key={idx}
                                style={style.v14}
                            // eslint-disable-next-line react/jsx-closing-bracket-location
                            >
                                <Text style={style.v13}>{`+${size(item?.assignUsersFull) - 5}`}</Text>
                            </View>);
                        }
                        return null;
                    }))
                }
            </View> : null
    );
};

renderCardContent = (item) => {
    return (
        <TouchableOpacity
            key={item?.card_id}
            activeOpacity={0.5}
            onPress={this.clickItem(item)}
            style={style.v1}
        >
            <View style={style.v2}>
                <View style={style.v3}>
                    <Text
                        numberOfLines={1}
                        style={style.v4}
                    >{item?.name}</Text>
                </View>
                <View style={{flexDirection: 'row'}}>
                    <TouchableOpacity
                        onPress={this.clickMoveCard(item)}
                        style={style.v5}
                    >
                        <FastImage
                            tintColor={'#1b2c3e'}
                            style={style.iconMoveCard}
                            source={require('@assets/images/ic_move_card.png')}
                        />
                    </TouchableOpacity>
                    <TouchableOpacity
                        onPress={this.clickDeleteCard(item)}
                        style={style.v5}
                    >
                        <CompassIcon
                            name='trash-can-outline'
                            size={16}
                            color={'#1b2c3e'}
                            style={style.v6}
                        />
                    </TouchableOpacity>
                </View>
            </View>
            {this.renderAssignUsers(item)}
            <View style={style.v7}>
                <Text
                    numberOfLines={3}
                    style={style.v8}
                >{item?.description}</Text>
            </View>
            {
                item?.tags ? <View style={style.v9}>
                    {
                        // eslint-disable-next-line react/jsx-closing-bracket-location
                        map(item?.tags, ((obj, index) => {
                            return (
                                <View
                                    key={index}
                                    style={[style.v10, {backgroundColor: tagToColor(obj)}]}
                                >
                                    <Text
                                        numberOfLines={1}
                                        style={style.v11}
                                    >{obj}</Text>
                                </View>
                            );
                        }))
                    }
                </View> : null
            }

        </TouchableOpacity>
    );
}

renderAddCardUI = (lane) => {
    return (
        <TouchableOpacity
            onPress={this.showModalAddCard(lane)}
            style={style.addCardBtn}
        >
            <FastImage
                tintColor={'#1b2c3e'}
                style={style.iconTini}
                source={require('@assets/images/add_card.png')}
            />
        </TouchableOpacity>);
}

renderRightHeaderEmptyColumn = (lane) => {
    return (
        <TouchableOpacity
            onPress={this.clickDeleteLane(lane)}
            style={style.addCardBtn}
        >
            <CompassIcon
                name='trash-can-outline'
                size={16}
                color={'#1b2c3e'}
                style={style.v6}
            />
        </TouchableOpacity>
    );
}

renderKanban = () => {
    // console.log('!!!!!-------dataKanban ', JSON.stringify(this.state.dataKanban));
    return (size(this.state.dataKanban) > 0 ? <View style={style.main}>
        <Board
            boardRepository={new BoardRepository(this.state.dataKanban)}
            emptyIconColor={'#1b2c3e'}
            boardBackground={'#fff'}

            // emptyText={intl.formatMessage({ id: 'kanban.emptyText', defaultMessage: 'Does not exist any card!' })}
            columnBackgroundColor={'#dddddd'}
            columnNameTextColor={'#1b2c3e'}
            columnNameFontSize={16}
            columnHeight={height - 80}
            badgeHeight={20}
            badgeWidth={20}
            badgeBorderRadius={8}
            badgeTextFontSize={10}
            badgeBackgroundColor={'#F01E24'}
            // eslint-disable-next-line @typescript-eslint/no-empty-function
            onDragEnd={() => { }}
            // eslint-disable-next-line @typescript-eslint/no-empty-function
            open={() => { }}
            cardContent={this.renderCardContent}
            viewRightHeaderColumn={this.renderAddCardUI}
            viewRightHeaderEmptyColumn={this.renderRightHeaderEmptyColumn}
            emptyComponent={this.renderEmptyComponent}
        />
    </View> : <></>);
}

render() {
    // Overriden in channel.android.js and channel.ios.js
    // but defined here for channel_base.test.js
    return; // eslint-disable-line no-useless-return
}

}

export const style = StyleSheet.create({
addCardBtn: {padding: 4, borderRadius: 4},
flex: {flex: 1},
icon: {width: 50, height: 50},
iconTini: {width: 20, height: 20},
iconMoveCard: {width: 18, height: 18},
main: {width: '100%', flex: 1},
ev1: {flex: 1, width: '100%', alignItems: 'center', justifyContent: 'center'},
ev2: {paddingVertical: 4},
ev3: {fontSize: 13, color: '#1b2c3e', textAlign: 'center'},
av4: {fontSize: 12, color: '#1b2c3e', textAlign: 'center', paddingVertical: 4},
ev4: {textDecorationStyle: 'solid', textDecorationLine: 'underline', fontSize: 14, color: '#1b2c3e', textAlign: 'center', paddingHorizontal: 16, paddingVertical: 4},
v1: {backgroundColor: '#fff', marginBottom: 8, padding: 8, borderRadius: 4},
v2: {width: '100%', borderBottomWidth: 0.5, borderBottomColor: '#00000050', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between'},
v3: {flex: 1},
v4: {paddingBottom: 4, fontSize: 13, fontWeight: 'bold', color: '#000'},
v5: {alignItems: 'center', paddingBottom: 4},
v6: {paddingLeft: 16},
v7: {width: '100%'},
v8: {paddingVertical: 4, fontSize: 13, color: '#000'},
v9: {width: '100%', flexDirection: 'row', flexWrap: 'wrap'},
v12: {width: '100%', flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'flex-end', alignItems: 'center', paddingTop: 8},
v10: {
alignItems: 'center',
justifyContent: 'center',
marginRight: 4,
marginTop: 4,
borderRadius: 4,
overflow: 'hidden',
},
v11: {paddingHorizontal: 4, paddingVertical: 3, color: '#fff', fontSize: 12},
v13: {paddingHorizontal: 4, paddingVertical: 3, color: '#162A4C', fontSize: 10, textTransform: 'uppercase'},
v14: {backgroundColor: '#CCCCCC80', width: 24, height: 24, borderRadius: 12, alignItems: 'center', justifyContent: 'center', marginRight: 2},
v15: {width: 24, height: 24, borderRadius: 12, backgroundColor: '#ccc', marginRight: 2},
});
`

from react-native-draganddrop-board.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.