diff --git a/.pnpm-debug.log b/.pnpm-debug.log deleted file mode 100644 index 41b00f6..0000000 --- a/.pnpm-debug.log +++ /dev/null @@ -1,14 +0,0 @@ -{ - "0 debug pnpm:scope": { - "selected": 1 - }, - "1 error pnpm": { - "code": "ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND", - "err": { - "name": "pnpm", - "message": "No package.json (or package.yaml, or package.json5) was found in \"/home/jasper/go/src/spahl.ddns.net/jasper/wok-able-backend\".", - "code": "ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND", - "stack": "pnpm: No package.json (or package.yaml, or package.json5) was found in \"/home/jasper/go/src/spahl.ddns.net/jasper/wok-able-backend\".\n at readProjectManifest (/usr/pnpm-global/5/node_modules/.pnpm/pnpm@6.32.3/node_modules/pnpm/dist/pnpm.cjs:19818:13)\n at async Object.readProjectManifestOnly (/usr/pnpm-global/5/node_modules/.pnpm/pnpm@6.32.3/node_modules/pnpm/dist/pnpm.cjs:19822:28)\n at async readProjectManifestOnly (/usr/pnpm-global/5/node_modules/.pnpm/pnpm@6.32.3/node_modules/pnpm/dist/pnpm.cjs:43721:24)\n at async Object.handler (/usr/pnpm-global/5/node_modules/.pnpm/pnpm@6.32.3/node_modules/pnpm/dist/pnpm.cjs:177918:24)\n at async /usr/pnpm-global/5/node_modules/.pnpm/pnpm@6.32.3/node_modules/pnpm/dist/pnpm.cjs:182194:21\n at async run (/usr/pnpm-global/5/node_modules/.pnpm/pnpm@6.32.3/node_modules/pnpm/dist/pnpm.cjs:182168:34)\n at async runPnpm (/usr/pnpm-global/5/node_modules/.pnpm/pnpm@6.32.3/node_modules/pnpm/dist/pnpm.cjs:182387:5)\n at async /usr/pnpm-global/5/node_modules/.pnpm/pnpm@6.32.3/node_modules/pnpm/dist/pnpm.cjs:182379:7" - } - } -} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 014fb60..75ac022 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,22 +1,26 @@ { - // Verwendet IntelliSense zum Ermitteln möglicher Attribute. - // Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen. - // Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Launch Server", - "type": "go", - "request": "launch", - "mode": "debug", - "program": "main.go" - }, - { - "name": "Launch Package", - "type": "go", - "request": "launch", - "mode": "auto", - "program": "${fileDirname}" - } - ] -} \ No newline at end of file + // Verwendet IntelliSense zum Ermitteln möglicher Attribute. + // Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen. + // Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + + + { + "name": "Attach to Process", + "type": "go", + "request": "attach", + "mode": "local", + "processId": 0 + }, + { + "name": "Run Go Server", + "type": "go", + "request": "launch", + "mode": "debug", + "program": "${workspaceFolder}", + "env": {}, + "args": [] + } + ] +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d1d1f2e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,55 @@ +# syntax=docker/dockerfile:1 + +## +## Build Backend +## +FROM golang:1.18-buster AS build_backend +ENV GO111MODULE=on \ + CGO_ENABLE=1 \ + GOOS=linux \ + GOARCH=amd64 +WORKDIR /app + +COPY go.mod . +COPY go.sum . + +RUN go mod download +RUN apt update && apt install -y ca-certificates + +COPY *.go ./ +COPY auth/. auth/. +COPY controllers/. controllers/. +COPY models/. models/. +COPY server/. server/. + +RUN go build -a --installsuffix cgo -v -tags netgo -ldflags '-extldflags "-static"' -o /main . + +## +## Build Frontend +## +FROM node:16 AS build_frontend +WORKDIR /usr/src/app +RUN npm install -g pnpm + +COPY assets/package.json ./ +COPY assets/pnpm-lock.yaml ./ + +RUN pnpm i + +COPY assets/. . + +RUN pnpm build + +## +## Deploy +## +FROM scratch +LABEL maintainer="Jasper Spahl " + +ENV WOKABLE_MODE="release" +WORKDIR / +COPY --from=build_backend /main ./ +COPY --from=build_frontend /usr/src/app/dist/. assets/dist/. +EXPOSE 8080 + +ENTRYPOINT [ "/main" ] \ No newline at end of file diff --git a/assets/.dockerignore b/assets/.dockerignore new file mode 100644 index 0000000..5171c54 --- /dev/null +++ b/assets/.dockerignore @@ -0,0 +1,2 @@ +node_modules +npm-debug.log \ No newline at end of file diff --git a/assets/src/App.tsx b/assets/src/App.tsx index cc73c82..6946626 100644 --- a/assets/src/App.tsx +++ b/assets/src/App.tsx @@ -5,6 +5,7 @@ import { Route, Navigate, } from "react-router-dom"; +import { ThemeProvider } from "styled-components"; import { useAppDispatch, useAppSelector } from "./app/hooks"; import AuthRedirect from "./components/AuthRedirect"; @@ -22,11 +23,13 @@ const Loading = () =>

Loading

; const App: React.FC = () => { const dispatch = useAppDispatch(); const state = useAppSelector((state) => state.auth.state); + const theme = useAppSelector((state) => state.theme); useEffect(() => { dispatch(verify()); }, []); return ( <> + {state == "loading" ? ( @@ -102,6 +105,7 @@ const App: React.FC = () => { )} + ); }; diff --git a/assets/src/app/store.ts b/assets/src/app/store.ts index 03ae4bf..d6d8292 100644 --- a/assets/src/app/store.ts +++ b/assets/src/app/store.ts @@ -1,11 +1,13 @@ import { configureStore } from "@reduxjs/toolkit"; import AuthReducer from "../features/auth/auth-slice"; +import ThemeSlice from "../features/theme/theme-slice"; import {cardDeckApiSlice} from "../features/cardDecks/cardDeck-api-slice"; export const store = configureStore({ reducer: { auth: AuthReducer, + theme: ThemeSlice, [cardDeckApiSlice.reducerPath]: cardDeckApiSlice.reducer }, middleware: (getDefaultMiddleware) => { diff --git a/assets/src/components/Card/Card.tsx b/assets/src/components/Card/Card.tsx new file mode 100644 index 0000000..da4fbe2 --- /dev/null +++ b/assets/src/components/Card/Card.tsx @@ -0,0 +1,12 @@ +import React from 'react' +import { StyledCard } from './styled' + +const Card: React.FC = ({children}) => { + return ( + + {children} + + ) +} + +export default Card \ No newline at end of file diff --git a/assets/src/components/Card/styled.ts b/assets/src/components/Card/styled.ts new file mode 100644 index 0000000..e88c226 --- /dev/null +++ b/assets/src/components/Card/styled.ts @@ -0,0 +1,9 @@ +import styled from "styled-components"; + +export const StyledCard = styled.div` +border-radius: ${props => props.theme.borderRadius}; +padding: 16px; +width: 100%; +height: 100%; +box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19); +`; \ No newline at end of file diff --git a/assets/src/components/Header/styled.tsx b/assets/src/components/Header/styled.tsx index bd1de73..2a9d73e 100644 --- a/assets/src/components/Header/styled.tsx +++ b/assets/src/components/Header/styled.tsx @@ -4,8 +4,10 @@ export const HeaderWrapper = styled.div` left: var(--navbar-width); height: var(--toolbar-height); width: 100%; + align-self: flex-start; & > h1 { padding: 16px; + margin: 0; display: flex; align-items: center; height: 100%; diff --git a/assets/src/components/TextareaWithLabel/TextareaWithLabel.tsx b/assets/src/components/TextareaWithLabel/TextareaWithLabel.tsx index ec9b4f5..e992408 100644 --- a/assets/src/components/TextareaWithLabel/TextareaWithLabel.tsx +++ b/assets/src/components/TextareaWithLabel/TextareaWithLabel.tsx @@ -1,4 +1,5 @@ import React from "react"; +import Card from "../Card/Card"; import { TextareaWithLabelWrapper } from "./styled"; export interface ITextareaWithLabel { @@ -19,19 +20,21 @@ const TextareaWithLabel: React.FC = ({ rows, }) => { return ( - - - - + + + + + + ); }; diff --git a/assets/src/features/theme/theme-slice.ts b/assets/src/features/theme/theme-slice.ts new file mode 100644 index 0000000..13b465a --- /dev/null +++ b/assets/src/features/theme/theme-slice.ts @@ -0,0 +1,48 @@ +import { createSlice } from "@reduxjs/toolkit"; +export interface Color { + main: string; + contrastText: string; +} + +export interface ColorPalette { + common: Color; + muted: Color; + primary: Color; + secondary: Color; +} + +export interface Theme { + borderRadius: string; + palette: ColorPalette +} + +const initialState: Theme = { + borderRadius: "4px", + palette: { + common: { + main: "#ffffff", + contrastText: "#222831", + }, + muted: { + main: "#aaaaaa", + contrastText: "#222831" + }, + primary: { + main: "#726a95", + contrastText: '#ffffff' + }, + secondary: { + main: "#709bf0", + contrastText: "#ffffff", + } + } +} +const themeSlice = createSlice({ + name: "theme", + initialState, + reducers: { + } +}) + +export const {} = themeSlice.actions; +export default themeSlice.reducer; \ No newline at end of file diff --git a/assets/src/layouts/Base/Base.tsx b/assets/src/layouts/Base/Base.tsx index a9140b3..10643df 100644 --- a/assets/src/layouts/Base/Base.tsx +++ b/assets/src/layouts/Base/Base.tsx @@ -6,8 +6,8 @@ import Navbar from "../../components/Navbar/Navbar"; const Base: React.FC = () => { return ( - - + + ); }; diff --git a/assets/src/layouts/Base/styled.tsx b/assets/src/layouts/Base/styled.tsx index 9105b26..c71cee3 100644 --- a/assets/src/layouts/Base/styled.tsx +++ b/assets/src/layouts/Base/styled.tsx @@ -3,7 +3,8 @@ import styled from "styled-components"; export const BaseLayoutWrapper = styled.div` display: flex; padding: 0 0 0 var(--navbar-width); + flex-direction: column; width: 100%; height: 100%; overflow: hidden; -`; +`; \ No newline at end of file diff --git a/assets/src/pages/Deck/Deck.tsx b/assets/src/pages/Deck/Deck.tsx index 318ba7d..97f97be 100644 --- a/assets/src/pages/Deck/Deck.tsx +++ b/assets/src/pages/Deck/Deck.tsx @@ -7,6 +7,7 @@ import { useFetchCardDeckByIdQuery } from "../../features/cardDecks/cardDeck-api import { Link, useParams } from "react-router-dom"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; +import Card from "../../components/Card/Card"; const Decks: React.FC = () => { const { id } = useParams(); @@ -23,12 +24,14 @@ const Decks: React.FC = () => {

{data?.description}

{data?.cards.map((card) => ( - -
-
{card.front}
-
{card.back}
-
-
+ + +
+
{card.front}
+
{card.back}
+
+
+
))}
diff --git a/assets/src/pages/Deck/styled.tsx b/assets/src/pages/Deck/styled.tsx index 9e803ae..def6405 100644 --- a/assets/src/pages/Deck/styled.tsx +++ b/assets/src/pages/Deck/styled.tsx @@ -3,6 +3,7 @@ import styled from "styled-components"; export const DecksOuterWrapper = styled.div` height: 100%; width: 100%; + flex-grow: 1; padding-top: calc(var(--toolbar-height)); `; diff --git a/assets/src/pages/Decks/Decks.tsx b/assets/src/pages/Decks/Decks.tsx index 0dbb620..faddc85 100644 --- a/assets/src/pages/Decks/Decks.tsx +++ b/assets/src/pages/Decks/Decks.tsx @@ -8,6 +8,7 @@ import { Link } from "react-router-dom"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faPlus } from "@fortawesome/free-solid-svg-icons"; import { useAppSelector } from "../../app/hooks"; +import Card from "../../components/Card/Card"; const Decks: React.FC = () => { const username = useAppSelector((state) => state.auth.user?.username); @@ -21,13 +22,15 @@ const Decks: React.FC = () => { ) : ( {data.map((cardDeck) => ( - -
-
{cardDeck.title}
-
{cardDeck.description}
-
Karten: {cardDeck.cards.length}
-
- + + +
+
{cardDeck.title}
+
{cardDeck.description}
+
Karten: {cardDeck.cards.length}
+
+ +
))}
diff --git a/assets/src/styled.d.ts b/assets/src/styled.d.ts new file mode 100644 index 0000000..2d99ecc --- /dev/null +++ b/assets/src/styled.d.ts @@ -0,0 +1,6 @@ +import "styled-components"; + +import {Theme} from "./features/theme/theme-slice"; +declare module 'styled-components' { + export interface DefaultTheme extends Theme {} +} \ No newline at end of file diff --git a/assets/src/styles/Variables.ts b/assets/src/styles/Variables.ts index 90e03c2..73d451b 100644 --- a/assets/src/styles/Variables.ts +++ b/assets/src/styles/Variables.ts @@ -15,4 +15,4 @@ const Variables = css` } `; -export default Variables; +export default Variables; \ No newline at end of file diff --git a/controllers/authentication/auth.controller.go b/controllers/authentication/auth.controller.go index e316fce..05bdd4a 100644 --- a/controllers/authentication/auth.controller.go +++ b/controllers/authentication/auth.controller.go @@ -5,8 +5,8 @@ import ( "net/http" "github.com/gin-gonic/gin" - "spahl.ddns.net/jasper/wok-able-backend/auth" - "spahl.ddns.net/jasper/wok-able-backend/models" + "spahl.ddns.net/jasper/wok-able/auth" + "spahl.ddns.net/jasper/wok-able/models" ) func Register(c *gin.Context) { diff --git a/controllers/setup.go b/controllers/setup.go index fae1b8a..7e935dc 100644 --- a/controllers/setup.go +++ b/controllers/setup.go @@ -2,8 +2,8 @@ package controllers import ( "github.com/gin-gonic/gin" - auth "spahl.ddns.net/jasper/wok-able-backend/controllers/authentication" - v1 "spahl.ddns.net/jasper/wok-able-backend/controllers/v1" + auth "spahl.ddns.net/jasper/wok-able/controllers/authentication" + v1 "spahl.ddns.net/jasper/wok-able/controllers/v1" ) func Setup(c *gin.Engine) { diff --git a/controllers/v1/card/card.controller.go b/controllers/v1/card/card.controller.go index 94db5cb..af04382 100644 --- a/controllers/v1/card/card.controller.go +++ b/controllers/v1/card/card.controller.go @@ -5,8 +5,8 @@ import ( "strconv" "github.com/gin-gonic/gin" - "spahl.ddns.net/jasper/wok-able-backend/auth" - "spahl.ddns.net/jasper/wok-able-backend/models" + "spahl.ddns.net/jasper/wok-able/auth" + "spahl.ddns.net/jasper/wok-able/models" ) func getCardById(c *gin.Context) { diff --git a/controllers/v1/carddeck/carddeck.controller.go b/controllers/v1/carddeck/carddeck.controller.go index ea77a2e..08b0b59 100644 --- a/controllers/v1/carddeck/carddeck.controller.go +++ b/controllers/v1/carddeck/carddeck.controller.go @@ -5,8 +5,8 @@ import ( "strconv" "github.com/gin-gonic/gin" - "spahl.ddns.net/jasper/wok-able-backend/auth" - "spahl.ddns.net/jasper/wok-able-backend/models" + "spahl.ddns.net/jasper/wok-able/auth" + "spahl.ddns.net/jasper/wok-able/models" ) func getCardDecks(c *gin.Context) { diff --git a/controllers/v1/setup.go b/controllers/v1/setup.go index 1dcb06d..6218028 100644 --- a/controllers/v1/setup.go +++ b/controllers/v1/setup.go @@ -2,9 +2,9 @@ package v1 import ( "github.com/gin-gonic/gin" - "spahl.ddns.net/jasper/wok-able-backend/auth" - "spahl.ddns.net/jasper/wok-able-backend/controllers/v1/card" - "spahl.ddns.net/jasper/wok-able-backend/controllers/v1/carddeck" + "spahl.ddns.net/jasper/wok-able/auth" + "spahl.ddns.net/jasper/wok-able/controllers/v1/card" + "spahl.ddns.net/jasper/wok-able/controllers/v1/carddeck" ) func Setup(r *gin.RouterGroup) { diff --git a/go.mod b/go.mod index bc23369..06d0064 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module spahl.ddns.net/jasper/wok-able-backend +module spahl.ddns.net/jasper/wok-able go 1.18 diff --git a/main.go b/main.go index 264e5ba..504f61e 100644 --- a/main.go +++ b/main.go @@ -4,9 +4,9 @@ import ( "os" "github.com/gin-gonic/gin" - "spahl.ddns.net/jasper/wok-able-backend/auth" - "spahl.ddns.net/jasper/wok-able-backend/models" - "spahl.ddns.net/jasper/wok-able-backend/server" + "spahl.ddns.net/jasper/wok-able/auth" + "spahl.ddns.net/jasper/wok-able/models" + "spahl.ddns.net/jasper/wok-able/server" ) func main() { diff --git a/models/user.go b/models/user.go index 0ae8033..c14f6a8 100644 --- a/models/user.go +++ b/models/user.go @@ -4,7 +4,7 @@ import ( "crypto/rand" "gorm.io/gorm" - "spahl.ddns.net/jasper/wok-able-backend/auth" + "spahl.ddns.net/jasper/wok-able/auth" ) const saltSize = 64 diff --git a/server/server.go b/server/server.go index 08e11fd..baf356d 100644 --- a/server/server.go +++ b/server/server.go @@ -8,7 +8,7 @@ import ( "github.com/gin-contrib/static" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" - "spahl.ddns.net/jasper/wok-able-backend/controllers" + "spahl.ddns.net/jasper/wok-able/controllers" ) var httpServer *http.Server