Программы Академии для VK mini-app
Здесь сложнее, чем с заездами
1. Контент страницы "Академия"
Ручка (со слешом на конце)
POST
https://apicms.tavrida.art/api/block/list/public/
https://demo.tavrida-cms-backend.kube.aventica.tech/api/swagger-ui/static/index.html
Сваггер ЦМС, на продакшен не деплоится, поэтому ссылка на демо.
Тело запроса
{
"ids": [ "66c2f122-ff22-4e50-8f92-9b342c50c6ed" ] // blockId
}
Текущий blockId для страницы Академия 2024 | 2 мая, 02:26
- 66c2f122-ff22-4e50-8f92-9b342c50c6ed
. При смене страницы придется прописать другой id в запросе.
Ответ
{
"result": {
"blocks": [
{
"id": "66c2f122-ff22-4e50-8f92-9b342c50c6ed", // тот самый blockId
"content": {
"data": {
"pageSettings": {
"multipleEvents": {
"ids": [
"ad03c794-4144-4b8d-82bb-a5f8e0b4e04b",
"ca0aa10a-b3f1-44f8-aa02-6b3d9425bfa6",
"441d587b-add8-4b07-aa0c-62175f21bdc4"
]
}
}
}
}
}
]
}
}
Если зарыться сюда, можно получить список Event.ID, которые являются программами Академии.
2. Подтянуть ивенты из АИС
Ручка POST https://api.tavrida.art/graphql
, см подробнее про GraphQL
Метод eventList
Метод не поддерживает пагинацию больше 30, поэтому в запрос нужно положить несколько query. 0-29, 30-59, и т.д.
Пример, как это реализовано на юзер-фронте
/** @param { Object } opts
* @param { string[] } eventIds
*
* @returns { import('../types/tavrida.js').Tavrida.Event } */
async getMultipleEvents({
eventIds
}) {
const maxLimit = 30
const buildQuery = ({
offset,
name,
}) => `${name}: eventList${GraphQLArguments.stringify({
IDs: eventIds ?? null,
pagination: {
offset,
limit: maxLimit,
}
})} {
nodes {
ID,
name,
beginsAt,
endsAt,
active,
registrationBeginsAt,
registrationEndsAt,
type,
}
}`
const steps = eventIds ? Math.ceil(eventIds.length / maxLimit) : 1
const multipleQueries = []
for (let i = 0; i < steps; i++) {
const offset = i * maxLimit
multipleQueries.push(buildQuery({
offset,
name: `events${offset}`,
}))
}
const query = `query events {
${multipleQueries.join('')}
}`
const request = new GraphQLRequest({
query,
})
await request.run()
if (!request.isSuccessful) {
throw new ErrorWithProps(request.errorMessage, {
from: 'api.getMultipleEventsByIds'
})
}
const result = []
for (let i = 0; i < steps; i++) {
const offset = i * maxLimit
const nodes = request.data[`events${offset}`]?.nodes
if (!Array.isArray(nodes)) {
throw new ErrorWithProps('One of pieces of GraphQL response was bad', {
from: 'api.getMultipleEventsByIds',
nodes,
offset,
data: request.data,
})
}
nodes.forEach(it => result.push(it))
}
return result
}
Что приходит в ответ
Можно понять по полям GraphQL
3. Коллекция программ в CMS
Нужна та же ручка, что в шаге с получением контента страницы:
POST
https://apicms.tavrida.art/api/block/list/public/
Тело запроса
{
"ids": [ "44ff599f-f72f-4c7c-8bc0-ae8a495f7495" ] // blockId
}
Актуальный blockId коллекции Программы Академии 2024 | 27 апр., 02:50
- 44ff599f-f72f-4c7c-8bc0-ae8a495f7495
Ответ
{
"result": {
"blocks": [
{
"id": "44ff599f-f72f-4c7c-8bc0-ae8a495f7495", // тот же самый blockId
"data": {
"items": [
{
"id": "132", // id в коллекции, это нам не нужно
"eventId": "cf8be064-6705-44e4-bae6-33758e949543", // eventId
// ... и еще куча полей
}
]
}
}
]
}
}
Каждый итем имеет поле eventId
, по которому можно его контент заджойнить в Event из АИС.
Обратите внимание, что в CMS name - это объект с переводами. В отличие от АИС, где name - строка.
const textByLocale = {
RU: 'Программа такая-то',
EN: 'Some academy program'
}
Интерфейс коллекции на typescript
Итем любой возможной коллекции
export interface CollectionItem {
id: string;
hidden: boolean;
createdAt: string;
name: Record<string, string>;
}
Итем любой коллекции Ивентов АИС
export interface EventFromCMS extends CollectionItem {
eventId?: string;
}
Итем коллекции конкретно программ Академии
export interface AcademyProgramFromCMS extends EventFromCMS {
_meta?: CollectionItemMeta;
image?: FileCMS;
/**
* Цвет карточки или обложки программы/онлайн-курса академии.
* На юзер-фронте каждому цвету отсюда должен соответствовать secondary цвет графического элемента
* (сделанный через опасити или как другой secondary цвет)
* */
color?: string;
/**
* Выбирается id графического элемента. Приходит как строка '1' / '2' / и т.д.
* */
graphicElement?: string;
/** id сложности из другой коллекции */
difficulty?: string;
/** Флаг.
* Если true - карточка считается онлайн-курсом */
isOnline?: boolean;
/** Флаг.
* Если true, выведется плашка "Новый".
* Возможно пригодится для фильтрации в будущем. */
isNew?: boolean;
externalRegistrationLink?: string;
/** Массив плашек. */
bars?: {
text: Record<string, string>;
}[];
/** Краткое описание */
anounce?: string;
/** Массив ID категорий из коллекции */
tagIds?: string[];
bottomBars?: {
icon?: CMSIcon.Pure,
text: Record<string, string>;
}[];
/** Серые карточки под обложкой.
* Обе деталки.
* */
infoBlocks?: {
graphicElement: string;
title: Record<string, string>;
text: Record<string, string>;
}[],
about?: {
hidden: boolean;
image?: FileCMS;
title: Record<string, string>;
text: Record<string, string>;
};
forWhom?: {
hidden: boolean;
title: Record<string, string>;
cards: {
title: Record<string, string>;
description: Record<string, string>;
color: string;
graphicElement: string;
}[];
};
persons?: SliderPersons.Module;
producers?: {
hidden: boolean;
title: Record<string, string>;
list: {
image?: FileCMS;
title: Record<string, string>;
text: Record<string, string>;
}[];
};
whatWillYouGet?: {
hidden: boolean;
title: Record<string, string>;
content: {
title: Record<string, string>;
text: Record<string, string>;
img?: FileCMS;
}[];
};
path?: {
hidden: boolean;
title: Record<string, string>;
steps: {
title: Record<string, string>;
text: Record<string, string>;
}[];
};
program?: {
hidden: boolean;
title: Record<string, string>;
bars: {
icon: CMSIcon.Pure,
text: Record<string, string>;
color: string;
}[];
prefix: Record<string, string>;
list: {
title: Record<string, string>;
description: Record<string, string>;
bars: {
text: Record<string, string>;
}[];
}[];
};
faq?: Omit<Faq.Module, 'title'>;
showBanner?: boolean;
}
4. Коллекция направлений
Нужна та же ручка, что в шаге с получением контента страницы:
POST
https://apicms.tavrida.art/api/block/list/public/
Тело запроса
{
"ids": [ "44ff599f-f72f-4c7c-8bc0-ae8a495f7495" ] // blockId
}
Актуальный blockId коллекции Направления программ Академии | 9 июл., 21:09
- 2a516897-fcf6-400c-82e0-dcece038ced3
Джойн с объектами программ
У программы, если она успешно заджойнилась с элементом коллекции, есть поле:
categoryIds: string[];
Каждый из этих ID соответствует полю id
у объекта направления. Можно джойнить.
Можно получить и коллекцию, и контент страницы одним запросом.
{
"ids": [
"66c2f122-ff22-4e50-8f92-9b342c50c6ed", // blockId страницы
"44ff599f-f72f-4c7c-8bc0-ae8a495f7495", // blockId коллекции
"2a516897-fcf6-400c-82e0-dcece038ced3" // blockId коллекции направлений
]
}
Тогда в ответе в массиве result.blocks
будут все три объекта.
5. Подытог
- либо тремя запросами, либо одним совмещенным достать публичный контент трех схем:
по ручке POST https://apicms.tavrida.art/api/block/list/public/
-- коллекции Программы Академии | ...
-- страницы Академия | ...
-- коллекции Направления программ Академии | ...
- подтянуть из АИС с помощью GraphQL query мероприятия, ID которых указаны в
pageSettings
страницыАкадемия | ...
- заджойнить элементы коллекции
Программы Академии
поItemFromCMS.eventId
к Ивентам АИС поEvent.ID
- заджойнить элементы коллекции
Направления программ Академии
поItemFromCMS.id
к элементам коллекции поItemFromCMS.categoryIds[]