Skip to content
This repository has been archived by the owner on Oct 1, 2019. It is now read-only.

All used tags by type #926

Open
1 of 8 tasks
xekc opened this issue Oct 26, 2017 · 5 comments
Open
1 of 8 tasks

All used tags by type #926

xekc opened this issue Oct 26, 2017 · 5 comments
Assignees

Comments

@xekc
Copy link

xekc commented Oct 26, 2017

Concept design

2017-mlbf4

In this concept interface user is able to see an alphabetical list of all hashtags on the site. You can See alphabetical sub-headers and then alphabetical list of all tags with counters (used times).

Implementation

  • We will do English only for now.

  • We need client-side implementation for this. @Oopscurity you'll need to work with the picture above, please mind the horizontal sizes (well, basically all sizes, but sidebar width is crucial) are done well.

    • If letter has no tags used it shouldn't be visible at all.
    • Text opacity is 90%, goes to 100% on hover.
  • (COULD Have) We'll likely need auto-load on scrolling here. @Oopscurity can you do it?

  • @voidxnull we'll need server side / data work to display all tags as pictured on those pictures. First implementation can have only tags output, or you can do both left and right sides of the picture together (then when you click on a tag you see all posts tagged with in, most recent first).

  • @indeyets ideally it would be great to work with your input on possible optimal implementation architecture here?

  • @voidxnull we'll need development and integration of the same list for School tags and Location tags. Just alphabetical output, code must be rather close to tag clouds pages code?

Integration

This sidebar with full tags list by type will be developed further with added filters (show only my own tags, show only tags from Europe etc.) and further selection features. The point of going to sidebar for the user is to explore content in various perspectives that he finds relevant to his situation.

We will call this sidebar from random pages. We'll want request operators to be implemented - so that the list of tags that opens in sidebar is pre-filtered by URL parameters, sorted not alphabetically but by last modified, by number of user engagements. That will follow in further tasks. Right now we need a solid client side + basically the same server side that tag clouds have, revised and re-thought through in new context (how would "Load more" work if there's 100k tags?).

@artkravchenko
Copy link
Member

artkravchenko commented Nov 19, 2017

@voidxnull, @indeyets, @xekc,

Насколько я понимаю, подобный интерфейс будет существовать для всех видов тегов. Кроме того, в скором времени будет применяться поиск, а также фильтрация по подпискам со стороны групп пользователей (друзей, например).

Предлагаю создать контроллер вида /tags/all (по аналогии с /posts/all), который может выдавать или сплошной массив значений (тегов), или их группы, сформированные по какому-либо признаку (интерфейс слева на скриншоте). Таким образом, значением "верхнего уровня" является либо тэг, либо группа тэгов. Группа выглядит подобным образом:

type TagGroup<T> = {
  count:   number,    // число всех тэгов, приналеджащих группе
  entries: Array<T>,  // массив тэгов с числом элементов N <= query.group_limit
  offset:  number,
  key:     string,    // признак группировки
  value:   string     // значение по ключу key, общее для тэгов в группе
          // (в случае с query.group_by === 'first_letter' обозначает заголовок группы)
}

Отсюда следующие query-параметры:

  • group_by - назначает группировку по первой букве названия group_by=first_letter, местоположению и т. д.; если используется, ответ в виде массива групп (объекты заданного вида с тэгами внутри), иначе в виде массива значений (тэгов);
  • sort - сортировка значений верхнего уровня, т. е. групп, если используется group_by, или тегов. Может выглядеть как sort=-first_letter для групп или, например, sort=-updated_at для тэгов;
  • group_sort - сортировка значений внутри группы; например, group_sort=-post_count; применимо, если используется параметр group_by;
  • type - тип тегов в выдаче; например, type=hashtag;
  • limit - максимальное количество значений верхнего уровня в одном ответе: если используется group_by, максимальное число групп в одном ответе, иначе максимальное количество тегов; по умолчанию 3-5 для групп или ... (сколько, @xekc ?) для тегов.
  • group_limit - максимальное число значений внутри группы, если используется group_by; по умолчанию 10;
  • query или q - поисковый запрос по названию (?) тэга;
  • offset - пропуск опр. числа первых значений верхнего уровня;

Позже появится фильтрация по пользователям:

  • followers - подписчики тэгов; например, me для текущего пользователя, friends для любого из его друзей или id конкретного пользователя; суммируется (может быть массивом);
  • likers - аналогично followers, только относится к лайкам.

Тогда запрос внутрь категории хэштэгов, собранной по первой букве названия, может быть выполнен следующим образом:

GET /api/v1/tags/all?q=A&sort=-q&type=hashtag

Запросим группированный список:

GET /api/v1/tags/all?group_by=first_letter&group_sort=-post_count&sort=-first_letter&type=hashtags

В рамках store результат может выглядеть примерно так:

store = {
  rivers: {
    sidebar_tags: {
      queries: {
        'group_by=first_letter&group_sort=-post_count&sort=-first_letter&type=hashtags': [
          {
            count: 20,
            entries: ['uuid_1', 'uuid_2'],
            key: 'starts_with',
            value: 'A'
          }
        ],
        // дополняемый массив, используемый на странице отдельной группы
        'sort=-post_count&starts_with=A&type=hashtags': [
          'uuid_1',
          'uuid_2'
        ]
      }
    }
  },
  hashtags: {
    'uuid_1': {},
    'uuid_2': {}
  }
}

В целом из-за будущего внедрения поиска и фильтрации здесь, вероятно, имеет смысл провести рефакторинг существующего клиентского кода, обслуживающего поисковую функциональность, чтобы осуществлять code sharing. Во всяком случае в store для кэширования результатов.

@voidxnull
Copy link
Member

voidxnull commented Nov 19, 2017

@Oopscurity
Если често, мне не нравится один большой контроллер. В частности, параметр type вместо трех котроллеров по типу. Для отдельных контроллеров точно так же можно сократить копипасту выносом общего кода. Поиск по всем типам тегов одновременно (кроме общего поиска по всем сущностям), как я понимаю, не нужен? Со всем остальным согласен.

Еще думаю что не стоит использовать query string как ключ в объекте: сложно будет отлаживать, когда порядок параметров где-нибудь случайно поменяться. Можно использовать объект как ключ, но тогда придется менять сериализацию store, т.к. json этого не поддерживает.

@artkravchenko
Copy link
Member

@voidxnull,

Поиск по всем типам тегов одновременно (кроме общего поиска по всем сущностям), как я понимаю, не нужен?

Вроде бы, не нужен. @xekc, стоит рассчитывать на появление этого в будущем?

не стоит использовать query string как ключ в объекте

Только что проверил: this.context.router.location.query (или this.props.location.query для routes) является объектом с упорядоченными по алфавиту ключами. Например, для

?b=b&cb=c&c=c&ca=c&a=a

результатом вызова Object.keys(this.props.location.query) является

["a", "b", "c", "ca", "cb"]

С другой стороны, мы можем считать поступающие в reducer данные априори не упорядоченными и исправлять эту ситуацию самим, попутно выкидывая лишние свойства (limit и др. - см. пример).

@artkravchenko
Copy link
Member

@xekc,

  • (COULD Have) We'll likely need auto-load on scrolling here. @Oopscurity can you do it?

Right now we need a solid client side + basically the same server side that tag clouds have, revised and re-thought through in new context (how would "Load more" work if there's 100k tags?)

Basically, we need to perform a bunch of optimizations to support real infinite scrolling when there are many elements to be rendered. After some investigation of the field, I have to say there aren't many possible ready-to-use open-source solutions and all of them have caveats. The task's complexity actually depends on the requirements and use cases such as support the scrolling to the given item in the river.

For example, it's important to know exact size (height) of the river elements before rendering them and it's recommended not to change their size dynamically (especially with screen size change) for the performance reasons.

react-list library seems the most suitable of the solutions. I'll use it to implement infinite scrolling here (#926). Most likely we'd like to migrate our existing rivers of posts to the scenario further since the performance of long ones is terrible.

@artkravchenko
Copy link
Member

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

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

Какое максимальное количество элементов может находиться на одной странице? (Ты говорил, что вполне может быть и более ста.) Планируется ли для списков тегов также вариант с автоматической загрузкой, а для категорий - с постраничным разделением?

Планируется ли использование клавиатуры для взаимодействия с элементами, как мы это видим в концепте публикаций?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants