From 0d249d982ffbf3f6b3f3fe7a1833620e31245595 Mon Sep 17 00:00:00 2001 From: Alexander Solovev Date: Thu, 5 Oct 2023 13:21:31 +0300 Subject: [PATCH 1/4] Update cookies helper --- .../theme-provider/theme-provider.jsx | 6 +--- src/app/common/utils/helpers/cookies.js | 34 ++++++++++++++++--- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/app/common/providers/theme-provider/theme-provider.jsx b/src/app/common/providers/theme-provider/theme-provider.jsx index 85b3228e..eb4a397f 100644 --- a/src/app/common/providers/theme-provider/theme-provider.jsx +++ b/src/app/common/providers/theme-provider/theme-provider.jsx @@ -71,7 +71,7 @@ class ThemeProvider extends React.Component { updateTheme(theme) { this.applyTheme(theme); - cookies.set({ name: themeCookieName, value: theme, options: { domain: this.documentationDomain } }); + cookies.set({ name: themeCookieName, value: theme }); this.darkQuery.removeListener(this.applySystemTheme); } @@ -81,10 +81,6 @@ class ThemeProvider extends React.Component { this.updateTheme(newTheme); } - get documentationDomain() { - return window.location.hostname.split('.').slice(-2).join('.'); - } - render() { return ( diff --git a/src/app/common/utils/helpers/cookies.js b/src/app/common/utils/helpers/cookies.js index 54d9db84..facb162e 100644 --- a/src/app/common/utils/helpers/cookies.js +++ b/src/app/common/utils/helpers/cookies.js @@ -1,28 +1,52 @@ +const DEFAULT_OPTIONS = { + domain: window.location.hostname.split('.').slice(-2).join('.'), +}; + const getCookie = ({ name }) => { const regex = `(?:^|; )${name.replace(/([.$?*|{}()[\]\\/+^])/g, '\\$1')}=([^;]*)`; const matches = document.cookie.match(new RegExp(regex)); return matches ? decodeURIComponent(matches[1]) : undefined; }; -const setCookie = ({ name, value, options = { path: '/' } }) => { +const setCookie = ({ + name, + value, + options = {}, +}) => { const encodedValue = encodeURIComponent(value); let updatedCookie = `${name}=${encodedValue}`; - if (!options.expires) { + const updatedOptions = { + ...DEFAULT_OPTIONS, + ...options, + }; + + if (!updatedOptions.expires) { const date = new Date(); date.setFullYear(2100); - options.expires = date.toUTCString(); + updatedOptions.expires = date.toUTCString(); } - Object.keys(options).forEach(propKey => { - const propValue = options[propKey]; + Object.keys(updatedOptions).forEach(propKey => { + const propValue = updatedOptions[propKey]; updatedCookie += `; ${propKey}=${propValue}`; }); document.cookie = updatedCookie; }; +const removeCookie = ({ name }) => { + setCookie({ + name, + value: '', + options: { + expires: new Date(0).toUTCString(), + }, + }); +}; + export default { get: getCookie, set: setCookie, + remove: removeCookie, }; From 94e164e2d50834d64f45b2459aa58eeaddb91e5b Mon Sep 17 00:00:00 2001 From: Alexander Solovev Date: Thu, 25 Jan 2024 12:43:44 +0300 Subject: [PATCH 2/4] Add sidebar method groups sorting --- src/app/common/services/sort-service.js | 29 +++++++++++++++++++ src/app/components/app/app.jsx | 9 ++++-- .../components/main-layout/main-layout.jsx | 5 ++++ .../page__aside_for_navigation.scss | 2 +- .../_for/_sort/page-stripe_for_sort.scss | 9 ++++++ src/app/components/page/index.js | 1 + src/app/components/sort-toggler/index.js | 3 ++ .../components/sort-toggler/sort-toggler.jsx | 21 ++++++++++++++ .../components/sort-toggler/sort-toggler.scss | 7 +++++ src/app/constants/sort.js | 3 ++ 10 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 src/app/common/services/sort-service.js create mode 100644 src/app/components/page/__stripe/_for/_sort/page-stripe_for_sort.scss create mode 100644 src/app/components/sort-toggler/index.js create mode 100644 src/app/components/sort-toggler/sort-toggler.jsx create mode 100644 src/app/components/sort-toggler/sort-toggler.scss create mode 100644 src/app/constants/sort.js diff --git a/src/app/common/services/sort-service.js b/src/app/common/services/sort-service.js new file mode 100644 index 00000000..69ec9ae8 --- /dev/null +++ b/src/app/common/services/sort-service.js @@ -0,0 +1,29 @@ +import cookies from 'app/common/utils/helpers/cookies'; + +import { SORT_METHOD_GROUPS_COOKIE_NAME } from 'app/constants/sort'; + +class SortService { + constructor() { + this.isGroupsSortingEnabled = !!cookies.get({ + name: SORT_METHOD_GROUPS_COOKIE_NAME, + }); + + this.toggleGroupsSorting = this.toggleGroupsSorting.bind(this); + } + + sortGroups(groups) { + return [...groups].sort((a, b) => a.title.localeCompare(b.title)); + } + + toggleGroupsSorting() { + if (this.isGroupsSortingEnabled) { + cookies.remove({ name: SORT_METHOD_GROUPS_COOKIE_NAME }); + } else { + cookies.set({ name: SORT_METHOD_GROUPS_COOKIE_NAME, value: true }); + } + + window.location.reload(); + } +} + +export const sortService = new SortService(); diff --git a/src/app/components/app/app.jsx b/src/app/components/app/app.jsx index f58cfa08..ed1b1dd5 100644 --- a/src/app/components/app/app.jsx +++ b/src/app/components/app/app.jsx @@ -4,6 +4,7 @@ import parseSourceFile from 'app/common/utils/helpers/parse-source-file'; import { HASH_DELIMITER } from 'app/common/utils/helpers/hash'; import IdProvider from 'app/common/utils/helpers/id-provider'; import sourceMock from 'app/source'; +import { sortService } from 'app/common/services/sort-service'; import MainLayout from 'app/components/main-layout'; import PageDescription from 'app/components/page-description'; @@ -28,6 +29,10 @@ const { actions, } = parsedSource; +const groupsToDisplay = sortService.isGroupsSortingEnabled + ? sortService.sortGroups(groups) + : groups; + const isModal = location => { const modalPaths = ['/service-help']; return modalPaths.indexOf(location.pathname) >= 0; @@ -98,7 +103,7 @@ export default class App extends React.Component { return ( @@ -127,7 +132,7 @@ export default class App extends React.Component { } )} diff --git a/src/app/components/main-layout/main-layout.jsx b/src/app/components/main-layout/main-layout.jsx index 7ff70dff..1033ea48 100644 --- a/src/app/components/main-layout/main-layout.jsx +++ b/src/app/components/main-layout/main-layout.jsx @@ -19,6 +19,7 @@ import Link from 'app/components/link'; import SearchStripe from 'app/components/search-stripe'; import ThemeToggler from 'app/components/theme-toggler'; import InfoButton from 'app/components/info-button'; +import SortToggler from 'app/components/sort-toggler'; import { API_DEFAULT_TITLE } from 'app/constants/defaults'; @@ -105,6 +106,10 @@ class MainLayout extends React.PureComponent { + + + + diff --git a/src/app/components/page/__aside/_for/_navigation/page__aside_for_navigation.scss b/src/app/components/page/__aside/_for/_navigation/page__aside_for_navigation.scss index 1a4e42bd..5e16f7ca 100644 --- a/src/app/components/page/__aside/_for/_navigation/page__aside_for_navigation.scss +++ b/src/app/components/page/__aside/_for/_navigation/page__aside_for_navigation.scss @@ -6,7 +6,7 @@ top: 0; box-sizing: border-box; height: 100vh; - padding: 24px 0; + padding-top: 24px; background-color: var(--background-color--sidebar); @media print { diff --git a/src/app/components/page/__stripe/_for/_sort/page-stripe_for_sort.scss b/src/app/components/page/__stripe/_for/_sort/page-stripe_for_sort.scss new file mode 100644 index 00000000..3dd04264 --- /dev/null +++ b/src/app/components/page/__stripe/_for/_sort/page-stripe_for_sort.scss @@ -0,0 +1,9 @@ +.page__stripe_for_sort { + margin-top: auto; + padding: 16px 18px 16px 30px; + border-top: 1px solid var(--stroke-color--primary); + + @media print { + display: none; + } +} diff --git a/src/app/components/page/index.js b/src/app/components/page/index.js index 8330929c..bfea7483 100644 --- a/src/app/components/page/index.js +++ b/src/app/components/page/index.js @@ -13,6 +13,7 @@ require('./__navigation/page__navigation.scss'); require('./__stripe/_for/_api-host/page__stripe_for_api-host.scss'); require('./__stripe/_for/_search/page__stripe_for_search.scss'); require('./__stripe/_for/_group/page__stripe_for_group.scss'); +require('./__stripe/_for/_sort/page-stripe_for_sort.scss'); require('./__title/page__title.scss'); require('./_type/_error/page_type_error.scss'); diff --git a/src/app/components/sort-toggler/index.js b/src/app/components/sort-toggler/index.js new file mode 100644 index 00000000..870f12de --- /dev/null +++ b/src/app/components/sort-toggler/index.js @@ -0,0 +1,3 @@ +export { default } from './sort-toggler'; + +require('./sort-toggler.scss'); diff --git a/src/app/components/sort-toggler/sort-toggler.jsx b/src/app/components/sort-toggler/sort-toggler.jsx new file mode 100644 index 00000000..97b120cf --- /dev/null +++ b/src/app/components/sort-toggler/sort-toggler.jsx @@ -0,0 +1,21 @@ +import { t } from '@lingui/macro'; +import Toggler from 'app/components/toggler'; + +import { sortService } from 'app/common/services/sort-service'; + +const SortToggler = (props) => ( +
+ + {t`Sort by name`} + + + + {t`Toggle sort by name`} + +
+); + +export default SortToggler; diff --git a/src/app/components/sort-toggler/sort-toggler.scss b/src/app/components/sort-toggler/sort-toggler.scss new file mode 100644 index 00000000..cf2054ee --- /dev/null +++ b/src/app/components/sort-toggler/sort-toggler.scss @@ -0,0 +1,7 @@ +.sort-toggler { + display: flex; + align-items: center; + justify-content: space-between; + font-weight: 500; + color: var(--color--secondary); +} diff --git a/src/app/constants/sort.js b/src/app/constants/sort.js new file mode 100644 index 00000000..9125c331 --- /dev/null +++ b/src/app/constants/sort.js @@ -0,0 +1,3 @@ +import cookiePrefix from './cookie-prefix'; + +export const SORT_METHOD_GROUPS_COOKIE_NAME = `${cookiePrefix}_is_groups_sorting_enabled`; From 03be83d650383f063bed82818535001c08e51135 Mon Sep 17 00:00:00 2001 From: Alexander Solovev Date: Thu, 25 Jan 2024 12:55:37 +0300 Subject: [PATCH 3/4] Update locales --- src/locales/en/messages.js | 2 +- src/locales/en/messages.json | 2 ++ src/locales/ru/messages.js | 2 +- src/locales/ru/messages.json | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/locales/en/messages.js b/src/locales/en/messages.js index eed365eb..c6074511 100644 --- a/src/locales/en/messages.js +++ b/src/locales/en/messages.js @@ -1 +1 @@ -/*eslint-disable*/window.i18n={messages:{"API resources":"API resources","Attributes":"Attributes","Body":"Body","Clear":"Clear","Close":"Close","Collapse":"Collapse","Content":"Content","Description":"Description","Errors and warnings":"Errors and warnings","Example {0}":["Example ",["0"]],"Expand":"Expand","General information":"General information","Headers":"Headers","Hotkeys":"Hotkeys","Menu":"Menu","Name":"Name","No results":"No results","Nothing to show.":"Nothing to show.","Recursive structure":"Recursive structure","Requests":"Requests","Responses":"Responses","Schema":"Schema","Search":"Search","Search modifiers":"Search modifiers","Show Body example":"Show Body example","Show help":"Show help","This message has no content":"This message has no content","This request has no content":"This request has no content","This response has no content":"This response has no content","To manual search page":"To manual search page","Toggle dark theme":"Toggle dark theme","Type a modifier in the search field before the search query.":"Type a modifier in the search field before the search query.","URI Parameters":"URI Parameters","Useful information":"Useful information","filters result to list only actions with the specified method":"filters result to list only actions with the specified method","finds only actions":"finds only actions","finds only groups":"finds only groups","finds only resources":"finds only resources","sets focus on the search field":"sets focus on the search field","toggles dark theme":"toggles dark theme","toggles sidebar":"toggles sidebar","where * is an HTTP method (GET, POST, PUT, DELETE, etc.),<0/>for example: <1>method:getor <2>method:post":"where * is an HTTP method (GET, POST, PUT, DELETE, etc.),<0/>for example: <1>method:get or <2>method:post"}}; \ No newline at end of file +/*eslint-disable*/window.i18n={messages:{"API resources":"API resources","Attributes":"Attributes","Body":"Body","Clear":"Clear","Close":"Close","Collapse":"Collapse","Content":"Content","Description":"Description","Errors and warnings":"Errors and warnings","Example {0}":["Example ",["0"]],"Expand":"Expand","General information":"General information","Headers":"Headers","Hotkeys":"Hotkeys","Menu":"Menu","Name":"Name","No results":"No results","Nothing to show.":"Nothing to show.","Recursive structure":"Recursive structure","Requests":"Requests","Responses":"Responses","Schema":"Schema","Search":"Search","Search modifiers":"Search modifiers","Show Body example":"Show Body example","Show help":"Show help","Sort by name":"Sort by name","This message has no content":"This message has no content","This request has no content":"This request has no content","This response has no content":"This response has no content","To manual search page":"To manual search page","Toggle dark theme":"Toggle dark theme","Toggle sort by name":"Toggle sort by name","Type a modifier in the search field before the search query.":"Type a modifier in the search field before the search query.","URI Parameters":"URI Parameters","Useful information":"Useful information","filters result to list only actions with the specified method":"filters result to list only actions with the specified method","finds only actions":"finds only actions","finds only groups":"finds only groups","finds only resources":"finds only resources","sets focus on the search field":"sets focus on the search field","toggles dark theme":"toggles dark theme","toggles sidebar":"toggles sidebar","where * is an HTTP method (GET, POST, PUT, DELETE, etc.),<0/>for example: <1>method:getor <2>method:post":"where * is an HTTP method (GET, POST, PUT, DELETE, etc.),<0/>for example: <1>method:get or <2>method:post"}}; \ No newline at end of file diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index ec140f73..3467d4aa 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -25,11 +25,13 @@ "Search modifiers": "Search modifiers", "Show Body example": "Show Body example", "Show help": "Show help", + "Sort by name": "Sort by name", "This message has no content": "This message has no content", "This request has no content": "This request has no content", "This response has no content": "This response has no content", "To manual search page": "To manual search page", "Toggle dark theme": "Toggle dark theme", + "Toggle sort by name": "Toggle sort by name", "Type a modifier in the search field before the search query.": "Type a modifier in the search field before the search query.", "URI Parameters": "URI Parameters", "Useful information": "Useful information", diff --git a/src/locales/ru/messages.js b/src/locales/ru/messages.js index 72f49ef2..5a17d7ca 100644 --- a/src/locales/ru/messages.js +++ b/src/locales/ru/messages.js @@ -1 +1 @@ -/*eslint-disable*/window.i18n={messages:{"API resources":"Ресурсы API","Attributes":"Атрибуты","Body":"Тело","Clear":"Очистить","Close":"Закрыть","Collapse":"Свернуть","Content":"Содержание","Description":"Описание","Errors and warnings":"Ошибки и предупреждения","Example {0}":["Пример ",["0"]],"Expand":"Раскрыть","General information":"Общие сведения","Headers":"Заголовки","Hotkeys":"Горячие клавиши","Menu":"Меню","Name":"Название","No results":"Ничего не найдено","Nothing to show.":"В документации пока ничего нет.","Recursive structure":"Рекурсивная структура","Requests":"Запросы","Responses":"Ответы","Schema":"Схема","Search":"Поиск","Search modifiers":"Модификаторы поиска","Show Body example":"Показать пример Body","Show help":"Открыть окно помощи","This message has no content":"Пустое сообщение","This request has no content":"Пустой запрос","This response has no content":"Пустой ответ","To manual search page":"Перейти на страницу ручного поиска","Toggle dark theme":"Включить тёмную тему","Type a modifier in the search field before the search query.":"Модификатор указывается в строке поиска перед поисковым запросом.","URI Parameters":"URI параметры","Useful information":"Полезная информация","filters result to list only actions with the specified method":"оставляет в результатах поиска только экшены с указанным методом","finds only actions":"ищет только экшены","finds only groups":"ищет только группы","finds only resources":"ищет только ресурсы","sets focus on the search field":"переводит фокус в поле поиска","toggles dark theme":"переключает светлую тему на тёмную и обратно","toggles sidebar":"скрывает и раскрывает сайдбар","where * is an HTTP method (GET, POST, PUT, DELETE, etc.),<0/>for example: <1>method:getor <2>method:post":"где * — HTTP-метод (GET, POST, PUT, DELETE и т.д.),<0/>например: <1>method:get или <2>method:post"}}; \ No newline at end of file +/*eslint-disable*/window.i18n={messages:{"API resources":"Ресурсы API","Attributes":"Атрибуты","Body":"Тело","Clear":"Очистить","Close":"Закрыть","Collapse":"Свернуть","Content":"Содержание","Description":"Описание","Errors and warnings":"Ошибки и предупреждения","Example {0}":["Пример ",["0"]],"Expand":"Раскрыть","General information":"Общие сведения","Headers":"Заголовки","Hotkeys":"Горячие клавиши","Menu":"Меню","Name":"Название","No results":"Ничего не найдено","Nothing to show.":"В документации пока ничего нет.","Recursive structure":"Рекурсивная структура","Requests":"Запросы","Responses":"Ответы","Schema":"Схема","Search":"Поиск","Search modifiers":"Модификаторы поиска","Show Body example":"Показать пример Body","Show help":"Открыть окно помощи","Sort by name":"Сортировать по названию","This message has no content":"Пустое сообщение","This request has no content":"Пустой запрос","This response has no content":"Пустой ответ","To manual search page":"Перейти на страницу ручного поиска","Toggle dark theme":"Включить тёмную тему","Toggle sort by name":"Включить сортировку по названию","Type a modifier in the search field before the search query.":"Модификатор указывается в строке поиска перед поисковым запросом.","URI Parameters":"URI параметры","Useful information":"Полезная информация","filters result to list only actions with the specified method":"оставляет в результатах поиска только экшены с указанным методом","finds only actions":"ищет только экшены","finds only groups":"ищет только группы","finds only resources":"ищет только ресурсы","sets focus on the search field":"переводит фокус в поле поиска","toggles dark theme":"переключает светлую тему на тёмную и обратно","toggles sidebar":"скрывает и раскрывает сайдбар","where * is an HTTP method (GET, POST, PUT, DELETE, etc.),<0/>for example: <1>method:getor <2>method:post":"где * — HTTP-метод (GET, POST, PUT, DELETE и т.д.),<0/>например: <1>method:get или <2>method:post"}}; \ No newline at end of file diff --git a/src/locales/ru/messages.json b/src/locales/ru/messages.json index c1caad87..494f81ee 100644 --- a/src/locales/ru/messages.json +++ b/src/locales/ru/messages.json @@ -25,11 +25,13 @@ "Search modifiers": "Модификаторы поиска", "Show Body example": "Показать пример Body", "Show help": "Открыть окно помощи", + "Sort by name": "Сортировать по названию", "This message has no content": "Пустое сообщение", "This request has no content": "Пустой запрос", "This response has no content": "Пустой ответ", "To manual search page": "Перейти на страницу ручного поиска", "Toggle dark theme": "Включить тёмную тему", + "Toggle sort by name": "Включить сортировку по названию", "Type a modifier in the search field before the search query.": "Модификатор указывается в строке поиска перед поисковым запросом.", "URI Parameters": "URI параметры", "Useful information": "Полезная информация", From 50dc2f367fa63e63007ed1b820d81512d053edce Mon Sep 17 00:00:00 2001 From: Alexander Solovev Date: Thu, 1 Feb 2024 11:30:08 +0300 Subject: [PATCH 4/4] 6.1.0 --- CHANGELOG.md | 4 ++++ CHANGELOG.ru.md | 4 ++++ package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8770a72..be0bf49c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 6.1.0 (01.02.2024) + +Added an option to sort method groups by name. + ## 6.0.0 (06.06.2023) Dropped support for Node.js 12. diff --git a/CHANGELOG.ru.md b/CHANGELOG.ru.md index 89e8ce76..0308006a 100644 --- a/CHANGELOG.ru.md +++ b/CHANGELOG.ru.md @@ -1,5 +1,9 @@ # История изменений проекта +## 6.1.0 (01.02.2024) + +Добавлена возможность сортировки групп методов по названию. + ## 6.0.0 (06.06.2023) Node.js 12 больше не поддерживается. diff --git a/package-lock.json b/package-lock.json index b818e3dd..eb2145b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@funboxteam/blueprinter", - "version": "6.0.0", + "version": "6.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@funboxteam/blueprinter", - "version": "6.0.0", + "version": "6.1.0", "license": "Apache-2.0", "dependencies": { "@funboxteam/crafter": "6.0.0", diff --git a/package.json b/package.json index 3fc638bd..c10e96ab 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@funboxteam/blueprinter", - "version": "6.0.0", + "version": "6.1.0", "description": "Replacement of Aglio library for rendering generated AST as HTML page.", "repository": { "type": "git",