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;