Merge branch 'master' into 'production'
1st Live deploy See merge request sahkoinsinoorikilta/vtmk/web2.0-frontend!48
@@ -130,7 +130,7 @@ deploy:prod:
|
||||
- production
|
||||
environment:
|
||||
name: production
|
||||
url: prod.sahkoinsinoorikilta.fi
|
||||
url: sahkoinsinoorikilta.fi
|
||||
when: manual
|
||||
variables:
|
||||
DOCKER_HOST: $CI_DOCKER_HOST
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"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.1",
|
||||
"swr": "0.4.2"
|
||||
@@ -3012,9 +3013,6 @@
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@hapi/accept": {
|
||||
@@ -3086,10 +3084,6 @@
|
||||
"source-map": "0.8.0-beta.0",
|
||||
"stacktrace-parser": "0.1.10",
|
||||
"strip-ansi": "6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.9.0 || ^17",
|
||||
"react-dom": "^16.9.0 || ^17"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/react-dev-overlay/node_modules/ansi-regex": {
|
||||
@@ -3109,9 +3103,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/react-dev-overlay/node_modules/chalk": {
|
||||
@@ -3124,9 +3115,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/react-dev-overlay/node_modules/color-convert": {
|
||||
@@ -3189,16 +3177,7 @@
|
||||
"node_modules/@next/react-refresh-utils": {
|
||||
"version": "10.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-10.0.8.tgz",
|
||||
"integrity": "sha512-ZMO77Xs2ioGV/nZB4GRDHgsNT2jhOp+cZIh6c7wf0xw9o/1KoTWN8nxWzwU/laAtkoSS+E6YdhuR4Mw3Ar3CSg==",
|
||||
"peerDependencies": {
|
||||
"react-refresh": "0.8.3",
|
||||
"webpack": "^4 || ^5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"webpack": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
"integrity": "sha512-ZMO77Xs2ioGV/nZB4GRDHgsNT2jhOp+cZIh6c7wf0xw9o/1KoTWN8nxWzwU/laAtkoSS+E6YdhuR4Mw3Ar3CSg=="
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.3",
|
||||
@@ -3489,19 +3468,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/parser": "^4.0.0",
|
||||
"eslint": "^5.0.0 || ^6.0.0 || ^7.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/experimental-utils": {
|
||||
@@ -3519,13 +3485,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
@@ -3541,18 +3500,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^5.0.0 || ^6.0.0 || ^7.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
@@ -3566,10 +3513,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
@@ -3579,10 +3522,6 @@
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
@@ -3601,15 +3540,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/@nodelib/fs.stat": {
|
||||
@@ -3686,9 +3616,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/ignore": {
|
||||
@@ -3745,10 +3672,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
|
||||
@@ -3785,10 +3708,7 @@
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
|
||||
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/acorn-walk": {
|
||||
"version": "8.0.1",
|
||||
@@ -3820,10 +3740,6 @@
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/amdefine": {
|
||||
@@ -4071,6 +3987,7 @@
|
||||
"integrity": "sha512-d2Ovma+bfqNpvBzY/KU8oPY67ZworixTpkjSx0PCXnQi67c2cXmssaTxpFDUM0ttopXoGx/KRxNg/GDThYbXQA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/glob": "^7.1.1",
|
||||
"chromium-pickle-js": "^0.2.0",
|
||||
"commander": "^2.20.0",
|
||||
"cuint": "^0.2.2",
|
||||
@@ -4084,9 +4001,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@types/glob": "^7.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/asn1.js": {
|
||||
@@ -4328,9 +4242,6 @@
|
||||
"@babel/helper-module-imports": "^7.0.0",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"lodash": "^4.17.11"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"styled-components": ">= 2"
|
||||
}
|
||||
},
|
||||
"node_modules/babel-plugin-syntax-jsx": {
|
||||
@@ -4747,9 +4658,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/camelize": {
|
||||
@@ -4974,6 +4882,14 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
|
||||
"integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
@@ -5452,10 +5368,6 @@
|
||||
"integrity": "sha512-NYyAg4wRmGVU4miKq5ivRACOODdZRY3q5WLmOJSq8djyzftYphU7dTHLcEtLqEvfqMKQ0jVv91P4BAwIjsXIcw==",
|
||||
"engines": {
|
||||
"node": ">=0.11"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/date-fns"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
@@ -6078,9 +5990,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-config-airbnb": {
|
||||
@@ -7230,9 +7139,6 @@
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/flatted": {
|
||||
@@ -7376,9 +7282,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
@@ -7453,9 +7356,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/globals/node_modules/type-fest": {
|
||||
@@ -7864,16 +7764,6 @@
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-5.1.3.tgz",
|
||||
"integrity": "sha512-fbNJ+Gz5wx2LIBtMweJNY1D7Uc8p1XERi5KNRMccwfQA+rXlxWNSdUxswo0gT8XqxywTIw7Ywm/F4v/O35RdMg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/typicode"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/husky"
|
||||
}
|
||||
],
|
||||
"bin": {
|
||||
"husky": "lib/bin.js"
|
||||
},
|
||||
@@ -7917,9 +7807,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/import-lazy": {
|
||||
@@ -8965,9 +8852,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/matcher/node_modules/escape-string-regexp": {
|
||||
@@ -8977,9 +8861,6 @@
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/mathml-tag-names": {
|
||||
@@ -9090,9 +8971,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/meow/node_modules/hosted-git-info": {
|
||||
@@ -9141,9 +9019,6 @@
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/merge-stream": {
|
||||
@@ -9491,24 +9366,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"fibers": ">= 3.1.0",
|
||||
"node-sass": "^4.0.0 || ^5.0.0",
|
||||
"react": "^16.6.0 || ^17",
|
||||
"react-dom": "^16.6.0 || ^17",
|
||||
"sass": "^1.3.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"fibers": {
|
||||
"optional": true
|
||||
},
|
||||
"node-sass": {
|
||||
"optional": true
|
||||
},
|
||||
"sass": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/next-sitemap": {
|
||||
@@ -9523,9 +9380,6 @@
|
||||
},
|
||||
"bin": {
|
||||
"next-sitemap": "bin/next-sitemap"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"next": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/next/node_modules/browserslist": {
|
||||
@@ -10412,9 +10266,6 @@
|
||||
"integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==",
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pidtree": {
|
||||
@@ -11260,11 +11111,7 @@
|
||||
"node_modules/react-mde": {
|
||||
"version": "11.0.6",
|
||||
"resolved": "https://registry.npmjs.org/react-mde/-/react-mde-11.0.6.tgz",
|
||||
"integrity": "sha512-yWiPSurQvjLVD070zycQR4x5zW3f/kxPlqOMmZoUtVQvUgcM+kwpDQAba5sqtqtAurgUx0Ae9p9Xzgqwt2+ZBA==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.0.0",
|
||||
"react-dom": "^16.0.0"
|
||||
}
|
||||
"integrity": "sha512-yWiPSurQvjLVD070zycQR4x5zW3f/kxPlqOMmZoUtVQvUgcM+kwpDQAba5sqtqtAurgUx0Ae9p9Xzgqwt2+ZBA=="
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "7.2.2",
|
||||
@@ -11320,6 +11167,18 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-toastify": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-7.0.3.tgz",
|
||||
"integrity": "sha512-cxZ5rfurC8LzcZQMTYc8RHIkQTs+BFur18Pzk6Loz6uS8OXUWm6nXVlH/wqglz4Z7UAE8xxcF5mRjfE13487uQ==",
|
||||
"dependencies": {
|
||||
"clsx": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16",
|
||||
"react-dom": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/read-file-relative": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/read-file-relative/-/read-file-relative-1.2.0.tgz",
|
||||
@@ -11355,9 +11214,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/read-pkg-up/node_modules/find-up": {
|
||||
@@ -11395,9 +11251,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/read-pkg-up/node_modules/p-locate": {
|
||||
@@ -11434,9 +11287,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/read-pkg-up/node_modules/path-exists": {
|
||||
@@ -12957,10 +12807,6 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/stylelint"
|
||||
}
|
||||
},
|
||||
"node_modules/stylelint-config-recommended": {
|
||||
@@ -13707,9 +13553,6 @@
|
||||
"integrity": "sha512-SKGxcAfyijj/lE5ja5zVMDqJNudASH3WZPRUakDVOePTM18FnsXgugndjl9BSRwj+jokFCulMDe7F2pQL+VhEw==",
|
||||
"dependencies": {
|
||||
"dequal": "2.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.11.0 || ^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/symbol-observable": {
|
||||
@@ -18480,8 +18323,7 @@
|
||||
"@next/react-refresh-utils": {
|
||||
"version": "10.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@next/react-refresh-utils/-/react-refresh-utils-10.0.8.tgz",
|
||||
"integrity": "sha512-ZMO77Xs2ioGV/nZB4GRDHgsNT2jhOp+cZIh6c7wf0xw9o/1KoTWN8nxWzwU/laAtkoSS+E6YdhuR4Mw3Ar3CSg==",
|
||||
"requires": {}
|
||||
"integrity": "sha512-ZMO77Xs2ioGV/nZB4GRDHgsNT2jhOp+cZIh6c7wf0xw9o/1KoTWN8nxWzwU/laAtkoSS+E6YdhuR4Mw3Ar3CSg=="
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
"version": "2.1.3",
|
||||
@@ -18942,8 +18784,7 @@
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
|
||||
"integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
"dev": true
|
||||
},
|
||||
"acorn-walk": {
|
||||
"version": "8.0.1",
|
||||
@@ -19934,6 +19775,11 @@
|
||||
"is-regexp": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"clsx": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
|
||||
"integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA=="
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
@@ -25128,8 +24974,7 @@
|
||||
"react-mde": {
|
||||
"version": "11.0.6",
|
||||
"resolved": "https://registry.npmjs.org/react-mde/-/react-mde-11.0.6.tgz",
|
||||
"integrity": "sha512-yWiPSurQvjLVD070zycQR4x5zW3f/kxPlqOMmZoUtVQvUgcM+kwpDQAba5sqtqtAurgUx0Ae9p9Xzgqwt2+ZBA==",
|
||||
"requires": {}
|
||||
"integrity": "sha512-yWiPSurQvjLVD070zycQR4x5zW3f/kxPlqOMmZoUtVQvUgcM+kwpDQAba5sqtqtAurgUx0Ae9p9Xzgqwt2+ZBA=="
|
||||
},
|
||||
"react-redux": {
|
||||
"version": "7.2.2",
|
||||
@@ -25181,6 +25026,14 @@
|
||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz",
|
||||
"integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg=="
|
||||
},
|
||||
"react-toastify": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-7.0.3.tgz",
|
||||
"integrity": "sha512-cxZ5rfurC8LzcZQMTYc8RHIkQTs+BFur18Pzk6Loz6uS8OXUWm6nXVlH/wqglz4Z7UAE8xxcF5mRjfE13487uQ==",
|
||||
"requires": {
|
||||
"clsx": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"read-file-relative": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/read-file-relative/-/read-file-relative-1.2.0.tgz",
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
"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.1",
|
||||
"swr": "0.4.2"
|
||||
|
||||
|
Before Width: | Height: | Size: 402 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 402 KiB |
|
Before Width: | Height: | Size: 593 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 166 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 242 KiB |
|
Before Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 171 KiB |
|
Before Width: | Height: | Size: 315 KiB |
|
Before Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 271 KiB |
|
Before Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 150 KiB |
|
Before Width: | Height: | Size: 556 KiB |
|
Before Width: | Height: | Size: 865 KiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 458 KiB |
|
Before Width: | Height: | Size: 914 KiB |
|
Before Width: | Height: | Size: 574 KiB |
|
Before Width: | Height: | Size: 407 KiB |
|
Before Width: | Height: | Size: 715 KiB |
|
Before Width: | Height: | Size: 954 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 865 KiB |
|
Before Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
@@ -1,7 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
|
||||
<g fill="#61DAFB">
|
||||
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
|
||||
<circle cx="420.9" cy="296.5" r="45.7"/>
|
||||
<path d="M520.5 78.1z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 954 KiB |
@@ -62,6 +62,20 @@ class FeedApi {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
static async deletePost(id: number) {
|
||||
try {
|
||||
const resp = await axios.delete(`${URL}${id}`, {
|
||||
headers: {
|
||||
Authorization: getAuthHeader(),
|
||||
},
|
||||
});
|
||||
return resp.data;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default FeedApi;
|
||||
|
||||
@@ -72,6 +72,20 @@ class JobAdApi {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
static async deleteJobAd(id: number) {
|
||||
try {
|
||||
const resp = await axios.delete(`${URL}${id}`, {
|
||||
headers: {
|
||||
Authorization: getAuthHeader(),
|
||||
},
|
||||
});
|
||||
return resp.data;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default JobAdApi;
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { Committee } from "@views/ContactsPage/ContactsPageView";
|
||||
import { colors } from "@theme/colors";
|
||||
import ContactCard from "./ContactCard";
|
||||
|
||||
const blank_profile = "/img/blank_profile.png";
|
||||
|
||||
interface CommitteeContainerProps {
|
||||
committee: Committee;
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
color: ${colors.darkBlue};
|
||||
|
||||
& > p {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 3px;
|
||||
line-height: 0.75;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
& > div {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: center;
|
||||
}
|
||||
`;
|
||||
|
||||
const CommitteeContainer: React.FC<CommitteeContainerProps> = ({ committee }) => (
|
||||
<Container>
|
||||
<p>
|
||||
{committee.name_fi || committee.name_en}
|
||||
</p>
|
||||
<div>
|
||||
{committee.roles.map((role) => (
|
||||
role.representatives.map((representative) => (
|
||||
<ContactCard
|
||||
key={representative.name}
|
||||
name={representative.name}
|
||||
phone={representative.phone_number}
|
||||
email={representative.email}
|
||||
// conditional image for dev
|
||||
image={!(committee.name_en === "Board") ? representative.image : blank_profile}
|
||||
role_fi={role.name_fi}
|
||||
role_en={role.name_en}
|
||||
/>
|
||||
))
|
||||
))}
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
|
||||
export default CommitteeContainer;
|
||||
@@ -5,21 +5,22 @@ import { colors } from "@theme/colors";
|
||||
|
||||
const Card = styled.article`
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
flex: 1 0 50%;
|
||||
padding: 0.5rem;
|
||||
color: ${colors.darkBlue};
|
||||
width: 19rem;
|
||||
`;
|
||||
|
||||
const Row = styled.div`
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
`;
|
||||
|
||||
const ImageContainer = styled.div`
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 5rem;
|
||||
width: 5rem;
|
||||
flex-shrink: 0;
|
||||
|
||||
img {
|
||||
padding: 0.5rem !important;
|
||||
@@ -39,7 +40,7 @@ const Info = styled.div`
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
& > h1 {
|
||||
& > h3 {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
@@ -58,22 +59,24 @@ const ContactCard: React.FC<ContactCardProps> = ({
|
||||
name, phone, email, image, role_fi, role_en,
|
||||
}) => (
|
||||
<Card>
|
||||
{image ? (
|
||||
<ImageContainer>
|
||||
<Image
|
||||
src={image}
|
||||
alt={name}
|
||||
layout="fill"
|
||||
objectFit="scale-down"
|
||||
/>
|
||||
</ImageContainer>
|
||||
) : null}
|
||||
<Info>
|
||||
<h1>{name}</h1>
|
||||
<p>{role_fi || role_en}</p>
|
||||
{phone ? <p>{phone}</p> : null}
|
||||
{email ? <p>{email}</p> : null}
|
||||
</Info>
|
||||
<Row>
|
||||
{image ? (
|
||||
<ImageContainer>
|
||||
<Image
|
||||
src={image}
|
||||
alt={name}
|
||||
layout="fill"
|
||||
objectFit="scale-down"
|
||||
/>
|
||||
</ImageContainer>
|
||||
) : null}
|
||||
<Info>
|
||||
<h3>{name}</h3>
|
||||
<p>{role_fi || role_en}</p>
|
||||
{phone ? <p>{phone}</p> : null}
|
||||
{email ? <p>{email}</p> : null}
|
||||
</Info>
|
||||
</Row>
|
||||
</Card>
|
||||
);
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ const CrossFadeImages: React.FC<CrossFadeImagesProps> = ({
|
||||
$duration={len * SINGLE_IMAGE_TIME}
|
||||
>
|
||||
{ images.map((image, idx) => (
|
||||
<div className={idx > 0 ? "not-first" : undefined}>
|
||||
<div key={idx} className={idx > 0 ? "not-first" : undefined}>
|
||||
<AnimatedImage
|
||||
key={image}
|
||||
src={image}
|
||||
|
||||
@@ -3,9 +3,11 @@ import React from "react";
|
||||
import type { AppProps /* , AppContext' */ } from "next/app";
|
||||
import Head from "next/head";
|
||||
import styled, { createGlobalStyle } from "styled-components";
|
||||
import { ToastContainer } from "react-toastify";
|
||||
import { colors } from "@theme/colors";
|
||||
|
||||
import "react-mde/lib/styles/css/react-mde-all.css";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
|
||||
const fontFamily = "'Montserrat', sans-serif";
|
||||
const fontSize = 12; // 16px
|
||||
@@ -141,6 +143,7 @@ const Web20App = ({ Component, pageProps }: AppProps) => (
|
||||
<AppContainer>
|
||||
<Component {...pageProps} />
|
||||
</AppContainer>
|
||||
<ToastContainer position="bottom-right" />
|
||||
</>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { NextPage } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { toast } from "react-toastify";
|
||||
import AdminCreateCommon from "@views/admin/AdminCreateCommon";
|
||||
import Tag from "@models/Tag";
|
||||
import TagApi from "@api/tagApi";
|
||||
@@ -66,6 +67,7 @@ const buildSchema = (formData: Event, signupForms: SignupForm[], tags: Tag[]) =>
|
||||
enumNames: signupForms.map((form) => form.title_fi),
|
||||
},
|
||||
uniqueItems: true,
|
||||
default: [],
|
||||
},
|
||||
image: {
|
||||
type: ["string", "null"],
|
||||
@@ -166,7 +168,6 @@ const EventCreatePage: NextPage = () => {
|
||||
const [tags, setTags] = useState<Tag[]>([]);
|
||||
const [signupForms, setSignupForms] = useState<SignupForm[]>([]);
|
||||
const [error, setError] = useState<string>(null);
|
||||
const [statusMessage, setStatusMessage] = useState<string>(null);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -212,7 +213,8 @@ const EventCreatePage: NextPage = () => {
|
||||
// resp.signupForm = (resp.signupForm as any).map(inst => inst.id);
|
||||
resp.tags = data.formData.tags;
|
||||
resp.signupForm = data.formData.signupForm;
|
||||
setStatusMessage("Event created successfully");
|
||||
toast.success("Event created successfully 😎");
|
||||
router.push("/admin/events");
|
||||
setFormData(resp);
|
||||
} else {
|
||||
const resp = await EventApi.updateEvent(payload);
|
||||
@@ -222,16 +224,17 @@ const EventCreatePage: NextPage = () => {
|
||||
// resp.signupForm = (resp.signupForm as any).map(inst => inst.id);
|
||||
resp.tags = data.formData.tags;
|
||||
resp.signupForm = data.formData.signupForm;
|
||||
setStatusMessage("Event updated successfully");
|
||||
toast.success("Event updated successfully 😎");
|
||||
router.push("/admin/events");
|
||||
setFormData(resp);
|
||||
}
|
||||
} catch (err) {
|
||||
toast.error("Uh oh! Something went wrong! Try again later. 😟");
|
||||
setError(err);
|
||||
}
|
||||
};
|
||||
|
||||
const onChange = (data: any) => setFormData(data.formData);
|
||||
const onFocus = () => setStatusMessage(null);
|
||||
const title = formData?.id
|
||||
? `Edit Event "${formData.title_fi}"`
|
||||
: "Create Event";
|
||||
@@ -243,9 +246,7 @@ const EventCreatePage: NextPage = () => {
|
||||
schema={buildSchema(formData, signupForms, tags)}
|
||||
UISchema={buildUISchema()}
|
||||
onChange={onChange}
|
||||
onFocus={onFocus}
|
||||
onSubmit={onSubmit}
|
||||
statusMessage={statusMessage}
|
||||
error={error}
|
||||
widgets={widgets}
|
||||
/>
|
||||
|
||||
@@ -1,14 +1,37 @@
|
||||
import React from "react";
|
||||
import { NextPage } from "next";
|
||||
import { formatRelative } from "date-fns";
|
||||
import { toast } from "react-toastify";
|
||||
import styled from "styled-components";
|
||||
import AdminListCommon from "@views/admin/AdminListCommon";
|
||||
import { Link } from "@components/index";
|
||||
import { Button, Link } from "@components/index";
|
||||
import AddLink from "@components/AddLink";
|
||||
import Event from "@models/Event";
|
||||
import EventApi from "@api/eventApi";
|
||||
import useFetchEvents from "@hooks/useFetchEvents";
|
||||
|
||||
const URL = "/admin/events";
|
||||
|
||||
const StyledButton = styled(Button) <{ $colorOverride: "red" }>`
|
||||
background-color: ${(p) => p.$colorOverride};
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
`;
|
||||
|
||||
const confirmDelete = async (event: Event) => {
|
||||
if (window.confirm(`Delete: ${event.id}: ${event.title_fi}/${event.title_en}; Are you sure?`) === true) {
|
||||
try {
|
||||
await EventApi.deleteEvent(event.id);
|
||||
toast.success("Event removed successfully 😎");
|
||||
window.location.reload(); // TODO: Fetch/update event list, so user sees the signup in the list
|
||||
} catch (err) {
|
||||
toast.error("Uh oh! Something went wrong! Try again later. 😟");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const renderData = (events: Event[]) => {
|
||||
if (!events || events.length === 0) {
|
||||
return <div>No events.</div>;
|
||||
@@ -29,12 +52,18 @@ const renderData = (events: Event[]) => {
|
||||
<td><Link to={`${URL}/${event.id}`}>{event.title_fi}</Link></td>
|
||||
<td>{formatRelative(new Date(event.start_time), new Date())}</td>
|
||||
<td>{formatRelative(new Date(event.end_time), new Date())}</td>
|
||||
<td>
|
||||
<StyledButton $colorOverride="red" buttonStyle="filled" onClick={() => confirmDelete(event)}>
|
||||
Delete
|
||||
</StyledButton>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
};
|
||||
|
||||
const AdminEventPage: NextPage = () => {
|
||||
const { data } = useFetchEvents({ options: { auth: true } });
|
||||
return (
|
||||
|
||||
@@ -9,6 +9,7 @@ import FeedApi from "@api/feedApi";
|
||||
import DatetimeWidget from "@components/Widgets/DatetimeWidget";
|
||||
import SectionDividerWidget from "@components/Widgets/SectionDividerWidget";
|
||||
import MarkdownEditorWidget from "@components/Widgets/MarkdownEditorWidget";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
const widgets = {
|
||||
datetime: DatetimeWidget,
|
||||
@@ -133,7 +134,6 @@ const FeedCreatePage: NextPage = () => {
|
||||
const [formData, setFormData] = useState<Post>(null);
|
||||
const [tags, setTags] = useState<Tag[]>([]);
|
||||
const [error, setError] = useState<string>(null);
|
||||
const [statusMessage, setStatusMessage] = useState<string>(null);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -167,21 +167,23 @@ const FeedCreatePage: NextPage = () => {
|
||||
if (payload.id === undefined) {
|
||||
const resp = await FeedApi.createPost(payload);
|
||||
// resp.tags = resp.tags;
|
||||
setStatusMessage("Post created successfully");
|
||||
toast.success("Post created successfully 😎");
|
||||
router.push("/admin/feed");
|
||||
setFormData(resp);
|
||||
} else {
|
||||
const resp = await FeedApi.updatePost(payload);
|
||||
// resp.tags = resp.tag_id;
|
||||
setStatusMessage("Post updated successfully");
|
||||
toast.success("Post updated successfully 😎");
|
||||
router.push("/admin/feed");
|
||||
setFormData(resp);
|
||||
}
|
||||
} catch (err) {
|
||||
toast.error("Uh oh! Something went wrong! Try again later. 😟");
|
||||
setError(err);
|
||||
}
|
||||
};
|
||||
|
||||
const onChange = (data) => setFormData(data.formData);
|
||||
const onFocus = () => setStatusMessage(null);
|
||||
|
||||
const title = formData?.id
|
||||
? `Edit Post "${formData.title_fi}"`
|
||||
@@ -194,9 +196,7 @@ const FeedCreatePage: NextPage = () => {
|
||||
schema={buildSchema(formData, tags)}
|
||||
UISchema={buildUISchema(formData)}
|
||||
onChange={onChange}
|
||||
onFocus={onFocus}
|
||||
onSubmit={onSubmit}
|
||||
statusMessage={statusMessage}
|
||||
error={error}
|
||||
widgets={widgets}
|
||||
/>
|
||||
|
||||
@@ -1,14 +1,37 @@
|
||||
import React from "react";
|
||||
import { NextPage } from "next";
|
||||
import { formatRelative } from "date-fns";
|
||||
import { toast } from "react-toastify";
|
||||
import styled from "styled-components";
|
||||
import AdminListCommon from "@views/admin/AdminListCommon";
|
||||
import { Link } from "@components/index";
|
||||
import { Button, Link } from "@components/index";
|
||||
import AddLink from "@components/AddLink";
|
||||
import Post from "@models/Feed";
|
||||
import PostApi from "@api/feedApi";
|
||||
import useFetchFeed from "@hooks/useFetchFeed";
|
||||
|
||||
const URL = "/admin/feed";
|
||||
|
||||
const StyledButton = styled(Button) <{ $colorOverride: "red" }>`
|
||||
background-color: ${(p) => p.$colorOverride};
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
`;
|
||||
|
||||
const confirmDelete = async (post: Post) => {
|
||||
if (window.confirm(`Delete: ${post.id}: ${post.title_fi}/${post.title_en}; Are you sure?`) === true) {
|
||||
try {
|
||||
await PostApi.deletePost(post.id);
|
||||
toast.success("Post removed successfully 😎");
|
||||
window.location.reload(); // TODO: Fetch/update post list, so user sees the signup in the list
|
||||
} catch (err) {
|
||||
toast.error("Uh oh! Something went wrong! Try again later. 😟");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const renderData = (feed: Post[]) => {
|
||||
if (!feed || feed.length === 0) {
|
||||
return <div>No posts.</div>;
|
||||
@@ -29,6 +52,11 @@ const renderData = (feed: Post[]) => {
|
||||
<td><Link to={`${URL}/${post.id}`}>{post.title_fi}</Link></td>
|
||||
<td>{post.description_fi}</td>
|
||||
<td>{formatRelative(new Date(post.publish_time), new Date())}</td>
|
||||
<td>
|
||||
<StyledButton $colorOverride="red" buttonStyle="filled" onClick={() => confirmDelete(post)}>
|
||||
Delete
|
||||
</StyledButton>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
@@ -7,6 +7,7 @@ import JobAdApi from "@api/jobAdApi";
|
||||
import DatetimeWidget from "@components/Widgets/DatetimeWidget";
|
||||
import SectionDividerWidget from "@components/Widgets/SectionDividerWidget";
|
||||
import MarkdownEditorWidget from "@components/Widgets/MarkdownEditorWidget";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
const widgets = {
|
||||
datetime: DatetimeWidget,
|
||||
@@ -108,7 +109,6 @@ const buildUISchema = (formData: JobAd) => ({
|
||||
const JobAdCreatePage: NextPage = () => {
|
||||
const [formData, setFormData] = useState<JobAd>(null);
|
||||
const [error, setError] = useState<string>(null);
|
||||
const [statusMessage, setStatusMessage] = useState<string>(null);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -132,20 +132,22 @@ const JobAdCreatePage: NextPage = () => {
|
||||
const payload = data.formData;
|
||||
if (payload.id === undefined) {
|
||||
const resp = await JobAdApi.createJobAd(payload);
|
||||
setStatusMessage("Post created successfully");
|
||||
toast.success("Job ad created successfully 😎");
|
||||
router.push("/admin/jobads");
|
||||
setFormData(resp);
|
||||
} else {
|
||||
const resp = await JobAdApi.updateJobAd(payload);
|
||||
setStatusMessage("Post updated successfully");
|
||||
toast.success("Job ad updated successfully 😎");
|
||||
router.push("/admin/jobads");
|
||||
setFormData(resp);
|
||||
}
|
||||
} catch (err) {
|
||||
toast.error("Uh oh! Something went wrong! Try again later. 😟");
|
||||
setError(err);
|
||||
}
|
||||
};
|
||||
|
||||
const onChange = (data) => setFormData(data.formData);
|
||||
const onFocus = () => setStatusMessage(null);
|
||||
|
||||
const title = formData?.id
|
||||
? `Edit Ad "${formData.title_fi}"`
|
||||
@@ -158,9 +160,7 @@ const JobAdCreatePage: NextPage = () => {
|
||||
schema={buildSchema(formData)}
|
||||
UISchema={buildUISchema(formData)}
|
||||
onChange={onChange}
|
||||
onFocus={onFocus}
|
||||
onSubmit={onSubmit}
|
||||
statusMessage={statusMessage}
|
||||
error={error}
|
||||
widgets={widgets}
|
||||
/>
|
||||
|
||||
@@ -1,14 +1,37 @@
|
||||
import React from "react";
|
||||
import { NextPage } from "next";
|
||||
import { formatRelative } from "date-fns";
|
||||
import { toast } from "react-toastify";
|
||||
import styled from "styled-components";
|
||||
import AdminListCommon from "@views/admin/AdminListCommon";
|
||||
import { Link } from "@components/index";
|
||||
import { Button, Link } from "@components/index";
|
||||
import AddLink from "@components/AddLink";
|
||||
import JobAd from "@models/JobAd";
|
||||
import useFetchJobAds from "@hooks/useFetchJobAds";
|
||||
import JobAdApi from "@api/jobAdApi";
|
||||
|
||||
const URL = "/admin/jobads";
|
||||
|
||||
const StyledButton = styled(Button) <{ $colorOverride: "red" }>`
|
||||
background-color: ${(p) => p.$colorOverride};
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
`;
|
||||
|
||||
const confirmDelete = async (jobad: JobAd) => {
|
||||
if (window.confirm(`Delete: ${jobad.id}: ${jobad.title_fi}/${jobad.title_en}; Are you sure?`) === true) {
|
||||
try {
|
||||
await JobAdApi.deleteJobAd(jobad.id);
|
||||
toast.success("Job ad removed successfully 😎");
|
||||
window.location.reload(); // TODO: Fetch/update event list, so user sees the signup in the list
|
||||
} catch (err) {
|
||||
toast.error("Uh oh! Something went wrong! Try again later. 😟");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const renderData = (jobAds: JobAd[]) => {
|
||||
if (!jobAds || jobAds.length === 0) {
|
||||
return <div>No advertisements.</div>;
|
||||
@@ -33,6 +56,11 @@ const renderData = (jobAds: JobAd[]) => {
|
||||
? formatRelative(new Date(ad.autohide_at), new Date())
|
||||
: "Disabled"}
|
||||
</td>
|
||||
<td>
|
||||
<StyledButton $colorOverride="red" buttonStyle="filled" onClick={() => confirmDelete(ad)}>
|
||||
Delete
|
||||
</StyledButton>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
@@ -8,6 +8,7 @@ import DatetimeWidget from "@components/Widgets/DatetimeWidget";
|
||||
import SignupQuestionsWidget from "@components/Widgets/SignupQuestionsWidget/SignupQuestionsWidget";
|
||||
import MarkdownEditorWidget from "@components/Widgets/MarkdownEditorWidget";
|
||||
import { buildValidationSchema } from "@views/SignUpPage/FormUtils";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
const DEFAULT_EMAIL = `Moikka,
|
||||
|
||||
@@ -98,7 +99,6 @@ const buildUISchema = () => {
|
||||
const SignupCreatePage: NextPage = () => {
|
||||
const [formData, setFormData] = useState<SignupForm>(null);
|
||||
const [error, setError] = useState<string>(null);
|
||||
const [statusMessage, setStatusMessage] = useState<string>(null);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -133,26 +133,28 @@ const SignupCreatePage: NextPage = () => {
|
||||
|
||||
if (payload.id === undefined) {
|
||||
const resp = await SignupApi.createForm(payload);
|
||||
setStatusMessage("Sign-up created successfully");
|
||||
toast.success("Sign-up created successfully 😎");
|
||||
router.push("/admin/signups");
|
||||
setFormData({
|
||||
...resp,
|
||||
questions: JSON.stringify(resp.questions) as any,
|
||||
});
|
||||
} else {
|
||||
const resp = await SignupApi.updateForm(payload);
|
||||
setStatusMessage("Sign-up updated successfully");
|
||||
toast.success("Sign-up updated successfully 😎");
|
||||
router.push("/admin/signups");
|
||||
setFormData({
|
||||
...resp,
|
||||
questions: JSON.stringify(resp.questions) as any,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
toast.error("Uh oh! Something went wrong! Try again later. 😟");
|
||||
setError(err);
|
||||
}
|
||||
};
|
||||
|
||||
const onChange = (data) => setFormData(data.formData);
|
||||
const onFocus = () => setStatusMessage(null);
|
||||
|
||||
const title = formData?.id
|
||||
? `Edit Sign-up Form "${formData.title_fi}"`
|
||||
@@ -166,9 +168,7 @@ const SignupCreatePage: NextPage = () => {
|
||||
schema={buildSchema(formData)}
|
||||
UISchema={buildUISchema()}
|
||||
onChange={onChange}
|
||||
onFocus={onFocus}
|
||||
onSubmit={onSubmit}
|
||||
statusMessage={statusMessage}
|
||||
error={error}
|
||||
widgets={widgets}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { NextPage } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { toast } from "react-toastify";
|
||||
import AdminCreateCommon from "@views/admin/AdminCreateCommon";
|
||||
import MarkdownEditorWidget from "@components/Widgets/MarkdownEditorWidget";
|
||||
import { SignupForm } from "@models/Signup";
|
||||
@@ -63,33 +64,26 @@ const SignupEmailPage: NextPage = () => {
|
||||
const signupForm = useInitializeData(id as string);
|
||||
|
||||
const [error, setError] = useState<string>(null);
|
||||
const [statusMessage, setStatusMessage] = useState<string>(null);
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
try {
|
||||
const payload = data.formData;
|
||||
await SignupApi.signupFormSendEmail(payload, Number(id));
|
||||
setStatusMessage("Email sent successfully");
|
||||
toast.success("Email sent successfully 😎");
|
||||
} catch (err) {
|
||||
setError(err);
|
||||
toast.error("Uh oh! Something went wrong! Try again later. 😟");
|
||||
}
|
||||
};
|
||||
|
||||
// const onChange = (data) => setFormData(data.formData);
|
||||
const onFocus = () => setStatusMessage(null);
|
||||
|
||||
const title = signupForm ? signupForm.title_fi : "Loading...";
|
||||
|
||||
return (
|
||||
<AdminCreateCommon
|
||||
title={title}
|
||||
// formData={formData}
|
||||
schema={buildSchema(title)}
|
||||
UISchema={buildUISchema()}
|
||||
// onChange={onChange}
|
||||
onFocus={onFocus}
|
||||
onSubmit={onSubmit}
|
||||
statusMessage={statusMessage}
|
||||
error={error}
|
||||
widgets={widgets}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { NextPage } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { toast } from "react-toastify";
|
||||
import styled from "styled-components";
|
||||
import { CSVLink } from "react-csv";
|
||||
import AdminListCommon from "@views/admin/AdminListCommon";
|
||||
@@ -11,6 +12,10 @@ import noop from "@utils/noop";
|
||||
|
||||
const StyledButton = styled(Button) <{ $colorOverride: "red" | "green" }>`
|
||||
background-color: ${(p) => p.$colorOverride};
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
`;
|
||||
|
||||
const SignupEmailPage: NextPage = () => {
|
||||
@@ -33,8 +38,9 @@ const SignupEmailPage: NextPage = () => {
|
||||
try {
|
||||
await SignupApi.deleteSignup(signup.id);
|
||||
setSignups(signups.filter((s) => s.id !== signup.id));
|
||||
toast.success("Signup removed successfully 😎");
|
||||
} catch (err) {
|
||||
window.alert("Delete failed!");
|
||||
toast.error("Uh oh! Something went wrong! Try again later. 😟");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,14 +1,36 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { NextPage } from "next";
|
||||
import { formatRelative } from "date-fns";
|
||||
import { toast } from "react-toastify";
|
||||
import styled from "styled-components";
|
||||
import AdminListCommon from "@views/admin/AdminListCommon";
|
||||
import { Link } from "@components/index";
|
||||
import { Button, Link } from "@components/index";
|
||||
import AddLink from "@components/AddLink";
|
||||
import { SignupForm } from "@models/Signup";
|
||||
import SignupApi from "@api/signupApi";
|
||||
|
||||
const URL = "/admin/signups";
|
||||
|
||||
const StyledButton = styled(Button) <{ $colorOverride: "red" }>`
|
||||
background-color: ${(p) => p.$colorOverride};
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
`;
|
||||
|
||||
const confirmDelete = async (signup: SignupForm) => {
|
||||
if (window.confirm(`Delete: ${signup.id}: ${signup.title_fi}/${signup.title_en}; Are you sure?`) === true) {
|
||||
try {
|
||||
await SignupApi.deleteForm(signup.id);
|
||||
toast.success("Signup removed successfully 😎");
|
||||
window.location.reload(); // TODO: Fetch/update event list, so user sees the signup in the list
|
||||
} catch (err) {
|
||||
toast.error("Uh oh! Something went wrong! Try again later. 😟");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const renderData = (signupForms: SignupForm[]) => {
|
||||
if (!signupForms || signupForms.length === 0) {
|
||||
return <div>No signup forms.</div>;
|
||||
@@ -33,6 +55,11 @@ const renderData = (signupForms: SignupForm[]) => {
|
||||
<td>{formatRelative(new Date(signupForm.end_time), new Date())}</td>
|
||||
<td><Link to={`${URL}/${signupForm.id}/list`}>View</Link></td>
|
||||
<td><Link to={`${URL}/${signupForm.id}/email`}>Send</Link></td>
|
||||
<td>
|
||||
<StyledButton $colorOverride="red" buttonStyle="filled" onClick={() => confirmDelete(signupForm)}>
|
||||
Delete
|
||||
</StyledButton>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
|
||||
@@ -8,6 +8,7 @@ import useFetchEvents from "@hooks/useFetchEvents";
|
||||
import EventPageView from "@views/EventPage/EventPageView";
|
||||
import PageWrapper from "@views/common/PageWrapper";
|
||||
import LoadingView from "@views/common/LoadingView";
|
||||
import NotFoundPage from "@pages/404";
|
||||
|
||||
interface InitialProps {
|
||||
initialEvent: Event;
|
||||
@@ -20,7 +21,13 @@ const EventPage: NextPage<InitialProps> = ({ initialEvent }) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { data, error } = useFetchEvents({ initialData: initialEvent, id: id as string });
|
||||
|
||||
if (!data || router.isFallback) return <LoadingView />;
|
||||
if (router.isFallback) return <LoadingView />;
|
||||
|
||||
if (!data) {
|
||||
return (
|
||||
<NotFoundPage />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -50,12 +57,19 @@ export const getStaticPaths: GetStaticPaths = async () => {
|
||||
|
||||
export const getStaticProps: GetStaticProps<InitialProps> = async ({ params }) => {
|
||||
const { id } = params;
|
||||
const initialEvent = await EventApi.getEvent(Number(id));
|
||||
let notFound = false;
|
||||
let initialEvent: Event;
|
||||
try {
|
||||
initialEvent = await EventApi.getEvent(Number(id));
|
||||
} catch (err) {
|
||||
notFound = true;
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
initialEvent,
|
||||
},
|
||||
revalidate: 10,
|
||||
notFound,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import useFetchFeed from "@hooks/useFetchFeed";
|
||||
import FeedPageView from "@views/FeedPage/FeedPageView";
|
||||
import PageWrapper from "@views/common/PageWrapper";
|
||||
import LoadingView from "@views/common/LoadingView";
|
||||
import NotFoundPage from "@pages/404";
|
||||
|
||||
interface InitialProps {
|
||||
initialPost: Post;
|
||||
@@ -20,7 +21,13 @@ const FeedPage: NextPage<InitialProps> = ({ initialPost }) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { data, error } = useFetchFeed({ initialData: initialPost, id: id as string });
|
||||
|
||||
if (!data || router.isFallback) return <LoadingView />;
|
||||
if (router.isFallback) return <LoadingView />;
|
||||
|
||||
if (!data) {
|
||||
return (
|
||||
<NotFoundPage />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -50,12 +57,20 @@ export const getStaticPaths: GetStaticPaths = async () => {
|
||||
|
||||
export const getStaticProps: GetStaticProps<InitialProps> = async ({ params }) => {
|
||||
const { id } = params;
|
||||
const initialPost = await FeedApi.getPost(Number(id));
|
||||
let notFound = false;
|
||||
let initialPost: Post;
|
||||
try {
|
||||
initialPost = await FeedApi.getPost(Number(id));
|
||||
} catch (err) {
|
||||
notFound = true;
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
initialPost,
|
||||
},
|
||||
revalidate: 10,
|
||||
notFound,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import React, { useState } from "react";
|
||||
import React from "react";
|
||||
import { NextPage, GetStaticProps, GetStaticPaths } from "next";
|
||||
import Head from "next/head";
|
||||
import { useRouter } from "next/router";
|
||||
import { toast } from "react-toastify";
|
||||
import { Signup, SignupForm } from "@models/Signup";
|
||||
import SignupApi from "@api/signupApi";
|
||||
import SignUpPageView from "@views/SignUpPage/SignUpPageView";
|
||||
import PageWrapper from "@views/common/PageWrapper";
|
||||
import LoadingView from "@views/common/LoadingView";
|
||||
import noop from "@utils/noop";
|
||||
import NotFoundPage from "@pages/404";
|
||||
|
||||
type InitialProps = {
|
||||
form: SignupForm;
|
||||
@@ -15,12 +17,17 @@ type InitialProps = {
|
||||
|
||||
const SignUpPage: NextPage<InitialProps> = ({ form }) => {
|
||||
const router = useRouter();
|
||||
const [statusMessage, setStatus] = useState(null);
|
||||
|
||||
if (router.isFallback) {
|
||||
return <LoadingView />;
|
||||
}
|
||||
|
||||
if (!form) {
|
||||
return (
|
||||
<NotFoundPage />
|
||||
);
|
||||
}
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
const payload: Signup = {
|
||||
signupForm_id: form.id,
|
||||
@@ -29,11 +36,11 @@ const SignUpPage: NextPage<InitialProps> = ({ form }) => {
|
||||
|
||||
try {
|
||||
await SignupApi.createSignup(payload);
|
||||
// TODO: Fetch/update signup list, so user sees the signup in the list
|
||||
setStatus("Sign-up submitted successfully");
|
||||
toast.success("Sign-up submitted successfully 😎");
|
||||
router.push(window.location.href); // TODO: Fetch/update signup list, so user sees the signup in the list
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setStatus("Bad request");
|
||||
toast.error("Uh oh! Sign-up failed! 😟");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,7 +53,6 @@ const SignUpPage: NextPage<InitialProps> = ({ form }) => {
|
||||
<SignUpPageView
|
||||
signUpForm={form}
|
||||
formData={{}}
|
||||
statusMessage={statusMessage}
|
||||
onChange={noop}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
@@ -71,12 +77,19 @@ export const getStaticPaths: GetStaticPaths = async () => {
|
||||
|
||||
export const getStaticProps: GetStaticProps<InitialProps> = async ({ params }) => {
|
||||
const { id } = params;
|
||||
const form = await SignupApi.getForm(Number(id));
|
||||
let notFound = false;
|
||||
let form: SignupForm;
|
||||
try {
|
||||
form = await SignupApi.getForm(Number(id));
|
||||
} catch {
|
||||
notFound = true;
|
||||
}
|
||||
return {
|
||||
props: {
|
||||
form,
|
||||
},
|
||||
revalidate: 10,
|
||||
notFound,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { NextPage } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
import { toast } from "react-toastify";
|
||||
import { Signup, SignupForm } from "@models/Signup";
|
||||
import SignupApi from "@api/signupApi";
|
||||
import SignUpPageView from "@views/SignUpPage/SignUpPageView";
|
||||
@@ -48,7 +49,6 @@ const useFetchSignup = (signupId: number, uuid: string) => {
|
||||
const EditSignUpPage: NextPage = () => {
|
||||
const router = useRouter();
|
||||
const { signupId, uuid } = parseQueryParams(router.query);
|
||||
const [statusMessage, setStatus] = useState(null);
|
||||
const [form, formData] = useFetchSignup(signupId, uuid);
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
@@ -61,10 +61,10 @@ const EditSignUpPage: NextPage = () => {
|
||||
try {
|
||||
await SignupApi.updateSignup(payload, uuid);
|
||||
// TODO: Update signup list, so user sees possible changes in the list
|
||||
setStatus("Sign-up submission updated successfully");
|
||||
toast.success("Sign-up updated successfully 😎");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setStatus("Bad request");
|
||||
toast.error("Uh oh! Updating sign-up failed! 😟");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -73,7 +73,6 @@ const EditSignUpPage: NextPage = () => {
|
||||
<SignUpPageView
|
||||
signUpForm={form}
|
||||
formData={formData}
|
||||
statusMessage={statusMessage}
|
||||
onChange={noop}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
|
||||
@@ -49,7 +49,6 @@ const ActualPageHero: React.FC = () => (
|
||||
linkText="Yritysyhteistyö ›"
|
||||
/>
|
||||
<HeroAsideItem
|
||||
// TODO: Too long
|
||||
header="Uusia suhteita ulkopaikkakuntalaisten kanssa"
|
||||
link="#ulkosuhteet"
|
||||
linkText="Ulkoiset suhteet ›"
|
||||
@@ -61,12 +60,12 @@ const ActualPageHero: React.FC = () => (
|
||||
>
|
||||
<HeroSecondarySectionItem note="Ma">
|
||||
<span>
|
||||
Killan hallitus päivystää kiltahuoneella <strong>maanantaisin klo 12.15–13.15.</strong> Tuolloin voit ostaa kiltatuotteita, kuten esim. haalarimerkkejä tai laulukirjoja.
|
||||
Killan hallitus päivystää kiltahuoneella <strong>maanantaisin.</strong> Tuolloin voit ostaa kiltatuotteita, kuten esim. haalarimerkkejä tai laulukirjoja.
|
||||
</span>
|
||||
</HeroSecondarySectionItem>
|
||||
<HeroSecondarySectionItem note="To">
|
||||
<span>
|
||||
Kiltapäiväkerho Kiltis kokoontuu <strong>torstaisin klo XX.XX kiltahuoneella.</strong> Lorem ipsum dolor sit amet. Lämpimästi tervetuloa kaikki SIKkiläiset ja SIK-mieliset!
|
||||
Kiltapäiväkerho Kiltis kokoontuu <strong>torstaisin kiltahuoneella.</strong>. Lämpimästi tervetuloa kaikki SIKkiläiset ja SIK-mieliset!
|
||||
</span>
|
||||
</HeroSecondarySectionItem>
|
||||
</HeroSecondarySection>
|
||||
|
||||
@@ -55,10 +55,10 @@ const ActualPageView: React.FC<ActualPageViewProps> = ({ events, feed }) => (
|
||||
presentationTime={5}
|
||||
fadeTime={1}
|
||||
images={[
|
||||
"/img/carousel_images/elecyykka-jani-mannonen-6.jpg",
|
||||
"/img/carousel_images/koydenveto-jani-mannonen-miika-koskela-17.jpg",
|
||||
"/img/carousel_images/koydenveto-jani-mannonen-miika-koskela-28.jpg",
|
||||
"/img/carousel_images/koydenveto-jani-mannonen-miika-koskela-78.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/elecyykka-jani-mannonen-6.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/koydenveto-jani-mannonen-miika-koskela-17.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/koydenveto-jani-mannonen-miika-koskela-28.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/koydenveto-jani-mannonen-miika-koskela-78.jpg",
|
||||
]}
|
||||
width={400}
|
||||
height={400}
|
||||
@@ -67,10 +67,10 @@ const ActualPageView: React.FC<ActualPageViewProps> = ({ events, feed }) => (
|
||||
presentationTime={5}
|
||||
fadeTime={1}
|
||||
images={[
|
||||
"/img/carousel_images/koydenveto-mikko-haapamaki-33.jpg",
|
||||
"/img/carousel_images/Varaslahto2020-AinoSuomi-73.jpg",
|
||||
"/img/carousel_images/varauksenpurku_2020_timitiira-80.jpg",
|
||||
"/img/carousel_images/otatarhan-ajot-timi-tiira-172.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/koydenveto-mikko-haapamaki-33.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/Varaslahto2020-AinoSuomi-73.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/varauksenpurku_2020_timitiira-80.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/otatarhan-ajot-timi-tiira-172.jpg",
|
||||
]}
|
||||
width={400}
|
||||
height={400}
|
||||
@@ -79,10 +79,10 @@ const ActualPageView: React.FC<ActualPageViewProps> = ({ events, feed }) => (
|
||||
presentationTime={5}
|
||||
fadeTime={1}
|
||||
images={[
|
||||
"/img/carousel_images/kokkarit_kiia_einola-0631.jpg",
|
||||
"/img/carousel_images/pota-jatkot-essi-jukkala-29.jpg",
|
||||
"/img/carousel_images/pota99-paajuhla-oskari-lahti-171.jpg",
|
||||
"/img/carousel_images/wappusitsit-jani-mannonen-29.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/kokkarit_kiia_einola-0631.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/pota-jatkot-essi-jukkala-29.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/pota99-paajuhla-oskari-lahti-171.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/wappusitsit-jani-mannonen-29.jpg",
|
||||
]}
|
||||
width={400}
|
||||
height={400}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import CommitteeContainer from "@components/CommitteeContainer";
|
||||
import { Divider, TextSection, Link } from "@components/index";
|
||||
import { colors } from "@theme/colors";
|
||||
import ContactCard from "@components/ContactCard";
|
||||
|
||||
import BoardJson from "./board.json";
|
||||
import HvtmkJson from "./hvtmk.json";
|
||||
@@ -15,6 +15,8 @@ import TtmkJson from "./ttmk.json";
|
||||
import UtmkJson from "./utmk.json";
|
||||
import YtmkJson from "./ytmk.json";
|
||||
|
||||
const blank_profile = "/img/blank_profile.png";
|
||||
|
||||
const BlueLink = styled(Link)`
|
||||
color: ${colors.blue1};
|
||||
|
||||
@@ -23,19 +25,59 @@ const BlueLink = styled(Link)`
|
||||
}
|
||||
`;
|
||||
|
||||
export interface Committee {
|
||||
const Container = styled.div`
|
||||
color: ${colors.darkBlue};
|
||||
|
||||
& > h2 {
|
||||
text-transform: uppercase;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
& > div {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
`;
|
||||
|
||||
const CommitteeContainer: React.FC<{
|
||||
committee: Committee;
|
||||
}> = ({ committee, children }) => (
|
||||
<Container>
|
||||
<h2>
|
||||
{committee.name_fi || committee.name_en}
|
||||
</h2>
|
||||
<div>
|
||||
{committee.roles.map((role) => (
|
||||
role.representatives.map((representative) => (
|
||||
<ContactCard
|
||||
key={representative.name}
|
||||
name={representative.name}
|
||||
phone={representative.phone_number}
|
||||
email={representative.email}
|
||||
image={(committee.name_en === "Board") ? (representative.image || blank_profile) : null}
|
||||
role_fi={role.name_fi}
|
||||
role_en={role.name_en}
|
||||
/>
|
||||
))
|
||||
))}
|
||||
</div>
|
||||
{children}
|
||||
</Container>
|
||||
);
|
||||
|
||||
interface Committee {
|
||||
name_fi: string;
|
||||
name_en: string;
|
||||
roles: Array<Role>;
|
||||
}
|
||||
|
||||
export interface Role {
|
||||
interface Role {
|
||||
name_fi: string;
|
||||
name_en: string;
|
||||
representatives: Array<Representative>
|
||||
}
|
||||
|
||||
export interface Representative {
|
||||
interface Representative {
|
||||
name: string;
|
||||
phone_number?: string;
|
||||
email?: string;
|
||||
@@ -45,6 +87,7 @@ export interface Representative {
|
||||
const ContactsPageView: React.FC = () => (
|
||||
<>
|
||||
<TextSection>
|
||||
<h1>Yhteystiedot</h1>
|
||||
<p>
|
||||
Asiaa olisi, mutta kehen ottaa yhteyttä?<br />
|
||||
Tämä sivu yrittää valottaa sen oikean ihmisen puhelinnumeroa ja sähköpostiosoitetta.
|
||||
@@ -52,87 +95,68 @@ const ContactsPageView: React.FC = () => (
|
||||
</TextSection>
|
||||
|
||||
<TextSection>
|
||||
<div>
|
||||
<CommitteeContainer committee={BoardJson} />
|
||||
<CommitteeContainer committee={BoardJson}>
|
||||
<p>
|
||||
{"Hallitukseen saa yhteyden lähettämällä sähköpostia "}
|
||||
<BlueLink to="mailto:hallitus@sahkoinsinoorikilta.fi">
|
||||
hallitus@sahkoinsinoorikilta.fi
|
||||
</BlueLink>
|
||||
</p>
|
||||
</div>
|
||||
</CommitteeContainer>
|
||||
</TextSection>
|
||||
|
||||
<Divider />
|
||||
|
||||
<TextSection>
|
||||
<div>
|
||||
<CommitteeContainer committee={HvtmkJson} />
|
||||
</div>
|
||||
<CommitteeContainer committee={HvtmkJson} />
|
||||
</TextSection>
|
||||
|
||||
<Divider />
|
||||
|
||||
<TextSection>
|
||||
<div>
|
||||
<CommitteeContainer committee={MtmkJson} />
|
||||
</div>
|
||||
<CommitteeContainer committee={MtmkJson} />
|
||||
</TextSection>
|
||||
|
||||
<Divider />
|
||||
|
||||
<TextSection>
|
||||
<div>
|
||||
<CommitteeContainer committee={OptmkJson} />
|
||||
</div>
|
||||
<CommitteeContainer committee={OptmkJson} />
|
||||
</TextSection>
|
||||
|
||||
<Divider />
|
||||
|
||||
<TextSection>
|
||||
<div>
|
||||
<CommitteeContainer committee={OtmkJson} />
|
||||
</div>
|
||||
<CommitteeContainer committee={OtmkJson} />
|
||||
</TextSection>
|
||||
|
||||
<Divider />
|
||||
|
||||
<TextSection id="eptmk">
|
||||
<div>
|
||||
<CommitteeContainer committee={PtmkJson} />
|
||||
</div>
|
||||
<CommitteeContainer committee={PtmkJson} />
|
||||
</TextSection>
|
||||
|
||||
<Divider />
|
||||
|
||||
<TextSection>
|
||||
<div>
|
||||
<CommitteeContainer committee={SstmkJson} />
|
||||
</div>
|
||||
<CommitteeContainer committee={SstmkJson} />
|
||||
</TextSection>
|
||||
|
||||
<Divider />
|
||||
|
||||
<TextSection id="ttmk">
|
||||
<div>
|
||||
<CommitteeContainer committee={TtmkJson} />
|
||||
</div>
|
||||
<CommitteeContainer committee={TtmkJson} />
|
||||
</TextSection>
|
||||
|
||||
<Divider />
|
||||
|
||||
<TextSection>
|
||||
<div>
|
||||
<CommitteeContainer committee={UtmkJson} />
|
||||
</div>
|
||||
<CommitteeContainer committee={UtmkJson} />
|
||||
</TextSection>
|
||||
|
||||
<Divider />
|
||||
|
||||
<TextSection>
|
||||
<div>
|
||||
<CommitteeContainer committee={YtmkJson} />
|
||||
</div>
|
||||
<CommitteeContainer committee={YtmkJson} />
|
||||
</TextSection>
|
||||
|
||||
<Divider />
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"name_en": "Chairman of the Board",
|
||||
"representatives": [
|
||||
{
|
||||
"name": "Johannes Ora"
|
||||
"name": "Johannes Ora",
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/chairman.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -19,7 +20,7 @@
|
||||
"name": "Salla Lyytikäinen",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/secretary.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -31,7 +32,7 @@
|
||||
"name": "Santeri Huhtala",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/treasurer.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -43,7 +44,7 @@
|
||||
"name": "Toni Ojala",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/captain1.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -55,7 +56,7 @@
|
||||
"name": "Toni Lyttinen",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/captain2.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -67,7 +68,7 @@
|
||||
"name": "Eveliina Ahonen",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/ceremonies.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -79,7 +80,7 @@
|
||||
"name": "Melisa Dönmez",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/court_cancelor.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -91,7 +92,7 @@
|
||||
"name": "Heidi Mäkitalo",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/isocoordinator.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -103,7 +104,7 @@
|
||||
"name": "Sauli Norja",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/wellbeing.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -115,7 +116,7 @@
|
||||
"name": "Simo Hakanummi",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/studies.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -127,7 +128,7 @@
|
||||
"name": "Oskari Ponkala",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/technology.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -139,7 +140,7 @@
|
||||
"name": "Oliver Hiekkamies",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/external.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -151,7 +152,7 @@
|
||||
"name": "Otto Julkunen",
|
||||
"phone_number": null,
|
||||
"email": null,
|
||||
"image": null
|
||||
"image": "https://static.sahkoinsinoorikilta.fi/img/board/corporate.jpg"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ interface EventPageViewProps {
|
||||
}
|
||||
|
||||
const StyledTextSection = styled(TextSection)`
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
|
||||
& > h1 {
|
||||
@@ -24,6 +23,17 @@ const StyledTextSection = styled(TextSection)`
|
||||
color: ${colors.orange1};
|
||||
}
|
||||
}
|
||||
|
||||
& > div {
|
||||
margin: auto;
|
||||
|
||||
& > p {
|
||||
font-size: 0.9rem;
|
||||
font-weight: bold;
|
||||
line-height: 0.4rem;
|
||||
}
|
||||
}
|
||||
|
||||
`;
|
||||
|
||||
const SignupButtons = styled.div`
|
||||
@@ -38,6 +48,8 @@ const Content = styled(MarkdownStyles)`
|
||||
|
||||
const EventPageView: React.FC<EventPageViewProps> = ({ event }) => {
|
||||
if (!event) return <LoadingView />;
|
||||
const date_start = new Date(event.start_time).toLocaleString("fi-FI");
|
||||
const date_end = new Date(event.end_time).toLocaleString("fi-FI");
|
||||
return (
|
||||
<StyledTextSection>
|
||||
<h1>
|
||||
@@ -48,13 +60,23 @@ const EventPageView: React.FC<EventPageViewProps> = ({ event }) => {
|
||||
<Image
|
||||
src={event.image || event.tags[0].icon}
|
||||
alt={event.title_fi}
|
||||
objectFit="scale-down"
|
||||
layout="responsive"
|
||||
width={0}
|
||||
height={0}
|
||||
width={16}
|
||||
height={9}
|
||||
/>
|
||||
</h1>
|
||||
<div>
|
||||
<Content source={event.content_fi} escapeHtml={false} />
|
||||
<p>
|
||||
Paikka: {event.location_fi}
|
||||
</p>
|
||||
<p>
|
||||
<time>Alkaa: {date_start}</time>
|
||||
</p>
|
||||
<p>
|
||||
<time>Päättyy: {date_end}</time>
|
||||
</p>
|
||||
{/* We may have multiple signup forms. Generate own Button for each one */}
|
||||
<SignupButtons>
|
||||
{event.signupForm.map((sf) => (
|
||||
|
||||
@@ -18,14 +18,14 @@ import noop from "@utils/noop";
|
||||
import FrontPageHero from "./FrontPageHero";
|
||||
|
||||
// Corporate logos import
|
||||
const ABB = "/img/corporate_logos/abb.png";
|
||||
const Caruna = "/img/corporate_logos/caruna.jpg";
|
||||
const Eaton = "/img/corporate_logos/eaton.png";
|
||||
const Ensto = "/img/corporate_logos/ensto.jpg";
|
||||
const eSett = "/img/corporate_logos/esett.png";
|
||||
const Fingrid = "/img/corporate_logos/fingrid.jpg";
|
||||
const NRCGroup = "/img/corporate_logos/nrcgroup.png";
|
||||
const Okmetic = "/img/corporate_logos/okmetic.png";
|
||||
const ABB = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/abb.jpg";
|
||||
const Caruna = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/caruna.jpg";
|
||||
const Eaton = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/eaton.jpg";
|
||||
const Ensto = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/ensto.jpg";
|
||||
const eSett = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/esett.jpg";
|
||||
const Fingrid = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/fingrid.jpg";
|
||||
const NRCGroup = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/nrcgroup.jpg";
|
||||
const Okmetic = "https://static.sahkoinsinoorikilta.fi/img/corporate_logos/okmetic.jpg";
|
||||
|
||||
interface FrontPageViewProps {
|
||||
events: Event[];
|
||||
|
||||
@@ -80,13 +80,10 @@ const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) =
|
||||
presentationTime={5}
|
||||
fadeTime={1}
|
||||
images={[
|
||||
|
||||
"/img/carousel_images/in_english/ulkoexcursio1-kiia-einola-3.jpg",
|
||||
"/img/carousel_images/in_english/international-sitsit-jani-mannonen-8.jpg",
|
||||
"/img/carousel_images/in_english/ulkoexcursio-kiia-einola-16.jpg",
|
||||
"/img/carousel_images/in_english/haalarigaala-jani-mannonen-1.jpg",
|
||||
"/img/carousel_images/in_english/Kaukkarit-2020-Elias-Hirvonen-44.jpg",
|
||||
"/img/carousel_images/in_english/koydenveto-jani-mannonen-miika-koskela-4.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/elecyykka-jani-mannonen-6.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/koydenveto-jani-mannonen-miika-koskela-17.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/koydenveto-jani-mannonen-miika-koskela-28.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/koydenveto-jani-mannonen-miika-koskela-78.jpg",
|
||||
]}
|
||||
width={400}
|
||||
height={400}
|
||||
@@ -95,12 +92,10 @@ const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) =
|
||||
presentationTime={5}
|
||||
fadeTime={1}
|
||||
images={[
|
||||
"/img/carousel_images/in_english/international-sitsit-jani-mannonen-8.jpg",
|
||||
"/img/carousel_images/in_english/Kaukkarit-2020-Elias-Hirvonen-44.jpg",
|
||||
"/img/carousel_images/in_english/koydenveto-jani-mannonen-miika-koskela-4.jpg",
|
||||
"/img/carousel_images/in_english/ulkoexcursio-kiia-einola-16.jpg",
|
||||
"/img/carousel_images/in_english/haalarigaala-jani-mannonen-1.jpg",
|
||||
"/img/carousel_images/in_english/ulkoexcursio1-kiia-einola-3.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/koydenveto-mikko-haapamaki-33.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/Varaslahto2020-AinoSuomi-73.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/varauksenpurku_2020_timitiira-80.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/otatarhan-ajot-timi-tiira-172.jpg",
|
||||
]}
|
||||
width={400}
|
||||
height={400}
|
||||
@@ -109,12 +104,10 @@ const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) =
|
||||
presentationTime={5}
|
||||
fadeTime={1}
|
||||
images={[
|
||||
"/img/carousel_images/in_english/haalarigaala-jani-mannonen-1.jpg",
|
||||
"/img/carousel_images/in_english/ulkoexcursio1-kiia-einola-3.jpg",
|
||||
"/img/carousel_images/in_english/international-sitsit-jani-mannonen-8.jpg",
|
||||
"/img/carousel_images/in_english/Kaukkarit-2020-Elias-Hirvonen-44.jpg",
|
||||
"/img/carousel_images/in_english/koydenveto-jani-mannonen-miika-koskela-4.jpg",
|
||||
"/img/carousel_images/in_english/ulkoexcursio-kiia-einola-16.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/kokkarit_kiia_einola-0631.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/pota-jatkot-essi-jukkala-29.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/pota99-paajuhla-oskari-lahti-171.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/carousel_images/wappusitsit-jani-mannonen-29.jpg",
|
||||
]}
|
||||
width={400}
|
||||
height={400}
|
||||
@@ -145,8 +138,8 @@ const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) =
|
||||
presentationTime={5}
|
||||
fadeTime={1}
|
||||
images={[
|
||||
"/img/carousel_images/in_english/tour/qtour1.jpg",
|
||||
"/img/carousel_images/in_english/tour/qtour2.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/tour/qtour1.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/tour/qtour2.jpg",
|
||||
]}
|
||||
width={400}
|
||||
height={400}
|
||||
@@ -155,8 +148,8 @@ const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) =
|
||||
presentationTime={5}
|
||||
fadeTime={1}
|
||||
images={[
|
||||
"/img/carousel_images/in_english/tour/qtour3.jpg",
|
||||
"/img/carousel_images/in_english/tour/qtour4.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/tour/qtour3.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/tour/qtour4.jpg",
|
||||
]}
|
||||
width={400}
|
||||
height={400}
|
||||
@@ -165,8 +158,8 @@ const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) =
|
||||
presentationTime={5}
|
||||
fadeTime={1}
|
||||
images={[
|
||||
"/img/carousel_images/in_english/tour/qtour5.jpg",
|
||||
"/img/carousel_images/in_english/tour/qtour1.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/tour/qtour5.jpg",
|
||||
"https://static.sahkoinsinoorikilta.fi/img/tour/qtour1.jpg",
|
||||
]}
|
||||
width={400}
|
||||
height={400}
|
||||
|
||||
@@ -18,22 +18,23 @@ const customWidgets = {
|
||||
interface SignUpPageViewProps {
|
||||
signUpForm: SignupForm;
|
||||
formData: any;
|
||||
statusMessage: string;
|
||||
onChange: (e: IChangeEvent<unknown>, es?: ErrorSchema) => unknown;
|
||||
onSubmit: (e: ISubmitEvent<unknown>) => unknown;
|
||||
}
|
||||
|
||||
const renderList = (signUpForm: SignupForm) => (
|
||||
<>
|
||||
<h6>
|
||||
Ilmoittautuneet{signUpForm.quota > 0 && (` (${signUpForm.signups.length}/${signUpForm.quota})`)}:
|
||||
</h6>
|
||||
<ol>
|
||||
{signUpForm.signups.map((s, idx) => (
|
||||
<li key={idx} className={signUpForm.quota && idx + 1 > signUpForm.quota ? "reserved" : ""}>{s}</li>
|
||||
))}
|
||||
</ol>
|
||||
</>
|
||||
<aside>
|
||||
<div>
|
||||
<h6>
|
||||
Ilmoittautuneet{signUpForm.quota > 0 && (` (${signUpForm.signups.length}/${signUpForm.quota})`)}:
|
||||
</h6>
|
||||
<ol>
|
||||
{signUpForm.signups.map((s, idx) => (
|
||||
<li key={idx} className={signUpForm.quota && idx + 1 > signUpForm.quota ? "reserved" : ""}>{s}</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
|
||||
const StyledSection = styled(TextSection)`
|
||||
@@ -62,7 +63,6 @@ const StyledSection = styled(TextSection)`
|
||||
const SignUpPageView: React.FC<SignUpPageViewProps> = ({
|
||||
signUpForm,
|
||||
formData,
|
||||
statusMessage,
|
||||
onChange,
|
||||
onSubmit,
|
||||
}) => {
|
||||
@@ -83,11 +83,34 @@ const SignUpPageView: React.FC<SignUpPageViewProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const form = signUpForm ? renderForm() : (
|
||||
<Loader $color={colors.darkBlue} />
|
||||
);
|
||||
let form: JSX.Element;
|
||||
let signups: JSX.Element = null;
|
||||
const startTime = new Date(signUpForm?.start_time);
|
||||
const endTime = new Date(signUpForm?.end_time);
|
||||
|
||||
if (!signUpForm) {
|
||||
// Show loader if in edit mode and form has not yet loaded.
|
||||
// For normal signup page, form is always defined on this level.
|
||||
form = (
|
||||
<Loader $color={colors.darkBlue} />
|
||||
);
|
||||
} else if (startTime > new Date()) {
|
||||
form = (
|
||||
<>
|
||||
<p>Ilmoittauminen ei ole vielä auennut!</p>
|
||||
<p>Se aukeaa {startTime.toLocaleString("fi-FI")}.</p>
|
||||
</>
|
||||
);
|
||||
} else if (new Date() > endTime) {
|
||||
form = (
|
||||
<p>Ilmoittauminen on umpeutunut!</p>
|
||||
);
|
||||
signups = renderList(signUpForm);
|
||||
} else {
|
||||
form = renderForm();
|
||||
signups = renderList(signUpForm);
|
||||
}
|
||||
|
||||
const signups = signUpForm && signUpForm.signups ? renderList(signUpForm) : null;
|
||||
return (
|
||||
<StyledSection>
|
||||
<h1>
|
||||
@@ -97,16 +120,9 @@ const SignUpPageView: React.FC<SignUpPageViewProps> = ({
|
||||
</h1>
|
||||
|
||||
<div>
|
||||
<span className="sign-up-statusmessage">
|
||||
{statusMessage}
|
||||
</span>
|
||||
{form}
|
||||
</div>
|
||||
<aside>
|
||||
<div>
|
||||
{signups}
|
||||
</div>
|
||||
</aside>
|
||||
{signups}
|
||||
</StyledSection>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -16,14 +16,6 @@ const Common = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const SuccessMsg = styled.p`
|
||||
margin-bottom: 0.5rem;
|
||||
border: 1px solid ${colors.green1};
|
||||
padding: 8px 16px;
|
||||
color: ${colors.green1};
|
||||
display: inline-block;
|
||||
`;
|
||||
|
||||
const ErrorMsg = styled.p`
|
||||
margin-bottom: 0.5rem;
|
||||
border: 1px solid ${colors.orange2};
|
||||
@@ -44,9 +36,8 @@ type AdminCreateCommonProps = {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
onChange?: (e: IChangeEvent<FormTypes>, es?: ErrorSchema) => unknown;
|
||||
onFocus: (id: string, value: string | number | boolean) => void;
|
||||
onFocus?: (id: string, value: string | number | boolean) => void;
|
||||
onSubmit: (e: ISubmitEvent<FormTypes>) => unknown;
|
||||
statusMessage: string;
|
||||
error: string;
|
||||
widgets: {
|
||||
[name: string]: any;
|
||||
@@ -61,7 +52,6 @@ const AdminCreateCommon: React.FC<AdminCreateCommonProps> = ({
|
||||
onChange,
|
||||
onFocus,
|
||||
onSubmit,
|
||||
statusMessage,
|
||||
error,
|
||||
widgets,
|
||||
}) => {
|
||||
@@ -74,9 +64,6 @@ const AdminCreateCommon: React.FC<AdminCreateCommonProps> = ({
|
||||
<AdminPageWrapper requiresAuthentication>
|
||||
<Common>
|
||||
<h1>{title}</h1>
|
||||
{statusMessage && (
|
||||
<SuccessMsg data-e2e="admin-form-status-message">{statusMessage}</SuccessMsg>
|
||||
)}
|
||||
<FormWrapper
|
||||
schema={schema}
|
||||
uiSchema={UISchema}
|
||||
|
||||
@@ -5,8 +5,6 @@ services:
|
||||
image: registry.gitlab.com/sahkoinsinoorikilta/vtmk/web2.0-frontend:latest
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
update_config:
|
||||
order: start-first
|
||||
ports:
|
||||
|
||||
@@ -5,8 +5,6 @@ services:
|
||||
image: registry.gitlab.com/sahkoinsinoorikilta/vtmk/web2.0-frontend:prod
|
||||
deploy:
|
||||
replicas: 1
|
||||
restart_policy:
|
||||
condition: on-failure
|
||||
update_config:
|
||||
order: start-first
|
||||
ports:
|
||||
|
||||
@@ -81,10 +81,10 @@ test("Logged in user can create event", async (t) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
t.fixtureCtx.eventId = parsed.id;
|
||||
|
||||
const statusMessage = Selector("[data-e2e=\"admin-form-status-message\"]");
|
||||
const statusMessage = Selector(".Toastify__toast-body");
|
||||
await t
|
||||
.hover(statusMessage)
|
||||
.expect(
|
||||
statusMessage.innerText,
|
||||
).eql("Event created successfully");
|
||||
).eql("Event created successfully 😎");
|
||||
});
|
||||
|
||||
@@ -86,10 +86,10 @@ test("Logged in user can create signup", async (t) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
t.fixtureCtx.formId = parsed.id;
|
||||
|
||||
const statusMessage = Selector("[data-e2e=\"admin-form-status-message\"]");
|
||||
const statusMessage = Selector(".Toastify__toast-body");
|
||||
await t
|
||||
.hover(statusMessage)
|
||||
.expect(
|
||||
statusMessage.innerText,
|
||||
).eql("Sign-up created successfully");
|
||||
).eql("Sign-up created successfully 😎");
|
||||
});
|
||||
|
||||
@@ -52,10 +52,10 @@ test("User signups to event from front page", async (t) => {
|
||||
|
||||
await t.click(Selector("button").nth(-1));
|
||||
|
||||
const statusMessage = Selector(".sign-up-statusmessage");
|
||||
const statusMessage = Selector(".Toastify__toast-body");
|
||||
await t
|
||||
.hover(statusMessage)
|
||||
.expect(
|
||||
statusMessage.innerText,
|
||||
).eql("Sign-up submitted successfully");
|
||||
).eql("Sign-up submitted successfully 😎");
|
||||
});
|
||||
|
||||