Skip to content

Commit

Permalink
Merge main to branch
Browse files Browse the repository at this point in the history
  • Loading branch information
lanttu1243 committed Oct 23, 2024
2 parents 0bb9740 + b404712 commit 66474ee
Show file tree
Hide file tree
Showing 67 changed files with 16,899 additions and 6,289 deletions.
8 changes: 7 additions & 1 deletion .env.docker-compose.prod
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,10 @@ NEXT_REVALIDATION_KEY="veryprivatekey"
PUBLIC_FRONTEND_URL="http://localhost:3000"
PUBLIC_SERVER_URL="http://cms:3001"
PUBLIC_ILMOMASIINA_URL="https://ilmo.tietokilta.fi"
PUBLIC_LEGACY_URL="https://old.tietokilta.fi"
PUBLIC_LEGACY_URL="https://tietokilta.fi"

MAILGUN_SENDER=""
MAILGUN_RECEIVER=""
MAILGUN_API_KEY=""
MAILGUN_DOMAIN=""
MAILGUN_URL=""
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ PUBLIC_ILMOMASIINA_URL="https://ilmo.tietokilta.fi"
PUBLIC_LEGACY_URL="https://old.tietokilta.fi"
NEXT_PUBLIC_LASKUGENERAATTORI_URL="https://laskutus.tietokilta.fi"

MAILGUN_SENDER=""
MAILGUN_RECEIVER=""
MAILGUN_API_KEY=""
MAILGUN_DOMAIN=""
MAILGUN_URL=""

# variables required for Google OAuth 2.0, otherwise disabled
#GOOGLE_OAUTH_CLIENT_ID=
#GOOGLE_OAUTH_CLIENT_SECRET=
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ jobs:
- uses: pnpm/action-setup@v4
with:
version: 9.9.0
version: 9.12.1

- name: Use Node.js 22
uses: actions/setup-node@v4
with:
node-version: 22.6.0
node-version: 22.8.0
cache: "pnpm"

- name: Install dependencies
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
22.6.0
22.8.0
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Base image with Node.js
ARG NODE_VERSION=22.6.0
ARG NODE_VERSION=22.8.0
# Use a specific version of the Node.js Alpine image as the base. Alpine images are minimal and lightweight.
FROM node:${NODE_VERSION}-alpine AS base
# Update the package list and install libc6-compat. This package is often required for binary Node.js modules.
Expand Down
11 changes: 0 additions & 11 deletions apps/cms/.eslintrc.js

This file was deleted.

8 changes: 8 additions & 0 deletions apps/cms/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import ts from "typescript-eslint";
import server from "@tietokilta/eslint-config/server";

export default ts.config(...server, {
rules: {
"unicorn/prefer-node-protocol": "off",
},
});
24 changes: 15 additions & 9 deletions apps/cms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,28 @@
"codegen": "pnpm generate:types & pnpm generate:graphQLSchema",
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png}\" dist/",
"dev": "tsx watch src/server.ts",
"email": "email dev --dir src/emails",
"generate:graphQLSchema": "PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:graphQLSchema",
"generate:types": "PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:types",
"lint": "eslint \"./src/**/*.{js,ts}\"",
"lint": "eslint \"./src/**/*.{js,ts,jsx,tsx}\"",
"start": "NODE_ENV=production PAYLOAD_CONFIG_PATH=dist/payload.config.js node dist/server.js",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@azure/storage-blob": "^12.24.0",
"@azure/storage-blob": "^12.25.0",
"@payloadcms/bundler-webpack": "^1.0.7",
"@payloadcms/db-mongodb": "^1.7.2",
"@payloadcms/plugin-cloud-storage": "^1.1.3",
"@payloadcms/db-mongodb": "^1.7.3",
"@payloadcms/plugin-cloud-storage": "^1.2.0",
"@payloadcms/richtext-lexical": "^0.11.3",
"@react-email/components": "0.0.25",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express": "^4.21.1",
"form-data": "^4.0.1",
"lodash": "^4.17.21",
"mailgun.js": "^10.2.3",
"nanoid": "^3.3.7",
"papaparse": "^5.4.1",
"payload": "^2.27.0",
"payload": "^2.30.1",
"payload-plugin-oauth": "^2.2.0"
},
"devDependencies": {
Expand All @@ -39,13 +43,15 @@
"@tietokilta/ui": "workspace:*",
"@types/express": "^4.17.21",
"@types/express-fileupload": "^1.5.1",
"@types/lodash": "^4.17.7",
"@types/lodash": "^4.17.10",
"@types/papaparse": "^5.3.14",
"@types/react": "catalog:",
"copyfiles": "^2.4.1",
"eslint": "catalog:",
"react": "catalog:",
"tsx": "^4.19.0",
"typescript": "catalog:"
"react-email": "3.0.1",
"tsx": "^4.19.1",
"typescript": "catalog:",
"typescript-eslint": "catalog:"
}
}
60 changes: 60 additions & 0 deletions apps/cms/src/collections/honors/awarded-honors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type { CollectionConfig, FieldHook } from "payload/types";
import type { AwardedHonor } from "@tietokilta/cms-types/payload";
import { signedIn } from "../../access/signed-in";
import { guildYearField } from "../../fields/guild-year";

const formatDisplayTitle: FieldHook<AwardedHonor> = ({
data: awardedHonor,
}) => {
if (!awardedHonor?.name) {
return "Untitled member";
}

if (!awardedHonor.guildYear) {
return awardedHonor.name;
}

return `${awardedHonor.name}, ${awardedHonor.guildYear}`;
};

export const AwardedHonors = {
slug: "awarded-honors",
defaultSort: "-guildYear",
admin: {
useAsTitle: "displayTitle",
defaultColumns: ["description", "guildYear"],
},
access: {
read: () => true,
create: signedIn,
update: signedIn,
delete: signedIn,
},
fields: [
{
name: "displayTitle",
type: "text",
admin: {
hidden: true,
},
hooks: {
beforeChange: [formatDisplayTitle],
},
},
guildYearField({
name: "guildYear",
required: true,
}),
{
name: "name",
type: "text",
required: true,
},
{
name: "description",
type: "textarea",
required: false,
localized: true,
},
],
} as const satisfies CollectionConfig;
38 changes: 38 additions & 0 deletions apps/cms/src/collections/honors/honors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { CollectionConfig } from "payload/types";
import { signedIn } from "../../access/signed-in";

export const Honors = {
slug: "honors",
defaultSort: "-name",
admin: {
useAsTitle: "name",
defaultColumns: ["name", "awardedHonors"],
},
access: {
read: () => true,
create: signedIn,
update: signedIn,
delete: signedIn,
},
fields: [
{
name: "name",
type: "text",
required: true,
localized: true,
},
{
name: "awardedHonors",
type: "array",
required: true,
minRows: 1,
fields: [
{
name: "awardedHonor",
type: "relationship",
relationTo: "awarded-honors",
},
],
},
],
} as const satisfies CollectionConfig;
22 changes: 22 additions & 0 deletions apps/cms/src/collections/news.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ export const News: CollectionConfig = {
label: "PageLink",
value: "page",
},
{
label: "ExternalLink",
value: "external",
},
],
},
{
Expand All @@ -65,6 +69,24 @@ export const News: CollectionConfig = {
relationTo: "pages",
required: true,
},
{
name: "externalLink",
type: "text",
admin: {
condition: (_, siblingData) => siblingData.ctaType === "external",
},
validate: (value: unknown) => {
try {
// eslint-disable-next-line no-new -- we want to throw an error if the URL is invalid
new URL(value as string);
} catch {
return "Invalid URL";
}

return true;
},
required: true,
},
{
name: "type",
type: "select",
Expand Down
126 changes: 126 additions & 0 deletions apps/cms/src/collections/weekly-newsletters/newsletter-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { Button } from "@tietokilta/ui";
import * as React from "react";

const getIdFromUrl = (): string => {
const pathArray = window.location.pathname.split("/");
const id = pathArray[pathArray.length - 1];
return id;
};

const getTelegramMessage = async (
locale: string,
): Promise<{
message: string;
}> => {
const newsletterId = getIdFromUrl();
const response = await fetch(
`/api/weekly-newsletters/telegram/${newsletterId}?locale=${locale}`,
);
return (await response.json()) as { message: string };
};

const copyTelegramMessage = async (locale: string): Promise<void> => {
const textToCopy = await getTelegramMessage(locale);
void navigator.clipboard.writeText(textToCopy.message);
};

const NewsletterButton = (): React.ReactElement => {
const handleButtonClick = async (): Promise<void> => {
// eslint-disable-next-line no-alert -- Good to have confirmation
const confirmed = confirm(
`Are you sure you want to send email? Remember to publish changes before.`,
);
if (!confirmed) return;
await fetch(`/api/weekly-newsletters/mail/${newsletterId}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
};
const buttonStyle = {
padding: "10px 20px",
fontSize: "16px",
borderRadius: "5px",
backgroundColor: "#000",
color: "white",
border: "none",
cursor: "pointer",
transition: "background-color 0.3s ease",
};
const buttonHoverStyle = {
backgroundColor: "#333333",
};
const newsletterId = getIdFromUrl();

return (
<div
style={{
display: "grid",
gridTemplateColumns: "repeat(2, 1fr)",
gridGap: "10px",
maxWidth: "400px",
margin: "0 auto",
}}
>
<Button
style={buttonStyle}
onMouseOver={(e) =>
((e.target as HTMLElement).style.backgroundColor =
buttonHoverStyle.backgroundColor)
}
onMouseOut={(e) =>
((e.target as HTMLElement).style.backgroundColor =
buttonStyle.backgroundColor)
}
onClick={() => void handleButtonClick()}
>
Send email
</Button>
<a
href={`/api/weekly-newsletters/mail/${newsletterId}`}
style={buttonStyle}
onMouseOver={(e) =>
((e.target as HTMLElement).style.backgroundColor =
buttonHoverStyle.backgroundColor)
}
onMouseOut={(e) =>
((e.target as HTMLElement).style.backgroundColor =
buttonStyle.backgroundColor)
}
>
Download HTML
</a>
<Button
style={buttonStyle}
onMouseOver={(e) =>
((e.target as HTMLElement).style.backgroundColor =
buttonHoverStyle.backgroundColor)
}
onMouseOut={(e) =>
((e.target as HTMLElement).style.backgroundColor =
buttonStyle.backgroundColor)
}
onClick={() => void copyTelegramMessage("fi")}
>
Copy finnish tg
</Button>
<Button
style={buttonStyle}
onMouseOver={(e) =>
((e.target as HTMLElement).style.backgroundColor =
buttonHoverStyle.backgroundColor)
}
onMouseOut={(e) =>
((e.target as HTMLElement).style.backgroundColor =
buttonStyle.backgroundColor)
}
onClick={() => void copyTelegramMessage("en")}
>
Copy english tg
</Button>
</div>
);
};

export default NewsletterButton;
Loading

0 comments on commit 66474ee

Please sign in to comment.