Merge branch 'master' into 'production'

Production deploy: Update packages, improved Docker images & style fixes

See merge request sahkoinsinoorikilta/vtmk/web2.0-frontend!64
This commit is contained in:
Aarni Halinen
2021-05-15 15:41:48 +00:00
29 changed files with 3195 additions and 3414 deletions
+11 -11
View File
@@ -1,16 +1,16 @@
{
"presets": [
"next/babel"
"next/babel"
],
"plugins": [
[
"babel-plugin-styled-components",
{
"ssr": true,
"displayName": true,
"preprocess": false,
"pure": true
}
]
[
"babel-plugin-styled-components",
{
"ssr": true,
"displayName": true,
"preprocess": false,
"pure": true
}
]
]
}
}
+8 -4
View File
@@ -1,7 +1,13 @@
Dockerfile
Dockerfile.prod
.dockerignore
node_modules
npm-debug.log
README*
LICENSE
.next
.vscode
e2e-screenshots
node_modules
tests
.env*
.eslintrc.json
@@ -10,6 +16,4 @@ tests
.gitlab-ci.yml
.nvmrc
.stylelintrc
LICENSE
README*
stack-compose*
stack-compose*
+58 -58
View File
@@ -1,61 +1,61 @@
{
"root": true,
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
"root": true,
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"node": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:jsx-a11y/recommended",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/recommended",
"airbnb-typescript"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:jsx-a11y/recommended",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/recommended",
"airbnb-typescript"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": [],
"settings": {
"react": {
"version": "detect"
}
},
"rules": {
"@typescript-eslint/naming-convention": "off",
"max-len": [
"warn",
240
],
"@typescript-eslint/quotes": [
"error",
"double"
],
"import/prefer-default-export": "warn",
"react/jsx-props-no-spreading": "off",
"react/prop-types": "off",
// Temp
"react/jsx-one-expression-per-line": "off",
"react/no-array-index-key": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"jsx-a11y/label-has-associated-control": "off",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off",
"jsx-a11y/no-static-element-interactions": "off"
"ecmaVersion": 2018,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": [],
"settings": {
"react": {
"version": "detect"
}
}
},
"rules": {
"@typescript-eslint/naming-convention": "off",
"max-len": [
"warn",
240
],
"@typescript-eslint/quotes": [
"error",
"double"
],
"import/prefer-default-export": "warn",
"react/jsx-props-no-spreading": "off",
"react/prop-types": "off",
// Temp
"react/jsx-one-expression-per-line": "off",
"react/no-array-index-key": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"jsx-a11y/label-has-associated-control": "off",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off",
"jsx-a11y/no-static-element-interactions": "off"
}
}
+120 -120
View File
@@ -1,42 +1,42 @@
stages:
- setup
- audit
- lint
- build
- test
- publish
- deploy
- setup
- audit
- lint
- build
- test
- publish
- deploy
install:
image: node:14
stage: setup
script:
- npm ci
artifacts:
paths:
- node_modules
expire_in: 1 week
image: node:14
stage: setup
script:
- npm ci
artifacts:
paths:
- node_modules
expire_in: 1 week
audit:
image: node:14
needs: ["install"]
stage: audit
script:
- npm audit --audit-level=critical
image: node:14
needs: ["install"]
stage: audit
script:
- npm audit --audit-level=critical
es:lint:
image: node:14
needs: ["install"]
stage: lint
script:
- npm run lint:es
image: node:14
needs: ["install"]
stage: lint
script:
- npm run lint:es
css:lint:
image: node:14
needs: ["install"]
stage: lint
script:
- npm run lint:css
image: node:14
needs: ["install"]
stage: lint
script:
- npm run lint:css
# test:unit:
# image: node:14
@@ -45,103 +45,103 @@ css:lint:
# - npm run test:unit
build:
image: node:14
needs: ["install"]
stage: build
script:
- NODE_ENV=test npm run build
dependencies:
- install
artifacts:
paths:
- .next
expire_in: 1 week
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .next/cache/
image: node:14
needs: ["install"]
stage: build
script:
- NODE_ENV=test npm run build
dependencies:
- install
artifacts:
paths:
- .next
expire_in: 1 week
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- .next/cache/
test:e2e:
image: circleci/node:14-browsers
needs: ["install", "build"]
stage: test
script:
- npm run test:e2e
artifacts:
paths:
- e2e-screenshots
expire_in: 1 week
when: on_failure
image: circleci/node:14-browsers
needs: ["install", "build"]
stage: test
script:
- npm run testcafe
artifacts:
paths:
- e2e-screenshots
expire_in: 1 week
when: on_failure
publish:dev:
stage: publish
image: docker:stable
needs: ["build", "test:e2e", "es:lint", "css:lint"]
services:
- docker:stable-dind
only:
- master
script:
- docker info
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker build . -t "$IMAGE_NAME":latest
- docker push "$IMAGE_NAME":latest
stage: publish
image: docker:stable
needs: ["build", "test:e2e", "es:lint", "css:lint"]
services:
- docker:stable-dind
only:
- master
script:
- docker info
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker build . -t "$IMAGE_NAME":latest --build-arg NEXT_PUBLIC_API_URL=https://api.dev.sahkoinsinoorikilta.fi/api --build-arg NEXT_PUBLIC_SITE_URL=https://dev.sahkoinsinoorikilta.fi
- docker push "$IMAGE_NAME":latest
publish:prod:
stage: publish
image: docker:stable
services:
- docker:stable-dind
only:
- production
script:
- docker info
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker build . -f Dockerfile.prod -t "$IMAGE_NAME":prod
- docker push "$IMAGE_NAME":prod
stage: publish
image: docker:stable
services:
- docker:stable-dind
only:
- production
script:
- docker info
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
- docker build . -t "$IMAGE_NAME":prod
- docker push "$IMAGE_NAME":prod
deploy:dev:
stage: deploy
image: docker:stable
only:
- master
environment:
name: dev
url: https://dev.sahkoinsinoorikilta.fi
variables:
DOCKER_HOST: $DEV_CI_DOCKER_HOST
DOCKER_TLS_VERIFY: 1
before_script:
- mkdir -p ~/.docker
- echo "$DEV_TLSCACERT" > ~/.docker/ca.pem
- echo "$DEV_TLSCERT" > ~/.docker/cert.pem
- echo "$DEV_TLSKEY" > ~/.docker/key.pem
- docker login -u gitlab-ci-token -p "$CI_BUILD_TOKEN" "$CI_REGISTRY"
script:
- docker stack deploy --with-registry-auth -c stack-compose-dev.yml "$SERVICE_NAME"
after_script:
- docker logout "$CI_REGISTRY"
stage: deploy
image: docker:stable
only:
- master
environment:
name: dev
url: https://dev.sahkoinsinoorikilta.fi
variables:
DOCKER_HOST: $DEV_CI_DOCKER_HOST
DOCKER_TLS_VERIFY: 1
before_script:
- mkdir -p ~/.docker
- echo "$DEV_TLSCACERT" > ~/.docker/ca.pem
- echo "$DEV_TLSCERT" > ~/.docker/cert.pem
- echo "$DEV_TLSKEY" > ~/.docker/key.pem
- docker login -u gitlab-ci-token -p "$CI_BUILD_TOKEN" "$CI_REGISTRY"
script:
- docker stack deploy --with-registry-auth -c stack-compose-dev.yml "$SERVICE_NAME"
after_script:
- docker logout "$CI_REGISTRY"
deploy:prod:
stage: deploy
image: docker:stable
only:
- production
environment:
name: production
url: https://sahkoinsinoorikilta.fi
when: manual
variables:
DOCKER_HOST: $CI_DOCKER_HOST
DOCKER_TLS_VERIFY: 1
before_script:
- mkdir -p ~/.docker
- echo "$TLSCACERT" > ~/.docker/ca.pem
- echo "$TLSCERT" > ~/.docker/cert.pem
- echo "$TLSKEY" > ~/.docker/key.pem
- docker login -u gitlab-ci-token -p "$CI_BUILD_TOKEN" "$CI_REGISTRY"
script:
- docker stack deploy --with-registry-auth -c stack-compose.yml "$SERVICE_NAME"
after_script:
- docker logout "$CI_REGISTRY"
stage: deploy
image: docker:stable
only:
- production
environment:
name: production
url: https://sahkoinsinoorikilta.fi
when: manual
variables:
DOCKER_HOST: $CI_DOCKER_HOST
DOCKER_TLS_VERIFY: 1
before_script:
- mkdir -p ~/.docker
- echo "$TLSCACERT" > ~/.docker/ca.pem
- echo "$TLSCERT" > ~/.docker/cert.pem
- echo "$TLSKEY" > ~/.docker/key.pem
- docker login -u gitlab-ci-token -p "$CI_BUILD_TOKEN" "$CI_REGISTRY"
script:
- docker stack deploy --with-registry-auth -c stack-compose.yml "$SERVICE_NAME"
after_script:
- docker logout "$CI_REGISTRY"
+1 -1
View File
@@ -1 +1 @@
14.16.0
14
+31 -16
View File
@@ -1,26 +1,41 @@
FROM node:14-alpine as builder
# Install dependencies only when needed
FROM node:14-alpine AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
RUN npm ci
COPY tsconfig.json next-env.d.ts .babelrc next.config.js next-sitemap.js ./
COPY src src/
COPY public public/
COPY types types/
# Rebuild the source code only when needed
FROM node:14-alpine AS builder
WORKDIR /app
COPY . .
COPY --from=deps /app/node_modules ./node_modules
ENV NEXT_TELEMETRY_DISABLED=1
ENV NEXT_PUBLIC_API_URL=https://api.dev.sahkoinsinoorikilta.fi/api
ENV NEXT_PUBLIC_SITE_URL=https://dev.sahkoinsinoorikilta.fi
ARG NEXT_PUBLIC_API_URL=https://api.sahkoinsinoorikilta.fi/api
ARG NEXT_PUBLIC_SITE_URL=https://sahkoinsinoorikilta.fi
RUN npm run build
FROM node:14-alpine as server
WORKDIR /www
COPY package.json package-lock.json next.config.js next-sitemap.js ./
COPY --from=builder .next .next
COPY --from=builder node_modules node_modules
COPY --from=builder public public
# Production image, copy all the files and run next
FROM node:14-alpine AS runner
WORKDIR /app
ENV NODE_ENV production
COPY --from=builder /app/next.config.js ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
RUN npm prune --production
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
RUN chown -R nextjs:nodejs /app/.next
USER nextjs
EXPOSE 3000
ENTRYPOINT ["npm", "run", "serve"]
CMD ["npm", "run", "serve"]
-26
View File
@@ -1,26 +0,0 @@
FROM node:14-alpine as builder
COPY package.json package-lock.json ./
RUN npm install
COPY tsconfig.json next-env.d.ts .babelrc next.config.js next-sitemap.js ./
COPY src src/
COPY public public/
COPY types types/
ENV NEXT_TELEMETRY_DISABLED=1
ENV NEXT_PUBLIC_API_URL=https://api.sahkoinsinoorikilta.fi/api
ENV NEXT_PUBLIC_SITE_URL=https://sahkoinsinoorikilta.fi
RUN npm run build
FROM node:14-alpine as server
WORKDIR /www
COPY package.json package-lock.json next.config.js next-sitemap.js ./
COPY --from=builder .next .next
COPY --from=builder node_modules node_modules
COPY --from=builder public public
RUN npm prune --production
EXPOSE 3000
ENTRYPOINT ["npm", "run", "serve"]
+2 -2
View File
@@ -1,5 +1,5 @@
module.exports = {
siteUrl: process.env.NEXT_PUBLIC_SITE_URL || "https://sahkoinsinoorikilta.fi",
generateRobotsTxt: true,
exclude: ["/events/*", "/feed/*", "/signup/*", "/admin/*"]
}
exclude: ["/events/*", "/feed/*", "/signup/*", "/admin/*"],
};
+3 -3
View File
@@ -6,12 +6,12 @@ module.exports = withBundleAnalyzer({
target: "server",
images: {
domains: [
"sahkoinsinoorikilta.fi",
"prod.sahkoinsinoorikilta.fi",
"api.sahkoinsinoorikilta.fi",
"static.sahkoinsinoorikilta.fi",
"api.dev.sahkoinsinoorikilta.fi",
"placehold.it",
],
},
future: {
webpack5: true,
},
});
+2304 -2528
View File
File diff suppressed because it is too large Load Diff
+49 -50
View File
@@ -27,62 +27,61 @@
"start": "next dev",
"start-prod": "next start --port ${SERVER_PORT:=80}",
"serve": "next start --port 3000",
"test": "npm run test:e2e:verbose",
"test:e2e": "testcafe --list-browsers && npm-run-all -p -r serve testcafe",
"test:e2e:verbose": "npm-run-all -p -r serve testcafe:verbose",
"testcafe": "testcafe --skip-js-errors -S -s 'e2e-screenshots' --app-init-delay 2000 chrome:headless tests/testcafe",
"testcafe:verbose": "testcafe --skip-js-errors -S -s 'e2e-screenshots' --app-init-delay 2000 chrome tests/testcafe",
"test": "npm run testcafe",
"testcafe": "testcafe --config-file testcafe.json",
"build-analyze": "ANALYZE=true npm run build",
"prepare": "husky install"
},
"devDependencies": {
"@types/js-cookie": "2.2.6",
"@types/react": "17.0.2",
"@types/react-beautiful-dnd": "13.0.0",
"@types/react-csv": "1.1.1",
"@types/react-dom": "17.0.1",
"@types/react-jsonschema-form": "1.7.4",
"@types/shortid": "0.0.29",
"@types/styled-components": "5.1.7",
"@typescript-eslint/eslint-plugin": "4.16.1",
"@typescript-eslint/parser": "4.16.1",
"babel-plugin-styled-components": "1.12.0",
"eslint": "7.21.0",
"eslint-config-airbnb-typescript": "12.3.1",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-jsx-a11y": "6.4.1",
"eslint-plugin-react": "7.22.0",
"eslint-plugin-react-hooks": "4.2.0",
"husky": "5.1.3",
"next-sitemap": "^1.6.9",
"npm-run-all": "4.1.5",
"stylelint": "13.11.0",
"stylelint-config-recommended": "3.0.0",
"stylelint-config-styled-components": "0.1.1",
"stylelint-processor-styled-components": "1.10.0",
"testcafe": "1.12.0",
"typescript": "4.2.2"
"@types/js-cookie": "^2.2.6",
"@types/react": "^17.0.5",
"@types/react-beautiful-dnd": "^13.0.0",
"@types/react-csv": "^1.1.1",
"@types/react-dom": "^17.0.5",
"@types/react-jsonschema-form": "^1.7.5",
"@types/shortid": "^0.0.29",
"@types/styled-components": "^5.1.9",
"@typescript-eslint/eslint-plugin": "^4.23.0",
"@typescript-eslint/parser": "^4.23.0",
"babel-plugin-styled-components": "^1.12.0",
"eslint": "^7.26.0",
"eslint-config-airbnb-typescript": "^12.3.1",
"eslint-plugin-import": "^2.23.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.2.0",
"husky": "^6.0.0",
"next-sitemap": "^1.6.57",
"npm-run-all": "^4.1.5",
"stylelint": "^13.13.1",
"stylelint-config-recommended": "^5.0.0",
"stylelint-config-styled-components": "^0.1.1",
"stylelint-processor-styled-components": "^1.10.0",
"testcafe": "^1.14.2",
"typescript": "^4.2.4"
},
"dependencies": {
"@next/bundle-analyzer": "10.0.7",
"axios": "0.21.1",
"date-fns": "2.18.0",
"@next/bundle-analyzer": "^10.2.0",
"axios": "^0.21.1",
"date-fns": "^2.21.3",
"fast-deep-equal": "^3.1.3",
"js-cookie": "2.2.1",
"lodash": "4.17.21",
"next": "10.1.2",
"normalize.css": "8.0.1",
"react": "17.0.1",
"react-beautiful-dnd": "13.1.0",
"react-csv": "2.0.3",
"react-dom": "17.0.1",
"react-is": "17.0.2",
"react-jsonschema-form": "1.8.1",
"react-markdown": "5.0.3",
"react-mde": "11.0.6",
"react-toastify": "^7.0.3",
"shortid": "2.2.16",
"styled-components": "5.2.3",
"swr": "0.4.2"
"js-cookie": "^2.2.1",
"lodash": "^4.17.21",
"next": "^10.2.0",
"normalize.css": "^8.0.1",
"react": "^17.0.2",
"react-beautiful-dnd": "^13.1.0",
"react-csv": "^2.0.3",
"react-dom": "^17.0.2",
"react-is": "^17.0.2",
"react-jsonschema-form": "^1.8.1",
"react-markdown": "^6.0.2",
"react-mde": "^11.5.0",
"react-toastify": "^7.0.4",
"rehype-raw": "^5.1.0",
"rehype-sanitize": "^4.0.0",
"shortid": "^2.2.16",
"styled-components": "^5.3.0",
"swr": "^0.5.6"
}
}
+2
View File
@@ -86,6 +86,8 @@ const FooterContent: React.FC = () => (
<Link to="https://api.sahkoinsinoorikilta.fi/members/application/">Jäseneksi</Link>
<Link to="mailto:hallitus@sahkoinsinoorikilta.fi">Palaute</Link>
<Link to="https://static.sahkoinsinoorikilta.fi">Dokumenttiarkisto</Link>
<Link to="https://sik.kuvat.fi">Kuvagalleria</Link>
<Link to="https://static.sahkoinsinoorikilta.fi/logot-ja-grafiikka/">Logot ja grafiikka</Link>
</div>
</Columns>
</MarginSpace>
+9 -8
View File
@@ -6,20 +6,21 @@ import Icon, { IconType } from "./Icon";
import NavbarDropdownLink from "./NavbarDropdownLink";
import NavbarChildLink from "./NavbarChildLink";
const renderNavigationDesktopItems = () => (
export const renderNavigationItems = (mobile = false) => (
<>
<NavbarDropdownLink to="/kilta" text="Kilta ">
<NavbarDropdownLink to="/kilta" text="Kilta " exploded={mobile}>
<NavbarChildLink to="/kilta/toiminta">Toiminta</NavbarChildLink>
<NavbarChildLink to="/kilta/fuksi">Fuksi</NavbarChildLink>
<NavbarChildLink to="/kilta/kunnia">Kunnianosoitukset</NavbarChildLink>
<NavbarChildLink to="/kilta/kunnianosoitukset">Kunnianosoitukset</NavbarChildLink>
<NavbarChildLink to="https://static.sahkoinsinoorikilta.fi">Dokumenttiarkisto</NavbarChildLink>
<NavbarChildLink to="https://sik.kuvat.fi">Kuvagalleria</NavbarChildLink>
</NavbarDropdownLink>
<NavbarDropdownLink to="/opinnot_ja_ura" text="Opinnot ja ura" />
<NavbarDropdownLink to="/yritysyhteistyo" text="Yritysyhteistyö" />
<NavbarDropdownLink to="/yhteystiedot" text="Yhteystiedot">
<NavbarDropdownLink to="/opinnot_ja_ura" text="Opinnot ja ura" exploded={mobile} />
<NavbarDropdownLink to="/yritysyhteistyo" text="Yritysyhteistyö" exploded={mobile} />
<NavbarDropdownLink to="/yhteystiedot" text="Yhteystiedot" exploded={mobile}>
{/* <NavbarChildLink to="https://en.wikipedia.org/wiki/Gay">Simo Höglund</NavbarChildLink> */}
</NavbarDropdownLink>
<NavbarDropdownLink to="/in_english" text="In English" />
<NavbarDropdownLink to="/in_english" text="In English" exploded={mobile} />
</>
);
@@ -104,7 +105,7 @@ interface NavigationProps {
}
const Navigation: React.FC<NavigationProps> = ({ onMobileMenuOpen }) => {
const desktopItems = renderNavigationDesktopItems();
const desktopItems = renderNavigationItems();
return (
<Nav>
<DesktopContainer>
+2 -20
View File
@@ -1,25 +1,7 @@
import React from "react";
import styled from "styled-components";
import { colors } from "@theme/colors";
import NavbarDropdownLink from "./NavbarDropdownLink";
import NavbarChildLink from "./NavbarChildLink";
const renderNavigationMobileItems = () => (
<>
<NavbarDropdownLink to="/kilta" text="Kilta " exploded>
<NavbarChildLink to="/kilta/toiminta">Toiminta</NavbarChildLink>
<NavbarChildLink to="/kilta/fuksi">Fuksi</NavbarChildLink>
<NavbarChildLink to="/kilta/kunnia">Kunnianosoitukset</NavbarChildLink>
<NavbarChildLink to="https://static.sahkoinsinoorikilta.fi">Dokumenttiarkisto</NavbarChildLink>
</NavbarDropdownLink>
<NavbarDropdownLink to="/opinnot_ja_ura" text="Opinnot ja ura" exploded />
<NavbarDropdownLink to="/yritysyhteistyo" text="Yritysyhteistyö" exploded />
<NavbarDropdownLink to="/yhteystiedot" text="Yhteystiedot" exploded>
{/* <NavbarChildLink to="https://en.wikipedia.org/wiki/Gay">Simo Höglund</NavbarChildLink> */}
</NavbarDropdownLink>
<NavbarDropdownLink to="/in_english" text="In English" exploded />
</>
);
import { renderNavigationItems } from "./Navigation";
const Nav = styled.nav`
padding: 1rem 2rem;
@@ -37,7 +19,7 @@ interface NavigationMobileProps {
const NavigationMobile: React.FC<NavigationMobileProps> = ({ mobileMenuOpen }) => (
<Nav hidden={!mobileMenuOpen}>
{renderNavigationMobileItems()}
{renderNavigationItems(true)}
</Nav>
);
@@ -32,7 +32,9 @@ const MarkdownEditorWidget: React.FC<MarkdownEditorWidgetProps> = ({ value, onCh
onChange={onChange}
selectedTab={selectedTab}
onTabChange={setSelectedTab}
generateMarkdownPreview={(markdown) => Promise.resolve(<MarkdownStyles source={markdown} />)}
generateMarkdownPreview={(markdown) => Promise.resolve(
<MarkdownStyles>{markdown}</MarkdownStyles>,
)}
/>
</Container>
);
+14 -8
View File
@@ -2,15 +2,18 @@ import React from "react";
import { NextPage } from "next";
import Head from "next/head";
import styled from "styled-components";
import Header from "@components/Header";
const NotFound = styled.main`
text-align: center;
font-size: 4rem;
font-weight: 200;
position: absolute;
height: 10rem;
top: calc(50vh - 5rem);
width: 100%;
flex: 1 0 auto;
display: flex;
justify-content: center;
align-items: center;
p {
text-align: center;
font-size: 4rem;
font-weight: 200;
}
`;
const NotFoundPage: NextPage = () => (
@@ -19,8 +22,11 @@ const NotFoundPage: NextPage = () => (
<title>404 | Ei vaan löydy</title>
<meta name="robots" content="noindex" />
</Head>
<Header />
<NotFound id="not-found">
<strong>404</strong> | Ei vaan löydy
<p>
<strong>404</strong> | Ei&nbsp;vaan&nbsp;löydy
</p>
</NotFound>
</>
);
+5 -16
View File
@@ -1,10 +1,10 @@
import React from "react";
// import App from "next/app";
import type { AppProps /* , AppContext' */ } from "next/app";
import Head from "next/head";
import { AppProps } from "next/app";
import styled, { createGlobalStyle } from "styled-components";
import { ToastContainer } from "react-toastify";
import { colors } from "@theme/colors";
import breakpoints from "@theme/breakpoints";
import LocaleStore from "../i18n";
import "react-mde/lib/styles/css/react-mde-all.css";
@@ -25,17 +25,17 @@ html {
font-size: ${fontSize * 0.75}pt;
line-height: ${lineHeight};
@media screen and (min-width: 1200px) {
@media screen and (min-width: ${breakpoints.medium}) {
/* 16px */
font-size: ${fontSize}pt;
}
@media screen and (min-width: 1920px) {
@media screen and (min-width: ${breakpoints.large}) {
/* 20px */
font-size: ${fontSize * 1.25}pt;
}
@media screen and (min-width: 2560px) {
@media screen and (min-width: ${breakpoints.xlarge}) {
/* 24px */
font-size: ${fontSize * 1.5}pt;
}
@@ -150,15 +150,4 @@ const Web20App = ({ Component, pageProps }: AppProps) => (
</>
);
// Only uncomment this method if you have blocking data requirements for
// every single page in your application. This disables the ability to
// perform automatic static optimization, causing every page in your app to
// be server-side rendered.
//
// export const getInitialProps = async (appContext: AppContext) => {
// // calls page's `getInitialProps` and fills `appProps.pageProps`
// const appProps = await App.getInitialProps(appContext);
// return { ...appProps }
// }
export default Web20App;
@@ -7,7 +7,7 @@ import PageWrapper from "@views/common/PageWrapper";
const HonoraryPage: NextPage = () => (
<>
<Head>
<link rel="canonical" href={`${process.env.NEXT_PUBLIC_SITE_URL}/kilta/kunnia`} />
<link rel="canonical" href={`${process.env.NEXT_PUBLIC_SITE_URL}/kilta/kunnianosoitukset`} />
</Head>
<PageWrapper>
<HonoraryPageView />
+4 -4
View File
@@ -1,10 +1,10 @@
type Keys = "mobile" | "medium" | "large" | "xlarge";
const breakpointsNumber: Record<Keys, number> = {
mobile: 800,
medium: 1200,
large: 1920,
xlarge: 2560,
mobile: 801,
medium: 1201,
large: 1921,
xlarge: 2561,
};
const breakpoints = Object.entries(breakpointsNumber).map(([k, v]) => [k, `${v}px`]).reduce((a, [k, v]) => ({ ...a, [k]: v }), {});
+5 -1
View File
@@ -3,6 +3,8 @@ import styled from "styled-components";
import JobAd from "@models/JobAd";
import { Accordion } from "@components/index";
import ReactMarkdown from "react-markdown";
import rehypeRaw from "rehype-raw";
import rehypeSanitize from "rehype-sanitize";
interface JobAdListProps {
jobAds: JobAd[];
@@ -25,7 +27,9 @@ const JobAdList: React.FC<JobAdListProps> = ({ jobAds }) => (
<p>
{ad.description_fi}
</p>
<ReactMarkdown source={ad.content_fi} escapeHtml={false} />
<ReactMarkdown rehypePlugins={[rehypeRaw, rehypeSanitize]}>
{ad.content_fi}
</ReactMarkdown>
</div>
</Accordion>
</li>
+3 -1
View File
@@ -1,6 +1,8 @@
import React from "react";
import Image from "next/image";
import styled from "styled-components";
import rehypeRaw from "rehype-raw";
import rehypeSanitize from "rehype-sanitize";
import colors from "@theme/colors";
import Event from "@models/Event";
import {
@@ -85,7 +87,7 @@ const EventPageView: React.FC<EventPageViewProps> = ({ event }) => {
/>
</h1>
<div>
<Content source={content} escapeHtml={false} />
<Content rehypePlugins={[rehypeRaw, rehypeSanitize]}>{content}</Content>
<p>
{`${t("Paikka")}: ${location}`}
</p>
+3 -1
View File
@@ -1,6 +1,8 @@
import React from "react";
import Image from "next/image";
import styled from "styled-components";
import rehypeRaw from "rehype-raw";
import rehypeSanitize from "rehype-sanitize";
import colors from "@theme/colors";
import Post from "@models/Feed";
import { TextSection, ChangeLanguageButton } from "@components/index";
@@ -70,7 +72,7 @@ const FeedPageView: React.FC<FeedPageViewProps> = ({ post }) => {
)}
</h1>
<div>
<Content source={content} escapeHtml={false} />
<Content rehypePlugins={[rehypeRaw, rehypeSanitize]}>{content}</Content>
</div>
</StyledTextSection>
</>
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -49,16 +49,16 @@ const StudiesPageView: React.FC = () => (
<p>
Fuksivuoden loppupuolella aloin haaveilla oman alan hommista ja päätin laittaa kesätyöhakemuksia yrityksiin ihan laidasta laitaan.
Lopulta taisin laittaa niitä jopa 50 Ei mennyt kauaa, kun Profit Softwarelta oltiin yhteydessä ja pääsin sinne haastatteluun.
Ennen pitkää olikin jo kesä ja olin päässyt osaksi Profit Softwaren automaatiotraineeteamiä.
Jatkoin kesän jälkeen osa-aikaisena traineenä ja seuraavana kesänä pääsinkin scrum master -roolissa ohjaamaan useita erilaisia traineeprojekteja.
Ennen pitkää olikin jo kesä ja olin päässyt osaksi Profit Softwaren automaatio-trainee-teamiä.
Jatkoin kesän jälkeen osa-aikaisena traineenä ja seuraavana kesänä pääsinkin scrum master -roolissa ohjaamaan useita erilaisia trainee-projekteja.
Ihastuin projektienhallintaan ja jatkan projektitaitojen harjoittamista töissä edelleen.
</p>
<h6>Toni</h6>
<p>
Kuulin fuksivuotenani erään kurssin vierasluennoitsijalta Fingrid Datahub hankkeesta.
Projekti vaikutti mielenkiintoiselta, koska se tulee muuttamaan suomen sähkömarkkinoiden viestintää.
Toisen vuoden opiskelijana kesätöitä hakemassa törmäsin työilmoitukseen, jossa haettiin Fingrid Datahub hankkeeseen testaajia.
Kuulin fuksivuotenani erään kurssin vierasluennoitsijalta Fingrid Datahub -hankkeesta.
Projekti vaikutti mielenkiintoiselta, koska se tulee muuttamaan Suomen sähkömarkkinoiden viestintää.
Toisen vuoden opiskelijana kesätöitä hakemassa törmäsin työilmoitukseen, jossa haettiin Fingrid Datahub -hankkeeseen testaajia.
Päätin laittaa hakemuksen vetämään ja onnekseni sain työpaikan.
Toimin koko kesän sovellustestauksen parissa sekä kehittäen useita erilaisia sovelluksia testauksen automatisoimiseksi.
Kesän päätyttyä sain onnekseni jatkoa työsopimukselle ja toimin sovellustestaajana kyseisessä projektissa edelleen.
+1 -1
View File
@@ -1,4 +1,4 @@
version: '3.4'
version: "3.4"
services:
frontend:
+1 -1
View File
@@ -1,4 +1,4 @@
version: '3.4'
version: "3.4"
services:
frontend:
+12
View File
@@ -0,0 +1,12 @@
{
"src": "tests/testcafe",
"browsers": "all",
"concurrency": 1,
"screenshots": {
"path": "e2e-screenshots",
"takeOnFails": true
},
"skipJsErrors": true,
"appCommand": "npm run serve",
"appInitDelay": 2000
}
-3
View File
@@ -4,9 +4,6 @@ import { getSiteRoot } from "./utils";
fixture`404 page renders and functions correctly`.page(`${getSiteRoot()}/404`);
test("Page contains the text 404", async (t) => {
/**
* Test if there is a favicon element on the page
*/
const elem = Selector("#not-found");
await t.expect(elem.textContent).contains("404");
});
+8 -2
View File
@@ -6,7 +6,10 @@
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"jsx": "preserve",
"lib": ["dom", "esnext"],
"lib": [
"dom",
"esnext"
],
"module": "esnext",
"moduleResolution": "node",
"noEmit": true,
@@ -19,7 +22,10 @@
"sourceMap": true,
"strict": false, // TODO: switch true
"target": "esnext",
"typeRoots": ["types", "node_modules/@types"],
"typeRoots": [
"types",
"node_modules/@types"
],
"baseUrl": "./",
"paths": {
"@api/*": [