В loklak apps добавлен World Mood Tracker с возможностью отображения агрегированных данных из классификатора эмоций loklak server. Следующим шагом в приложении было добавление функции отображения потока твитов из страны по мере их обнаружения локлаком. С добавлением потокового сервлета в loklak его можно было использовать в этом приложении.

В этом сообщении блога я расскажу о шагах, предпринятых при добавлении этой функции в приложение World Mood Tracker.

Реквизит для WorldMap компонента

Компонент WorldMap содержит вид карты, отображаемой в приложении. Здесь выполняются вызовы API к конечной точке классификатора, а результаты отображаются на карте. Чтобы отображать твиты при нажатии на страну, нам нужно определить свойства реакции, чтобы можно было вызывать методы из компонентов более высокого уровня.

Чтобы включить реквизиты, нам нужно изменить конструктор для компонента -

export default class WorldMap extends React.Component {
    constructor(props) {
        super(props);
        ...
    }
    ...
}

Теперь мы можем передать метод из родительского компонента, чтобы включить потоковую передачу, а другие компоненты могут закрыть поток, используя в них реквизиты -

export default class WorldMoodTracker extends React.Component {
    ...
    showStream(countryName, countryCode) {
        /* Do something to enable streaming component */
        ...
    }
 
    render() {
        return (
             ...
                <WorldMap showStream={this.showStream}/>
             ...
        )
    }
}

Определение действий при нажатии на карту страны

Как упоминалось в предыдущем сообщении в блоге, World Mood Tracker использует Datamaps для визуализации данных на карте. Чтобы запустить фрагмент кода при щелчке по стране, мы можем использовать метод готово экземпляра Datamaps. Здесь мы используем пропс, переданный ранее -

done: function(datamap) {
    datamap.svg.selectAll('.datamaps-subunit').on('click', function (geography) {
        props.showStream(geography.properties.name, reverseCountryCode(geography.id));
    })
}

Имя и идентификатор страны будут использоваться для отображения имени и вызова API для конечной точки потока соответственно.

Компонент StreamOverlay

Компоненты StreamOverlay содержат все утилиты для отображения потока твитов от loklak. Этот компонент используется из его родительских компонентов, состояние которых содержит информацию об отображении этого компонента -

export default class WorldMoodTracker extends React.Component {
    ...
    getStreamOverlay() {
        if (this.state.enabled) {
            return (<StreamOverlay
                show={true} channel={this.state.channel}
                country={this.state.country} onClose={this.onOverlayClose}/>);
        }
    }

    render() {
        return (
            ...
                {this.getStreamOverlay()}
            ...
        )
    }
}

Соответствующие переданные реквизиты используются для рендеринга компонента и подключения к потоку с сервера loklak.

Создание модального наложения

При щелчке по карте отображается наложение. Для отображения этого оверлея используется react-overlays. Модальный компонент, предлагаемый пакетами, обеспечивает очень простой интерфейс для определения дизайна и интерфейса компонента, включая стиль, onclose ловушку и т. Д.

import {Modal} from 'react-overlays';

<Modal aria-labelledby='modal-label'
    style={modalStyle}
    backdropStyle={backdropStyle}
    show={true}
    onHide={this.close}>
    <div style={dialogStyle()}>
        ...
    </div>
</Modal>

Следует отметить, что modalStyle и backdropStyle являются объектами стиля React.

Стиль диалога

Стиль диалога определен таким образом, чтобы предоставить некоторое пространство вверху, щелкнув там, где наложение закрывается. Для этого используются единицы высоты по вертикали -

const dialogStyle = function () {
    return {
        position: 'absolute',
        width: '100%',
        top: '5vh',
        height: '95vh',
        padding: 20
        ...
    };
};

Подключение к локлаку Tweet Stream

loklak отправляет события, отправленные сервером, клиентам, подключенным к нему. Чтобы использовать этот поток, мы можем использовать изначально поддерживаемый объект EventSource. Поток событий запускается методом рендеринга компонента StreamOverlay -

render () {
    this.startEventSource(this.props.channel);
    ...
}

Этот канал используется для подключения к twitter/country/<country-ID> каналу в потоке, а затем его можно передать конструктору EventStream. При получении сообщения список твитов добавляется и позже отображается в представлении -

startEventSource(country) {
    let channel = 'twitter%2Fcountry%2F' + country;
    if (this.eventSource) {
        return;
    }
    this.eventSource = new EventSource(host + '/api/stream.json?channel=' + channel);
    this.eventSource.onmessage = (event) => {
        let json = JSON.parse(event.data);
        this.state.tweets.push(json);
        if (this.state.tweets.length > 250) {
            this.state.tweets.shift();
        }
        this.setState(this.state);
    };
}

Размер списка здесь ограничен 250, поэтому, когда приходит новый твит, самый старый удаляется. А благодаря быстрым действиям DOM в React рендеринг не занимает много времени.

Рендеринг твитов

Твиты отображаются в виде простых карточек, щелкнув по которым пользователь может открыть их в Твиттере в новой вкладке. Он содержит основную информацию о твите - экранное имя и текст твита. Изображения не отображаются, так как нет смысла загружать их, когда твиты приходят с высокой частотой.

function getTweetHtml(json) {
    return (
        <div style={{padding: '5px', borderRadius: '3px', border: '1px solid black', margin: '10px'}}>
            <a href={json.link} target="_blank">
            <div style={{marginBottom: '5px'}}>
                <b>@{json['screen_name']}</b>
            </div>
            <div style={{overflowX: 'hidden'}}>{json['text']}</div>
            </a>
        </div>
    )
}

Они отображаются с использованием простой карты в методе рендеринга компонента StreamOverlay -

<div className={styles.container} style={{'height': '100%', 'overflowY': 'auto',
    'overflowX': 'hidden', maxWidth: '100%'}}>
    {this.state.tweets.reverse().map(getTweetHtml)}
</div>

Закрытие оверлея

С предыдущей настройкой мы теперь можем видеть твиты из бэкэнда loklak по мере их поступления. Но проблема в том, что мы все равно будем подключены к потоку, когда закроем модальное окно. Кроме того, нам нужно будет закрыть оверлей родительского компонента, чтобы остановить его рендеринг.

Мы можем использовать метод onclose для модального здесь -

close() {
    if (this.eventSource) {
        this.eventSource.close();
        this.eventSource = null;
    }
    this.props.onClose();
}

Здесь props.onClose() отключает рендеринг StreamOverlay в родительском компоненте.

Вывод

В этом сообщении блога я объяснил, как поток реквизитов используется в приложении World Mood Tracker для включения и выключения потоковой передачи в наложении, определенном с помощью наложений с реакцией. Эта функция показывает базовую настройку для использования недавно представленного потокового API в loklak.

Мотивация такого приложения была взята из emojitracker by mroth, как упоминалось в fossasia / labs.fossasia.org # 136. Изменения были предложены в fossasia / apps.loklak.org # 315 пользователем @singhpratyush (мной).

Доступ к приложению можно получить в режиме реального времени по адресу https://singhpratyush.github.io/world-mood-tracker/index.html.

Ресурсы

Первоначально опубликовано на blog.fossasia.org 1 сентября 2017 г.