Browse Source

HW<21>continued

Gennadysht 2 years ago
parent
commit
c84c98e570

+ 1 - 1
js/08/hw08_03_!Flats.html

@@ -6,7 +6,7 @@
     <script>
         const padikNum = (flatNum, floors = 9, flats = 4) => {
             let entrance = Math.floor(flatNum / flats / floors) + 1;
-            let floor = Math.floor((flatNum - (entrance * 36)) / flats) + 1;
+            //let floor = Math.floor((flatNum - (entrance * 36)) / flats) + 1; использовал при отладке
             return { entrance, floor };
         }
         let flatNum = +prompt("Enter flat number");

+ 1 - 1
js/18Rest_Graph/hw_18_04_graph.html

@@ -52,7 +52,7 @@
                             	login(login:$login, password:$password)
                         }`;
 
-                const token = await gql("http://shop-roles.node.ed.asmer.org.ua/graphql", loginQuery, { login: "test457", password: "123123" });
+                const token = await gql("http://shop-roles.node.ed.asmer.org.ua/graphql", loginQuery, { login: "Berg", password: "123456789" });
                 console.log(token);
             }
             await test1();

+ 1 - 1
js/19_Redux_pro/hw_19_01 _1.html

@@ -61,7 +61,7 @@
         const actionFulfilled = (name, payload) => ({ type: 'PROMISE', name: name, payload: payload, status: 'FULFILLED' });
         const actionRejected = (name, error) => ({ type: 'PROMISE', name: name, error: error, status: 'REJECTED' });
 
-        const store = createStore(promiseReducer)
+        const store = createStore(promiseReducer);
 
         store.subscribe(() => {
             console.log(store.getState())

+ 218 - 0
js/lesson21/Gql_promis.html

@@ -0,0 +1,218 @@
+<Header>Gql</Header>
+
+<body>
+    <script>
+        function jwtDecode(token) {                         // расщифровки токена авторизации
+            if (!token || typeof token != "string")
+                return undefined;
+            let tokenArr = token.split(".");
+            if (tokenArr.length != 3)
+                return undefined;
+            try {
+                let tokenJsonStr = atob(tokenArr[1]);
+                let tokenJson = JSON.parse(tokenJsonStr);
+                return tokenJson;
+            }
+            catch {
+                return undefined;
+            }
+        }
+        function combineReducers(reducers) {
+            function totalReducer(totalState = {}, action) {
+                const newTotalState = {} //объект, который будет хранить только новые состояния дочерних редьюсеров
+
+                //цикл + квадратные скобочки позволяют написать код, который будет работать с любыми количеством дочерных редьюсеров
+                for (const [reducerName, childReducer] of Object.entries(reducers)) {
+                    const newState = childReducer(totalState[reducerName], action) //запуск дочернего редьюсера
+                    if (newState !== totalState[reducerName]) { //если он отреагировал на action
+                        newTotalState[reducerName] = newState //добавляем его в newTotalState
+                    }
+                }
+
+                //Универсальная проверка на то, что хотя бы один дочерний редьюсер создал новый стейт:
+                if (Object.values(newTotalState).length) {
+                    return { ...totalState, ...newTotalState } //создаем новый общий стейт, накладывая новый стейты дочерних редьюсеров на старые
+                }
+
+                return totalState //если экшен не был понят ни одним из дочерних редьюсеров, возвращаем общий стейт как был.
+            }
+
+            return totalReducer
+        }
+        function promiseReducer(state = {}, action) {                   // диспетчер обработки
+            if (action) {
+                if (action.type === 'PROMISE') {
+                    let newState = { ...state };
+                    newState[action.name] = { status: action.status, payload: action.payload, error: action.error };
+                    return newState;
+                }
+            }
+            return state;
+        }
+        function authReducer(state = {}, action) {                   // диспетчер обработки login
+            if (action) {
+                if (action.type === 'AUTH_LOGIN') {
+                    let newState = { ...state };
+                    newState.token = action.token;
+                    newState.payload = jwtDecode(action.token);
+                    if (!newState.payload) {
+                        newState.token = undefined;
+                    }
+                    return newState;
+                }
+                else if (action.type === 'AUTH_LOGOUT') {
+                    let newState = { ...state };
+                    newState.token = undefined;
+                    newState.payload = undefined;
+                    return newState;
+                }
+            }
+            return state;
+        }
+        function createStore(reducer) {
+            let state = reducer(undefined, {})              //стартовая инициализация состояния, запуск редьюсера со state === undefined
+            let cbs = []                                      //массив подписчиков
+
+            const getState = () => state                   //функция, возвращающая переменную из замыкания
+            const subscribe = cb => (cbs.push(cb),            //запоминаем подписчиков в массиве
+                () => cbs = cbs.filter(c => c !== cb))      //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
+
+            function dispatch(action) {
+                if (typeof action === 'function') {         //если action - не объект, а функция
+                    return action(dispatch, getState)       //запускаем эту функцию и даем ей dispatch и getState для работы
+                }
+                const newState = reducer(state, action)      //пробуем запустить редьюсер
+                if (newState !== state) {                    //проверяем, смог ли редьюсер обработать action
+                    state = newState                        //если смог, то обновляем state 
+                    for (let cb of cbs) cb()                //и запускаем подписчиков
+                }
+            }
+
+            return {
+                getState,                                   //добавление функции getState в результирующий объект
+                dispatch,
+                subscribe                                   //добавление subscribe в объект
+            }
+        }
+
+        function gql(url, query, vars) {
+            let fetchSettings =
+            {
+                method: "POST",
+                headers:
+                {
+                    "Content-Type": "application/json",
+                    "Accept": "application/json"
+                },
+                body: JSON.stringify(
+                    {
+                        query: query,
+                        variables: vars
+
+                    })
+            };
+            return fetch(url, fetchSettings).then(res => res.json());
+        }
+
+        function actionPromiseGql(name, promise) {
+            return async function Exec(dispatch) {
+                dispatch(actionPending(name))               //сигнализируем redux, что промис начался
+                try {
+                    const payload = await promise;           //ожидаем промиса;
+                    let result = Object.values(payload.data)[0];
+                    dispatch(actionFulfilled(name, result)); //сигнализируем redux, что промис успешно выполнен
+                    return result;                              //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
+                }
+                catch (error) {
+                    dispatch(actionRejected(name, error))           //в случае ошибки - сигнализируем redux, что промис несложился
+                }
+            };
+        }
+        function actionAuthGql(promise) {
+            return async function Exec(dispatch) {
+                try {
+                    const payload = await promise           //ожидаем промиса;
+                    let result = Object.values(payload.data)[0];
+                    dispatch(actionAuthLogin(result)); //сигнализируем redux, что промис успешно выполнен
+                    return result;                               //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
+                }
+                catch (error) {
+                    dispatch(actionLogOut())           //в случае ошибки - сигнализируем redux, что промис несложился
+                }
+            };
+        }
+        const actionPending = (name) => ({ type: 'PROMISE', name: name, status: 'PENDING' });
+        const actionFulfilled = (name, payload) => ({ type: 'PROMISE', name: name, payload: payload, status: 'FULFILLED' });
+        const actionRejected = (name, error) => ({ type: 'PROMISE', name: name, error: error, status: 'REJECTED' });
+        const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token });
+        const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' });
+
+        const gqlRootCats = () => {
+            const catQuery = `query roots {
+                CategoryFind(query: "[{\\"parent\\": null }]") {
+                                        _id name
+                                    }}`;
+            return gql("http://shop-roles.node.ed.asmer.org.ua/graphql", catQuery);
+        }
+        const actionRootCats = () =>
+            actionPromiseGql('rootCats', gqlRootCats());
+
+
+
+        ///////////////////////////////////////
+        const gqlCategoryFindOne = (id) => {
+            const catQuery = `query CategoryFindOne($q: String) {
+                    CategoryFindOne(query: $q) {
+                            _id name
+                            parent { _id name }
+                            subCategories { _id name }
+                            goods { _id name price description
+                            images { url }
+                        }
+                    }
+                }`;
+            return gql("http://shop-roles.node.ed.asmer.org.ua/graphql", catQuery, { q: `[{\"_id\": \"${id}\"}]` });
+        }
+        const actionCategoryFindOne = (id) =>
+            actionPromiseGql('catFindOne', gqlCategoryFindOne(id));
+        /////////////////////////////////////////
+        const gqlGoodFindOne = (id) => {
+            const catQuery = `
+                        query GoodFindOne($q: String) {
+                            GoodFindOne(query: $q) {
+                                _id name  price description
+                                images {
+                                    url
+                                }
+                            }
+                        }
+                        `;
+            return gql("http://shop-roles.node.ed.asmer.org.ua/graphql", catQuery, { q: `[{\"_id\": \"${id}\"}]` });
+        }
+        const actionGoodFindOne = (id) =>
+            actionPromiseGql('goodsFindOne', gqlGoodFindOne(id));
+        //////////////////////////////////
+        const gqlAuthLogin = (login, password) => {
+            const loginQuery = `query login($login:String, $password:String){
+                            	login(login:$login, password:$password)
+                        }`;
+
+            return gql("http://shop-roles.node.ed.asmer.org.ua/graphql", loginQuery, { login: login, password: password });
+        }
+        const actionAuthLoginFunc = (login, password) =>
+            actionAuthGql(gqlAuthLogin(login, password));
+        ////////////////////////////////////////
+        const store = createStore(combineReducers({ promiseReducer, authReducer }));
+
+        store.subscribe(() => {
+            console.log(store.getState())
+        });
+        //store.dispatch(actionRootCats());
+        //store.dispatch(actionCategoryFindOne("6262ca7dbf8b206433f5b3d1"));
+        //store.dispatch(actionGoodFindOne("62d3099ab74e1f5f2ec1a125"));
+        store.dispatch(actionAuthLoginFunc("Berg", "123456789"));
+
+
+
+    </script>
+</body>

File diff suppressed because it is too large
+ 229 - 0
js/lesson21/getGQL.html