diff --git a/app/Http/Controllers/PlayerController.php b/app/Http/Controllers/PlayerController.php index f35dd2cd..c130d7fd 100644 --- a/app/Http/Controllers/PlayerController.php +++ b/app/Http/Controllers/PlayerController.php @@ -53,9 +53,13 @@ class PlayerController extends Controller ]; $grid = $filter->apply('grid:user.player', $grid); + /** @var User */ + $user = auth()->user(); + return view('user.player') ->with('grid', $grid) ->with('extra', [ + 'count' => $user->players()->count(), 'rule' => trans('user.player.player-name-rule.'.option('player_name_rule')), 'length' => trans( 'user.player.player-name-length', diff --git a/package.json b/package.json index 89b9ed72..820fae53 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "react-dom": "^16.13.0", "react-draggable": "^4.4.2", "react-hot-loader": "^4.12.21", + "react-loading-skeleton": "^2.1.1", "reaptcha": "^1.7.2", "rxjs": "^6.5.5", "skinview-utils": "^0.5.5", diff --git a/resources/assets/src/views/user/Players/LoadingRow.tsx b/resources/assets/src/views/user/Players/LoadingRow.tsx new file mode 100644 index 00000000..2fd5266b --- /dev/null +++ b/resources/assets/src/views/user/Players/LoadingRow.tsx @@ -0,0 +1,20 @@ +import React from 'react' +import styled from '@emotion/styled' +import Skeleton from 'react-loading-skeleton' + +const TableRow = styled.tr` + height: 64px; +` +const ThickSkeleton = styled(Skeleton)` + line-height: 2; +` + +const RowLoading: React.FC = () => ( + + + + + +) + +export default RowLoading diff --git a/resources/assets/src/views/user/Players/index.tsx b/resources/assets/src/views/user/Players/index.tsx index 2c1ba137..58264bfa 100644 --- a/resources/assets/src/views/user/Players/index.tsx +++ b/resources/assets/src/views/user/Players/index.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react' import { hot } from 'react-hot-loader/root' +import useBlessingExtra from '@/scripts/hooks/useBlessingExtra' import useEmitMounted from '@/scripts/hooks/useEmitMounted' import useTexture from '@/scripts/hooks/useTexture' import { t } from '@/scripts/i18n' @@ -7,8 +8,8 @@ import * as fetch from '@/scripts/net' import { showModal, toast } from '@/scripts/notify' import { Player, TextureType } from '@/scripts/types' import urls from '@/scripts/urls' -import Loading from '@/components/Loading' import Row from './Row' +import LoadingRow from './LoadingRow' import Previewer from './Previewer' import ModalAddPlayer from './ModalAddPlayer' import ModalReset from './ModalReset' @@ -22,6 +23,7 @@ const Players: React.FC = () => { const [search, setSearch] = useState('') const [showModalAddPlayer, setShowModalAddPlayer] = useState(false) const [showModalReset, setShowModalReset] = useState(false) + const playersCount = useBlessingExtra('count') useEmitMounted() @@ -157,7 +159,7 @@ const Players: React.FC = () => { const closeModalReset = () => setShowModalReset(false) return ( - <> +
{ - {players.length === 0 ? ( + {isLoading ? ( + new Array(playersCount) + .fill(null) + .map((_, i) => ) + ) : players.length === 0 ? ( - {isLoading ? : t('general.noResult')} + {t('general.noResult')} ) : ( @@ -223,7 +229,7 @@ const Players: React.FC = () => { onSubmit={resetTexture} onClose={closeModalReset} /> - + ) } diff --git a/resources/assets/tests/views/user/Players.test.tsx b/resources/assets/tests/views/user/Players.test.tsx index 1971f04e..7dc7d26f 100644 --- a/resources/assets/tests/views/user/Players.test.tsx +++ b/resources/assets/tests/views/user/Players.test.tsx @@ -23,6 +23,7 @@ beforeEach(() => { document.body.appendChild(container) blessing.extra = { + count: 1, rule: 'please follow the rule', length: 'greater than 3', score: 1000, @@ -34,12 +35,6 @@ afterEach(() => { document.querySelector('#previewer')!.remove() }) -test('loading indicator', () => { - fetch.get.mockResolvedValue([]) - const { queryByTitle } = render() - expect(queryByTitle('Loading...')).toBeInTheDocument() -}) - test('search players', async () => { const fixture2: Player = { pid: 2, diff --git a/yarn.lock b/yarn.lock index 64c49e16..8b3ddb36 100644 --- a/yarn.lock +++ b/yarn.lock @@ -486,7 +486,7 @@ "@emotion/utils" "0.11.3" "@emotion/weak-memoize" "0.2.5" -"@emotion/core@^10.0.28": +"@emotion/core@^10.0.22", "@emotion/core@^10.0.28": version "10.0.28" resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.28.tgz#bb65af7262a234593a9e952c041d0f1c9b9bef3d" integrity sha512-pH8UueKYO5jgg0Iq+AmCLxBsvuGtvlmiDCOuv8fGNYn3cowFpLN98L8zO56U0H1PjDIyAlXymgL3Wu7u7v6hbA== @@ -7626,6 +7626,13 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-loading-skeleton@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/react-loading-skeleton/-/react-loading-skeleton-2.1.1.tgz#2c075ea9683587c163408c8eec0703047c4203b1" + integrity sha512-+fGvgG9ieUw4D5QVgpqJkJ75jhzUdz96GRsA0HjTlR0Mpj9DJUEFc0AKELs7ZkqWVH8/DiroaaufSrOPld1kGA== + dependencies: + "@emotion/core" "^10.0.22" + react-themeable@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/react-themeable/-/react-themeable-1.1.0.tgz#7d4466dd9b2b5fa75058727825e9f152ba379a0e"