From 04f9f6f345ac71f70c2e2320fa4596ffa23b960b Mon Sep 17 00:00:00 2001 From: Aleksey Zverev Date: Wed, 14 Feb 2024 11:27:27 +0200 Subject: [PATCH] Add last login --- web/internal/service/auth/auth.go | 8 + web/internal/storage/auth.go | 4 + website/package-lock.json | 113 ++++++++++ website/package.json | 1 + website/src/components/Sidebar.tsx | 16 +- .../layouts/dictionary/positions/index.tsx | 2 +- website/src/layouts/orderByDay/index.tsx | 35 ++- website/src/layouts/saleByMonth/index.tsx | 2 +- website/src/layouts/stock/index.tsx | 2 +- website/src/layouts/test/index.tsx | 204 +++++++++++++++++- 10 files changed, 354 insertions(+), 33 deletions(-) diff --git a/web/internal/service/auth/auth.go b/web/internal/service/auth/auth.go index 7a3ccbf..c663430 100644 --- a/web/internal/service/auth/auth.go +++ b/web/internal/service/auth/auth.go @@ -3,6 +3,7 @@ package auth import ( "github.com/golang-jwt/jwt/v5" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/yoda/web/internal/api" "github.com/yoda/web/internal/middleware" "github.com/yoda/web/internal/storage" @@ -12,6 +13,7 @@ import ( type IAuthStorage interface { GetPermissionByUserId(id int32) (*[]string, error) GetProleByLogin(login string) (*storage.UserProfile, error) + UpdateLastLogin(id int32) error UserExists(id int32) bool } @@ -54,6 +56,12 @@ func (s *AuthService) CreateToken(login *api.LoginInfo) (string, time.Time, erro } func (s *AuthService) CheckUserById(id int32) bool { + go func(id int32) { + err := s.storage.UpdateLastLogin(id) + if err != nil { + logrus.Error("failed to update last login: ", err) + } + }(id) return s.storage.UserExists(id) } diff --git a/web/internal/storage/auth.go b/web/internal/storage/auth.go index 9edb537..f01d77b 100644 --- a/web/internal/storage/auth.go +++ b/web/internal/storage/auth.go @@ -55,6 +55,10 @@ func (s *Storage) GetProleByLogin(login string) (*UserProfile, error) { return &profile, nil } +func (s *Storage) UpdateLastLogin(id int32) error { + return s.db.Exec(`update ml.users set last_login = now() where id=?`, id).Error +} + func (s *Storage) UserExists(id int32) bool { var count int32 s.db.Raw(`select count(1) from ml.users where id=?`, id).Scan(&count) diff --git a/website/package-lock.json b/website/package-lock.json index 18998df..5a1f0a9 100755 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -21,6 +21,7 @@ "@types/react-dom": "latest", "dayjs": "^1.11.9", "deep-equal": "^2.2.2", + "material-react-table": "^2.10.0", "moment": "^2.29.4", "react": "^17.0.0 || ^18.0.0", "react-date-range": "^1.4.0", @@ -4512,6 +4513,77 @@ "url": "https://github.com/sponsors/gregberge" } }, + "node_modules/@tanstack/match-sorter-utils": { + "version": "8.11.7", + "resolved": "https://registry.npmjs.org/@tanstack/match-sorter-utils/-/match-sorter-utils-8.11.7.tgz", + "integrity": "sha512-4PUKgaaFpiB7MK406N5VAiLu2VUhDumojGWhEC8kNQ767RGU2vsJDI7Xp4D8lMBzijqswRWz3U8ioa2zUKnFeQ==", + "dependencies": { + "remove-accents": "0.4.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-table": { + "version": "8.11.7", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.11.7.tgz", + "integrity": "sha512-ZbzfMkLjxUTzNPBXJYH38pv2VpC9WUA+Qe5USSHEBz0dysDTv4z/ARI3csOed/5gmlmrPzVUN3UXGuUMbod3Jg==", + "dependencies": { + "@tanstack/table-core": "8.11.7" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, + "node_modules/@tanstack/react-virtual": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.0.2.tgz", + "integrity": "sha512-9XbRLPKgnhMwwmuQMnJMv+5a9sitGNCSEtf/AZXzmJdesYk7XsjYHaEDny+IrJzvPNwZliIIDwCRiaUqR3zzCA==", + "dependencies": { + "@tanstack/virtual-core": "3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@tanstack/table-core": { + "version": "8.11.7", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.11.7.tgz", + "integrity": "sha512-N3ksnkbPbsF3PjubuZCB/etTqvctpXWRHIXTmYfJFnhynQKjeZu8BCuHvdlLPpumKbA+bjY4Ay9AELYLOXPWBg==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.0.0.tgz", + "integrity": "sha512-SYXOBTjJb05rXa2vl55TTwO40A6wKu0R5i1qQwhJYNDIqaIGF7D0HsLw+pJAyi2OvntlEIVusx3xtbbgSUi6zg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -10111,6 +10183,15 @@ "integrity": "sha512-tUCGvt191vNSQgttSyJoibR+VO+I6+iCHIUdhzEMJKE+EAL8BwCN7fUOZlY4ofOelNHsK+gEjxB/B+9N3EWtdA==", "dev": true }, + "node_modules/highlight-words": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/highlight-words/-/highlight-words-1.2.2.tgz", + "integrity": "sha512-Mf4xfPXYm8Ay1wTibCrHpNWeR2nUMynMVFkXCi4mbl+TEgmNOe+I4hV7W3OCZcSvzGL6kupaqpfHOemliMTGxQ==", + "engines": { + "node": ">= 16", + "npm": ">= 8" + } + }, "node_modules/highlight-words-core": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.2.tgz", @@ -14031,6 +14112,33 @@ "tmpl": "1.0.5" } }, + "node_modules/material-react-table": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/material-react-table/-/material-react-table-2.10.0.tgz", + "integrity": "sha512-khKm/AMuLp6zV/Lj7ttdTy59cNXuEc0LyD6jh6GydslEWMHqasn4PKElGQKDnO+u5AInB+CzoK1U4zTOqRiIlQ==", + "dependencies": { + "@tanstack/match-sorter-utils": "8.11.7", + "@tanstack/react-table": "8.11.7", + "@tanstack/react-virtual": "3.0.2", + "highlight-words": "1.2.2" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kevinvandy" + }, + "peerDependencies": { + "@emotion/react": ">=11.11", + "@emotion/styled": ">=11.11", + "@mui/icons-material": ">=5.11", + "@mui/material": ">=5.13", + "@mui/x-date-pickers": ">=6.15.0", + "react": ">=18.0", + "react-dom": ">=18.0" + } + }, "node_modules/mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -17399,6 +17507,11 @@ "node": ">= 0.10" } }, + "node_modules/remove-accents": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", + "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" + }, "node_modules/renderkid": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", diff --git a/website/package.json b/website/package.json index e463d21..cd6b341 100755 --- a/website/package.json +++ b/website/package.json @@ -13,6 +13,7 @@ "@types/react-dom": "latest", "dayjs": "^1.11.9", "deep-equal": "^2.2.2", + "material-react-table": "^2.10.0", "moment": "^2.29.4", "react": "^17.0.0 || ^18.0.0", "react-date-range": "^1.4.0", diff --git a/website/src/components/Sidebar.tsx b/website/src/components/Sidebar.tsx index 007774c..8193047 100755 --- a/website/src/components/Sidebar.tsx +++ b/website/src/components/Sidebar.tsx @@ -116,7 +116,21 @@ export default function Sidebar(this: any) { }} onClick={() => closeSidebar()} /> + + + `linear-gradient(45deg, ${theme.vars.palette.primary.solidBg}, ${theme.vars.palette.primary.solidBg} 30%, ${theme.vars.palette.primary.softBg})`, + borderRadius: '50%', + boxShadow: (theme) => theme.shadow.md, + '--joy-shadowChannel': (theme) => + theme.vars.palette.primary.mainChannel, + }} + /> toggleSidebar()} variant="outlined" @@ -130,7 +144,7 @@ export default function Sidebar(this: any) { > - + {/**/} { dispatch(SetMenuActive("menu-dict-item1c-id")) }, []); diff --git a/website/src/layouts/orderByDay/index.tsx b/website/src/layouts/orderByDay/index.tsx index 4366a60..020cbbf 100755 --- a/website/src/layouts/orderByDay/index.tsx +++ b/website/src/layouts/orderByDay/index.tsx @@ -1,23 +1,21 @@ import * as React from 'react'; -import {Fragment, useEffect, useState} from 'react'; +import { Fragment, useEffect, useState } from 'react'; import Typography from '@mui/joy/Typography'; import Button from '@mui/joy/Button'; import DownloadRoundedIcon from '@mui/icons-material/DownloadRounded'; import Box from '@mui/joy/Box'; import OrderTable from './OrderTable'; -import {AdapterDayjs} from '@mui/x-date-pickers/AdapterDayjs'; -import JoyDatePicker from 'components/JoyDatePicker'; -import {LocalizationProvider} from '@mui/x-date-pickers'; import 'dayjs/locale/ru'; import dayjs from 'dayjs'; -import {CustomOrdersService} from 'layouts/orderByDay/customOrderService'; -import {SetMenuActive} from "../../context/actions"; -import {useController} from "../../context"; +import { CustomOrdersService } from 'layouts/orderByDay/customOrderService'; +import { SetMenuActive } from "../../context/actions"; +import { useController } from "../../context"; +import PickerWithJoyField from 'components/PickerWithJoyField'; export function OrderByDay() { const {dispatch} = useController() - const [date, setDate] = useState(dayjs().subtract(1, 'day')) + const [date, setDate] = useState(dayjs()) const [isLoading, setIsLoading] = useState(false) useEffect(() => { @@ -57,21 +55,12 @@ export function OrderByDay() { justifyContent: 'space-between', }} > - - setDate(event ?? date)} - /> - - + setDate(event ?? date)} + />