diff --git a/graphql.config.yml b/graphql.config.yml new file mode 100644 index 0000000..c52a166 --- /dev/null +++ b/graphql.config.yml @@ -0,0 +1,4 @@ +schema: + - http://localhost:8000/api/v1/graphql: + headers: + Authorization: Bearer eyJ1c2VyX2lkIjogMSwgInNhbHQiOiAiMTkxNDZhIiwgImV4cGlyZXMiOiAxNzIxMjMyMzM3Ljk4MTUyN30HZ3bA-tzG2JebZhmLQJRmODYQj6_aM1ZEQ23uDJreKg== \ No newline at end of file diff --git a/next.config.mjs b/next.config.mjs index 4678774..d5a22f1 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,6 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + reactStrictMode: false +}; export default nextConfig; diff --git a/package-lock.json b/package-lock.json index dcd79ec..9e8f312 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,11 @@ "dependencies": { "@ant-design/icons": "^5.3.7", "@ant-design/nextjs-registry": "^1.0.0", + "@apollo/client": "^3.10.8", + "@apollo/experimental-nextjs-app-support": "^0.11.2", "antd": "^5.19.2", + "graphql": "^16.9.0", + "js-cookie": "^3.0.5", "next": "14.2.5", "react": "^18", "react-dom": "^18" @@ -111,6 +115,73 @@ "react": ">=16.9.0" } }, + "node_modules/@apollo/client": { + "version": "3.10.8", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.10.8.tgz", + "integrity": "sha512-UaaFEitRrPRWV836wY2L7bd3HRCfbMie1jlYMcmazFAK23MVhz/Uq7VG1nwbotPb5xzFsw5RF4Wnp2G3dWPM3g==", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "@wry/caches": "^1.0.0", + "@wry/equality": "^0.5.6", + "@wry/trie": "^0.5.0", + "graphql-tag": "^2.12.6", + "hoist-non-react-statics": "^3.3.2", + "optimism": "^0.18.0", + "prop-types": "^15.7.2", + "rehackt": "^0.1.0", + "response-iterator": "^0.2.6", + "symbol-observable": "^4.0.0", + "ts-invariant": "^0.10.3", + "tslib": "^2.3.0", + "zen-observable-ts": "^1.2.5" + }, + "peerDependencies": { + "graphql": "^15.0.0 || ^16.0.0", + "graphql-ws": "^5.5.5", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", + "subscriptions-transport-ws": "^0.9.0 || ^0.11.0" + }, + "peerDependenciesMeta": { + "graphql-ws": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "subscriptions-transport-ws": { + "optional": true + } + } + }, + "node_modules/@apollo/client-react-streaming": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@apollo/client-react-streaming/-/client-react-streaming-0.11.2.tgz", + "integrity": "sha512-rRA/dIA09/Y6+jtGGBnXHQfPOv6BYYVZwQP8OzQtWrWbSgDEI6uAhqULssU5f0ZhQJVzKDuslqGE9QAX0gdfRQ==", + "dependencies": { + "ts-invariant": "^0.10.3" + }, + "peerDependencies": { + "@apollo/client": "^3.10.4", + "react": "^18" + } + }, + "node_modules/@apollo/experimental-nextjs-app-support": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/@apollo/experimental-nextjs-app-support/-/experimental-nextjs-app-support-0.11.2.tgz", + "integrity": "sha512-HRQ8/Ux/tM2pezrhZeoHsJs55+nJvJZRV1B21QwEVtWhslQXjT5gqs5nKw86KURF0xR7gX18Nyy659NzJ09Pmw==", + "dependencies": { + "@apollo/client-react-streaming": "0.11.2" + }, + "peerDependencies": { + "@apollo/client": "^3.10.4", + "next": "^13.4.1 || ^14.0.0 || 15.0.0-rc.0", + "react": "^18" + } + }, "node_modules/@babel/runtime": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.8.tgz", @@ -196,6 +267,14 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -816,6 +895,50 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@wry/caches": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz", + "integrity": "sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wry/context": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.4.tgz", + "integrity": "sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wry/equality": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.7.tgz", + "integrity": "sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wry/trie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.5.0.tgz", + "integrity": "sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -2632,6 +2755,28 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, + "node_modules/graphql": { + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -2713,6 +2858,14 @@ "node": ">= 0.4" } }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dependencies": { + "react-is": "^16.7.0" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -3216,6 +3369,14 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-cookie": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz", + "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==", + "engines": { + "node": ">=14" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3560,7 +3721,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3701,6 +3861,28 @@ "wrappy": "1" } }, + "node_modules/optimism": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.18.0.tgz", + "integrity": "sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ==", + "dependencies": { + "@wry/caches": "^1.0.0", + "@wry/context": "^0.7.0", + "@wry/trie": "^0.4.3", + "tslib": "^2.3.0" + } + }, + "node_modules/optimism/node_modules/@wry/trie": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.4.3.tgz", + "integrity": "sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -4024,7 +4206,6 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -4663,8 +4844,7 @@ "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/read-cache": { "version": "1.0.0", @@ -4731,6 +4911,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/rehackt": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/rehackt/-/rehackt-0.1.0.tgz", + "integrity": "sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==", + "peerDependencies": { + "@types/react": "*", + "react": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", @@ -4771,6 +4968,14 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, + "node_modules/response-iterator": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/response-iterator/-/response-iterator-0.2.6.tgz", + "integrity": "sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -5308,6 +5513,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/tailwindcss": { "version": "3.4.4", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", @@ -5424,6 +5637,17 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true }, + "node_modules/ts-invariant": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz", + "integrity": "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -5808,6 +6032,19 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + }, + "node_modules/zen-observable-ts": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz", + "integrity": "sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==", + "dependencies": { + "zen-observable": "0.8.15" + } } } } diff --git a/package.json b/package.json index c6d80fd..7413a2c 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,12 @@ "dependencies": { "@ant-design/icons": "^5.3.7", "@ant-design/nextjs-registry": "^1.0.0", + "@apollo/client": "^3.10.8", + "@apollo/experimental-nextjs-app-support": "^0.11.2", "antd": "^5.19.2", + "axios": "^1.7.9", + "graphql": "^16.9.0", + "js-cookie": "^3.0.5", "next": "14.2.5", "react": "^18", "react-dom": "^18" diff --git a/src/app/auth/loading.js b/src/app/auth/loading.js new file mode 100644 index 0000000..282653b --- /dev/null +++ b/src/app/auth/loading.js @@ -0,0 +1,8 @@ +import {cookies} from "next/headers"; +import {redirect} from "next/navigation"; + +export default function Loading() { + if (cookies().get("session_token")) { + return redirect('/my') + } +} \ No newline at end of file diff --git a/src/app/auth/page.js b/src/app/auth/page.js index aaead16..755f236 100644 --- a/src/app/auth/page.js +++ b/src/app/auth/page.js @@ -1,16 +1,46 @@ "use client" -import {Form, Button, Input} from "antd"; +import {Form, Button, Input, message} from "antd"; +import {useRouter} from "next/navigation"; + + +const msgLoginSuccess = () => message.success("Вы успешно вошли в систему") +const msgLoginError = () => message.error("Неверный логин или пароль") const AuthPage = () => { + const router = useRouter() + const onFinish = (values) => { + + fetch("http://localhost:8000/api/v1/auth", { + headers: { + "Content-Type": "application/json" + }, + credentials: "include", + method: "POST", + body: JSON.stringify(values) + }).then((response) => { + if (response.ok) { + msgLoginSuccess() + router.push("/my") + } else { + msgLoginError() + } + }) + }; return ( <> -
- - + { + e.preventDefault() + }} + > + + - + diff --git a/src/app/globals.css b/src/app/globals.css index 405ce3f..91b3ffc 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -2,29 +2,6 @@ @tailwind components; @tailwind utilities; -/*:root {*/ -/* --foreground-rgb: 0, 0, 0;*/ -/* --background-start-rgb: 214, 219, 220;*/ -/* --background-end-rgb: 255, 255, 255;*/ -/*}*/ - -/*@media (prefers-color-scheme: dark) {*/ -/* :root {*/ -/* --foreground-rgb: 255, 255, 255;*/ -/* --background-start-rgb: 0, 0, 0;*/ -/* --background-end-rgb: 0, 0, 0;*/ -/* }*/ -/*}*/ - -/*body {*/ -/* color: rgb(var(--foreground-rgb));*/ -/* background: linear-gradient(*/ -/* to bottom,*/ -/* transparent,*/ -/* rgb(var(--background-end-rgb))*/ -/* )*/ -/* rgb(var(--background-start-rgb));*/ -/*}*/ @layer utilities { .text-balance { diff --git a/src/app/layout.js b/src/app/layout.js index 34dbf24..4f1919a 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -3,6 +3,7 @@ import "./globals.css"; import {Col, ConfigProvider, Layout, Row, Typography} from "antd"; import Logo from "@/components/header/logo"; import {AntdRegistry} from "@ant-design/nextjs-registry"; +import Link from "next/link"; const inter = Inter({subsets: ["latin"]}); @@ -17,27 +18,33 @@ export default function RootLayout({children}) { -
- + Система Обновлений MPUpdate
- {children} + {children}
diff --git a/src/app/my/application/[appId]/page.js b/src/app/my/application/[appId]/page.js new file mode 100644 index 0000000..059fc01 --- /dev/null +++ b/src/app/my/application/[appId]/page.js @@ -0,0 +1,40 @@ +"use client" +import {Col, Row} from "antd"; +import UpdationTable from "@/components/my/application/updationTable"; +import Title from "@/components/my/application/title" +import AddUpdate from "@/components/my/application/addUpdateModal"; +import {useEffect, useState} from "react"; +import AppService from "@/services/appService"; + + + +const ApplicationPage = ({params: { appId }}) => { + + const [isLoading, setIsLoading] = useState(false) + const [appData, setAppData] = useState({ + + }) + + useEffect(() => { + setIsLoading(true) + AppService.listApplications().then((res) => { + console.log(res.data[appId]) + setAppData(res.data[appId]) + setIsLoading(false) + }) + }, [appId]); + return ( + <> + + + {appData.appName} + + + + + + + ) +} + +export default ApplicationPage \ No newline at end of file diff --git a/src/app/my/layout.js b/src/app/my/layout.js new file mode 100644 index 0000000..213c2f4 --- /dev/null +++ b/src/app/my/layout.js @@ -0,0 +1,14 @@ +import {Col, Row} from "antd"; + +export const metadata = { + title: "Список приложений | Система обновлений MPUpdate", +}; + +export default function AppWrapper({children}) { + return ( + + {children} + + + ) +} \ No newline at end of file diff --git a/src/app/my/page.js b/src/app/my/page.js index 86de46c..23b7477 100644 --- a/src/app/my/page.js +++ b/src/app/my/page.js @@ -1,13 +1,27 @@ "use client" -import {Button, Col, Form, Input, Modal, Row, Table, Typography} from "antd"; -import {useState} from "react"; +import {Button, Col, Row, Table, Typography} from "antd"; +import {useEffect, useState} from "react"; import CreateAppModal from "@/components/my/createAppModal"; +import {useRouter} from "next/navigation"; +import AppService from "@/services/appService"; const MyPage = () => { + const [apps, setApps] = useState([]) + const [isLoading, setIsLoading] = useState(true) + const router = useRouter() const [isCreateAppModalOpened, setIsCreateAppModalOpened] = useState(false) + useEffect(() => { + setIsLoading(true) + AppService.listApplications().then((res) => { + setApps(Object.values(res.data)) + setIsLoading(false) + }) + + }, []); + const handleOkIsCreateAppModalOpened = () => { setIsCreateAppModalOpened(false) } @@ -18,37 +32,33 @@ const MyPage = () => { return ( <> - - - - - Список приложений - - - - - - - - - - - - - { - return - } - }> -
+ + + Список приложений + + + + + + + + + + {d.versions[0].id}}/> + { + return + } + }> +
) } - export default MyPage; \ No newline at end of file diff --git a/src/app/page.js b/src/app/page.js index 65fd309..01a1bae 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -1,9 +1,5 @@ -import Image from "next/image"; +import {redirect} from "next/navigation"; export default function Home() { - return ( -
- -
- ); + return redirect("/my") } diff --git a/src/components/my/application/addUpdateModal.js b/src/components/my/application/addUpdateModal.js new file mode 100644 index 0000000..9536ae6 --- /dev/null +++ b/src/components/my/application/addUpdateModal.js @@ -0,0 +1,88 @@ +"use client" + +import {Button, Col, Form, Input, Modal, Progress, Row, Typography, Upload} from "antd"; +import {useState} from "react"; +import AppService from "@/services/appService"; + +export function AddUpdateModalBtn(setIsModalVisible) { + return ( + + ) +} + +export function AddUpdateModal({isVisible, onOk, onCancel}) { + const [description, setDescription] = useState("") + const [versionId, setVersionId] = useState("") + const [link, setLink] = useState("") + const [progressUpload, setProgressUpload] = useState(0) + + const sendFileHandler = (file) => { + AppService.uploadApp(file, {onProgress: (p) => setProgressUpload(p)}).then(d => { + setLink(d.link) + }) + } + + return ( + {}} onCancel={onCancel} okText={"Добавить обновление"} footer={() => <>}> + + + + + + + setDescription(e.target.value)}/> + + + + + + setVersionId(e.target.value)}/> + + + + + + + + + + sendFileHandler(e.target.files[0])}/> + + + + + + + + + + + + ) + +} + +export default function AddUpdate({appId}) { + const [isModalVisible, setIsModalVisible] = useState(false); + const onOkCb = ({id, link, description}) => { + if (id ) + AppService.addVersion({id, appId, link, description}).then(d => { + setIsModalVisible(false) + }) + + } + const onCancelCb = () => { + setIsModalVisible(false) + } + + return ( + <> + + + + + + ) + +} diff --git a/src/components/my/application/title.js b/src/components/my/application/title.js new file mode 100644 index 0000000..b7c9726 --- /dev/null +++ b/src/components/my/application/title.js @@ -0,0 +1,6 @@ +"use client" +import {Typography} from "antd"; + +export default function Title({children}) { + return {children} +} \ No newline at end of file diff --git a/src/components/my/application/updationTable.js b/src/components/my/application/updationTable.js new file mode 100644 index 0000000..d0653e1 --- /dev/null +++ b/src/components/my/application/updationTable.js @@ -0,0 +1,17 @@ +"use client" + +import {Button, Table} from "antd"; + +export default function UpdationTable({dataSource}) { + + return ( +
+ + + + + }/> +
+
+ ) +} \ No newline at end of file diff --git a/src/components/my/createAppModal.jsx b/src/components/my/createAppModal.jsx index edd6354..6839d54 100644 --- a/src/components/my/createAppModal.jsx +++ b/src/components/my/createAppModal.jsx @@ -1,48 +1,42 @@ -import {Button, Col, Divider, Form, Input, message, Modal, Row, Space, Typography} from "antd"; -import Upload from "@/components/my/upload"; +import {Button, Col, Divider, Form, Input, message, Modal, Progress, Row, Space, Typography} from "antd"; import {useState} from "react"; - - -const uploadProps = { - name: 'file', - multiple: false, - action: 'https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload', - - beforeUpload: (file) => { - const isAPK = file.type === 'application/vnd.android.package-archive'; - if (!isAPK) { - message.error(`${file.name} не является APK файлом`); - } - return isAPK || Upload.LIST_IGNORE; - }, - - onChange(info) { - const { status } = info.file; - if (status !== 'uploading') { - console.log(info.file, info.fileList); - } - if (status === 'done') { - message.success(`${info.file.name} file uploaded successfully.`); - } else if (status === 'error') { - message.error(`${info.file.name} file upload failed.`); - } - }, - onDrop(e) { - console.log('Dropped files', e.dataTransfer.files); - }, -}; +import {useRouter} from "next/navigation"; +import AppService from "@/services/appService"; const CreateAppModal = ({isOpen, handleCancel}) => { - + const router = useRouter() const [isTitleFocused, setIsTitleFocused] = useState(false) const [appName, setAppName] = useState("Название приложения") + const [appVersion, setAppVersion] = useState("") + const [appDescription, setAppDescription] = useState("") + const [link, setLink] = useState() + const [appId, setAppId] = useState() + + const [progressUpload, setProgressUpload] = useState(0) + + + const sendFileHandler = (file) => { + AppService.uploadApp(file, {onProgress: (p) => setProgressUpload(p)}).then(d => { + setLink(d.link) + }) + } + return ( AppService.createApp({ + id: appId, + appName, + version: appVersion, + description: appDescription, + link + }).then(() => { + handleCancel() + router.refresh() + })} onCancel={handleCancel} width={"50%"} > @@ -51,21 +45,28 @@ const CreateAppModal = ({isOpen, handleCancel}) => {
- + setIsTitleFocused(true)}>{appName} setAppName(e.target.value)} className={isTitleFocused ? "inline": "!hidden"} /> + - - + + setAppId(e.target.value)}/> + + + + + + setAppDescription(e.target.value)}/> - - + + setAppVersion(e.target.value)}/> @@ -73,11 +74,12 @@ const CreateAppModal = ({isOpen, handleCancel}) => { - + + + sendFileHandler(e.target.files[0])}/> + - -
) diff --git a/src/components/my/upload.jsx b/src/components/my/upload.jsx index f3e209f..c75ba76 100644 --- a/src/components/my/upload.jsx +++ b/src/components/my/upload.jsx @@ -1,18 +1,30 @@ import {Upload} from 'antd'; import {InboxOutlined} from "@ant-design/icons"; +import AppService from "@/services/appService"; -const UploadComponent = (props) => { - return ( - -

- -

-

Загрузка .apk файла

-

- Выберите или перетащите файл в данную область -

-
- ) + +const uploadHandler = () => { + AppService.uploadApp() } +// const UploadComponent = (props) => { +// return ( +// { +// return new Promise((resolve, reject) => { +// AppService.uploadApp(file).then(d => +// resolve(d.data.link) +// ) +// }) +// }}> +//

+// +//

+//

Загрузка .apk файла

+//

+// Выберите или перетащите файл в данную область +//

+//
+// ) +// } + export default UploadComponent; \ No newline at end of file diff --git a/src/services/appService.js b/src/services/appService.js new file mode 100644 index 0000000..544b9e3 --- /dev/null +++ b/src/services/appService.js @@ -0,0 +1,50 @@ +import $instance, {BASE_URL} from "@/services/default"; +export default class AppService { + static async listApplications() { + return await $instance.get("/updates/list-app") + } + + static uploadApp(file, {onProgress}) { + return new Promise((resolve, reject) => { + const xhr = new XMLHttpRequest() + + xhr.upload.onprogress = (event) => { + onProgress?.(Math.round((event.loaded / event.total) * 100)); + }; + + xhr.open("POST", `${BASE_URL}/updates/upload`) + xhr.onload = () => { + xhr.status === 200 ? resolve(JSON.parse(xhr.response)) : reject(xhr.response) + } + + const fileData = new FormData(); + fileData.append("version", file) + + xhr.send(fileData) + + + + + }) + // return await $instance.postForm("/updates/upload", { + // "version": file + // }, { + // headers: { + // "Content-Type": "multipart/form-data" + // } + // }) + } + + static async createApp({id, appName, version, description, link}) { + return await $instance.post("/updates/create-app", { + id, appName, version, description, link + }) + + } + + static async addVersion({id, appId, link, description}) { + return await $instance.post("/updates/create", { + id, appId, link, description + }) + } +} \ No newline at end of file diff --git a/src/services/default.js b/src/services/default.js new file mode 100644 index 0000000..9aae95a --- /dev/null +++ b/src/services/default.js @@ -0,0 +1,10 @@ +import axios from "axios"; + +export const BASE_URL = "http://localhost:8001/api" + +const $instance = axios.create({ + baseURL: BASE_URL +}) + + +export default $instance; \ No newline at end of file