Merge branch 'i18n' into 'master'

i18n support for event, post and job ads

See merge request sahkoinsinoorikilta/vtmk/web2.0-frontend!51
This commit is contained in:
Aarni Halinen
2021-04-01 15:54:01 +00:00
32 changed files with 721 additions and 111 deletions
+3
View File
@@ -4,6 +4,9 @@ const withBundleAnalyzer = require("@next/bundle-analyzer")({
module.exports = withBundleAnalyzer({ module.exports = withBundleAnalyzer({
target: "server", target: "server",
publicRuntimeConfig: {
localeSubpaths: {},
},
images: { images: {
domains: [ domains: [
"sahkoinsinoorikilta.fi", "sahkoinsinoorikilta.fi",
+389
View File
@@ -15,6 +15,7 @@
"js-cookie": "2.2.1", "js-cookie": "2.2.1",
"lodash": "4.17.21", "lodash": "4.17.21",
"next": "10.1.2", "next": "10.1.2",
"next-i18next": "7.0.1",
"normalize.css": "8.0.1", "normalize.css": "8.0.1",
"react": "17.0.1", "react": "17.0.1",
"react-beautiful-dnd": "13.1.0", "react-beautiful-dnd": "13.1.0",
@@ -1887,6 +1888,23 @@
"postcss-syntax": ">=0.36.2" "postcss-syntax": ">=0.36.2"
} }
}, },
"node_modules/@types/body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
"dependencies": {
"@types/connect": "*",
"@types/node": "*"
}
},
"node_modules/@types/connect": {
"version": "3.4.34",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz",
"integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/error-stack-parser": { "node_modules/@types/error-stack-parser": {
"version": "1.3.18", "version": "1.3.18",
"resolved": "https://registry.npmjs.org/@types/error-stack-parser/-/error-stack-parser-1.3.18.tgz", "resolved": "https://registry.npmjs.org/@types/error-stack-parser/-/error-stack-parser-1.3.18.tgz",
@@ -1899,6 +1917,27 @@
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
"dev": true "dev": true
}, },
"node_modules/@types/express": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.11.tgz",
"integrity": "sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg==",
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.18",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"node_modules/@types/express-serve-static-core": {
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.19.tgz",
"integrity": "sha512-DJOSHzX7pCiSElWaGR8kCprwibCB/3yW6vcT8VG3P0SJjnv19gnWG/AZMfM60Xj/YJIp/YCaDHyvzsFVeniARA==",
"dependencies": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*"
}
},
"node_modules/@types/glob": { "node_modules/@types/glob": {
"version": "7.1.3", "version": "7.1.3",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
@@ -1950,6 +1989,11 @@
"@types/unist": "*" "@types/unist": "*"
} }
}, },
"node_modules/@types/mime": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
},
"node_modules/@types/minimatch": { "node_modules/@types/minimatch": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz",
@@ -1984,6 +2028,16 @@
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw=="
}, },
"node_modules/@types/qs": {
"version": "6.9.6",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz",
"integrity": "sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA=="
},
"node_modules/@types/range-parser": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
},
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "17.0.2", "version": "17.0.2",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.2.tgz",
@@ -2041,6 +2095,15 @@
"redux": "^4.0.0" "redux": "^4.0.0"
} }
}, },
"node_modules/@types/serve-static": {
"version": "1.13.9",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz",
"integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==",
"dependencies": {
"@types/mime": "^1",
"@types/node": "*"
}
},
"node_modules/@types/shortid": { "node_modules/@types/shortid": {
"version": "0.0.29", "version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/shortid/-/shortid-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/shortid/-/shortid-0.0.29.tgz",
@@ -6343,6 +6406,14 @@
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
"dev": true "dev": true
}, },
"node_modules/html-parse-stringify2": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz",
"integrity": "sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=",
"dependencies": {
"void-elements": "^2.0.1"
}
},
"node_modules/html-tags": { "node_modules/html-tags": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz",
@@ -6443,6 +6514,40 @@
"node": ">= 10" "node": ">= 10"
} }
}, },
"node_modules/i18next": {
"version": "19.9.2",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-19.9.2.tgz",
"integrity": "sha512-0i6cuo6ER6usEOtKajUUDj92zlG+KArFia0857xxiEHAQcUwh/RtOQocui1LPJwunSYT574Pk64aNva1kwtxZg==",
"dependencies": {
"@babel/runtime": "^7.12.0"
}
},
"node_modules/i18next-browser-languagedetector": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-5.0.1.tgz",
"integrity": "sha512-7K4A6DJ2rNz3Yd835Y493UgkzUxgpGsCeIMKLGkt6Ps0cbgSaJ+LdATFNFA+ujp2brmsUM9BeDThXKhabXUbUw==",
"dependencies": {
"@babel/runtime": "^7.5.5"
}
},
"node_modules/i18next-fs-backend": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-1.1.1.tgz",
"integrity": "sha512-RFkfy10hNxJqc7MVAp5iAZq0Tum6msBCNebEe3OelOBvrROvzHUPaR8Qe10RQrOGokTm0W4vJGEJzruFkEt+hQ=="
},
"node_modules/i18next-http-backend": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-1.2.1.tgz",
"integrity": "sha512-9L2sa+wybqi57/+VsrJPo5DCI7WLoudaK12xz0okYSmsi3Izyj7sCgrYL52WHy/O3BFY9HGORBwSwlD1WYuH6Q==",
"dependencies": {
"node-fetch": "2.6.1"
}
},
"node_modules/i18next-http-middleware": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/i18next-http-middleware/-/i18next-http-middleware-3.1.0.tgz",
"integrity": "sha512-65rP8bi5b7znBzfgIUy0KE00SWg1X6mL5XEkassgTrjAeLSfSb4vQ2bs9cN3qwHCynKIpmHjmNDu5c8NylTVmw=="
},
"node_modules/iconv-lite": { "node_modules/iconv-lite": {
"version": "0.6.2", "version": "0.6.2",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz",
@@ -8162,6 +8267,46 @@
} }
} }
}, },
"node_modules/next-i18next": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/next-i18next/-/next-i18next-7.0.1.tgz",
"integrity": "sha512-x97lSfB11q/5Flf1Ocz02WoXeIRuVi7oJQ+8p9kNSfoIJExz1nTLPpJmWr2SF8wDxaljzL/kjlETUOyptGhSjQ==",
"dependencies": {
"@types/express": "^4.16.1",
"core-js": "^3",
"hoist-non-react-statics": "^3.2.0",
"i18next": "^19.6.3",
"i18next-browser-languagedetector": "^5.0.0",
"i18next-fs-backend": "^1.0.7",
"i18next-http-backend": "^1.0.17",
"i18next-http-middleware": "^3.0.2",
"path-match": "^1.2.4",
"prop-types": "^15.6.2",
"react-i18next": "^11.7.3",
"url": "^0.11.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/isaachinman"
},
"peerDependencies": {
"next": ">= 9.5.0",
"react": ">= 16.8.0"
}
},
"node_modules/next-i18next/node_modules/core-js": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.10.0.tgz",
"integrity": "sha512-MQx/7TLgmmDVamSyfE+O+5BHvG1aUGj/gHhLn1wVtm2B5u1eVIPvh7vkfjwWKNCjrTJB8+He99IntSQ1qP+vYQ==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
"node_modules/next-sitemap": { "node_modules/next-sitemap": {
"version": "1.6.18", "version": "1.6.18",
"resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-1.6.18.tgz", "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-1.6.18.tgz",
@@ -9173,12 +9318,51 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/path-match": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/path-match/-/path-match-1.2.4.tgz",
"integrity": "sha1-pidH88fgwlFHYml/JEQ1hbCRAOo=",
"dependencies": {
"http-errors": "~1.4.0",
"path-to-regexp": "^1.0.0"
}
},
"node_modules/path-match/node_modules/http-errors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.4.0.tgz",
"integrity": "sha1-bAJC3qaz33r9oVPHEImzHG6Cqr8=",
"dependencies": {
"inherits": "2.0.1",
"statuses": ">= 1.2.1 < 2"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/path-match/node_modules/inherits": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
},
"node_modules/path-parse": { "node_modules/path-parse": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"dev": true "dev": true
}, },
"node_modules/path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"dependencies": {
"isarray": "0.0.1"
}
},
"node_modules/path-to-regexp/node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"node_modules/path-type": { "node_modules/path-type": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@@ -10268,6 +10452,19 @@
"react": "17.0.1" "react": "17.0.1"
} }
}, },
"node_modules/react-i18next": {
"version": "11.8.12",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.8.12.tgz",
"integrity": "sha512-M2PSVP9MzT/7yofXfCOF5gAVotinrM4BXWiguk8uFSznJsfFzTjrp3K9CBWcXitpoCBVZGZJ2AnbaWGSNkJqfw==",
"dependencies": {
"@babel/runtime": "^7.13.6",
"html-parse-stringify2": "^2.0.1"
},
"peerDependencies": {
"i18next": ">= 19.0.0",
"react": ">= 16.8.0"
}
},
"node_modules/react-is": { "node_modules/react-is": {
"version": "17.0.2", "version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -14074,6 +14271,14 @@
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ=="
}, },
"node_modules/void-elements": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
"integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/watchpack": { "node_modules/watchpack": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz",
@@ -15944,6 +16149,23 @@
"unist-util-find-all-after": "^3.0.2" "unist-util-find-all-after": "^3.0.2"
} }
}, },
"@types/body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
"requires": {
"@types/connect": "*",
"@types/node": "*"
}
},
"@types/connect": {
"version": "3.4.34",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.34.tgz",
"integrity": "sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==",
"requires": {
"@types/node": "*"
}
},
"@types/error-stack-parser": { "@types/error-stack-parser": {
"version": "1.3.18", "version": "1.3.18",
"resolved": "https://registry.npmjs.org/@types/error-stack-parser/-/error-stack-parser-1.3.18.tgz", "resolved": "https://registry.npmjs.org/@types/error-stack-parser/-/error-stack-parser-1.3.18.tgz",
@@ -15956,6 +16178,27 @@
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
"dev": true "dev": true
}, },
"@types/express": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.11.tgz",
"integrity": "sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg==",
"requires": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.18",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"@types/express-serve-static-core": {
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.19.tgz",
"integrity": "sha512-DJOSHzX7pCiSElWaGR8kCprwibCB/3yW6vcT8VG3P0SJjnv19gnWG/AZMfM60Xj/YJIp/YCaDHyvzsFVeniARA==",
"requires": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*"
}
},
"@types/glob": { "@types/glob": {
"version": "7.1.3", "version": "7.1.3",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
@@ -16007,6 +16250,11 @@
"@types/unist": "*" "@types/unist": "*"
} }
}, },
"@types/mime": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
},
"@types/minimatch": { "@types/minimatch": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz",
@@ -16041,6 +16289,16 @@
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz",
"integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw=="
}, },
"@types/qs": {
"version": "6.9.6",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz",
"integrity": "sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA=="
},
"@types/range-parser": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
},
"@types/react": { "@types/react": {
"version": "17.0.2", "version": "17.0.2",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.2.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.2.tgz",
@@ -16098,6 +16356,15 @@
"redux": "^4.0.0" "redux": "^4.0.0"
} }
}, },
"@types/serve-static": {
"version": "1.13.9",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz",
"integrity": "sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA==",
"requires": {
"@types/mime": "^1",
"@types/node": "*"
}
},
"@types/shortid": { "@types/shortid": {
"version": "0.0.29", "version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/shortid/-/shortid-0.0.29.tgz", "resolved": "https://registry.npmjs.org/@types/shortid/-/shortid-0.0.29.tgz",
@@ -19446,6 +19713,14 @@
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
"dev": true "dev": true
}, },
"html-parse-stringify2": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz",
"integrity": "sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=",
"requires": {
"void-elements": "^2.0.1"
}
},
"html-tags": { "html-tags": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz",
@@ -19515,6 +19790,40 @@
"integrity": "sha512-fbNJ+Gz5wx2LIBtMweJNY1D7Uc8p1XERi5KNRMccwfQA+rXlxWNSdUxswo0gT8XqxywTIw7Ywm/F4v/O35RdMg==", "integrity": "sha512-fbNJ+Gz5wx2LIBtMweJNY1D7Uc8p1XERi5KNRMccwfQA+rXlxWNSdUxswo0gT8XqxywTIw7Ywm/F4v/O35RdMg==",
"dev": true "dev": true
}, },
"i18next": {
"version": "19.9.2",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-19.9.2.tgz",
"integrity": "sha512-0i6cuo6ER6usEOtKajUUDj92zlG+KArFia0857xxiEHAQcUwh/RtOQocui1LPJwunSYT574Pk64aNva1kwtxZg==",
"requires": {
"@babel/runtime": "^7.12.0"
}
},
"i18next-browser-languagedetector": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-5.0.1.tgz",
"integrity": "sha512-7K4A6DJ2rNz3Yd835Y493UgkzUxgpGsCeIMKLGkt6Ps0cbgSaJ+LdATFNFA+ujp2brmsUM9BeDThXKhabXUbUw==",
"requires": {
"@babel/runtime": "^7.5.5"
}
},
"i18next-fs-backend": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-1.1.1.tgz",
"integrity": "sha512-RFkfy10hNxJqc7MVAp5iAZq0Tum6msBCNebEe3OelOBvrROvzHUPaR8Qe10RQrOGokTm0W4vJGEJzruFkEt+hQ=="
},
"i18next-http-backend": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-1.2.1.tgz",
"integrity": "sha512-9L2sa+wybqi57/+VsrJPo5DCI7WLoudaK12xz0okYSmsi3Izyj7sCgrYL52WHy/O3BFY9HGORBwSwlD1WYuH6Q==",
"requires": {
"node-fetch": "2.6.1"
}
},
"i18next-http-middleware": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/i18next-http-middleware/-/i18next-http-middleware-3.1.0.tgz",
"integrity": "sha512-65rP8bi5b7znBzfgIUy0KE00SWg1X6mL5XEkassgTrjAeLSfSb4vQ2bs9cN3qwHCynKIpmHjmNDu5c8NylTVmw=="
},
"iconv-lite": { "iconv-lite": {
"version": "0.6.2", "version": "0.6.2",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz",
@@ -20831,6 +21140,32 @@
} }
} }
}, },
"next-i18next": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/next-i18next/-/next-i18next-7.0.1.tgz",
"integrity": "sha512-x97lSfB11q/5Flf1Ocz02WoXeIRuVi7oJQ+8p9kNSfoIJExz1nTLPpJmWr2SF8wDxaljzL/kjlETUOyptGhSjQ==",
"requires": {
"@types/express": "^4.16.1",
"core-js": "^3",
"hoist-non-react-statics": "^3.2.0",
"i18next": "^19.6.3",
"i18next-browser-languagedetector": "^5.0.0",
"i18next-fs-backend": "^1.0.7",
"i18next-http-backend": "^1.0.17",
"i18next-http-middleware": "^3.0.2",
"path-match": "^1.2.4",
"prop-types": "^15.6.2",
"react-i18next": "^11.7.3",
"url": "^0.11.0"
},
"dependencies": {
"core-js": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.10.0.tgz",
"integrity": "sha512-MQx/7TLgmmDVamSyfE+O+5BHvG1aUGj/gHhLn1wVtm2B5u1eVIPvh7vkfjwWKNCjrTJB8+He99IntSQ1qP+vYQ=="
}
}
},
"next-sitemap": { "next-sitemap": {
"version": "1.6.18", "version": "1.6.18",
"resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-1.6.18.tgz", "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-1.6.18.tgz",
@@ -21581,12 +21916,52 @@
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true "dev": true
}, },
"path-match": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/path-match/-/path-match-1.2.4.tgz",
"integrity": "sha1-pidH88fgwlFHYml/JEQ1hbCRAOo=",
"requires": {
"http-errors": "~1.4.0",
"path-to-regexp": "^1.0.0"
},
"dependencies": {
"http-errors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.4.0.tgz",
"integrity": "sha1-bAJC3qaz33r9oVPHEImzHG6Cqr8=",
"requires": {
"inherits": "2.0.1",
"statuses": ">= 1.2.1 < 2"
}
},
"inherits": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
}
}
},
"path-parse": { "path-parse": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"dev": true "dev": true
}, },
"path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"requires": {
"isarray": "0.0.1"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
}
}
},
"path-type": { "path-type": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@@ -22443,6 +22818,15 @@
"scheduler": "^0.20.1" "scheduler": "^0.20.1"
} }
}, },
"react-i18next": {
"version": "11.8.12",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.8.12.tgz",
"integrity": "sha512-M2PSVP9MzT/7yofXfCOF5gAVotinrM4BXWiguk8uFSznJsfFzTjrp3K9CBWcXitpoCBVZGZJ2AnbaWGSNkJqfw==",
"requires": {
"@babel/runtime": "^7.13.6",
"html-parse-stringify2": "^2.0.1"
}
},
"react-is": { "react-is": {
"version": "17.0.2", "version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -25515,6 +25899,11 @@
"resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
"integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ=="
}, },
"void-elements": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
"integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
},
"watchpack": { "watchpack": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.1.1.tgz",
+1
View File
@@ -71,6 +71,7 @@
"js-cookie": "2.2.1", "js-cookie": "2.2.1",
"lodash": "4.17.21", "lodash": "4.17.21",
"next": "10.1.2", "next": "10.1.2",
"next-i18next": "7.0.1",
"normalize.css": "8.0.1", "normalize.css": "8.0.1",
"react": "17.0.1", "react": "17.0.1",
"react-beautiful-dnd": "13.1.0", "react-beautiful-dnd": "13.1.0",
+51
View File
@@ -0,0 +1,51 @@
{
"Lue lisää": "Read more",
"lngButton": "Suomeksi",
"Paikka": "Location",
"Alkaa": "Starts at",
"Päättyy": "Ends at",
"Lataa lisää": "Load more",
"Tapahtumat": "Events",
"Uutiset": "News",
"Hakemaasi sivua":
"Page",
"ei löydy":
"does not exist",
"Hups, tapahtui virhe": "Oops, an error occured",
"Lue lisää täältä": "More information here",
"Tärkeä tiedote!": "Important notice!",
"Katso kaikki tapahtumat":
"All events",
"Ilmoittaudu":
"Sign-up",
"Ilmoittautuminen":
"Sign-up",
"Peruuta":
"Cancel",
"Kokonaishinta":
"Total price",
"Ilmoittautuminen ei ole vielä auki!":
"Signup is not open yet!",
"Se aukeaa":
"Signup opens at",
"Ilmoittautumalla hyväksyn":
"By signing up I accept the",
"tietosuojaselosteen":
"privacy policy",
"ja tietojeni tallentamisen.":
"and storing of my data."
}
+3
View File
@@ -0,0 +1,3 @@
{
"lngButton": "In English"
}
+10 -24
View File
@@ -7,7 +7,7 @@ import breakpoints from "@theme/breakpoints";
interface WrappedCardProps { interface WrappedCardProps {
title: string; title: string;
start_time: string; startTime: string;
text: string; text: string;
link: string; link: string;
image?: { image?: {
@@ -15,6 +15,7 @@ interface WrappedCardProps {
alt: string; alt: string;
}; };
buttonOnClick?: () => void; buttonOnClick?: () => void;
buttonText?: string;
} }
const StyledCard = styled.article` const StyledCard = styled.article`
@@ -69,36 +70,21 @@ const StyledCard = styled.article`
`; `;
const WrappedCard: React.FC<WrappedCardProps> = ({ const WrappedCard: React.FC<WrappedCardProps> = ({
title, text, link, image, start_time, buttonOnClick, ...props title, text, link, image, startTime, buttonOnClick, buttonText, ...props
}) => { }) => (
const options: Intl.DateTimeFormatOptions = {
day: "numeric",
month: "numeric",
year: "numeric",
hour: "numeric",
minute: "2-digit",
};
const datetime = new Date(start_time).toLocaleString("fi-FI", options);
const button = (
<Link to={link}>
<button type="button" onClick={buttonOnClick}>
Lue lisää&nbsp;
</button>
</Link>
);
return (
<StyledCard {...props}> <StyledCard {...props}>
{image && ( {image && (
<Image src={image.src} alt={image.alt} layout="responsive" width={0} height={0} objectFit="scale-down" /> <Image src={image.src} alt={image.alt} layout="responsive" width={0} height={0} objectFit="scale-down" />
)} )}
<p>{datetime}</p> <p>{startTime}</p>
<h3>{title}</h3> <h3>{title}</h3>
<p>{text}</p> <p>{text}</p>
{button} <Link to={link}>
<button type="button" onClick={buttonOnClick}>
{buttonText}
</button>
</Link>
</StyledCard> </StyledCard>
); );
};
export default WrappedCard; export default WrappedCard;
+26
View File
@@ -0,0 +1,26 @@
import React from "react";
import styled from "styled-components";
import i18nNext from "../i18n";
import Icon, { IconType } from "./Icon";
const ChangeLanguageButton: React.FC = (props) => {
const { language, changeLanguage } = i18nNext.i18n;
return (
<button
{...props}
type="button"
onClick={() => {
changeLanguage(language === "fi" ? "en" : "fi");
}}
>
<Icon name={language === "fi" ? IconType.GBFlag : IconType.FinlandFlag} />
</button>
);
};
export default styled(ChangeLanguageButton)`
font-size: 4rem;
background: none;
border: none;
width: fit-content;
`;
+10 -2
View File
@@ -69,10 +69,18 @@ const nameToIcon = (name: IconType): JSX.Element | string => {
); );
} }
if (name === IconType.FinlandFlag) { if (name === IconType.FinlandFlag) {
return "🇫🇮"; return (
<span role="img">
🇫🇮
</span>
);
} }
if (name === IconType.GBFlag) { if (name === IconType.GBFlag) {
return "🇬🇧"; return (
<span role="img">
🇬🇧
</span>
);
} }
return null; return null;
}; };
+1
View File
@@ -10,3 +10,4 @@ export { default as InfoBox } from "./InfoBox";
export { default as Accordion } from "./Accordion/Accordion"; export { default as Accordion } from "./Accordion/Accordion";
export { default as Link } from "./Link"; export { default as Link } from "./Link";
export { default as CrossFadeImages } from "./CrossFadeImages"; export { default as CrossFadeImages } from "./CrossFadeImages";
export { default as ChangeLanguageButton } from "./ChangeLanguageButton";
+16
View File
@@ -0,0 +1,16 @@
import NextI18Next from "next-i18next";
import Config from "next/config";
import path from "path";
const NextI18NextInstance = new NextI18Next({
defaultLanguage: "fi",
defaultNS: "common",
localeSubpaths: Config().publicRuntimeConfig.localeSubpaths,
localePath: path.resolve("./public/locales"),
otherLanguages: ["en"],
});
export const { appWithTranslation, useTranslation } = NextI18NextInstance;
export default NextI18NextInstance;
+3 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import Head from "next/head"; import Head from "next/head";
import styled from "styled-components"; import styled from "styled-components";
@@ -25,4 +25,6 @@ const NotFoundPage: NextPage = () => (
</> </>
); );
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default NotFoundPage; export default NotFoundPage;
+2 -1
View File
@@ -5,6 +5,7 @@ import Head from "next/head";
import styled, { createGlobalStyle } from "styled-components"; import styled, { createGlobalStyle } from "styled-components";
import { ToastContainer } from "react-toastify"; import { ToastContainer } from "react-toastify";
import { colors } from "@theme/colors"; import { colors } from "@theme/colors";
import { appWithTranslation } from "../i18n";
import "react-mde/lib/styles/css/react-mde-all.css"; import "react-mde/lib/styles/css/react-mde-all.css";
import "react-toastify/dist/ReactToastify.css"; import "react-toastify/dist/ReactToastify.css";
@@ -158,4 +159,4 @@ const Web20App = ({ Component, pageProps }: AppProps) => (
// return { ...appProps } // return { ...appProps }
// } // }
export default Web20App; export default appWithTranslation(Web20App);
+3 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import { formatRelative } from "date-fns"; import { formatRelative } from "date-fns";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import styled from "styled-components"; import styled from "styled-components";
@@ -75,4 +75,6 @@ const AdminEventPage: NextPage = () => {
); );
}; };
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default AdminEventPage; export default AdminEventPage;
+3 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import { formatRelative } from "date-fns"; import { formatRelative } from "date-fns";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import styled from "styled-components"; import styled from "styled-components";
@@ -75,4 +75,6 @@ const AdminFeedPage: NextPage = () => {
); );
}; };
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default AdminFeedPage; export default AdminFeedPage;
+3 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import Head from "next/head"; import Head from "next/head";
import AdminPageWrapper from "@views/common/AdminPageWrapper"; import AdminPageWrapper from "@views/common/AdminPageWrapper";
@@ -16,4 +16,6 @@ const AdminFrontPage: NextPage = () => (
</> </>
); );
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default AdminFrontPage; export default AdminFrontPage;
+3 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import { formatRelative } from "date-fns"; import { formatRelative } from "date-fns";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import styled from "styled-components"; import styled from "styled-components";
@@ -79,4 +79,6 @@ const AdminJobAdPage: NextPage = () => {
); );
}; };
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default AdminJobAdPage; export default AdminJobAdPage;
+3 -1
View File
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import styled from "styled-components"; import styled from "styled-components";
import { generateToken, setTokenCookie, isAuthenticated } from "@utils/auth"; import { generateToken, setTokenCookie, isAuthenticated } from "@utils/auth";
@@ -80,4 +80,6 @@ const AdminLoginPage: NextPage = () => {
); );
}; };
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default AdminLoginPage; export default AdminLoginPage;
+3 -1
View File
@@ -1,4 +1,4 @@
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { deleteTokenCookie } from "@utils/auth"; import { deleteTokenCookie } from "@utils/auth";
@@ -12,4 +12,6 @@ const AdminLogoutPage: NextPage = () => {
return null; return null;
}; };
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default AdminLogoutPage; export default AdminLogoutPage;
+3 -1
View File
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import { formatRelative } from "date-fns"; import { formatRelative } from "date-fns";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import styled from "styled-components"; import styled from "styled-components";
@@ -84,4 +84,6 @@ const AdminSignupPage: NextPage = () => {
); );
}; };
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default AdminSignupPage; export default AdminSignupPage;
+3 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import Head from "next/head"; import Head from "next/head";
import FreshmenPageView from "@views/FreshmenPage/FreshmenPageView"; import FreshmenPageView from "@views/FreshmenPage/FreshmenPageView";
import PageWrapper from "@views/common/PageWrapper"; import PageWrapper from "@views/common/PageWrapper";
@@ -15,4 +15,6 @@ const FreshmenPage: NextPage = () => (
</> </>
); );
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default FreshmenPage; export default FreshmenPage;
+3 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import Head from "next/head"; import Head from "next/head";
import GuildPageView from "@views/GuildPage/GuildPageView"; import GuildPageView from "@views/GuildPage/GuildPageView";
import PageWrapper from "@views/common/PageWrapper"; import PageWrapper from "@views/common/PageWrapper";
@@ -15,4 +15,6 @@ const GuildPage: NextPage = () => (
</> </>
); );
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default GuildPage; export default GuildPage;
+3 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import Head from "next/head"; import Head from "next/head";
import HonoraryPageView from "@views/HonoraryPage/HonoraryPageView"; import HonoraryPageView from "@views/HonoraryPage/HonoraryPageView";
import PageWrapper from "@views/common/PageWrapper"; import PageWrapper from "@views/common/PageWrapper";
@@ -15,4 +15,6 @@ const HonoraryPage: NextPage = () => (
</> </>
); );
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default HonoraryPage; export default HonoraryPage;
+3 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import Head from "next/head"; import Head from "next/head";
import StudiesPageView from "@views/StudiesPage/StudiesPageView"; import StudiesPageView from "@views/StudiesPage/StudiesPageView";
import PageWrapper from "@views/common/PageWrapper"; import PageWrapper from "@views/common/PageWrapper";
@@ -15,4 +15,6 @@ const StudiesPage: NextPage = () => (
</> </>
); );
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default StudiesPage; export default StudiesPage;
+3 -1
View File
@@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { NextPage } from "next"; import { NextPage, GetStaticProps } from "next";
import Head from "next/head"; import Head from "next/head";
import ContactsPageView from "@views/ContactsPage/ContactsPageView"; import ContactsPageView from "@views/ContactsPage/ContactsPageView";
import PageWrapper from "@views/common/PageWrapper"; import PageWrapper from "@views/common/PageWrapper";
@@ -15,4 +15,6 @@ const ContactsPage: NextPage = () => (
</> </>
); );
export const getStaticProps: GetStaticProps = async () => ({ props: {} });
export default ContactsPage; export default ContactsPage;
+7 -3
View File
@@ -5,7 +5,7 @@ import Event from "@models/Event";
import Post from "@models/Feed"; import Post from "@models/Feed";
import { import {
Divider, CTASection, TextSection, Link, CrossFadeImages, Divider, CTASection, TextSection, Link, CrossFadeImages, ChangeLanguageButton,
} from "@components/index"; } from "@components/index";
import ActualPageHero from "./ActualPageHero"; import ActualPageHero from "./ActualPageHero";
import EventCalendar from "./EventCalendar"; import EventCalendar from "./EventCalendar";
@@ -32,14 +32,18 @@ const Gallery = styled.div`
} }
`; `;
const LngButton = styled(ChangeLanguageButton)`
align-self: flex-end;
margin-right: 1rem;
`;
const ActualPageView: React.FC<ActualPageViewProps> = ({ events, feed }) => ( const ActualPageView: React.FC<ActualPageViewProps> = ({ events, feed }) => (
<> <>
<ActualPageHero /> <ActualPageHero />
<LngButton />
<EventCalendar events={events} /> <EventCalendar events={events} />
<Divider /> <Divider />
<News feed={feed} /> <News feed={feed} />
<CTASection <CTASection
+30 -6
View File
@@ -5,6 +5,7 @@ import Button from "@components/Button";
import { CardSection, Card, FullWidthSection } from "@components/index"; import { CardSection, Card, FullWidthSection } from "@components/index";
import noop from "@utils/noop"; import noop from "@utils/noop";
import FilterContainer from "./FilterContainer"; import FilterContainer from "./FilterContainer";
import i18nNext, { useTranslation } from "../../i18n";
interface EventCalendarProps { interface EventCalendarProps {
events: Event[]; events: Event[];
@@ -13,11 +14,33 @@ interface EventCalendarProps {
const EventCalendar: React.FC<EventCalendarProps> = ({ events }) => { const EventCalendar: React.FC<EventCalendarProps> = ({ events }) => {
// const [filterSelected, setFilter] = useState(0); // const [filterSelected, setFilter] = useState(0);
const [numberShown, setNumberShown] = useState(8); const [numberShown, setNumberShown] = useState(8);
const filteredEvents = events.slice(0, numberShown);
const { t } = useTranslation();
const { language } = i18nNext.i18n;
const isFi = language === "fi";
const options: Intl.DateTimeFormatOptions = {
day: "numeric",
month: "numeric",
year: "numeric",
hour: "numeric",
minute: "2-digit",
};
const filteredEvents = events.slice(0, numberShown).map((e) => ({
...e,
title: isFi ? e.title_fi : e.title_en,
description: isFi ? e.description_fi : e.description_en,
content: isFi ? e.content_fi : e.content_en,
location: isFi ? e.location_fi : e.location_en,
startDate: new Date(e.start_time).toLocaleString(isFi ? "fi-FI" : "en-GB", options),
endDate: new Date(e.end_time).toLocaleString(isFi ? "fi-FI" : "en-GB", options),
}));
return ( return (
<FullWidthSection> <FullWidthSection>
<h1 id="tapahtumat"> <h1 id="tapahtumat">
Tapahtumat {t("Tapahtumat")}
{/* <FilterContainer> {/* <FilterContainer>
<Button buttonStyle="filter" onClick={() => { setFilter(0); }} selected={filterSelected === 0}> <Button buttonStyle="filter" onClick={() => { setFilter(0); }} selected={filterSelected === 0}>
Näytä kaikki Näytä kaikki
@@ -35,18 +58,19 @@ const EventCalendar: React.FC<EventCalendarProps> = ({ events }) => {
{filteredEvents.map((e) => ( {filteredEvents.map((e) => (
<Card <Card
key={e.id} key={e.id}
title={e.title_fi} title={e.title}
start_time={e.start_time} startTime={e.startDate}
text={e.description_fi} text={e.description}
link={`/events/${e.id}`} link={`/events/${e.id}`}
buttonOnClick={noop} buttonOnClick={noop}
buttonText={`${t("Lue lisää")} `}
/> />
))} ))}
</CardSection> </CardSection>
{ numberShown < events.length && ( { numberShown < events.length && (
<FilterContainer> <FilterContainer>
<Button buttonStyle="bordered" onClick={() => { setNumberShown(numberShown + 8); }}> <Button buttonStyle="bordered" onClick={() => { setNumberShown(numberShown + 8); }}>
Lataa lisää {t("Lataa lisää")}
</Button> </Button>
</FilterContainer> </FilterContainer>
)} )}
+27 -6
View File
@@ -5,6 +5,7 @@ import Button from "@components/Button";
import { CardSection, Card, FullWidthSection } from "@components/index"; import { CardSection, Card, FullWidthSection } from "@components/index";
import noop from "@utils/noop"; import noop from "@utils/noop";
import FilterContainer from "./FilterContainer"; import FilterContainer from "./FilterContainer";
import i18nNext, { useTranslation } from "../../i18n";
interface NewsProps { interface NewsProps {
feed: Post[]; feed: Post[];
@@ -13,11 +14,30 @@ interface NewsProps {
const News: React.FC<NewsProps> = ({ feed }) => { const News: React.FC<NewsProps> = ({ feed }) => {
// const [filterSelected, setFilter] = useState(0); // const [filterSelected, setFilter] = useState(0);
const [numberShown, setNumberShown] = useState(8); const [numberShown, setNumberShown] = useState(8);
const filteredFeed = feed.slice(0, numberShown);
const { t } = useTranslation();
const { language } = i18nNext.i18n;
const isFi = language === "fi";
const options: Intl.DateTimeFormatOptions = {
day: "numeric",
month: "numeric",
year: "numeric",
hour: "numeric",
minute: "2-digit",
};
const filteredFeed = feed.slice(0, numberShown).map((p) => ({
...p,
title: isFi ? p.title_fi : p.title_en,
description: isFi ? p.description_fi : p.description_en,
content: isFi ? p.content_fi : p.content_en,
publishTime: new Date(p.publish_time).toLocaleString(isFi ? "fi-FI" : "en-GB", options),
}));
return ( return (
<FullWidthSection> <FullWidthSection>
<h1 id="uutiset"> <h1 id="uutiset">
Uutiset {t("Uutiset")}
{/* <FilterContainer> {/* <FilterContainer>
<Button buttonStyle="filter" onClick={() => { setFilter(0); }} selected={filterSelected === 0}> <Button buttonStyle="filter" onClick={() => { setFilter(0); }} selected={filterSelected === 0}>
Näytä kaikki Näytä kaikki
@@ -34,18 +54,19 @@ const News: React.FC<NewsProps> = ({ feed }) => {
{filteredFeed.map((post) => ( {filteredFeed.map((post) => (
<Card <Card
key={post.id} key={post.id}
title={post.title_fi} title={post.title}
start_time={post.publish_time} startTime={post.publishTime}
text={post.description_fi} text={post.description}
link={`/feed/${post.id}`} link={`/feed/${post.id}`}
buttonOnClick={noop} buttonOnClick={noop}
buttonText={`${t("Lue lisää")} `}
/> />
))} ))}
</CardSection> </CardSection>
{ numberShown < feed.length && ( { numberShown < feed.length && (
<FilterContainer> <FilterContainer>
<Button buttonStyle="bordered" onClick={() => { setNumberShown(numberShown + 8); }}> <Button buttonStyle="bordered" onClick={() => { setNumberShown(numberShown + 8); }}>
Lataa lisää {t("Lataa lisää")}
</Button> </Button>
</FilterContainer> </FilterContainer>
)} )}
+33 -14
View File
@@ -4,11 +4,11 @@ import styled from "styled-components";
import colors from "@theme/colors"; import colors from "@theme/colors";
import Event from "@models/Event"; import Event from "@models/Event";
import Button from "@components/Button"; import Button from "@components/Button";
import { Link, TextSection } from "@components/index"; import { Link, TextSection, ChangeLanguageButton } from "@components/index";
import noop from "@utils/noop"; import noop from "@utils/noop";
import MarkdownStyles from "@views/common/MarkdownStyles"; import MarkdownStyles from "@views/common/MarkdownStyles";
import LoadingView from "@views/common/LoadingView"; import LoadingView from "@views/common/LoadingView";
import i18nNext, { useTranslation } from "../../i18n";
interface EventPageViewProps { interface EventPageViewProps {
event?: Event; event?: Event;
@@ -33,7 +33,6 @@ const StyledTextSection = styled(TextSection)`
line-height: 0.4rem; line-height: 0.4rem;
} }
} }
`; `;
const SignupButtons = styled.div` const SignupButtons = styled.div`
@@ -46,20 +45,39 @@ const Content = styled(MarkdownStyles)`
margin-top: 1.5rem; margin-top: 1.5rem;
`; `;
const LngButton = styled(ChangeLanguageButton)`
align-self: flex-end;
margin-right: 1rem;
`;
const EventPageView: React.FC<EventPageViewProps> = ({ event }) => { const EventPageView: React.FC<EventPageViewProps> = ({ event }) => {
const { t } = useTranslation();
if (!event) return <LoadingView />; if (!event) return <LoadingView />;
const date_start = new Date(event.start_time).toLocaleString("fi-FI"); const { language } = i18nNext.i18n;
const date_end = new Date(event.end_time).toLocaleString("fi-FI"); const isFi = language === "fi";
const {
title, description, content, location, startDate, endDate,
} = {
title: isFi ? event.title_fi : event.title_en,
description: isFi ? event.description_fi : event.description_en,
content: isFi ? event.content_fi : event.content_en,
location: isFi ? event.location_fi : event.location_en,
startDate: new Date(event.start_time).toLocaleString(isFi ? "fi-FI" : "en-GB"),
endDate: new Date(event.end_time).toLocaleString(isFi ? "fi-FI" : "en-GB"),
};
return ( return (
<>
<LngButton />
<StyledTextSection> <StyledTextSection>
<h1> <h1>
{event.title_fi} {title}
<p> <p>
{event.description_fi} {description}
</p> </p>
<Image <Image
src={event.image || event.tags[0].icon} src={event.image || event.tags[0].icon}
alt={event.title_fi} alt={title}
objectFit="scale-down" objectFit="scale-down"
layout="responsive" layout="responsive"
width={16} width={16}
@@ -67,28 +85,29 @@ const EventPageView: React.FC<EventPageViewProps> = ({ event }) => {
/> />
</h1> </h1>
<div> <div>
<Content source={event.content_fi} escapeHtml={false} /> <Content source={content} escapeHtml={false} />
<p> <p>
Paikka: {event.location_fi} {`${t("Paikka")}: ${location}`}
</p> </p>
<p> <p>
<time>Alkaa: {date_start}</time> <time>{`${t("Alkaa")}: ${startDate}`}</time>
</p> </p>
<p> <p>
<time>Päättyy: {date_end}</time> <time>{`${t("Päättyy")}: ${endDate}`}</time>
</p> </p>
{/* We may have multiple signup forms. Generate own Button for each one */} {/* We may have multiple signup forms. Generate own Button for each one */}
<SignupButtons> <SignupButtons>
{event.signupForm.map((sf) => ( {event.signupForm.map((sf) => (
<Link key={sf.id} to={`/signup/${sf.id}`}> <Link key={sf.id} to={`/signup/${sf.id}`}>
<Button buttonStyle="filled" onClick={noop}> <Button data-e2e="signup-button" buttonStyle="filled" onClick={noop}>
{sf.title_fi} {isFi ? sf.title_fi : sf.title_en}
</Button> </Button>
</Link> </Link>
))} ))}
</SignupButtons> </SignupButtons>
</div> </div>
</StyledTextSection> </StyledTextSection>
</>
); );
}; };
export default EventPageView; export default EventPageView;
+15 -4
View File
@@ -6,6 +6,7 @@ import Post from "@models/Feed";
import { TextSection } from "@components/index"; import { TextSection } from "@components/index";
import MarkdownStyles from "@views/common/MarkdownStyles"; import MarkdownStyles from "@views/common/MarkdownStyles";
import LoadingView from "@views/common/LoadingView"; import LoadingView from "@views/common/LoadingView";
import i18nNext from "../../i18n";
interface FeedPageViewProps { interface FeedPageViewProps {
post?: Post; post?: Post;
@@ -32,17 +33,27 @@ const Content = styled(MarkdownStyles)`
const FeedPageView: React.FC<FeedPageViewProps> = ({ post }) => { const FeedPageView: React.FC<FeedPageViewProps> = ({ post }) => {
if (!post) return <LoadingView />; if (!post) return <LoadingView />;
const { language } = i18nNext.i18n;
const isFi = language === "fi";
const {
title, description, content,
} = {
title: isFi ? post.title_fi : post.title_en,
description: isFi ? post.description_fi : post.description_en,
content: isFi ? post.content_fi : post.content_en,
};
return ( return (
<StyledTextSection> <StyledTextSection>
<h1> <h1>
{post.title_fi} {title}
<p> <p>
{post.description_fi} {description}
</p> </p>
{post.image && ( {post.image && (
<Image <Image
src={post.image} src={post.image}
alt={post.title_fi} alt={title}
objectFit="scale-down" objectFit="scale-down"
layout="responsive" layout="responsive"
width={16} width={16}
@@ -51,7 +62,7 @@ const FeedPageView: React.FC<FeedPageViewProps> = ({ post }) => {
)} )}
</h1> </h1>
<div> <div>
<Content source={post.content_fi} escapeHtml={false} /> <Content source={content} escapeHtml={false} />
</div> </div>
</StyledTextSection> </StyledTextSection>
); );
+12 -2
View File
@@ -32,6 +32,14 @@ interface FrontPageViewProps {
feed: Post[]; feed: Post[];
} }
const cardTimeOpts: Intl.DateTimeFormatOptions = {
day: "numeric",
month: "numeric",
year: "numeric",
hour: "numeric",
minute: "2-digit",
};
const SponsorReel = styled.div` const SponsorReel = styled.div`
text-align: center; text-align: center;
& > div { & > div {
@@ -72,7 +80,7 @@ const FrontPageView: React.FC<FrontPageViewProps> = ({ events, feed }) => (
<Card <Card
key={event.id} key={event.id}
title={event.title_fi} title={event.title_fi}
start_time={event.start_time} startTime={new Date(event.start_time).toLocaleString("fi-FI", cardTimeOpts)}
text={event.description_fi} text={event.description_fi}
link={`/events/${event.id}`} link={`/events/${event.id}`}
image={{ image={{
@@ -80,6 +88,7 @@ const FrontPageView: React.FC<FrontPageViewProps> = ({ events, feed }) => (
alt: event.title_fi, alt: event.title_fi,
}} }}
buttonOnClick={noop} buttonOnClick={noop}
buttonText="Lue lisää&nbsp;"
data-e2e="event-card" data-e2e="event-card"
/> />
))} ))}
@@ -104,10 +113,11 @@ const FrontPageView: React.FC<FrontPageViewProps> = ({ events, feed }) => (
<Card <Card
key={inst.id} key={inst.id}
title={inst.title_fi} title={inst.title_fi}
start_time={inst.publish_time} startTime={new Date(inst.publish_time).toLocaleString("fi-FI", cardTimeOpts)}
text={inst.description_fi} text={inst.description_fi}
link={`/feed/${inst.id}`} link={`/feed/${inst.id}`}
buttonOnClick={noop} buttonOnClick={noop}
buttonText="Lue lisää&nbsp;"
/> />
))} ))}
<aside> <aside>
+12 -2
View File
@@ -37,6 +37,14 @@ interface InEnglishPageViewProps {
feed: Post[]; feed: Post[];
} }
const cardTimeOpts: Intl.DateTimeFormatOptions = {
day: "numeric",
month: "numeric",
year: "numeric",
hour: "numeric",
minute: "2-digit",
};
const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) => ( const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) => (
<> <>
<InEnglishPageHero /> <InEnglishPageHero />
@@ -198,7 +206,7 @@ const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) =
<Card <Card
key={event.id} key={event.id}
title={event.title_en} title={event.title_en}
start_time={event.start_time} startTime={new Date(event.start_time).toLocaleString("en-GB", cardTimeOpts)}
text={event.description_en} text={event.description_en}
link={`/events/${event.id}`} link={`/events/${event.id}`}
image={{ image={{
@@ -206,6 +214,7 @@ const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) =
alt: event.title_en, alt: event.title_en,
}} }}
buttonOnClick={noop} buttonOnClick={noop}
buttonText="Read more&nbsp;"
data-e2e="event-card" data-e2e="event-card"
/> />
))} ))}
@@ -227,10 +236,11 @@ const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) =
<Card <Card
key={inst.id} key={inst.id}
title={inst.title_en} title={inst.title_en}
start_time={inst.publish_time} startTime={new Date(inst.publish_time).toLocaleString("en-GB", cardTimeOpts)}
text={inst.description_en} text={inst.description_en}
link={`/feed/${inst.id}`} link={`/feed/${inst.id}`}
buttonOnClick={noop} buttonOnClick={noop}
buttonText="Read more&nbsp;"
/> />
))} ))}
<aside> <aside>
+1 -1
View File
@@ -32,7 +32,7 @@ test("User signups to event from front page", async (t) => {
await t.wait(3000); await t.wait(3000);
await t.expect(await getPageUrl()).match(/\/events\/\d{1,4}/, "URL isn't /events/<id>"); await t.expect(await getPageUrl()).match(/\/events\/\d{1,4}/, "URL isn't /events/<id>");
const SignupButton = Selector("button"); const SignupButton = Selector("[data-e2e=\"signup-button\"]");
await t await t
.click(SignupButton); .click(SignupButton);