diff --git a/resources/js/components/MenuApp.tsx b/resources/js/components/MenuApp.tsx new file mode 100644 index 0000000..16e61b1 --- /dev/null +++ b/resources/js/components/MenuApp.tsx @@ -0,0 +1,231 @@ +import { Button } from '@SharePoint/rencredit_uikit'; +import React, { useEffect, useState } from "react"; + +function MenuApp () +{ + //Приложения и процессы Magic для отображения в меню + const [menuApps, setMenuApps] = useState<{ + 'proccesses': object, + 'scripts': object + }>({ + 'proccesses': {}, + 'scripts': {} + }); + //TODO + //ВНЕДРИ В КОНТРОЛЛЕРЕ ПРОВЕРКУ ДОСТУПОВ, А НЕ ВОЗВРАЩАЙ ВСЕ ПОДРЯД ПРИЛОЖЕНИЯ + //Избранные приложения пользователя + const [favApps, setFavApps] = useState([]); + //Массив избраннных процессов, в приложениях которых есть хотя бы одно избранное + const [favProcs, setFavProcs] = useState([]); + //Состояния видимости скрипта + const [hideScriptClass, setHideScriptClass] = useState(''); + //const [sanctumToken, setSanctumToken] = useState(''); + + const sanctumToken = () => { + const metaTag = document.getElementById('sanctum_token_block') as HTMLMetaElement; + return metaTag.dataset.token; + } + + //Получаем при рендере страницы все приложения Magic и все избранные приложения пользователя + useEffect( () => { + Promise.all( + [ + fetch('api/magic_apps').then(menuAppsRes => menuAppsRes.json()), + //TODO + //СЮДА ПОТЯГИВАЙ ЛОГИН ПОЛЬЗОВАТЕЛЯ, А НЕ DGAVRILOV + fetch('api/user_fav_app/dgavrilov').then(favAppsRes => favAppsRes.json()) + ] + ).then( + ([ + responseMenuApp, + responseFavApp + ]) => { + setMenuApps(responseMenuApp); + setFavApps(responseFavApp); + } + ) + }, []); + + + //Обновление видимости процесса (собрания приложений) в зависимости от того находится ли в избранном хотя бы одно приложение + useEffect( () => { + if (menuApps === null) { return } + //Массив с процессами, в которых есть хотя бы одно избранное приложение + const favProcsArr:string[] = []; + //Мы собираем все избранные приложения в массив-состояние, чтобы при изменении состояния каждого приложения (например при переключении switcher) проверять входит ли это приложение в избранные. Если входит - его родительский процесс не прячем, так как в его дочерних приложениях есть избранные + Object.entries(menuApps.proccesses).forEach( (procData) => { + //Флаг - есть ли в приложениях процесса хотя бы 1 избранное + const hasFavorite: boolean = procData[1].tabs.split(';').some( (tab: string) => { + return favApps.includes(tab); + }) + if (hideScriptClass !== 'script-hide' || hasFavorite) { + favProcsArr.push(procData[0]); + } + }) + setFavProcs(favProcsArr); + }, [hideScriptClass, menuApps, favApps]); + + //console.log(sanctumToken()) + + //ГАВРИЛОВ + //ПОЧЕМУ КОД НИЖЕ ИСПОЛНЯЕТСЯ ПОСТОЯННО ПОКА НЕ БУДЕТ ПОЛУЧЕН КОНТЕНТ ДЛЯ СТРАНИЦЫ ИЗ ПРОМИСОВ ВЫШЕ, А НЕ ОТРАБАТЫВАЕТ ТОЛЬКО ПРИ РЕНДЕРИНГЕ СТРАНИЦЫ + //Уместно ли отслеживать состояние до получения запросов fetch в подобном виде? + if (menuApps === null || favApps === null) { + return прелоадер + } else { + return ( + + ) + } +} + + +//Гаврилов +//ПЕРЕПИСАТЬ АРГУМЕНТЫ ПОД ОБЪЕКТ СО СВОЙСТВАМИ, ИСПОЛЬЗОВАТЬ ...obj +/** + * + * @param {int} appIndex ключ для экземлпяра компонента + * @param {string} appName уникальное имя скрипта + * @param {string} appTitle название скрипта в меню + * @param {string} favIconClassName класс для иконки избранного + * @param {string} hideAppClass класс для видимости приложения + * @param {string} setUpdateFavApps функция для обновления состояния избранны приложений (при снятия, установки признака избранности) + * @returns + */ +function AppElem({ + appIndex, + appName, + appTitle, + appUrl, + favIconClassName, + hideAppClass, + setUpdateFavApps +} : { + appIndex: string, + appName: string, + appTitle: string, + appUrl: string, + favIconClassName: string, + hideAppClass: string, + setUpdateFavApps: string +}) { + const [appElemClass, changeFav] = useState(favIconClassName); + const callChangeFav = ( changeAppName: string ) => { + fetch('api/user_fav_app', { + method: 'post', + body: JSON.stringify({ appName: changeAppName }), + headers: { + 'content-type': 'application/json' + } + } + ) + .then( (response) => response.json() ) + .then( (response) => { + //Если скрипт был избранным - удаляем из избранного и наоборот + appElemClass == 'favorite' ? changeFav('not_favorite') : changeFav('favorite'); + //Возвращаем обновленный список избранных приложений пользователя + setUpdateFavApps(response?.fav_apps?.split( ';' ) || []) + } ) + } + + return ( + //Если приложение в избранном - оно всегда должно быть "видимо", даже если переключатель в положении Скрыть неизбранные приложения +
+
{ appTitle }
+ {/* Анонимная функция нужна для создания функции смены состояния для каждого компонента в отдельности, в противном случае вызов функции в одном экземпляре компонента вызывает функцию изменения для каждого экземпляра компонента */} + callChangeFav(appName) }> +
+ ) +} + + +//TODO +//ВЫНЕСИ В ПАПКУ COMPONENTS/MAIN +/** + * Компонент переключателя В ДАННОМ СЛУЧАЕ видимости скриптов (видны только избранные или все) + * @param {string} switcherId идентификатор переключателя (для стилей css), так как в будущем, на странице можно будет размещать несколько переключателей + * @param {function} toggleAppsVisible функция обновления состояния hideScriptClass + * @returns + */ +function Switcher({ switcherId, toggleAppsVisible }) { + const [favSwitcherClass, setFavSwitcherClass] = useState('showAll'); + + //Переключение состояния переключателя после рендеринга страницы + useEffect( () => { + //Получаем из локал сторадж состояние переключателя + const savedState = localStorage.getItem('magicMenuFavSwitcher'); + if (savedState) { + setFavSwitcherClass(savedState); + } + }, []); + + //При изменении состояния Переключателя изменяется состояние всех приложени (переключается их видимость в зависимости от состояния переключателя - только избранные или все) + useEffect( () => { + //Синхронизируем зависимые компоненты + toggleAppsVisible(favSwitcherClass === 'showFav' ? 'script-hide' : ''); + }, [favSwitcherClass] ); + + const callToggleFavSwitcher = () => { + let switcherState = (favSwitcherClass === 'showFav' ? 'showAll' : 'showFav'); + //favSwitcherClass => favSwitcherClass = ... - функциональное обновление. Здесь оно не особо нужно, но чтобы не забыть + //Меняем класс switcher, а также меняем состояние видимости всех приложений (в зависимости от того избранные они или нет) + setFavSwitcherClass( favSwitcherClass => { + if (favSwitcherClass === 'showFav') { + toggleAppsVisible('script-hide') + } else { + toggleAppsVisible('') + } + localStorage.setItem('magicMenuFavSwitcher', switcherState) + + return switcherState; + } ) + } + + return ( +
+ +
+ ) +} + +export default MenuApp;