Skip to content

Commit

Permalink
Merge branch 'main' into google
Browse files Browse the repository at this point in the history
  • Loading branch information
rjsdn0 authored Nov 19, 2024
2 parents 8504421 + dbcf6d2 commit 4ba7832
Show file tree
Hide file tree
Showing 13 changed files with 239 additions and 90 deletions.
71 changes: 71 additions & 0 deletions .github/workflows/cd-prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Push Prod Image to GHCR
permissions:
contents: read
packages: write

on:
push:
branches:
- main

jobs:
publish-docker-image:
name: Build and Push
runs-on: ubuntu-latest

strategy:
fail-fast: true
matrix:
include:
- dockerfile: ./.docker/web.Dockerfile
image: ghcr.io/sparcs-kaist/biseo-web
- dockerfile: ./.docker/api.Dockerfile
image: ghcr.io/sparcs-kaist/biseo-api

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Cache Docker Layers
uses: actions/cache@v3
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Log in to Github Container Registry
uses: docker/login-action@v3
with:
registry: "ghcr.io"
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract Metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ matrix.image }}
tags: |
type=raw,value=latest
type=sha,format=long
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ${{ matrix.dockerfile }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new

- name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
64 changes: 0 additions & 64 deletions .github/workflows/push_image_ecr.yml

This file was deleted.

7 changes: 6 additions & 1 deletion packages/api/src/listener/agenda.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as schema from "@biseo/interface/agenda";
import { retrieveAll, vote } from "@biseo/api/service/agenda";
import { retrieveAll, editVote, vote } from "@biseo/api/service/agenda";

import { Router } from "@biseo/api/lib/listener";

Expand All @@ -9,6 +9,11 @@ router.on("agenda.retrieveAll", schema.RetrieveAll, async (_, { user }) =>
retrieveAll(user),
);

router.on("agenda.edit", schema.EditVote, async (req, { io, user }) => {
await editVote(req, io, user);
return {};
});

router.on("agenda.vote", schema.Vote, async (req, { io, user }) => {
await vote(req, io, user);
return {};
Expand Down
48 changes: 48 additions & 0 deletions packages/api/src/service/agenda.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,54 @@ export const retrieveAll = async (
return res;
};

export const editVote = async (
{ choiceId, agendaId }: schema.Vote,
io: BiseoServer,
user: User,
) => {
const existingVote = await prisma.userChoice.findFirst({
where: {
userId: user.id,
choice: {
agendaId,
},
},
});

if (!existingVote) throw new BiseoError("No previous vote found");

await prisma.userChoice.delete({
where: {
userId_choiceId: {
userId: user.id,
choiceId: existingVote.choiceId,
},
},
});

await prisma.userChoice.create({
data: {
userId: user.id,
choiceId,
},
});

io.to(`user/${user.username}`).emit("agenda.voted", {
id: agendaId,
user: { voted: choiceId },
voters: {
voted: await prisma.userChoice.count({
where: {
choice: { agendaId },
},
}),
total: await prisma.userAgendaVotable.count({
where: { agendaId },
}),
},
});
};

export const vote = async (
{ choiceId, agendaId }: schema.Vote,
io: BiseoServer,
Expand Down
12 changes: 12 additions & 0 deletions packages/interface/src/agenda/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ export type RetrieveAll = z.infer<typeof RetrieveAll>;
export const RetrieveAllCb = z.array(Agenda);
export type RetrieveAllCb = z.infer<typeof RetrieveAllCb>;

/**
* Edit Vote
* description
*/
export const EditVote = z.object({
choiceId: z.number(),
agendaId: z.number(),
});
export type EditVote = z.infer<typeof EditVote>;
export const EditVoteCb = z.object({});
export type EditVoteCb = z.infer<typeof EditVoteCb>;

/**
* Vote
* description
Expand Down
2 changes: 2 additions & 0 deletions packages/interface/src/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type ClientToServerEvents = Events<{
agenda: {
retrieveAll: Ev<agenda.RetrieveAll, agenda.RetrieveAllCb>;
vote: Ev<agenda.Vote, agenda.VoteCb>;
edit: Ev<agenda.EditVote, agenda.EditVoteCb>;
template: {
create: Ev<agendaTemplate.Create, agendaTemplate.CreateCb>;
retrieveAll: Ev<agendaTemplate.RetrieveAll, agendaTemplate.RetrieveAllCb>;
Expand Down Expand Up @@ -59,6 +60,7 @@ export type ServerToClientEvents = Events<{
updated: Ev<agenda.Updated>;
started: Ev<agenda.Started>;
voted: Ev<agenda.Voted>;
voteEdited: Ev<agenda.Voted>;
terminated: Ev<agenda.Terminated>;
deleted: Ev<agenda.Deleted>;
reminded: Ev<agenda.Reminded>;
Expand Down
11 changes: 10 additions & 1 deletion packages/web/src/components/atoms/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,17 @@ export const Button = styled.button<{
w?: Size;
h?: Size;
color?: Color;
textColor?: Color;
padHorizontal?: number;
}>(
({ w = "fill", h = 28, color = "blue200", padHorizontal = 0, theme }) => css`
({
w = "fill",
h = 28,
color = "blue200",
textColor = "black",
padHorizontal = 0,
theme,
}) => css`
display: flex;
width: ${calcSize(w)};
height: ${calcSize(h)};
Expand All @@ -26,6 +34,7 @@ export const Button = styled.button<{
align-items: center;
line-height: 28px;
background-color: ${theme.colors[color]};
color: ${theme.colors[textColor]};
&:hover {
cursor: pointer;
Expand Down
3 changes: 3 additions & 0 deletions packages/web/src/components/atoms/ToggleSwitch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { bg, colors, h, margin, round, row, text, w } from "@biseo/web/styles";
import React from "react";

interface ToggleSwitchProps {
defaultValue: boolean;
handleToggle: () => void;
label: string;
}

export const ToggleSwitch: React.FC<ToggleSwitchProps> = ({
defaultValue,
handleToggle,
label,
}) => (
Expand All @@ -15,6 +17,7 @@ export const ToggleSwitch: React.FC<ToggleSwitchProps> = ({
type="checkbox"
id="toggle"
onChange={handleToggle}
checked={defaultValue}
css={[
w(0),
h(0),
Expand Down
8 changes: 7 additions & 1 deletion packages/web/src/components/molecules/AgendaCard/Group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ import { EmptyAgendaCard } from "./EmptyAgendaCard";

interface Props extends PropsWithChildren {
agendaStatus: AgendaStatus;
recentOnly?: boolean;
handleRecentOnly?: () => void;
}

export const Group: React.FC<Props> = ({
agendaStatus,
recentOnly = false,
handleRecentOnly = () => {},
children = null,
}) => (
Expand All @@ -50,7 +52,11 @@ export const Group: React.FC<Props> = ({
</div>
</div>
{agendaStatus === "terminated" && (
<ToggleSwitch label="최근 투표만" handleToggle={handleRecentOnly} />
<ToggleSwitch
label="최근 투표만"
defaultValue={recentOnly}
handleToggle={handleRecentOnly}
/>
)}
</div>
{Children.count(children) ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ const agendaTags = {

export const OngoingAgendaCard: React.FC<OngoingAgendaProps> = ({ agenda }) => {
const [chosenChoiceId, setChosenChoiceId] = useState(0);
const { voteAgenda } = useAgenda(state => ({
const [isEditing, setIsEditing] = useState(false);
const { voteAgenda, editVote } = useAgenda(state => ({
voteAgenda: state.voteAgenda,
editVote: state.editVote,
}));

const vote = useCallback(() => {
Expand All @@ -47,14 +49,20 @@ export const OngoingAgendaCard: React.FC<OngoingAgendaProps> = ({ agenda }) => {
[chosenChoiceId],
);

const submitEdit = useCallback(() => {
editVote(chosenChoiceId, agenda.id);
setIsEditing(false);
}, [chosenChoiceId, agenda.id]);

let choices: JSX.Element | JSX.Element[] = <NotVotableChoice />;
if (agenda.user.votable) {
if (agenda.user.voted) {
if (agenda.user.voted && !isEditing) {
choices = (
<CompletedChoice
choice={agenda.choices.find(
choice => choice.id === agenda.user.voted,
)}
onEdit={() => setIsEditing(true)}
/>
);
} else {
Expand Down Expand Up @@ -85,9 +93,20 @@ export const OngoingAgendaCard: React.FC<OngoingAgendaProps> = ({ agenda }) => {
<p css={[text.subtitle, text.gray500]}>{agenda.content}</p>
</div>
</div>
<div css={[column, gap(6)]}>
<p css={[text.body, text.blue600]}>{agenda.resolution}</p>
{choices}
<div css={[column, gap(10)]}>
<div css={[column, gap(6)]}>
<p css={[text.body, text.blue600]}>{agenda.resolution}</p>
{choices}
</div>
{isEditing && (
<div css={[row, justify.end, w("fill")]}>
<Button w={90} disabled={!chosen} onClick={submitEdit}>
<p css={[text.option1, chosen ? text.blue600 : text.blue300]}>
제출하기
</p>
</Button>
</div>
)}
</div>
{agenda.user.votable && !agenda.user.voted && (
<div css={[row, justify.end, w("fill")]}>
Expand Down
Loading

0 comments on commit 4ba7832

Please sign in to comment.