Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

データフェッチおよびDockerビルドフローを追加 #22

Merged
merged 24 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9fffc0c
fix: フィールド名が間違えていた問題を修正
testusuke Apr 22, 2024
088d42a
change: protect route
testusuke Apr 22, 2024
a53530f
change: ユーザー一覧画面のデータフェッチを実装
testusuke Apr 22, 2024
cef7493
Merge branch 'refs/heads/main' into feature/data-fetching
testusuke Apr 22, 2024
75727b8
refactor: propsを改行するように変更
testusuke Apr 22, 2024
1f30d85
change: 行がクリックされた場合にユーザー詳細ページに飛ぶように変更
testusuke Apr 22, 2024
76d1c49
feat: add role models
testusuke Apr 22, 2024
a4493fc
wip commit
testusuke Apr 22, 2024
a2dc0a3
feat: userEditor
1nayu Apr 22, 2024
ba410da
feat: add method for create users with csv
testusuke Apr 22, 2024
ede2ffa
change: remove role permissions endpoint
testusuke Apr 22, 2024
1313bf7
feat: role list
testusuke Apr 22, 2024
c298071
feat: role editor
testusuke Apr 23, 2024
4af6c36
change: cardBackgroundでクリック時の関数を指定できるように変更
testusuke Apr 23, 2024
61676ae
change: revert cardBackgroundでクリック時の関数を指定できるように変更
testusuke Apr 23, 2024
22edc96
feat: ロール作成機能を追加
testusuke Apr 23, 2024
ea81942
change: 保存後画面移遷するように変更
testusuke Apr 23, 2024
6d017d1
refactor: remove unused import
testusuke Apr 23, 2024
e31b6bf
change: userにrole関連の関数を実装
testusuke Apr 23, 2024
e4a2090
change: user編集画面を実装
testusuke Apr 23, 2024
65344fb
change: roleルートを保護
testusuke Apr 23, 2024
8f3e757
chore: docker build を実装
testusuke Apr 23, 2024
4acd523
change: yarnファイルの追加
testusuke Apr 23, 2024
6158028
feat: healthエンドポイントの追加
testusuke Apr 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Docker

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

on:
push:
branches: [ 'main' ]
# Publish semver tags as releases.
tags: [ 'v*.*.*' ]
pull_request:
branches: [ main ]

env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}


jobs:
build:

runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v2

# Install the cosign tool except on PR
# https://github.com/sigstore/cosign-installer
- name: Install cosign
uses: sigstore/[email protected]
with:
cosign-release: 'v1.4.0'


# Workaround: https://github.com/docker/build-push-action/issues/461
- name: Setup Docker buildx
uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf

# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
29 changes: 29 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM node:18.20.0 AS Builder

WORKDIR /app

# fetch packages
COPY package*.json ./
COPY yarn.lock ./
RUN yarn

FROM node:18.20.0-alpine AS Runner

WORKDIR /app

COPY --from=Builder /app/package.json ./
COPY --from=Builder /app/node_modules/ ./node_modules/

# copy files for build
COPY app/ ./app/
COPY components/ ./components/
COPY src/ ./src/
COPY public/ ./public/
COPY tsconfig.json .
COPY next.config.mjs .
COPY middleware.ts .


EXPOSE 3000

CMD yarn build && yarn start
43 changes: 43 additions & 0 deletions app/(authenticated)/roles/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {Alert, Breadcrumbs, Button, Link, Stack, Typography} from "@mui/material";
import CardBackground from "@/components/layout/cardBackground";
import {roleFactory} from "@/src/models/RoleModel";
import {permissionFactory} from "@/src/models/PermissionModel";
import RoleEditor from "@/components/roles/roleEditor";

export default async function RoleDetailPage({params}: { params: { id: string } }) {
const roleId = parseInt(params.id, 10)
const role = await roleFactory().show(roleId)
const permissions = await permissionFactory().index()

if (isNaN(roleId) || !role) {
return (
<Stack spacing={1} mx={2} my={3}>
<Alert severity="error">
<Typography>ロールが存在しません。</Typography>
</Alert>

<Button variant="contained" href="/roles/">
ロール管理に戻る
</Button>
</Stack>
)
}

return (
<Stack spacing={1} mx={2} my={3}>
<Breadcrumbs aria-label="breadcrumb" sx={{pl: 2}}>
<Link underline="hover" color="inherit" href="/">
管理者のダッシュボード
</Link>
<Link underline="hover" color="inherit" href="/roles/">
ロール管理
</Link>
<Typography color="text.primary">{role.name}</Typography>
</Breadcrumbs>

<CardBackground title={`ロール情報`}>
<RoleEditor role={role} permissions={permissions}/>
</CardBackground>
</Stack>
)
}
26 changes: 26 additions & 0 deletions app/(authenticated)/roles/create/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {Stack, Breadcrumbs, Link, Typography} from "@mui/material";
import CardBackground from "@/components/layout/cardBackground";
import RoleCreator from "@/components/roles/roleCreator";

export default function RoleCreatePage() {


return (
<Stack spacing={1} mx={2} my={3}>
<Breadcrumbs aria-label="breadcrumb" sx={{pl: 2}}>
<Link underline="hover" color="inherit" href="/">
管理者のダッシュボード
</Link>
<Link underline="hover" color="inherit" href="/roles/">
ロール管理
</Link>
<Typography color="text.primary">ロール作成</Typography>
</Breadcrumbs>
<CardBackground
title={"ロール作成"}
>
<RoleCreator />
</CardBackground>
</Stack>
);
}
26 changes: 26 additions & 0 deletions app/(authenticated)/roles/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {Stack, Breadcrumbs, Link, Typography} from "@mui/material";
import {roleFactory} from "@/src/models/RoleModel";
import RolesAgGrid from "@/components/roles/rolesAgGrid";
import CardBackground from "@/components/layout/cardBackground";

export default async function RolesPage() {
const roles = await roleFactory().index()

return (
<Stack spacing={1} mx={2} my={3}>
<Breadcrumbs aria-label="breadcrumb" sx={{pl: 2}}>
<Link underline="hover" color="inherit" href="/">
管理者のダッシュボード
</Link>
<Typography color="text.primary">ロール管理</Typography>
</Breadcrumbs>
<CardBackground
title={"すべてのロール"}
button={"作成"}
link={"/roles/create"}
>
<RolesAgGrid roles={roles}/>
</CardBackground>
</Stack>
);
}
52 changes: 52 additions & 0 deletions app/(authenticated)/users/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {Alert, Breadcrumbs, Button, Link, Stack, Typography} from "@mui/material";
import CardBackground from "@/components/layout/cardBackground";
import {userFactory} from "@/src/models/UserModel";
import React from "react";
import UserEditor from "@/components/users/userEditor";
import {roleFactory} from "@/src/models/RoleModel";
import {classFactory} from "@/src/models/ClassModel";

export default async function UserDetailPage({params}: { params: { id: string } }) {
const userId = parseInt(params.id, 10)
const user = await userFactory().show(userId)
const userRole = await userFactory().getRole(userId)
const classes = await classFactory().index()
const roles = await roleFactory().index()

if (isNaN(userId) || !user) {
return (
<Stack spacing={1} mx={2} my={3}>
<Alert severity="error">
<Typography>ユーザーが存在しません。</Typography>
</Alert>

<Button variant="contained" href="/users/">
ユーザー管理に戻る
</Button>
</Stack>
)
}

return (
<Stack spacing={1} mx={2} my={3}>
<Breadcrumbs aria-label="breadcrumb" sx={{pl: 2}}>
<Link underline="hover" color="inherit" href="/">
管理者のダッシュボード
</Link>
<Link underline="hover" color="inherit" href="/users/">
ユーザー管理
</Link>
<Typography color="text.primary">{user.name}</Typography>
</Breadcrumbs>

<CardBackground title={`${user.name} さんの情報`}>
<UserEditor
user={user}
userRole={userRole}
classes={classes}
roles={roles}
/>
</CardBackground>
</Stack>
)
}
26 changes: 26 additions & 0 deletions app/(authenticated)/users/csv/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import {Stack, Breadcrumbs, Link, Typography} from "@mui/material";
import CardBackground from "@/components/layout/cardBackground";
import {classFactory} from "@/src/models/ClassModel";
import UserCreatingAutomation from "@/components/users/csv/userCreatingAutomation";

export default async function UsersPage() {
const classes = await classFactory().index()

return (
<Stack spacing={1} mx={2} my={3}>
<Breadcrumbs aria-label="breadcrumb" sx={{pl: 2}}>
<Link underline="hover" color="inherit" href="/">
管理者のダッシュボード
</Link>
<Link underline="hover" color="inherit" href="/users/" >
ユーザー管理
</Link>
<Typography color="text.primary">CSV</Typography>
</Breadcrumbs>

<CardBackground title={"ユーザーのCSV一括作成"} >
<UserCreatingAutomation classes={classes} />
</CardBackground>
</Stack>
);
}
19 changes: 15 additions & 4 deletions app/(authenticated)/users/page.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
import {Stack, Breadcrumbs, Link, Typography} from "@mui/material";
import CardBackground from "@/components/layout/cardBackground";
import UsersAgGrid from "@/components/users/usersAgGrid";
import {userFactory} from "@/src/models/UserModel";
import {classFactory} from "@/src/models/ClassModel";
import {teamFactory} from "@/src/models/TeamModel";

export default async function UsersPage() {
const users = await userFactory().index()
const classes = await classFactory().index()
const teams = await teamFactory().index()

export default function UsersPage() {
return (
<Stack spacing={1} mx={2} my={3}>
<Breadcrumbs aria-label="breadcrumb" sx={{pl:2}}>
<Breadcrumbs aria-label="breadcrumb" sx={{pl: 2}}>
<Link underline="hover" color="inherit" href="/">
管理者のダッシュボード
</Link>
<Typography color="text.primary">ユーザー管理</Typography>
</Breadcrumbs>
<CardBackground title={"すべてのユーザー"} button={"CSVで一括作成"}>
<UsersAgGrid/>
<CardBackground title={"すべてのユーザー"} button={"CSVで一括作成"} link={"/users/csv"}>
<UsersAgGrid
users={users}
classes={classes}
teams={teams}
/>
</CardBackground>
</Stack>
);
Expand Down
5 changes: 5 additions & 0 deletions app/api/healthz/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {NextResponse} from "next/server";

export async function GET() {
return NextResponse.json({ status: 'ok' });
}
17 changes: 12 additions & 5 deletions components/layout/cardBackground.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {Button, Card, Stack, Typography} from "@mui/material";
import React, { ReactNode } from 'react';
import React, {ReactNode} from 'react';

type CardProps = {
title?: string;
Expand All @@ -8,13 +8,20 @@ type CardProps = {
children?: ReactNode;
};

const CardBackground: React.FC<CardProps> = ({ title, button, link, children }) => {
const CardBackground: React.FC<CardProps> = ({title, button, link, children}) => {
return (
<>
<Card sx={{py:2, px:2}}>
<Stack pb={2} spacing={1} direction={"row"} justifyContent={"flex-start"} alignItems="center">
<Card sx={{py: 2, px: 2}}>
<Stack pb={2} spacing={1} direction={"row"} justifyContent={"flex-start"} alignItems="center">
{title && <Typography color={"primary.light"}>{title}</Typography>}
{button && <Button variant={"contained"} href={link}>{button}</Button>}
{button &&
<Button
variant={"contained"}
href={link}
>
{button}
</Button>
}
</Stack>
{children}
</Card>
Expand Down
Loading
Loading