├── website ├── static │ ├── .nojekyll │ ├── CNAME │ └── img │ │ ├── app.png │ │ ├── admin.png │ │ ├── input.png │ │ ├── logo.png │ │ ├── play.png │ │ ├── aerogear.png │ │ ├── config.png │ │ ├── favicon.ico │ │ ├── features.png │ │ ├── rocket.png │ │ ├── architecture.png │ │ └── plugin-blog.jpg ├── .gitignore ├── sidebars.js ├── src │ ├── pages │ │ ├── styles.module.css │ │ └── index.js │ ├── components │ │ ├── styles.module.css │ │ ├── Hero │ │ │ ├── styles.module.css │ │ │ └── index.jsx │ │ ├── Terminal │ │ │ ├── styles.module.css │ │ │ └── index.jsx │ │ ├── Video │ │ │ └── index.jsx │ │ └── Features │ │ │ └── styles.module.css │ └── css │ │ └── custom.css └── package.json ├── .env ├── platform ├── server │ ├── src │ │ ├── config │ │ │ ├── playground.gql │ │ │ ├── keycloak.json │ │ │ ├── auth.ts │ │ │ └── config.ts │ │ ├── CrudService.ts │ │ ├── db.ts │ │ ├── pubsub.ts │ │ ├── index.ts │ │ ├── graphql.ts │ │ └── auth.ts │ ├── .dockerignore │ ├── .gitignore │ ├── mongodump │ │ └── showcase │ │ │ ├── product │ │ │ ├── 5ef7401712f76aecc84af1f1.bson │ │ │ ├── 5ef7410912f76aecc84af1f3.bson │ │ │ ├── 5ef7419b12f76aecc84af1f5.bson │ │ │ ├── 5ef741a512f76aecc84af1f6.bson │ │ │ ├── 5ef741b812f76aecc84af1f7.bson │ │ │ ├── 5ef741d812f76aecc84af1f8.bson │ │ │ ├── 5ef741f012f76aecc84af1f9.bson │ │ │ ├── 5ef7421512f76aecc84af1fa.bson │ │ │ ├── 5ef7423012f76aecc84af1fb.bson │ │ │ ├── 5ef7430812f76aecc84af1fc.bson │ │ │ ├── 5ef7442912f76aecc84af1fe.bson │ │ │ ├── 5ef7444012f76aecc84af1ff.bson │ │ │ └── 5ef7449d12f76aecc84af200.bson │ │ │ ├── recipient │ │ │ ├── 5ef73f9412f76aecc84af1f0.bson │ │ │ ├── 5ef7418312f76aecc84af1f4.bson │ │ │ ├── 5ef90768f37edb606082f456.bson │ │ │ ├── 5ef907b0f37edb606082f463.bson │ │ │ ├── 5ef907d2f37edb606082f479.bson │ │ │ ├── 5ef907e3f37edb606082f480.bson │ │ │ ├── 5ef907f5f37edb606082f485.bson │ │ │ ├── 5ef90811f37edb606082f48c.bson │ │ │ ├── 5ef90824f37edb606082f4a2.bson │ │ │ ├── 5ef90831f37edb606082f4a7.bson │ │ │ └── 5ef90845f37edb606082f4ac.bson │ │ │ ├── volunteer │ │ │ ├── 5ef6262d90701a3b90ebb227.bson │ │ │ ├── 5ef6266890701a3b90ebb237.bson │ │ │ ├── 5ef6269490701a3b90ebb245.bson │ │ │ ├── 5ef626c190701a3b90ebb24f.bson │ │ │ ├── 5ef626e690701a3b90ebb25b.bson │ │ │ ├── 5ef6271a90701a3b90ebb26a.bson │ │ │ └── 5ef9c631da553f262c7a95dc.bson │ │ │ ├── dailyactionplan │ │ │ ├── 5efa28d793802a8fb60e8acf.bson │ │ │ ├── 5efa28de93802a8fb60e8ad0.bson │ │ │ ├── 5efa28e593802a8fb60e8ad1.bson │ │ │ ├── 5efa2a1a0f9e4e90fe73a30d.bson │ │ │ ├── 5efa2a2c0f9e4e90fe73a30e.bson │ │ │ ├── 5efa2a7e0f9e4e90fe73a30f.bson │ │ │ ├── 5efa2a800f9e4e90fe73a310.bson │ │ │ ├── 5efa2a810f9e4e90fe73a311.bson │ │ │ ├── 5efa2a850f9e4e90fe73a312.bson │ │ │ ├── 5efa2aa60f9e4e90fe73a313.bson │ │ │ ├── 5efa2aa70f9e4e90fe73a314.bson │ │ │ └── 5efa2aaa0f9e4e90fe73a315.bson │ │ │ ├── volunteeraction │ │ │ ├── 5ef9c4f9da553f262c7a95d7.bson │ │ │ ├── 5ef9c684da553f262c7a95dd.bson │ │ │ ├── 5efa273a93802a8fb60e8ac0.bson │ │ │ ├── 5efa27d993802a8fb60e8ac4.bson │ │ │ ├── 5efa280793802a8fb60e8ac8.bson │ │ │ └── 5efa282893802a8fb60e8acc.bson │ │ │ ├── distributioncentre │ │ │ ├── 5ef740ac12f76aecc84af1f2.bson │ │ │ └── 5ef7437a12f76aecc84af1fd.bson │ │ │ └── volunteeractionproduct │ │ │ ├── 5ef9c4f9da553f262c7a95d8.bson │ │ │ ├── 5ef9c4f9da553f262c7a95d9.bson │ │ │ ├── 5ef9c4f9da553f262c7a95da.bson │ │ │ ├── 5ef9c4f9da553f262c7a95db.bson │ │ │ ├── 5efa273a93802a8fb60e8ac1.bson │ │ │ ├── 5efa273a93802a8fb60e8ac2.bson │ │ │ ├── 5efa273a93802a8fb60e8ac3.bson │ │ │ ├── 5efa27d993802a8fb60e8ac5.bson │ │ │ ├── 5efa27d993802a8fb60e8ac6.bson │ │ │ ├── 5efa27d993802a8fb60e8ac7.bson │ │ │ ├── 5efa280793802a8fb60e8ac9.bson │ │ │ ├── 5efa280793802a8fb60e8aca.bson │ │ │ ├── 5efa280793802a8fb60e8acb.bson │ │ │ ├── 5efa282893802a8fb60e8acd.bson │ │ │ └── 5efa282893802a8fb60e8ace.bson │ ├── Dockerfile │ ├── integrations │ │ ├── mqtt │ │ │ └── docker-compose.yml │ │ └── keycloak │ │ │ ├── docker-compose.yml │ │ │ └── getToken.js │ ├── .env │ ├── .graphqlrc.yml │ ├── docker-compose.yml │ ├── tsconfig.json │ └── package.json ├── client │ ├── src │ │ ├── react-app-env.d.ts │ │ ├── config │ │ │ ├── index.ts │ │ │ ├── SimpleSchema.ts │ │ │ └── clientConfig.ts │ │ ├── hooks │ │ │ ├── index.ts │ │ │ └── useSubscribeToMore.ts │ │ ├── helpers │ │ │ ├── index.ts │ │ │ ├── ConflictLogger.ts │ │ │ └── CapacitorNetworkStatus.ts │ │ ├── pages │ │ │ ├── index.ts │ │ │ └── ActionPage.tsx │ │ ├── graphql │ │ │ └── queries │ │ │ │ ├── findLoggedVolunteer.graphql │ │ │ │ └── findMyVolunteerActions.graphql │ │ ├── components │ │ │ ├── index.ts │ │ │ ├── Loading.tsx │ │ │ ├── Empty.tsx │ │ │ ├── ActionsList.tsx │ │ │ ├── Action.tsx │ │ │ ├── Router.tsx │ │ │ └── Header.tsx │ │ ├── App.tsx │ │ ├── index.tsx │ │ ├── transformer │ │ │ └── volunteerTransformer.ts │ │ ├── declarations.ts │ │ ├── theme │ │ │ ├── index.ts │ │ │ └── styles.css │ │ ├── forms │ │ │ ├── distributionCentre.ts │ │ │ ├── volunteerAction.ts │ │ │ ├── recipient.ts │ │ │ └── volunteer.ts │ │ ├── context │ │ │ └── AuthContext.tsx │ │ ├── AppContainer.tsx │ │ └── keycloakAuth.ts │ ├── .env │ ├── public │ │ ├── assets │ │ │ ├── icon │ │ │ │ ├── icon.png │ │ │ │ ├── favicon.png │ │ │ │ ├── aerogear.png │ │ │ │ └── keycloak.png │ │ │ └── shapes.svg │ │ ├── keycloak.example.json │ │ ├── keycloak.json │ │ ├── manifest.json │ │ └── index.html │ ├── ionic.config.json │ ├── capacitor.config.json │ ├── .gitignore │ ├── tsconfig.json │ ├── README.adoc │ ├── .graphqlrc.yml │ ├── samples.graphql │ └── package.json ├── client-admin │ ├── src │ │ ├── react-app-env.d.ts │ │ ├── config │ │ │ ├── index.ts │ │ │ ├── SimpleSchema.ts │ │ │ ├── MarkerIcons.ts │ │ │ └── clientConfig.ts │ │ ├── hooks │ │ │ ├── index.ts │ │ │ └── useSubscribeToMore.ts │ │ ├── pages │ │ │ ├── index.ts │ │ │ ├── ProductsPage.tsx │ │ │ ├── VolunteersPage.tsx │ │ │ ├── RecipientsPage.tsx │ │ │ ├── ActionPage.tsx │ │ │ ├── ProfilePage.tsx │ │ │ └── SchedulePage.tsx │ │ ├── graphql │ │ │ ├── queries │ │ │ │ ├── findLoggedVolunteer.graphql │ │ │ │ ├── findIdAndNamesOfAllDistributionCentres.graphql │ │ │ │ ├── findAllDistributionCenters.graphql │ │ │ │ └── findVolunteerActionDetails.graphql │ │ │ └── mutations │ │ │ │ └── assignVolunteers.graphql │ │ ├── App.tsx │ │ ├── components │ │ │ ├── index.ts │ │ │ ├── generic │ │ │ │ ├── Loading.tsx │ │ │ │ └── Empty.tsx │ │ │ ├── model │ │ │ │ ├── ActionList.tsx │ │ │ │ ├── ProductList.tsx │ │ │ │ ├── VolunteerList.tsx │ │ │ │ ├── RecipientList.tsx │ │ │ │ ├── Product.tsx │ │ │ │ ├── Action.tsx │ │ │ │ ├── Recipient.tsx │ │ │ │ └── Volunteer.tsx │ │ │ ├── Map.tsx │ │ │ ├── Header.tsx │ │ │ ├── Menu.css │ │ │ └── Menu.tsx │ │ ├── context │ │ │ └── AuthContext.tsx │ │ ├── index.tsx │ │ ├── declarations.ts │ │ ├── transformer │ │ │ └── volunteerTransformer.ts │ │ ├── forms │ │ │ ├── volunteerActionRecipient.ts │ │ │ ├── admin.ts │ │ │ ├── product.ts │ │ │ ├── distributionCentre.ts │ │ │ ├── dailyAction.ts │ │ │ ├── volunteerAction.ts │ │ │ ├── recipient.ts │ │ │ ├── createVolunteer.ts │ │ │ ├── createVolunteerAction.ts │ │ │ └── volunteer.ts │ │ ├── theme │ │ │ ├── index.ts │ │ │ └── styles.css │ │ ├── AppContainer.tsx │ │ └── keycloakAuth.ts │ ├── public │ │ ├── assets │ │ │ ├── icon │ │ │ │ ├── icon.png │ │ │ │ ├── aerogear.png │ │ │ │ ├── favicon.png │ │ │ │ └── keycloak.png │ │ │ └── shapes.svg │ │ ├── keycloak.example.json │ │ ├── keycloak.json │ │ ├── manifest.json │ │ └── index.html │ ├── ionic.config.json │ ├── .env │ ├── capacitor.config.json │ ├── .gitignore │ ├── tsconfig.json │ ├── README.adoc │ ├── .graphqlrc.yml │ └── package.json ├── .openshift │ ├── amq.yml │ ├── amq-topics.yml │ └── README.md └── package.json ├── cli ├── types │ ├── index.d.ts │ ├── components │ │ ├── index.d.ts │ │ └── init.d.ts │ ├── utils │ │ └── index.d.ts │ ├── init │ │ ├── starterTemplates.d.ts │ │ └── templateMetadata.d.ts │ └── commands │ │ └── init.d.ts ├── dist │ ├── init │ │ └── templateMetadata.js │ ├── components │ │ └── index.js │ ├── index.js │ └── utils │ │ └── index.js ├── tests │ └── workflow-test.ts ├── tsconfig.json ├── src │ ├── index.ts │ ├── utils │ │ └── index.ts │ ├── init │ │ └── templateMetadata.ts │ └── commands │ │ └── init.ts ├── README.md ├── jest.config.js └── package.json ├── scripts └── docker.sh ├── renovate.json ├── docs ├── client.md ├── features.md ├── referencegs.md ├── architecture.md ├── clientref.md ├── gettingstarted.md └── integrations_graphback_keycloak.md ├── .github ├── ISSUE_TEMPLATE │ ├── 3-ask-for-help.md │ ├── 1-bug-report.md │ └── 2-feature-request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── node.js.yml ├── .gitignore ├── .vscode └── launch.json ├── LICENSE └── .circleci └── config.yml /website/static/.nojekyll : -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true -------------------------------------------------------------------------------- /website/static/CNAME: -------------------------------------------------------------------------------- 1 | openvolunteer.org -------------------------------------------------------------------------------- /platform/server/src/config/playground.gql: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cli/types/index.d.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | export {}; 3 | -------------------------------------------------------------------------------- /platform/server/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log -------------------------------------------------------------------------------- /cli/dist/init/templateMetadata.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | -------------------------------------------------------------------------------- /platform/client/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /platform/client-admin/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /platform/client/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export { clientConfig } from './clientConfig'; 2 | -------------------------------------------------------------------------------- /platform/client-admin/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export { clientConfig } from './clientConfig'; 2 | -------------------------------------------------------------------------------- /platform/client/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { useSubscribeToMore } from './useSubscribeToMore'; -------------------------------------------------------------------------------- /platform/client-admin/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { useSubscribeToMore } from './useSubscribeToMore'; -------------------------------------------------------------------------------- /platform/client/src/helpers/index.ts: -------------------------------------------------------------------------------- 1 | 2 | export { ConflictLogger } from './ConflictLogger'; 3 | -------------------------------------------------------------------------------- /website/static/img/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/app.png -------------------------------------------------------------------------------- /platform/client/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | REACT_APP_GOOGLE_MAP_API_KEY=AIzaSyAmAwkv8-x2I--ne-NtA3C_4E_-aLCsFJ1 3 | -------------------------------------------------------------------------------- /platform/server/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | types 4 | yarn.lock 5 | yarn-error.log 6 | data/* 7 | admin 8 | website -------------------------------------------------------------------------------- /website/static/img/admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/admin.png -------------------------------------------------------------------------------- /website/static/img/input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/input.png -------------------------------------------------------------------------------- /website/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/logo.png -------------------------------------------------------------------------------- /website/static/img/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/play.png -------------------------------------------------------------------------------- /scripts/docker.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | 3 | docker build -t wtrocki/openvolunteer:latest . 4 | docker push wtrocki/openvolunteer:latest -------------------------------------------------------------------------------- /website/static/img/aerogear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/aerogear.png -------------------------------------------------------------------------------- /website/static/img/config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/config.png -------------------------------------------------------------------------------- /website/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/favicon.ico -------------------------------------------------------------------------------- /website/static/img/features.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/features.png -------------------------------------------------------------------------------- /website/static/img/rocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/rocket.png -------------------------------------------------------------------------------- /website/static/img/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/architecture.png -------------------------------------------------------------------------------- /website/static/img/plugin-blog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/website/static/img/plugin-blog.jpg -------------------------------------------------------------------------------- /platform/client/public/assets/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/client/public/assets/icon/icon.png -------------------------------------------------------------------------------- /platform/client/public/assets/icon/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/client/public/assets/icon/favicon.png -------------------------------------------------------------------------------- /cli/types/components/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './db'; 2 | export * from './generate'; 3 | export * from './config'; 4 | export * from './transformOpenApiSpec'; 5 | -------------------------------------------------------------------------------- /platform/client/public/assets/icon/aerogear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/client/public/assets/icon/aerogear.png -------------------------------------------------------------------------------- /platform/client/public/assets/icon/keycloak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/client/public/assets/icon/keycloak.png -------------------------------------------------------------------------------- /platform/client-admin/public/assets/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/client-admin/public/assets/icon/icon.png -------------------------------------------------------------------------------- /platform/client-admin/public/assets/icon/aerogear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/client-admin/public/assets/icon/aerogear.png -------------------------------------------------------------------------------- /platform/client-admin/public/assets/icon/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/client-admin/public/assets/icon/favicon.png -------------------------------------------------------------------------------- /platform/client-admin/public/assets/icon/keycloak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/client-admin/public/assets/icon/keycloak.png -------------------------------------------------------------------------------- /platform/client/ionic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "appId": "com.datasync.starter", 4 | "integrations": { 5 | "capacitor": {} 6 | }, 7 | "type": "react" 8 | } 9 | -------------------------------------------------------------------------------- /platform/client/src/pages/index.ts: -------------------------------------------------------------------------------- 1 | export { ActionPage } from './ActionPage'; 2 | export { ProfilePage } from './ProfilePage'; 3 | export { ViewActionPage } from './ViewActionPage'; 4 | -------------------------------------------------------------------------------- /platform/client-admin/ionic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "appId": "com.datasync.starter", 4 | "integrations": { 5 | "capacitor": {} 6 | }, 7 | "type": "react" 8 | } 9 | -------------------------------------------------------------------------------- /platform/client-admin/src/pages/index.ts: -------------------------------------------------------------------------------- 1 | export { ActionPage } from './ActionPage'; 2 | export { ProfilePage } from './ProfilePage'; 3 | export { ViewActionPage } from './ViewActionPage'; 4 | -------------------------------------------------------------------------------- /platform/client-admin/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | REACT_APP_GOOGLE_MAP_API_KEY=AIzaSyDLv7YJxcswz2uJGuHKXICnddMjZ_CyLas 3 | REACT_APP_REPORT_COLUMN_SIZE=4 4 | REACT_APP_NEARBY_MAX_DISTANCE=100 -------------------------------------------------------------------------------- /cli/tests/workflow-test.ts: -------------------------------------------------------------------------------- 1 | import { existsSync } from 'fs'; 2 | import { join, resolve } from 'path'; 3 | 4 | test('Test cli workflow', async () => { 5 | // TODO 6 | expect(true).toBe(true); 7 | }); 8 | 9 | -------------------------------------------------------------------------------- /platform/client/src/config/SimpleSchema.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from 'simpl-schema'; 2 | 3 | // Register custom property. 4 | SimpleSchema.extendOptions(['uniforms']); 5 | 6 | export default SimpleSchema; 7 | -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef7401712f76aecc84af1f1.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef7401712f76aecc84af1f1.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef7410912f76aecc84af1f3.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef7410912f76aecc84af1f3.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef7419b12f76aecc84af1f5.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef7419b12f76aecc84af1f5.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef741a512f76aecc84af1f6.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef741a512f76aecc84af1f6.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef741b812f76aecc84af1f7.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef741b812f76aecc84af1f7.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef741d812f76aecc84af1f8.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef741d812f76aecc84af1f8.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef741f012f76aecc84af1f9.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef741f012f76aecc84af1f9.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef7421512f76aecc84af1fa.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef7421512f76aecc84af1fa.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef7423012f76aecc84af1fb.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef7423012f76aecc84af1fb.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef7430812f76aecc84af1fc.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef7430812f76aecc84af1fc.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef7442912f76aecc84af1fe.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef7442912f76aecc84af1fe.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef7444012f76aecc84af1ff.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef7444012f76aecc84af1ff.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/product/5ef7449d12f76aecc84af200.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/product/5ef7449d12f76aecc84af200.bson -------------------------------------------------------------------------------- /platform/client-admin/src/config/SimpleSchema.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from 'simpl-schema'; 2 | 3 | // Register custom property. 4 | SimpleSchema.extendOptions(['uniforms']); 5 | 6 | export default SimpleSchema; 7 | -------------------------------------------------------------------------------- /platform/client/capacitor.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "appId": "io.ionic.starter", 3 | "appName": "client", 4 | "bundledWebRuntime": true, 5 | "npmClient": "npm", 6 | "webDir": "build", 7 | "cordova": {} 8 | } 9 | -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/recipient/5ef73f9412f76aecc84af1f0.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/recipient/5ef73f9412f76aecc84af1f0.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/recipient/5ef7418312f76aecc84af1f4.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/recipient/5ef7418312f76aecc84af1f4.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/recipient/5ef90768f37edb606082f456.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/recipient/5ef90768f37edb606082f456.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/recipient/5ef907b0f37edb606082f463.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/recipient/5ef907b0f37edb606082f463.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/recipient/5ef907d2f37edb606082f479.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/recipient/5ef907d2f37edb606082f479.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/recipient/5ef907e3f37edb606082f480.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/recipient/5ef907e3f37edb606082f480.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/recipient/5ef907f5f37edb606082f485.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/recipient/5ef907f5f37edb606082f485.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/recipient/5ef90811f37edb606082f48c.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/recipient/5ef90811f37edb606082f48c.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/recipient/5ef90824f37edb606082f4a2.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/recipient/5ef90824f37edb606082f4a2.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/recipient/5ef90831f37edb606082f4a7.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/recipient/5ef90831f37edb606082f4a7.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/recipient/5ef90845f37edb606082f4ac.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/recipient/5ef90845f37edb606082f4ac.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteer/5ef6262d90701a3b90ebb227.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteer/5ef6262d90701a3b90ebb227.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteer/5ef6266890701a3b90ebb237.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteer/5ef6266890701a3b90ebb237.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteer/5ef6269490701a3b90ebb245.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteer/5ef6269490701a3b90ebb245.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteer/5ef626c190701a3b90ebb24f.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteer/5ef626c190701a3b90ebb24f.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteer/5ef626e690701a3b90ebb25b.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteer/5ef626e690701a3b90ebb25b.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteer/5ef6271a90701a3b90ebb26a.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteer/5ef6271a90701a3b90ebb26a.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteer/5ef9c631da553f262c7a95dc.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteer/5ef9c631da553f262c7a95dc.bson -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base", 4 | ":pinVersions" 5 | ], 6 | "groupName": "all", 7 | "automerge": false, 8 | "major": { 9 | "automerge": false 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /platform/client-admin/capacitor.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "appId": "io.ionic.starter", 3 | "appName": "client", 4 | "bundledWebRuntime": true, 5 | "npmClient": "npm", 6 | "webDir": "build", 7 | "cordova": {} 8 | } 9 | -------------------------------------------------------------------------------- /platform/client-admin/src/config/MarkerIcons.ts: -------------------------------------------------------------------------------- 1 | export const RED_ICON = "http://maps.google.com/mapfiles/ms/icons/red-dot.png"; 2 | export const YELLOW_ICON = "http://maps.google.com/mapfiles/ms/icons/yellow-dot.png"; 3 | -------------------------------------------------------------------------------- /platform/server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12.18.3 2 | 3 | # Create app directory 4 | WORKDIR /usr/src/app 5 | 6 | COPY . . 7 | RUN npm install 8 | 9 | VOLUME ./files 10 | 11 | EXPOSE 4000 12 | CMD [ "npm", "start" ] 13 | -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa28d793802a8fb60e8acf.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa28d793802a8fb60e8acf.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa28de93802a8fb60e8ad0.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa28de93802a8fb60e8ad0.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa28e593802a8fb60e8ad1.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa28e593802a8fb60e8ad1.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa2a1a0f9e4e90fe73a30d.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa2a1a0f9e4e90fe73a30d.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa2a2c0f9e4e90fe73a30e.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa2a2c0f9e4e90fe73a30e.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa2a7e0f9e4e90fe73a30f.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa2a7e0f9e4e90fe73a30f.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa2a800f9e4e90fe73a310.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa2a800f9e4e90fe73a310.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa2a810f9e4e90fe73a311.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa2a810f9e4e90fe73a311.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa2a850f9e4e90fe73a312.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa2a850f9e4e90fe73a312.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa2aa60f9e4e90fe73a313.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa2aa60f9e4e90fe73a313.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa2aa70f9e4e90fe73a314.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa2aa70f9e4e90fe73a314.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/dailyactionplan/5efa2aaa0f9e4e90fe73a315.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/dailyactionplan/5efa2aaa0f9e4e90fe73a315.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeraction/5ef9c4f9da553f262c7a95d7.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeraction/5ef9c4f9da553f262c7a95d7.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeraction/5ef9c684da553f262c7a95dd.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeraction/5ef9c684da553f262c7a95dd.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeraction/5efa273a93802a8fb60e8ac0.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeraction/5efa273a93802a8fb60e8ac0.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeraction/5efa27d993802a8fb60e8ac4.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeraction/5efa27d993802a8fb60e8ac4.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeraction/5efa280793802a8fb60e8ac8.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeraction/5efa280793802a8fb60e8ac8.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeraction/5efa282893802a8fb60e8acc.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeraction/5efa282893802a8fb60e8acc.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/distributioncentre/5ef740ac12f76aecc84af1f2.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/distributioncentre/5ef740ac12f76aecc84af1f2.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/distributioncentre/5ef7437a12f76aecc84af1fd.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/distributioncentre/5ef7437a12f76aecc84af1fd.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5ef9c4f9da553f262c7a95d8.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5ef9c4f9da553f262c7a95d8.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5ef9c4f9da553f262c7a95d9.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5ef9c4f9da553f262c7a95d9.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5ef9c4f9da553f262c7a95da.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5ef9c4f9da553f262c7a95da.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5ef9c4f9da553f262c7a95db.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5ef9c4f9da553f262c7a95db.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5efa273a93802a8fb60e8ac1.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5efa273a93802a8fb60e8ac1.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5efa273a93802a8fb60e8ac2.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5efa273a93802a8fb60e8ac2.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5efa273a93802a8fb60e8ac3.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5efa273a93802a8fb60e8ac3.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5efa27d993802a8fb60e8ac5.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5efa27d993802a8fb60e8ac5.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5efa27d993802a8fb60e8ac6.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5efa27d993802a8fb60e8ac6.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5efa27d993802a8fb60e8ac7.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5efa27d993802a8fb60e8ac7.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5efa280793802a8fb60e8ac9.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5efa280793802a8fb60e8ac9.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5efa280793802a8fb60e8aca.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5efa280793802a8fb60e8aca.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5efa280793802a8fb60e8acb.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5efa280793802a8fb60e8acb.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5efa282893802a8fb60e8acd.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5efa282893802a8fb60e8acd.bson -------------------------------------------------------------------------------- /platform/server/mongodump/showcase/volunteeractionproduct/5efa282893802a8fb60e8ace.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aerogear/OpenVolunteerPlatform/HEAD/platform/server/mongodump/showcase/volunteeractionproduct/5efa282893802a8fb60e8ace.bson -------------------------------------------------------------------------------- /platform/client/src/graphql/queries/findLoggedVolunteer.graphql: -------------------------------------------------------------------------------- 1 | query findActiveVolunteer($username: String!) { 2 | findVolunteers(filter: { username: {eq: $username} }, page: {limit: 1}) { 3 | items { 4 | ...VolunteerFields 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /platform/client-admin/src/graphql/queries/findLoggedVolunteer.graphql: -------------------------------------------------------------------------------- 1 | query findActiveVolunteer($username: String!) { 2 | findVolunteers(filter: { username: {eq: $username} }, page: {limit: 1}) { 3 | items { 4 | ...VolunteerFields 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /platform/client-admin/src/graphql/mutations/assignVolunteers.graphql: -------------------------------------------------------------------------------- 1 | mutation assignVolunteers{ 2 | assignVolunteers{ 3 | _id 4 | owner 5 | date 6 | numberOfVolunteersAssigned 7 | numberOfCasesCreated 8 | numberOfRecipients 9 | } 10 | } -------------------------------------------------------------------------------- /platform/client/src/components/index.ts: -------------------------------------------------------------------------------- 1 | 2 | export { Action } from './Action'; 3 | export { Empty } from './Empty'; 4 | export { Header } from './Header'; 5 | export { Router } from './Router'; 6 | export { Loading } from './Loading'; 7 | export { ActionsList } from './ActionsList'; -------------------------------------------------------------------------------- /platform/server/integrations/mqtt/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | # Mosca is a simple MQTT Broker 4 | # In OpenShift/Production we would use the Red Hat AMQ broker 5 | mosca: 6 | image: eclipse-mosquitto:latest 7 | ports: 8 | - "1883:1883" # MQTT -------------------------------------------------------------------------------- /platform/client/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Router } from './components'; 3 | 4 | // load all styles 5 | import './theme'; 6 | export const App: React.FC= () => { 7 | 8 | return ( 9 | <> 10 | 11 | 12 | ); 13 | }; 14 | 15 | -------------------------------------------------------------------------------- /platform/client-admin/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Router } from './components'; 3 | 4 | // load all styles 5 | import './theme'; 6 | export const App: React.FC= () => { 7 | 8 | return ( 9 | <> 10 | 11 | 12 | ); 13 | }; 14 | 15 | -------------------------------------------------------------------------------- /platform/client/public/keycloak.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "realm": "", 3 | "auth-server-url": "https://your-server/auth", 4 | "ssl-required": "none", 5 | "resource": "", 6 | "public-client": true, 7 | "use-resource-role-mappings": true, 8 | "confidential-port": 0 9 | } -------------------------------------------------------------------------------- /platform/client-admin/public/keycloak.example.json: -------------------------------------------------------------------------------- 1 | { 2 | "realm": "", 3 | "auth-server-url": "https://your-server/auth", 4 | "ssl-required": "none", 5 | "resource": "", 6 | "public-client": true, 7 | "use-resource-role-mappings": true, 8 | "confidential-port": 0 9 | } -------------------------------------------------------------------------------- /platform/server/integrations/keycloak/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | keycloak: 5 | image: jboss/keycloak:3.4.3.Final 6 | ports: 7 | - "8080:8080" 8 | environment: 9 | DB_VENDOR: h2 10 | KEYCLOAK_USER: admin 11 | KEYCLOAK_PASSWORD: admin -------------------------------------------------------------------------------- /platform/client-admin/src/components/index.ts: -------------------------------------------------------------------------------- 1 | 2 | export { Volunteer } from './model/Volunteer'; 3 | export { Empty } from './generic/Empty'; 4 | export { Header } from './Header'; 5 | export { Router } from './Router'; 6 | export { ActionsList } from './model/ActionList'; 7 | export { Loading } from './generic/Loading'; -------------------------------------------------------------------------------- /platform/client-admin/src/graphql/queries/findIdAndNamesOfAllDistributionCentres.graphql: -------------------------------------------------------------------------------- 1 | query findIdAndNamesOfAllDistributionCentres($limit: Int, $offset: Int) { 2 | findDistributionCentres(page: {limit: $limit, offset: $offset}) { 3 | items { 4 | _id, 5 | name 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /platform/client/public/keycloak.json: -------------------------------------------------------------------------------- 1 | { 2 | "realm": "open-volunteer-platform", 3 | "auth-server-url": "http://localhost:8080/auth", 4 | "ssl-required": "none", 5 | "resource": "open-volunteer-platform-public", 6 | "public-client": true, 7 | "use-resource-role-mappings": true, 8 | "confidential-port": 0 9 | } -------------------------------------------------------------------------------- /platform/client-admin/public/keycloak.json: -------------------------------------------------------------------------------- 1 | { 2 | "realm": "open-volunteer-platform", 3 | "auth-server-url": "http://localhost:8080/auth", 4 | "ssl-required": "none", 5 | "resource": "open-volunteer-platform-public", 6 | "public-client": true, 7 | "use-resource-role-mappings": true, 8 | "confidential-port": 0 9 | } -------------------------------------------------------------------------------- /platform/server/src/config/keycloak.json: -------------------------------------------------------------------------------- 1 | { 2 | "realm": "open-volunteer-platform", 3 | "auth-server-url": "http://localhost:8080/auth", 4 | "ssl-required": "none", 5 | "resource": "open-volunteer-platform-bearer", 6 | "public-client": true, 7 | "use-resource-role-mappings": true, 8 | "confidential-port": 0 9 | } -------------------------------------------------------------------------------- /cli/types/components/init.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * init command handler 3 | * @param name name of project folder 4 | * @param templateName name of the template provided(if any) 5 | * @param templateUrl github url to the template 6 | */ 7 | export declare function init(name: string, templateName?: string, templateUrl?: string): Promise; 8 | -------------------------------------------------------------------------------- /cli/dist/components/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function __export(m) { 3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; 4 | } 5 | exports.__esModule = true; 6 | __export(require("./db")); 7 | __export(require("./generate")); 8 | __export(require("./config")); 9 | __export(require("./transformOpenApiSpec")); 10 | -------------------------------------------------------------------------------- /cli/types/utils/index.d.ts: -------------------------------------------------------------------------------- 1 | export declare const log: { 2 | (message?: any, ...optionalParams: any[]): void; 3 | (message?: any, ...optionalParams: any[]): void; 4 | }; 5 | export declare const logError: (s: string) => void; 6 | export declare const logInfo: (s: string) => void; 7 | export declare const logDetail: (s: string) => void; 8 | -------------------------------------------------------------------------------- /platform/client/src/components/Loading.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IonLoading } from '@ionic/react'; 3 | import { ILoadingProps } from '../declarations'; 4 | 5 | export const Loading: React.FC = ({ loading }) => { 6 | return ; 10 | }; -------------------------------------------------------------------------------- /platform/client/src/graphql/queries/findMyVolunteerActions.graphql: -------------------------------------------------------------------------------- 1 | query findMyVolunteerActions($volunteerId: GraphbackObjectID!, $status: String) { 2 | findVolunteerActions(filter: { volunteerId: {eq: $volunteerId}, status: { 3 | eq: $status 4 | } }) { 5 | items { 6 | ...VolunteerActionFields 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /platform/client-admin/src/context/AuthContext.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { KeycloakInstance, KeycloakProfile } from 'keycloak-js'; 3 | export interface IAuthContext { 4 | keycloak?: KeycloakInstance | undefined 5 | profile?: KeycloakProfile | undefined 6 | } 7 | 8 | export const AuthContext = React.createContext({}); -------------------------------------------------------------------------------- /cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": [ 3 | "./src/**/*.ts" 4 | ], 5 | "compilerOptions": { 6 | "outDir": "./dist/", 7 | "declaration": true, 8 | "declarationDir": "types", 9 | "lib": [ 10 | "esnext.asynciterable", 11 | "es2015", 12 | "es2018.promise", 13 | "dom", 14 | "es2016" 15 | ] 16 | } 17 | } -------------------------------------------------------------------------------- /platform/client/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { App } from './App'; 4 | import { AppContainer } from './AppContainer'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | serviceWorker.register(); 10 | -------------------------------------------------------------------------------- /platform/client-admin/src/components/generic/Loading.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IonLoading } from '@ionic/react'; 3 | import { ILoadingProps } from '../../declarations'; 4 | 5 | export const Loading: React.FC = ({ loading }) => { 6 | return ; 10 | }; -------------------------------------------------------------------------------- /platform/client-admin/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { App } from './App'; 4 | import { AppContainer } from './AppContainer'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | serviceWorker.register(); 10 | -------------------------------------------------------------------------------- /platform/client-admin/src/graphql/queries/findAllDistributionCenters.graphql: -------------------------------------------------------------------------------- 1 | 2 | query findFlatDistributionCentres($page: PageRequest, $orderBy: OrderByInput) { 3 | findDistributionCentres(page: $page, orderBy: $orderBy) { 4 | items { 5 | ...DistributionCentreFields 6 | } 7 | offset 8 | limit 9 | count 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /platform/client/src/hooks/useSubscribeToMore.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | export const useSubscribeToMore: any = ({ options, subscribeToMore } : { options: any, subscribeToMore: Function }) => { 4 | 5 | useEffect(()=>{ 6 | options.forEach((option: any) => { 7 | subscribeToMore(option); 8 | }); 9 | }, [options, subscribeToMore]); 10 | 11 | }; 12 | -------------------------------------------------------------------------------- /website/sidebars.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | docs: { 3 | Introduction: ["gettingstarted", "features", "architecture"], 4 | "Reference Apps": ["gettingstartedref", "coding"], 5 | Development: ["clientref", "serverfullstack"], 6 | Customizations: ["datamodel", "keycloak-authz", "liveupdates", "adding-and-customizing-forms"], 7 | Tools: ["client"] 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /platform/client-admin/src/hooks/useSubscribeToMore.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | export const useSubscribeToMore: any = ({ options, subscribeToMore } : { options: any, subscribeToMore: Function }) => { 4 | 5 | useEffect(()=>{ 6 | options.forEach((option: any) => { 7 | subscribeToMore(option); 8 | }); 9 | }, [options, subscribeToMore]); 10 | 11 | }; 12 | -------------------------------------------------------------------------------- /cli/src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import * as yargs from 'yargs'; 4 | 5 | if (require.main === module) { 6 | // eslint-disable-next-line no-unused-expressions 7 | yargs 8 | .commandDir('commands') 9 | .demandCommand(1) 10 | .strict() 11 | .recommendCommands() 12 | .help() 13 | .alias('h', 'help') 14 | .version() 15 | .alias('v', 'version') 16 | .argv; 17 | } -------------------------------------------------------------------------------- /platform/client-admin/src/declarations.ts: -------------------------------------------------------------------------------- 1 | import { KeycloakInstance } from "keycloak-js"; 2 | 3 | 4 | export interface IContainerProps { 5 | app: React.FC 6 | }; 7 | 8 | export interface ILoadingProps { 9 | loading: boolean 10 | }; 11 | 12 | export interface IUpdateMatchParams { 13 | id: string 14 | } 15 | 16 | export interface IAuthHeaders { 17 | headers: { 18 | Authorization: String 19 | } 20 | } -------------------------------------------------------------------------------- /cli/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | import * as chalk from 'chalk'; 2 | import * as emoji from 'node-emoji'; 3 | 4 | //tslint:disable-next-line: no-console 5 | export const log = console.log; 6 | export const logError = (s: string) => log(emoji.emojify(chalk.default.bold.red(s))); 7 | export const logInfo = (s: string) => log(emoji.emojify(chalk.default.bold(s))); 8 | export const logDetail = (s: string) => log(emoji.emojify(chalk.default.dim(s))); 9 | -------------------------------------------------------------------------------- /platform/client/src/transformer/volunteerTransformer.ts: -------------------------------------------------------------------------------- 1 | import { VolunteerFieldsFragment } from "../dataFacade"; 2 | 3 | export const volunteerTransformer = (volunteer: VolunteerFieldsFragment) => { 4 | // Restructure data 5 | if (volunteer.dateOfBirth) { 6 | //volunteer.dateOfBirth = new Date(volunteer.dateOfBirth); 7 | } 8 | //delete volunteer.__typename; 9 | 10 | return volunteer as VolunteerFieldsFragment; 11 | } -------------------------------------------------------------------------------- /cli/types/init/starterTemplates.d.ts: -------------------------------------------------------------------------------- 1 | import { Template } from './templateMetadata'; 2 | /** 3 | * available templates 4 | */ 5 | export declare const allTemplates: Template[]; 6 | /** 7 | * download and extract template from repository into project folder 8 | * @param template template information 9 | * @param name name of project folder 10 | */ 11 | export declare function extractTemplate(template: Template, name: string): Promise; 12 | -------------------------------------------------------------------------------- /platform/server/.env: -------------------------------------------------------------------------------- 1 | ## Mongo 2 | MONGO_USER=user 3 | MONGO_PASSWORD=password 4 | MONGO_ADMIN_PASSWORD=password 5 | MONGO_DATABASE=showcase 6 | MONGO_HOST= 7 | 8 | ## MQTT 9 | MQTT_HOST= 10 | MQTT_PORT= 11 | MQTT_PASSWORD= 12 | MQTT_USERNAME= 13 | MQTT_PROTOCOL= 14 | 15 | # Hack to enable keycloak with self signed certs 16 | # don't do it in production 17 | NODE_TLS_REJECT_UNAUTHORIZED=0 18 | 19 | BACKUP_DEMO_DATA=false 20 | USE_DEMO_DATA=true -------------------------------------------------------------------------------- /platform/client-admin/src/transformer/volunteerTransformer.ts: -------------------------------------------------------------------------------- 1 | import { VolunteerFieldsFragment } from "../dataFacade"; 2 | 3 | export const volunteerTransformer = (volunteer: VolunteerFieldsFragment) => { 4 | // Restructure data 5 | if (volunteer.dateOfBirth) { 6 | volunteer.dateOfBirth = new Date(volunteer.dateOfBirth); 7 | } 8 | delete volunteer.__typename; 9 | 10 | return volunteer as VolunteerFieldsFragment; 11 | } 12 | -------------------------------------------------------------------------------- /platform/client/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | .vscode 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /platform/client-admin/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | .vscode 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | -------------------------------------------------------------------------------- /cli/types/commands/init.d.ts: -------------------------------------------------------------------------------- 1 | import { Argv } from 'yargs'; 2 | declare type Params = { 3 | name?: string; 4 | templateName?: string; 5 | templateUrl: string; 6 | }; 7 | export declare const command = "init "; 8 | export declare const desc = "Create project from available templates"; 9 | export declare const builder: (args: Argv<{}>) => void; 10 | export declare function handler({ name, templateName, templateUrl }: Params): Promise; 11 | export {}; 12 | -------------------------------------------------------------------------------- /cli/dist/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | "use strict"; 3 | exports.__esModule = true; 4 | var yargs = require("yargs"); 5 | if (require.main === module) { 6 | // eslint-disable-next-line no-unused-expressions 7 | yargs 8 | .commandDir('commands') 9 | .demandCommand(1) 10 | .strict() 11 | .recommendCommands() 12 | .help() 13 | .alias('h', 'help') 14 | .version() 15 | .alias('v', 'version') 16 | .argv; 17 | } 18 | -------------------------------------------------------------------------------- /cli/dist/utils/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var chalk = require("chalk"); 4 | var emoji = require("node-emoji"); 5 | //tslint:disable-next-line: no-console 6 | exports.log = console.log; 7 | exports.logError = function (s) { return exports.log(emoji.emojify(chalk["default"].bold.red(s))); }; 8 | exports.logInfo = function (s) { return exports.log(emoji.emojify(chalk["default"].bold(s))); }; 9 | exports.logDetail = function (s) { return exports.log(emoji.emojify(chalk["default"].dim(s))); }; 10 | -------------------------------------------------------------------------------- /docs/client.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: client 3 | title: CLI commands 4 | --- 5 | 6 | # Open Volunteer Platform CLI 7 | 8 | The command-line tool (CLI) helps you bootstrap your Open Volunteer Platform template. 9 | 10 | ## Requirements 11 | 12 | * [Node.js 10.0.0](https://nodejs.org/en/download/) or later version 13 | * Docker and Docker compose 14 | 15 | ## Usage 16 | 17 | 1. Execute starter 18 | 19 | ``` 20 | npx openvp init yourproject 21 | ``` 22 | 2. Answer the question prompts and pick the template that suits your needs. 23 | -------------------------------------------------------------------------------- /cli/src/init/templateMetadata.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Template name, description and Repository information 3 | */ 4 | export interface Template { 5 | name: string 6 | description: string 7 | repo: TemplateRepository 8 | } 9 | 10 | /** 11 | * Github Repository information, uri, branch and path 12 | */ 13 | export interface TemplateRepository { 14 | uri: string 15 | branch: string 16 | path: string 17 | } 18 | 19 | /** 20 | * name of example model, content 21 | */ 22 | export interface GraphQLModel { 23 | name: string 24 | content: string 25 | } -------------------------------------------------------------------------------- /platform/client/src/declarations.ts: -------------------------------------------------------------------------------- 1 | import { ApolloClient, InMemoryCache } from "@apollo/client"; 2 | 3 | export interface IContainerProps { 4 | app: React.FC 5 | }; 6 | 7 | export interface ILoadingProps { 8 | loading: boolean 9 | }; 10 | 11 | export interface IUpdateMatchParams { 12 | id: string 13 | } 14 | 15 | export interface IAuthHeaders { 16 | headers: { 17 | Authorization: String 18 | } 19 | } 20 | 21 | export interface ILogoutParams { 22 | keycloak: Keycloak.KeycloakInstance | undefined, 23 | client: ApolloClient 24 | } -------------------------------------------------------------------------------- /platform/client-admin/src/graphql/queries/findVolunteerActionDetails.graphql: -------------------------------------------------------------------------------- 1 | query findVolunteerActionDetails($id: GraphbackObjectID!) { 2 | getVolunteerAction(id: $id ) { 3 | _id, 4 | title, 5 | description, 6 | status, 7 | distributionCentre { 8 | ...DistributionCentreFields 9 | }, 10 | recipient { 11 | ...RecipientFields 12 | }, 13 | volunteer { 14 | ...VolunteerFields 15 | }, 16 | products { 17 | _id, 18 | product { 19 | ...ProductFields 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/3-ask-for-help.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "⁉️ Need some help with this project?" 3 | about: Please file an issue in our repo. 4 | 5 | --- 6 | 7 | ## Help Wanted 8 | 9 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /cli/types/init/templateMetadata.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Template name, description and Repository information 3 | */ 4 | export interface Template { 5 | name: string; 6 | description: string; 7 | repo: TemplateRepository; 8 | } 9 | /** 10 | * Github Repository information, uri, branch and path 11 | */ 12 | export interface TemplateRepository { 13 | uri: string; 14 | branch: string; 15 | path: string; 16 | } 17 | /** 18 | * name of example model, content 19 | */ 20 | export interface GraphQLModel { 21 | name: string; 22 | content: string; 23 | } 24 | -------------------------------------------------------------------------------- /cli/README.md: -------------------------------------------------------------------------------- 1 | ## Open Volunteer Platform Client 2 | 3 | **Website**: https://openvolunteer.org 4 | 5 | **Repository**: https://github.com/aerogear/openvolunteerplatform/ 6 | 7 | The command-line tool (CLI) helps you bootstrap your Open Volunteer Platform template 8 | 9 | ## Requirements 10 | 11 | * [Node.js 10.0.0](https://nodejs.org/en/download/) or later version 12 | * Docker and Docker compose 13 | 14 | ## Usage 15 | 16 | Execute starter 17 | ``` 18 | npx openvp init yourproject 19 | ``` 20 | Answer the question prompts and pick the template that suits your needs. 21 | -------------------------------------------------------------------------------- /platform/server/.graphqlrc.yml: -------------------------------------------------------------------------------- 1 | ## GraphQL Config Generated by Graphback 2 | ## Please review configuration and adjust it for your own project 3 | schema: ./src/schema/schema.graphql 4 | extensions: 5 | graphback: 6 | model: ./model/main.graphql 7 | crud: 8 | create: true 9 | update: true 10 | findOne: true 11 | find: true 12 | delete: true 13 | subCreate: true 14 | subUpdate: true 15 | subDelete: true 16 | plugins: 17 | graphback-schema: 18 | format: graphql 19 | outputPath: ./src/schema/schema.graphql -------------------------------------------------------------------------------- /platform/client-admin/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "AeroGear OpenVolunteer", 3 | "name": "OpenVolunteer", 4 | "icons": [ 5 | { 6 | "src": "assets/icon/aerogear.png", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "assets/icon/aerogear.png", 12 | "type": "image/png", 13 | "sizes": "512x512", 14 | "purpose": "maskable" 15 | } 16 | ], 17 | "start_url": ".", 18 | "display": "standalone", 19 | "theme_color": "#ffffff", 20 | "background_color": "#ffffff" 21 | } 22 | -------------------------------------------------------------------------------- /platform/client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "AeroGear Open Volunteer", 3 | "name": "AeroGear Open Volunteer", 4 | "icons": [ 5 | { 6 | "src": "assets/icon/aerogear.png", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "assets/icon/aerogear.png", 12 | "type": "image/png", 13 | "sizes": "512x512", 14 | "purpose": "maskable" 15 | } 16 | ], 17 | "start_url": ".", 18 | "display": "standalone", 19 | "theme_color": "#ffffff", 20 | "background_color": "#ffffff" 21 | } 22 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | ### Description 9 | 10 | 11 | 12 | ##### Checklist 13 | 14 | 15 | - [ ] `npm test` passes 16 | - [ ] `npm run build` works 17 | - [ ] tests are included 18 | - [ ] documentation is changed or added 19 | -------------------------------------------------------------------------------- /platform/client/src/components/Empty.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IonContent, IonGrid, IonRow, IonCol, IonText } from '@ionic/react'; 3 | 4 | export const Empty: React.FC = ({ message }) => { 5 | return ( 6 | 7 | 8 | 9 | 10 | 11 | { message } 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /platform/server/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | mongodb: 4 | image: centos/mongodb-34-centos7 5 | container_name: "mongodb" 6 | environment: 7 | - MONGODB_USER=user 8 | - MONGODB_PASSWORD=password 9 | - MONGODB_ADMIN_PASSWORD=password 10 | - MONGODB_DATABASE=showcase 11 | ports: 12 | - 27017:27017 13 | keycloak: 14 | image: jboss/keycloak:3.4.3.Final 15 | ports: 16 | - "8080:8080" 17 | environment: 18 | DB_VENDOR: h2 19 | KEYCLOAK_USER: ovp-admin 20 | KEYCLOAK_PASSWORD: ovp-admin -------------------------------------------------------------------------------- /platform/client-admin/src/components/generic/Empty.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IonContent, IonGrid, IonRow, IonCol, IonText } from '@ionic/react'; 3 | 4 | export const Empty: React.FC = ({ message }) => { 5 | return ( 6 | 7 | 8 | 9 | 10 | 11 | { message } 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /platform/client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "noEmit": true, 20 | "jsx": "react" 21 | }, 22 | "include": [ 23 | "src" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/1-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41B Bug report" 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | ## Bug Report 8 | 9 | 17 | 18 | * **Version/Commit**: 19 | * **Ionic Version**: 20 | * **Node.js / npm versions**: 21 | 22 | -------------------------------------------------------------------------------- /platform/client-admin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "noEmit": true, 20 | "jsx": "react" 21 | }, 22 | "include": [ 23 | "src" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /platform/client-admin/src/forms/volunteerActionRecipient.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const recipientSchema = new SimpleSchema({ 5 | firstName: { 6 | type: String, 7 | max: 220 8 | }, 9 | lastName: { 10 | type: String, 11 | max: 220 12 | }, 13 | phone: { 14 | type: String, 15 | max: 220 16 | }, 17 | prefferedProducts: { 18 | type: String, 19 | max: 220, 20 | required: false 21 | } 22 | } as any); 23 | 24 | export default new SimpleSchema2Bridge(recipientSchema); 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F680 Feature request" 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | ## Feature Request 8 | 9 | 14 | 15 | **Is your feature request related to a problem? Please describe.** 16 | Please describe the problem you are trying to solve. 17 | 18 | **Describe the solution you'd like** 19 | Please describe the desired behavior. 20 | 21 | **Describe alternatives you've considered** 22 | Please describe alternative solutions or features you have considered. -------------------------------------------------------------------------------- /platform/client/src/components/ActionsList.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Action } from './Action'; 3 | import { IonList } from '@ionic/react'; 4 | import { Empty } from './Empty'; 5 | 6 | export const ActionsList: React.FC = ({ actions }) => { 7 | if(!actions || actions.length < 1) { 8 | const message = (

You currently have no actions.

); 9 | return 10 | }; 11 | 12 | return ( 13 | <> 14 | 15 | { 16 | actions.map((action : any) => { 17 | return ; 18 | }) 19 | } 20 | 21 | 22 | ); 23 | 24 | }; 25 | -------------------------------------------------------------------------------- /platform/client-admin/src/components/model/ActionList.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Action } from './Action'; 3 | import { IonList } from '@ionic/react'; 4 | import { Empty } from '../generic/Empty'; 5 | 6 | export const ActionsList: React.FC = ({ actions }) => { 7 | if(!actions || actions.length < 1) { 8 | const message = (

You currently have no tasks.

); 9 | return 10 | }; 11 | 12 | return ( 13 | <> 14 | 15 | { 16 | actions.map((action : any) => { 17 | return ; 18 | }) 19 | } 20 | 21 | 22 | ); 23 | 24 | }; 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Specifies intentionally untracked files to ignore when using Git 2 | # http://git-scm.com/docs/gitignore 3 | 4 | *~ 5 | *.sw[mnpcod] 6 | *.log 7 | *.tmp 8 | *.tmp.* 9 | log.txt 10 | *.sublime-project 11 | *.sublime-workspace 12 | npm-debug.log* 13 | 14 | .idea/ 15 | .ionic/ 16 | .sourcemaps/ 17 | .sass-cache/ 18 | .tmp/ 19 | .versions/ 20 | coverage/ 21 | www/ 22 | node_modules/ 23 | tmp/ 24 | temp/ 25 | platforms/ 26 | plugins/ 27 | plugins/android.json 28 | plugins/ios.json 29 | $RECYCLE.BIN/ 30 | 31 | .DS_Store 32 | Thumbs.db 33 | UserInterfaceState.xcuserstate 34 | package-lock.json 35 | yarn.lock 36 | 37 | platform/client/ios/ 38 | platform/client/android/ 39 | platform/client/.gradle/ 40 | testApp 41 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "Launch server", 11 | "args": ["${workspaceFolder}/server/src/index.ts"], 12 | "sourceMaps": true, 13 | "runtimeArgs": ["--nolazy", "-r", "ts-node/register"], 14 | "outFiles": ["${workspaceFolder}/server/dist/**/*.js"], 15 | "cwd": "${workspaceRoot}/server", 16 | "protocol": "inspector", 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /platform/server/integrations/keycloak/getToken.js: -------------------------------------------------------------------------------- 1 | const tokenRequester = require('keycloak-request-token') 2 | 3 | const username = process.argv[2] 4 | const password = process.argv[3] 5 | 6 | const baseUrl = 'http://localhost:8080/auth'; 7 | const settings = { 8 | username: username || 'developer', 9 | password: password || 'developer', 10 | grant_type: 'password', 11 | client_id: 'open-volunteer-platform-public', 12 | realmName: 'open-volunteer-platform' 13 | } 14 | 15 | tokenRequester(baseUrl, settings) 16 | .then((token) => { 17 | const headers = { 18 | Authorization: `Bearer ${token}` 19 | } 20 | console.log(JSON.stringify(headers)) 21 | }).catch((err) => { 22 | console.log('err', err) 23 | }) -------------------------------------------------------------------------------- /website/src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * CSS files with the .module.css suffix will be treated as CSS modules 4 | * and scoped locally. 5 | */ 6 | 7 | .heroBanner { 8 | padding: 4rem 0; 9 | text-align: center; 10 | position: relative; 11 | overflow: hidden; 12 | } 13 | 14 | @media screen and (max-width: 966px) { 15 | .heroBanner { 16 | padding: 2rem; 17 | } 18 | } 19 | 20 | .buttons { 21 | display: flex; 22 | align-items: center; 23 | justify-content: center; 24 | } 25 | 26 | .features { 27 | display: flex; 28 | align-items: center; 29 | padding: 2rem 0; 30 | width: 100%; 31 | } 32 | 33 | .featureImage { 34 | height: 200px; 35 | width: 200px; 36 | } -------------------------------------------------------------------------------- /website/src/components/styles.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * CSS files with the .module.css suffix will be treated as CSS modules 4 | * and scoped locally. 5 | */ 6 | 7 | .heroBanner { 8 | padding: 4rem 0; 9 | text-align: center; 10 | position: relative; 11 | overflow: hidden; 12 | } 13 | 14 | @media screen and (max-width: 966px) { 15 | .heroBanner { 16 | padding: 2rem; 17 | } 18 | } 19 | 20 | .buttons { 21 | display: flex; 22 | align-items: center; 23 | justify-content: center; 24 | } 25 | 26 | .features { 27 | display: flex; 28 | align-items: center; 29 | padding: 2rem 0; 30 | width: 100%; 31 | } 32 | 33 | .featureImage { 34 | height: 200px; 35 | width: 200px; 36 | } -------------------------------------------------------------------------------- /docs/features.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: features 3 | title: Platform features 4 | sidebar_label: Features 5 | --- 6 | 7 | ![](/img/features.png) 8 | 9 | 10 | ## Feature list 11 | 12 | - Open platform for rapid development of volunteer management systems 13 | - Out of the box, secure API exposing your data using role based authorization 14 | - Reference implementations to cover basic use cases 15 | - Out of the box components for forms, communication, and maps 16 | - Live updates and tracking thanks to GraphQL subscriptions 17 | - Optimization of volunteer assignments and various processes 18 | - Rule-based automatic scheduling and time management 19 | - Simplicity in producing reports and collecting feedback from the field 20 | - Offline support and conflict resolution -------------------------------------------------------------------------------- /platform/client/src/theme/index.ts: -------------------------------------------------------------------------------- 1 | /* Core CSS required for Ionic components to work properly */ 2 | import '@ionic/react/css/core.css'; 3 | 4 | /* Basic CSS for apps built with Ionic */ 5 | import '@ionic/react/css/normalize.css'; 6 | import '@ionic/react/css/structure.css'; 7 | import '@ionic/react/css/typography.css'; 8 | 9 | /* Optional CSS utils that can be commented out */ 10 | import '@ionic/react/css/padding.css'; 11 | import '@ionic/react/css/float-elements.css'; 12 | import '@ionic/react/css/text-alignment.css'; 13 | import '@ionic/react/css/text-transformation.css'; 14 | import '@ionic/react/css/flex-utils.css'; 15 | import '@ionic/react/css/display.css'; 16 | 17 | /* Theme variables */ 18 | import './variables.css'; 19 | 20 | import './styles.css'; 21 | -------------------------------------------------------------------------------- /platform/client/src/forms/distributionCentre.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const distributionCentre = new SimpleSchema({ 5 | name: { 6 | type: String, 7 | max: 120 8 | }, 9 | address1: { 10 | type: String, 11 | max: 400 12 | }, 13 | address2: { 14 | type: String, 15 | required: false, 16 | max: 400 17 | }, 18 | city: { 19 | type: String, 20 | required: false, 21 | max: 100 22 | }, 23 | postcode: { 24 | type: Number, 25 | required: false, 26 | } 27 | } as any); 28 | 29 | export default new SimpleSchema2Bridge(distributionCentre); 30 | -------------------------------------------------------------------------------- /platform/client-admin/src/theme/index.ts: -------------------------------------------------------------------------------- 1 | /* Core CSS required for Ionic components to work properly */ 2 | import '@ionic/react/css/core.css'; 3 | 4 | /* Basic CSS for apps built with Ionic */ 5 | import '@ionic/react/css/normalize.css'; 6 | import '@ionic/react/css/structure.css'; 7 | import '@ionic/react/css/typography.css'; 8 | 9 | /* Optional CSS utils that can be commented out */ 10 | import '@ionic/react/css/padding.css'; 11 | import '@ionic/react/css/float-elements.css'; 12 | import '@ionic/react/css/text-alignment.css'; 13 | import '@ionic/react/css/text-transformation.css'; 14 | import '@ionic/react/css/flex-utils.css'; 15 | import '@ionic/react/css/display.css'; 16 | 17 | /* Theme variables */ 18 | import './variables.css'; 19 | 20 | import './styles.css'; 21 | -------------------------------------------------------------------------------- /website/src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Layout from '@theme/Layout'; 3 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 4 | 5 | import { Hero } from '../components/Hero'; 6 | import { Features } from '../components/Features'; 7 | import { Terminal } from '../components/Terminal'; 8 | import { Video } from '../components/Video'; 9 | 10 | function Home() { 11 | const context = useDocusaurusContext(); 12 | const { siteConfig = {} } = context; 13 | return ( 14 | 17 | 18 | 19 | 20 | 22 | ); 23 | } 24 | 25 | export default Home; 26 | -------------------------------------------------------------------------------- /docs/referencegs.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: gettingstartedref 3 | title: Getting Started 4 | sidebar_label: Getting Started 5 | --- 6 | 7 | # Getting Started 8 | 9 | Open Platform for Rapid Development of Volunteer Management Systems 10 | 11 | ## Client side application 12 | 13 | Client side application is dedicated to volunteers. 14 | Reference application affords volunteers 2 types of actions: 15 | 16 | - Delivery of goods 17 | - Phone calls to speak with people in need 18 | 19 | ![app](https://openvolunteer.org/img/app.png) 20 | 21 | ## Admin application 22 | 23 | Admin application is dedicated to the management of the volounteers and recipients. 24 | It provides insights, reports, and the ability to manage volunteers and the delivery goods. 25 | 26 | ![app](https://openvolunteer.org/img/admin.png) 27 | -------------------------------------------------------------------------------- /docs/architecture.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: architecture 3 | title: Architecture 4 | sidebar_label: Architecture 5 | --- 6 | 7 | Open Volunteer can be deployed to any cloud provider thanks to 8 | automation for building docker images 9 | 10 | ## Reference deployment 11 | 12 | Open Volunteer Platform is being tested and deployed 13 | to Red Hat Managed Integration 14 | 15 | ![](/img/architecture.png) 16 | 17 | Organizations can base of simplicity of the deployment 18 | and management thanks to Red Hat Managed Integration managed services like: 19 | 20 | - Red Hat SSO (Keycloak Authentication) 21 | - Red Hat AMQ Online (MQTT protocol broker) 22 | - Red Hat Code Ready (Clound Native Development Environments) 23 | - Red Hat OpenShift Dedicated (base layer for running services) 24 | - MongoDB and Postgress data providers 25 | -------------------------------------------------------------------------------- /platform/client-admin/src/components/model/ProductList.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IonList } from '@ionic/react'; 3 | import { Empty } from '../generic/Empty'; 4 | import { ProductFieldsFragment } from '../../dataFacade'; 5 | import { Product } from './Product'; 6 | 7 | export const ProductList: React.FC<{ products: [ProductFieldsFragment] }> = ({ products }) => { 8 | if (!products || products.length < 1) { 9 | const message = (

You currently have no products.

); 10 | return 11 | }; 12 | 13 | return ( 14 | <> 15 | 16 | { 17 | products.map((product: ProductFieldsFragment) => { 18 | return ; 19 | }) 20 | } 21 | 22 | 23 | ); 24 | 25 | }; 26 | -------------------------------------------------------------------------------- /platform/client-admin/src/components/model/VolunteerList.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IonList } from '@ionic/react'; 3 | import { Empty } from '../generic/Empty'; 4 | import { Volunteer } from './Volunteer'; 5 | import { VolunteerFieldsFragment } from '../../dataFacade'; 6 | 7 | export const VolunteersList: React.FC<{ volunteers: [VolunteerFieldsFragment] }> = ({ volunteers }) => { 8 | if (!volunteers || volunteers.length < 1) { 9 | const message = (

You currently have no volunteers.

); 10 | return 11 | }; 12 | 13 | return ( 14 | <> 15 | 16 | { 17 | volunteers.map((volunteer: any) => { 18 | return ; 19 | }) 20 | } 21 | 22 | 23 | ); 24 | 25 | }; 26 | -------------------------------------------------------------------------------- /platform/client-admin/src/components/model/RecipientList.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { IonList } from '@ionic/react'; 3 | import { Empty } from '../generic/Empty'; 4 | import { RecipientFieldsFragment } from '../../dataFacade'; 5 | import { Recipient } from './Recipient'; 6 | 7 | export const RecipientList: React.FC<{ recipients: [RecipientFieldsFragment] }> = ({ recipients }) => { 8 | if (!recipients || recipients.length < 1) { 9 | const message = (

You currently have no recipients.

); 10 | return 11 | }; 12 | 13 | return ( 14 | <> 15 | 16 | { 17 | recipients.map((recipient: RecipientFieldsFragment) => { 18 | return ; 19 | }) 20 | } 21 | 22 | 23 | ); 24 | 25 | }; 26 | -------------------------------------------------------------------------------- /platform/client-admin/src/forms/admin.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const adminForm = new SimpleSchema({ 5 | firstName: { 6 | type: String, 7 | max: 120, 8 | uniforms: { 9 | readonly: true 10 | } 11 | }, 12 | lastName: { 13 | type: String, 14 | max: 120, 15 | uniforms: { 16 | readonly: true 17 | } 18 | }, 19 | email: { 20 | type: String, 21 | max: 220, 22 | uniforms: { 23 | readonly: true 24 | } 25 | }, 26 | username: { 27 | type: String, 28 | max: 220, 29 | uniforms: { 30 | readonly: true 31 | } 32 | } 33 | } as any); 34 | 35 | export default new SimpleSchema2Bridge(adminForm); -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OpenVolunteerPlatform-website", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "docusaurus start", 7 | "build": "docusaurus build", 8 | "swizzle": "docusaurus swizzle", 9 | "deploy": "docusaurus deploy" 10 | }, 11 | "dependencies": { 12 | "@docusaurus/core": "2.0.0-alpha.64", 13 | "@docusaurus/preset-classic": "2.0.0-alpha.63", 14 | "classnames": "2.2.6", 15 | "react": "16.13.1", 16 | "react-dom": "16.13.1" 17 | }, 18 | "browserslist": { 19 | "production": [ 20 | ">0.2%", 21 | "not dead", 22 | "not op_mini all" 23 | ], 24 | "development": [ 25 | "last 1 chrome version", 26 | "last 1 firefox version", 27 | "last 1 safari version" 28 | ] 29 | }, 30 | "devDependencies": { 31 | "raw-loader": "4.0.1" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cli/jest.config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | const baseConfig = require("../../jest.config"); 3 | const packageName = require("./package.json").name; 4 | 5 | module.exports = { 6 | ...baseConfig, 7 | rootDir: '../..', 8 | 'preset': 'ts-jest', 9 | moduleFileExtensions: [ 10 | "ts", 11 | "js", 12 | "json", 13 | "jsx", 14 | "tsx", 15 | "node" 16 | ], 17 | roots: [ 18 | `/packages/${packageName}`, 19 | ], 20 | collectCoverageFrom: [ 21 | `/packages/${packageName}/src/**/*`, 22 | ], 23 | testRegex: '(/tests/.*)\\.(tsx?)$', 24 | testURL: 'http://localhost/', 25 | moduleDirectories: [ 26 | 'node_modules', 27 | ], 28 | modulePaths: [ 29 | `/packages/${packageName}/src/`, 30 | ], 31 | projects: [`/packages/${packageName}/jest.config.js`], 32 | name: packageName, 33 | displayName: packageName, 34 | rootDir: '../..' 35 | }; 36 | -------------------------------------------------------------------------------- /cli/src/commands/init.ts: -------------------------------------------------------------------------------- 1 | import { Argv } from 'yargs'; 2 | import { init } from '../components/init' 3 | 4 | type Params = { name?: string, templateName?: string, templateUrl: string } 5 | 6 | export const command = 'init ' 7 | 8 | export const desc = 'Create project from available templates' 9 | 10 | // tslint:disable-next-line: typedef 11 | export const builder = (args: Argv) => { 12 | args.positional('name', { 13 | describe: 'Project name', 14 | type: 'string', 15 | }) 16 | args.option('templateName', { 17 | describe: 'Name of the predefined template', 18 | type: 'string' 19 | }) 20 | args.option('templateUrl', { 21 | describe: 'GitHub URL of the template. For example (http://github.com/wtrocki/hapijs#master)', 22 | type: 'string' 23 | }) 24 | } 25 | 26 | export async function handler({ name, templateName, templateUrl }: Params) { 27 | await init(name, templateName, templateUrl); 28 | } -------------------------------------------------------------------------------- /platform/client/src/helpers/ConflictLogger.ts: -------------------------------------------------------------------------------- 1 | import { ConflictListener } from 'offix-client'; 2 | 3 | export class ConflictLogger implements ConflictListener { 4 | conflictOccurred(operationName:any, resolvedData:any, server:any, client:any) { 5 | console.log("Conflict occurred with the following:") 6 | console.log(` 7 | data: ${JSON.stringify(resolvedData)}, 8 | server: ${JSON.stringify(server)}, 9 | client: ${JSON.stringify(client)}, 10 | operation: ${JSON.stringify(operationName)} 11 | `); 12 | } 13 | mergeOccurred(operationName:any, resolvedData:any, server:any, client:any) { 14 | console.log("Merge occurred with the following:") 15 | console.log(` 16 | data: ${JSON.stringify(resolvedData)}, 17 | server: ${JSON.stringify(server)}, 18 | client: ${JSON.stringify(client)}, 19 | operation: ${JSON.stringify(operationName)} 20 | `); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [14.x] 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - name: Use Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v1 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | - run: npm install -g yarn 28 | - run: cd platform && yarn 29 | - run: cd platform/server && yarn build 30 | - run: cd platform && yarn prepare:client 31 | 32 | 33 | -------------------------------------------------------------------------------- /website/src/components/Hero/styles.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * CSS files with the .module.css suffix will be treated as CSS modules 4 | * and scoped locally. 5 | */ 6 | 7 | .heroBanner { 8 | padding: 4rem 0; 9 | text-align: center; 10 | position: relative; 11 | overflow: hidden; 12 | } 13 | 14 | .heroImage { 15 | width: 60%; 16 | margin: 0 auto; 17 | } 18 | 19 | .heroGraphback { 20 | min-height: calc(100vh - 60px); 21 | background-color: #fff !important; 22 | color: #404040 !important; 23 | } 24 | 25 | @media screen and (max-width: 966px) { 26 | .heroBanner { 27 | padding: 2rem; 28 | } 29 | } 30 | 31 | .buttons { 32 | display: flex; 33 | align-items: center; 34 | justify-content: center; 35 | } 36 | 37 | .features { 38 | display: flex; 39 | align-items: center; 40 | padding: 2rem 0; 41 | width: 100%; 42 | } 43 | 44 | .featureImage { 45 | height: 200px; 46 | width: 200px; 47 | } -------------------------------------------------------------------------------- /platform/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "dist", 4 | "declarationDir": "types", 5 | "lib": [ 6 | "esnext", 7 | "esnext.asynciterable", 8 | "es2015", 9 | "es2018.promise", 10 | "dom", 11 | "es2016" 12 | ], 13 | "resolveJsonModule": true, 14 | "noImplicitAny": false, 15 | "preserveConstEnums": true, 16 | "strict": false, 17 | "strictNullChecks": true, 18 | "esModuleInterop": true, 19 | "target": "es6", 20 | "module": "commonjs", 21 | "moduleResolution": "node", 22 | "allowSyntheticDefaultImports": true, 23 | "importHelpers": true, 24 | "alwaysStrict": false, 25 | "sourceMap": true, 26 | "declaration": true, 27 | "noImplicitReturns": true, 28 | "noUnusedLocals": false, 29 | "noUnusedParameters": false, 30 | "noImplicitThis": false 31 | }, 32 | "exclude": [ 33 | "node_modules", 34 | "dist", 35 | "types" 36 | ] 37 | } -------------------------------------------------------------------------------- /platform/client-admin/src/forms/product.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | export default function createProductSchema(distributionCentres: string[], defaultDistributionCentre: string) { 5 | const productSchema = new SimpleSchema({ 6 | label: { 7 | type: String, 8 | max: 50 9 | }, 10 | description: { 11 | type: String, 12 | max: 500 13 | }, 14 | distributionCentre: { 15 | type: String, 16 | max: 100, 17 | required: false, 18 | uniforms: { 19 | label: "Name of the Distribution Centre", 20 | readonly: false, 21 | defaultValue: defaultDistributionCentre, 22 | allowedValues: distributionCentres 23 | } 24 | }, 25 | } as any); 26 | 27 | return new SimpleSchema2Bridge(productSchema) 28 | } 29 | -------------------------------------------------------------------------------- /platform/client/README.adoc: -------------------------------------------------------------------------------- 1 | = OpenVolunteer React Client 2 | 3 | Example React Web application using AeroGear Open Volunteer Platform 4 | 5 | == Getting Started 6 | 7 | Requirements: 8 | 9 | - Node.js 12.x or above to run server 10 | - (optional) Keycloack server 11 | 12 | === Running the Client in dev mode 13 | 14 | 15 | . Install Ionic 16 | + 17 | ```shell 18 | npm install -g @ionic/cli 19 | ``` 20 | 21 | . Install dependencies 22 | + 23 | ```shell 24 | npm install 25 | ``` 26 | 27 | . Start the app 28 | + 29 | ```shell 30 | npm run dev 31 | ``` 32 | 33 | === Adding keycloak integration to the client 34 | 35 | Rename the `keycloak.example.json` to `keycloak.json` and update the fields 36 | accordingly. 37 | 38 | [source,js] 39 | ---- 40 | { 41 | "realm": "", 42 | "auth-server-url": "https://your-server/auth", 43 | "ssl-required": "none", 44 | "resource": "", 45 | "public-client": true, 46 | "use-resource-role-mappings": true, 47 | "confidential-port": 0 48 | } 49 | ---- 50 | 51 | -------------------------------------------------------------------------------- /platform/server/src/config/auth.ts: -------------------------------------------------------------------------------- 1 | import { CrudServicesAuthConfig } from "@graphback/keycloak-authz" 2 | 3 | export const authConfig: CrudServicesAuthConfig = { 4 | DistributionCentre: { 5 | create: { roles: ['admin'] }, 6 | read: { roles: [] }, 7 | update: { roles: ['admin'] }, 8 | delete: { roles: ['admin'] }, 9 | }, 10 | Volunteer: { 11 | create: { roles: [] }, 12 | read: { roles: [] }, 13 | update: { roles: [] }, 14 | delete: { roles: ['admin'] }, 15 | }, 16 | Recipient: { 17 | create: { roles: ['admin'] }, 18 | read: { roles: [] }, 19 | update: { roles: ['admin'] }, 20 | delete: { roles: ['admin'] }, 21 | }, 22 | VolunteerAction: { 23 | create: { roles: ['admin'] }, 24 | read: { roles: [] }, 25 | update: {roles: [] }, 26 | delete: { roles: ['admin'] }, 27 | }, 28 | VolunteerActionProduct: { 29 | create: { roles: ['admin'] }, 30 | read: { roles: [] }, 31 | update: { roles: ['admin'] }, 32 | delete: { roles: ['admin'] }, 33 | }, 34 | } -------------------------------------------------------------------------------- /platform/client-admin/src/forms/distributionCentre.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const distributionCentre = new SimpleSchema({ 5 | name: { 6 | type: String, 7 | max: 120 8 | }, 9 | address1: { 10 | type: String, 11 | max: 400 12 | }, 13 | address2: { 14 | type: String, 15 | max: 400 16 | }, 17 | city: { 18 | type: String, 19 | required: false, 20 | max: 100 21 | }, 22 | postcode: { 23 | type: Number, 24 | required: false, 25 | }, 26 | lat: { 27 | type: Number, 28 | required: true, 29 | uniforms: { 30 | label: "Latitude" 31 | } 32 | }, 33 | long: { 34 | type: Number, 35 | required: true, 36 | uniforms: { 37 | label: "Longitude" 38 | } 39 | } 40 | } as any); 41 | 42 | export default new SimpleSchema2Bridge(distributionCentre); 43 | -------------------------------------------------------------------------------- /platform/client/src/forms/volunteerAction.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const volunteerActionForm = new SimpleSchema({ 5 | title: { 6 | type: String, 7 | max: 120, 8 | uniforms: { 9 | readonly: true 10 | } 11 | }, 12 | description: { 13 | type: String, 14 | max: 120, 15 | uniforms: { 16 | readonly: true 17 | } 18 | }/*, 19 | products: { 20 | type: String, 21 | max: 220, 22 | uniforms: { 23 | readonly: true 24 | } 25 | },*/, 26 | status: { 27 | type: String, 28 | max: 220, 29 | uniforms: { 30 | readonly: false, 31 | defaultValue: 'ASSIGNED', 32 | allowedValues: [ 33 | 'ASSIGNED', 'COMPLETED' 34 | ] 35 | } 36 | }, 37 | 38 | } as any); 39 | 40 | export default new SimpleSchema2Bridge(volunteerActionForm); -------------------------------------------------------------------------------- /platform/server/src/CrudService.ts: -------------------------------------------------------------------------------- 1 | 2 | import { KeycloakCrudService, CrudServiceAuthConfig } from '@graphback/keycloak-authz' 3 | import { ModelDefinition, GraphbackDataProvider, GraphbackCRUDService } from 'graphback'; 4 | import { createDataSyncCRUDService } from '@graphback/datasync'; 5 | import { getPubSub } from './pubsub'; 6 | 7 | /** 8 | * Creates Graphback service with following capabilities: 9 | * 10 | * - DataSync 11 | * - Keycloak 12 | * - AMQ custom topics 13 | * 14 | * @param authConfig 15 | */ 16 | export function createKeycloakCRUDService(authConfig: CrudServiceAuthConfig) { 17 | const pubSub = getPubSub(); 18 | return (model: ModelDefinition, dataProvider: GraphbackDataProvider): GraphbackCRUDService => { 19 | const service = createDataSyncCRUDService({ 20 | pubSub 21 | })(model, dataProvider); 22 | const objConfig = authConfig[model.graphqlType.name]; 23 | const authService = new KeycloakCrudService(model, { service, authConfig }); 24 | 25 | return authService; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /platform/client-admin/src/forms/dailyAction.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const dailyAction = new SimpleSchema({ 5 | owner: { 6 | type: String, 7 | max: 120, 8 | uniforms: { 9 | readonly: true 10 | } 11 | }, 12 | date: { 13 | type: String, 14 | max: 120, 15 | uniforms: { 16 | readonly: true 17 | } 18 | }, 19 | numberOfCasesCreated: { 20 | type: Number, 21 | max: 220, 22 | uniforms: { 23 | readonly: true 24 | } 25 | }, 26 | numberOfRecipients: { 27 | type: Number, 28 | max: 220, 29 | uniforms: { 30 | readonly: true 31 | } 32 | }, 33 | numberOfVolunteersAssigned: { 34 | type: Number, 35 | max: 220, 36 | uniforms: { 37 | readonly: true 38 | } 39 | } 40 | } as any); 41 | 42 | export default new SimpleSchema2Bridge(dailyAction); -------------------------------------------------------------------------------- /platform/client/src/forms/recipient.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const recipientSchema = new SimpleSchema({ 5 | name: { 6 | type: String, 7 | max: 220, 8 | uniforms: { 9 | readonly: true 10 | } 11 | }, 12 | phone: { 13 | type: String, 14 | max: 220, 15 | uniforms: { 16 | readonly: true 17 | } 18 | }, 19 | address1: { 20 | type: String, 21 | max: 220, 22 | uniforms: { 23 | readonly: true 24 | } 25 | }, 26 | address2: { 27 | type: String, 28 | max: 220, 29 | required: false, 30 | uniforms: { 31 | readonly: true 32 | } 33 | }, 34 | prefferedProducts: { 35 | type: String, 36 | max: 220, 37 | uniforms: { 38 | readonly: true 39 | } 40 | } 41 | } as any); 42 | 43 | export default new SimpleSchema2Bridge(recipientSchema); -------------------------------------------------------------------------------- /platform/client-admin/src/forms/volunteerAction.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const volunteerActionForm = new SimpleSchema({ 5 | title: { 6 | type: String, 7 | max: 120, 8 | uniforms: { 9 | readonly: false 10 | } 11 | }, 12 | description: { 13 | type: String, 14 | max: 120, 15 | uniforms: { 16 | readonly: false 17 | } 18 | }, 19 | products: { 20 | type: String, 21 | max: 220, 22 | required: false, 23 | uniforms: { 24 | readonly: true 25 | } 26 | }, 27 | status: { 28 | type: String, 29 | max: 220, 30 | uniforms: { 31 | readonly: false, 32 | defaultValue: 'CREATED', 33 | allowedValues: [ 34 | 'CREATED', 'ASSIGNED', 'COMPLETED' 35 | ] 36 | } 37 | }, 38 | 39 | } as any); 40 | 41 | export default new SimpleSchema2Bridge(volunteerActionForm); -------------------------------------------------------------------------------- /website/src/components/Terminal/styles.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * CSS files with the .module.css suffix will be treated as CSS modules 4 | * and scoped locally. 5 | */ 6 | 7 | .terminalHeader { 8 | display: flex; 9 | justify-content: center; 10 | align-items: flex-end; 11 | width: 100%; 12 | height: 50vh; 13 | /* background: #e535ab; */ 14 | color: #161e26; 15 | font-size: 2.5rem; 16 | font-weight: 300; 17 | } 18 | 19 | .terminal { 20 | height: 50vh; 21 | width: 100%; 22 | /* background: #161e26; */ 23 | display: flex; 24 | justify-content: center; 25 | align-items: flex-start; 26 | /* color: #e535ab; */ 27 | color: #161e26; 28 | font-size: 4rem; 29 | font-weight: 600; 30 | font-style: 'mono'; 31 | } 32 | 33 | .underscore { 34 | display: inline-block; 35 | position: relative; 36 | } 37 | 38 | @media screen and (max-width: 966px) { 39 | .terminalHeader { 40 | height: 25vh; 41 | } 42 | .terminal { 43 | height: 25vh; 44 | font-size: 0.8rem; 45 | font-weight: 400; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /platform/client/src/components/Action.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | IonItem, 4 | IonButton, 5 | IonLabel, 6 | IonNote, 7 | IonBadge, 8 | IonIcon, 9 | IonButtons 10 | } from '@ionic/react'; 11 | import { helpBuoy, open } from 'ionicons/icons'; 12 | import { Link } from 'react-router-dom'; 13 | 14 | export const Action: React.FC = ({ action }) => { 15 | 16 | return ( 17 | 18 | 19 | 20 |

{action.title}

21 | 22 | {action.description} 23 | 24 |
25 | 26 | 27 | {action.status} 28 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 | ); 42 | 43 | }; 44 | -------------------------------------------------------------------------------- /platform/client-admin/src/components/model/Product.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | IonItem, 4 | IonButton, 5 | IonLabel, 6 | IonNote, 7 | IonIcon, 8 | IonButtons 9 | } from '@ionic/react'; 10 | import { cartSharp, open } from 'ionicons/icons'; 11 | import { Link } from 'react-router-dom'; 12 | import { ProductFieldsFragment } from '../../dataFacade'; 13 | 14 | export const Product: React.FC<{ product: ProductFieldsFragment }> = ({ product }) => { 15 | // TODO - link a product to volunteer action. See https://github.com/aerogear/OpenVolunteerPlatform/issues/69 16 | 17 | return ( 18 | 19 | 20 | 21 | 22 | {product.label} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | ); 36 | 37 | }; 38 | -------------------------------------------------------------------------------- /platform/client-admin/src/components/model/Action.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | IonItem, 4 | IonButton, 5 | IonLabel, 6 | IonNote, 7 | IonBadge, 8 | IonIcon, 9 | IonButtons 10 | } from '@ionic/react'; 11 | import { codeWorking, open } from 'ionicons/icons'; 12 | import { Link } from 'react-router-dom'; 13 | 14 | export const Action: React.FC = ({ action }) => { 15 | 16 | return ( 17 | 18 | 19 | 20 |

{action.title}

21 | 22 | {action.description} 23 | 24 |
25 | 26 | 27 | {action.status} 28 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 | ); 42 | 43 | }; 44 | -------------------------------------------------------------------------------- /platform/client/public/assets/shapes.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /platform/client-admin/public/assets/shapes.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /platform/client/src/context/AuthContext.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { KeycloakInstance, KeycloakProfile } from 'keycloak-js'; 3 | import { VolunteerFieldsFragment } from '../dataFacade'; 4 | 5 | type VolunteerType = VolunteerFieldsFragment | undefined; 6 | 7 | export interface IAuthContext { 8 | keycloak?: KeycloakInstance | undefined 9 | profile?: KeycloakProfile | undefined 10 | volunteer?: VolunteerType, 11 | setVolunteer: (volunteer: VolunteerType) => void 12 | } 13 | 14 | export const AuthContext = React.createContext({ 15 | setVolunteer: () => {} 16 | }); 17 | 18 | export const AuthContextProvider = (props: any) => { 19 | const setVolunteer = (volunteer: VolunteerType) => { 20 | setState({...state, volunteer: volunteer}) 21 | } 22 | 23 | const authContextInitialState: IAuthContext = { 24 | setVolunteer: setVolunteer, 25 | volunteer: undefined, 26 | ...props.value 27 | } 28 | 29 | const [state, setState] = useState(authContextInitialState) 30 | 31 | return ( 32 | 33 | {props.children} 34 | 35 | ) 36 | } -------------------------------------------------------------------------------- /platform/client-admin/src/components/Map.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Map as GoogleMap, GoogleApiWrapper, IMapProps } from 'google-maps-react'; 3 | 4 | interface Location { 5 | lat: number 6 | lng: number 7 | } 8 | 9 | interface MapProps { 10 | center: Location, 11 | zoom?: number 12 | } 13 | 14 | class MapContainer extends Component & MapProps> { 15 | render() { 16 | return ( 17 |
18 | 31 | 32 | {this.props.children} 33 | 34 | 35 |
36 | ); 37 | } 38 | } 39 | 40 | export const Map = GoogleApiWrapper({ 41 | apiKey: process.env.REACT_APP_GOOGLE_MAP_API_KEY || "" 42 | })(MapContainer) 43 | -------------------------------------------------------------------------------- /platform/server/src/db.ts: -------------------------------------------------------------------------------- 1 | import { Config } from './config/config'; 2 | import e = require('express'); 3 | import { resolve } from 'path'; 4 | 5 | const MongoClient = require('mongodb').MongoClient; 6 | 7 | export async function connect(config: Config) { 8 | // TODO config 9 | let url: string; 10 | 11 | if (config.db.user && config.db.password) { 12 | url = `mongodb://${config.db.user}:${config.db.password}@${config.db.host}:${config.db.port}/${config.db.database}`; 13 | } else { 14 | url = `mongodb://${config.db.host}:${config.db.port}/${config.db.database}` 15 | } 16 | 17 | if (process.env.BACKUP_DEMO_DATA === 'true') { 18 | const backup = require('mongodb-backup'); 19 | backup({ 20 | uri: url, 21 | root: resolve(__dirname, '../mongodump') 22 | }); 23 | } 24 | 25 | if (process.env.USE_DEMO_DATA === 'true') { 26 | const restore = require('mongodb-restore'); 27 | restore({ 28 | uri: url, 29 | root: resolve(__dirname, '../mongodump/showcase') 30 | }); 31 | } 32 | 33 | // Use connect method to connect to the server 34 | const client = await MongoClient.connect(url, { useUnifiedTopology: true }); 35 | const db = client.db(config.db.database); 36 | return db; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /platform/client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Open Volunteer 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /platform/server/src/pubsub.ts: -------------------------------------------------------------------------------- 1 | import mqtt from 'mqtt'; 2 | import { PubSub } from 'apollo-server-express'; 3 | import { MQTTPubSub } from '@aerogear/graphql-mqtt-subscriptions'; 4 | 5 | export function getPubSub() { 6 | const mqttHost = process.env.MQTT_HOST 7 | 8 | if (mqttHost) { 9 | console.log('Using MQTT PubSub') 10 | const mqttOptions = { 11 | host: mqttHost, 12 | servername: mqttHost, // needed to work in OpenShift. Lookup SNI. 13 | username: process.env.MQTT_USERNAME || '', 14 | password: process.env.MQTT_PASSWORD || '', 15 | port: process.env.MQTT_PORT || '1883', 16 | protocol: process.env.MQTT_PROTOCOL || 'mqtt', 17 | rejectUnauthorized: false 18 | } 19 | 20 | // Types are broken 21 | const client = mqtt.connect(mqttHost, mqttOptions as any) 22 | 23 | console.log(`attempting to connect to messaging service ${mqttHost}`) 24 | 25 | client.on('connect', () => { 26 | console.log('connected to messaging service') 27 | }) 28 | 29 | client.on('error', (error) => { 30 | console.log('error with mqtt connection') 31 | console.log(error) 32 | }) 33 | 34 | return new MQTTPubSub({ client }) 35 | } 36 | console.log('Using In Memory PubSub') 37 | return new PubSub() 38 | } -------------------------------------------------------------------------------- /platform/client-admin/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AeroGear AeroGear OpenVolunteer 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /platform/client-admin/src/forms/recipient.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const recipientSchema = new SimpleSchema({ 5 | firstName: { 6 | type: String, 7 | max: 220 8 | }, 9 | lastName: { 10 | type: String, 11 | max: 220 12 | }, 13 | phone: { 14 | type: String, 15 | max: 220 16 | }, 17 | address1: { 18 | type: String, 19 | max: 220 20 | }, 21 | address2: { 22 | type: String, 23 | max: 220 24 | }, 25 | city: { 26 | type: String, 27 | max: 220, 28 | required: false 29 | }, 30 | postcode: { 31 | type: Number, 32 | required: false 33 | }, 34 | prefferedProducts: { 35 | type: String, 36 | max: 220, 37 | required: false 38 | }, 39 | lat: { 40 | type: Number, 41 | required: false, 42 | uniforms: { 43 | label: "Latitude" 44 | } 45 | }, 46 | long: { 47 | type: Number, 48 | required: false, 49 | uniforms: { 50 | label: "Longitude" 51 | } 52 | } 53 | } as any); 54 | 55 | export default new SimpleSchema2Bridge(recipientSchema); 56 | -------------------------------------------------------------------------------- /platform/server/src/index.ts: -------------------------------------------------------------------------------- 1 | import dotenv from 'dotenv'; 2 | // Setup env variables 3 | dotenv.config() 4 | 5 | import cors from 'cors'; 6 | import express from 'express'; 7 | import http from 'http' 8 | import { config } from './config/config' 9 | import { createApolloServer } from './graphql'; 10 | 11 | async function start() { 12 | const app = express(); 13 | 14 | app.use(cors()); 15 | app.use('/', express.static('website')) 16 | app.use('/admin', express.static('admin')) 17 | app.get('/health', (req, res) => res.sendStatus(200)); 18 | 19 | const apolloServer = await createApolloServer(app, config); 20 | const httpServer = http.createServer(app) 21 | apolloServer.installSubscriptionHandlers(httpServer) 22 | 23 | httpServer.listen(config.port, () => { 24 | console.log(`\n *********************************************************** 25 | 🎮 Ionic PWA application available at http://localhost:${config.port} 26 | 🎮 Admin PWA application available at http://localhost:${config.port}/admin 27 | ***********************************************************`) 28 | }) 29 | } 30 | 31 | start().catch((err) => { 32 | console.error(err); 33 | process.exit(1); 34 | }) 35 | 36 | 37 | process.on('unhandledRejection', (error: any) => { 38 | console.error(error.message, error.stack) 39 | process.exit(1) 40 | }) 41 | -------------------------------------------------------------------------------- /platform/client/src/AppContainer.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { clientConfig } from './config'; 3 | import { Loading } from './components/Loading'; 4 | import { IContainerProps } from './declarations'; 5 | import { getKeycloakInstance } from './keycloakAuth'; 6 | import { AuthContextProvider } from './context/AuthContext'; 7 | import { ApolloClient, ApolloProvider } from '@apollo/client' 8 | 9 | let keycloak: any; 10 | const apolloClient = new ApolloClient(clientConfig); 11 | 12 | export const AppContainer: React.FC = ({ app: App }) => { 13 | const [keycloakInitialized, setKeycloakInitialized] = useState(false); 14 | 15 | // Initialize the client 16 | useEffect(() => { 17 | const init = async () => { 18 | keycloak = await getKeycloakInstance(); 19 | if (keycloak) { 20 | await keycloak?.loadUserProfile(); 21 | } 22 | setKeycloakInitialized(true); 23 | } 24 | init(); 25 | }, []); 26 | 27 | if (!keycloakInitialized || !keycloak.profile) return ; 28 | 29 | // return container with keycloak provider 30 | return ( 31 | 32 | 33 | 34 | 35 | 36 | ); 37 | }; 38 | -------------------------------------------------------------------------------- /platform/client-admin/src/AppContainer.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import { ApolloProvider, ApolloClient } from '@apollo/client'; 3 | import { clientConfig } from './config'; 4 | import { Loading } from './components/generic/Loading'; 5 | import { IContainerProps } from './declarations'; 6 | import { getKeycloakInstance } from './keycloakAuth'; 7 | import { AuthContext } from './context/AuthContext'; 8 | 9 | let keycloak: any; 10 | const apolloClient = new ApolloClient(clientConfig); 11 | 12 | export const AppContainer: React.FC = ({ app: App }) => { 13 | const [keycloakInitialized, setKeycloakInitialized] = useState(false); 14 | 15 | // Initialize the client 16 | useEffect(() => { 17 | const init = async () => { 18 | keycloak = await getKeycloakInstance(); 19 | if (keycloak) { 20 | await keycloak.loadUserProfile(); 21 | } 22 | setKeycloakInitialized(true); 23 | } 24 | init(); 25 | }, []); 26 | 27 | if (!keycloakInitialized || !keycloak.profile) return ; 28 | 29 | // return container with keycloak provider 30 | return ( 31 | 32 | 33 | 34 | 35 | 36 | ); 37 | }; 38 | -------------------------------------------------------------------------------- /platform/client-admin/src/forms/createVolunteer.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const volunteerForm = new SimpleSchema({ 5 | firstName: { 6 | type: String, 7 | max: 120 8 | }, 9 | lastName: { 10 | type: String, 11 | max: 120 12 | }, 13 | email: { 14 | type: String, 15 | max: 220, 16 | uniforms: { 17 | type: 'email' 18 | } 19 | }, 20 | username: { 21 | type: String, 22 | max: 220 23 | }, 24 | address1: { 25 | type: String, 26 | max: 400 27 | }, 28 | address2: { 29 | type: String, 30 | max: 400 31 | }, 32 | city: { 33 | type: String, 34 | required: false, 35 | max: 100 36 | }, 37 | postcode: { 38 | type: Number, 39 | required: false, 40 | }, 41 | dateOfBirth: { 42 | type: Date, 43 | required: false, 44 | uniforms: { 45 | label: "Date Of Birth" 46 | } 47 | }, 48 | canDeliver: { 49 | type: Boolean, 50 | uniforms: { 51 | label: "Volunteer can do delivery to recipients", 52 | defaultValue: false 53 | } 54 | } 55 | } as any); 56 | 57 | export default new SimpleSchema2Bridge(volunteerForm); 58 | -------------------------------------------------------------------------------- /platform/client/src/helpers/CapacitorNetworkStatus.ts: -------------------------------------------------------------------------------- 1 | import { NetworkStatus, NetworkStatusChangeCallback } from "offix-offline"; 2 | import { Plugins } from '@capacitor/core'; 3 | const { Network } = Plugins; 4 | 5 | /** 6 | * Web networks status implementation based on: Mozilla 7 | * See: https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine 8 | */ 9 | export class CapacitorNetworkStatus implements NetworkStatus { 10 | 11 | listeners: NetworkStatusChangeCallback[] = []; 12 | 13 | constructor() { 14 | Network.addListener("networkStatusChange", this.handleNetworkStatusChange.bind(this)); 15 | } 16 | 17 | public addListener(listener: NetworkStatusChangeCallback): void { 18 | this.listeners.push(listener); 19 | } 20 | 21 | public removeListener(listener: NetworkStatusChangeCallback): void { 22 | const index = this.listeners.indexOf(listener); 23 | if (index >= 0) { 24 | this.listeners.splice(index, 1); 25 | } 26 | } 27 | 28 | public isOffline(): Promise { 29 | return new Promise(async (resolve) => { 30 | let status = await Network.getStatus(); 31 | // @ts-ignore 32 | resolve(!status.connected); 33 | }); 34 | } 35 | 36 | private handleNetworkStatusChange(status: any) { 37 | const online = status.connected; 38 | this.listeners.forEach((listener) => { 39 | listener({ online }); 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /platform/client-admin/src/components/Header.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { IonHeader, IonToolbar, IonButtons, IonTitle, IonButton, IonIcon } from '@ionic/react'; 3 | import { person, exit } from 'ionicons/icons'; 4 | import { AuthContext } from '../context/AuthContext'; 5 | import { logout } from '../keycloakAuth'; 6 | import { Link } from 'react-router-dom'; 7 | 8 | export const Header: React.FC<{ title: string, match: any }> = ({ title, match }) => { 9 | const { url } = match; 10 | 11 | const { keycloak } = useContext(AuthContext); 12 | 13 | const handleLogout = async () => { 14 | await logout(keycloak ); 15 | return; 16 | } 17 | 18 | // if keycloak is not configured, don't display logout and 19 | // profile icons. Only show login and profile icons on the home 20 | // screen 21 | const buttons = (!keycloak || url !== '/actions') ? <> : ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | ); 33 | 34 | return ( 35 | <> 36 | 37 | 38 | {title} 39 | {buttons} 40 | 41 | 42 | 43 | ); 44 | }; 45 | -------------------------------------------------------------------------------- /platform/client-admin/README.adoc: -------------------------------------------------------------------------------- 1 | = React Client 2 | 3 | React Web implementation for OpenVolunteer 4 | 5 | == Getting Started 6 | 7 | Requirements: 8 | 9 | - Node.js 12.x or above to run server 10 | - (optional) Keycloack server 11 | 12 | === Running the Client in dev mode 13 | 14 | . Install Ionic 15 | + 16 | ```shell 17 | npm install -g @ionic/cli 18 | ``` 19 | 20 | . Install dependencies 21 | + 22 | ```shell 23 | npm install 24 | ``` 25 | 26 | . Start the app 27 | + 28 | ```shell 29 | npm run dev 30 | ``` 31 | 32 | === Adding keycloak integration to the client 33 | 34 | Rename the `keycloak.example.json` to `keycloak.json` and update the fields 35 | accordingly. 36 | 37 | [source,js] 38 | ---- 39 | { 40 | "realm": "", 41 | "auth-server-url": "https://your-server/auth", 42 | "ssl-required": "none", 43 | "resource": "", 44 | "public-client": true, 45 | "use-resource-role-mappings": true, 46 | "confidential-port": 0 47 | } 48 | ---- 49 | 50 | 51 | === Customizing the Action Reports Grid 52 | 53 | Column size can be customized via the `REACT_APP_REPORT_COLUMN_SIZE` environment variable. This value can be changed in `.env` file. The default value is `4`. 54 | 55 | === Customizing action report nearby distance 56 | 57 | Nearby distance to calculate actions reports depending on closeness of recipient location can be customized via `REACT_APP_NEARBY_MAX_DISTANCE` environment variable. 58 | This value can be changed in `.env` file. The default value is `100` km. -------------------------------------------------------------------------------- /platform/server/src/config/config.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import path from 'path' 3 | 4 | export class Config { 5 | public port: string | number 6 | public db: { database: string; user?: string; password?: string; host: string, port: number | string } 7 | public keycloakConfigPath: string 8 | public keycloakConfig: any 9 | public playgroundConfig: { tabs: { endpoint: string; variables: {}; query: string }[] } 10 | 11 | constructor() { 12 | this.port = process.env.PORT || 4000 13 | 14 | this.db = { 15 | database: process.env.MONGO_COLLECTION || 'showcase', 16 | host: process.env.MONGO_HOST || '127.0.0.1', 17 | user: process.env.MONGO_USER, 18 | password: process.env.MONGO_PASSWORD, 19 | port: process.env.MONGO_PORT || 27017 20 | } 21 | 22 | this.keycloakConfigPath = process.env.KEYCLOAK_CONFIG || path.resolve(__dirname, './keycloak.json') 23 | this.keycloakConfig = readConfig(this.keycloakConfigPath) 24 | 25 | this.playgroundConfig = { 26 | tabs: [ 27 | { 28 | endpoint: `/graphql`, 29 | variables: {}, 30 | query: fs.readFileSync(path.resolve(__dirname, './playground.gql'), 'utf8') 31 | } 32 | ] 33 | } 34 | } 35 | } 36 | 37 | function readConfig(path) { 38 | try { 39 | return JSON.parse(fs.readFileSync(path, 'utf8')) 40 | } catch (e) { 41 | console.error(`Warning: couldn't find keycloak config at ${path}`) 42 | } 43 | } 44 | 45 | export const config = new Config() -------------------------------------------------------------------------------- /platform/client-admin/src/pages/ProductsPage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | IonPage, 4 | IonFooter, 5 | IonLoading, 6 | IonContent, 7 | IonIcon, 8 | IonFab, 9 | IonFabButton, 10 | } from '@ionic/react'; 11 | import { Header } from '../components'; 12 | import { RouteComponentProps } from 'react-router'; 13 | import { useFindProductsQuery } from '../dataFacade'; 14 | import { ProductList } from '../components/model/ProductList'; 15 | import { add } from 'ionicons/icons'; 16 | 17 | 18 | export const ProductsPage: React.FC = ({ match }) => { 19 | let { data, loading, error } = useFindProductsQuery(); 20 | 21 | if (error) { 22 | console.log(error); 23 | } 24 | 25 | if (loading) return ; 29 | 30 | const products = data?.findProducts?.items || []; 31 | const content = 32 | 33 | return ( 34 | 35 |
36 | 37 | {content} 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 | OpenVolunteer Platform 47 |
48 |
49 | 50 | ); 51 | 52 | }; 53 | -------------------------------------------------------------------------------- /platform/client-admin/src/forms/createVolunteerAction.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | export default function createVolunteerActionForm(recipients: string[], volunteers: string[], distributionCentres: string[], products: string[]) { 5 | const volunteerActionForm = new SimpleSchema({ 6 | title: { 7 | type: String, 8 | max: 120 9 | }, 10 | description: { 11 | type: String, 12 | max: 120 13 | }, 14 | recipientName: { 15 | type: String, 16 | max: 220, 17 | uniforms: { 18 | allowedValues: recipients 19 | } 20 | }, 21 | volunteerName: { 22 | type: String, 23 | max: 220, 24 | uniforms: { 25 | allowedValues: volunteers 26 | } 27 | }, 28 | distributionCentreName: { 29 | type: String, 30 | max: 220, 31 | uniforms: { 32 | allowedValues: distributionCentres 33 | } 34 | }, 35 | products: { 36 | type: Array, 37 | uniforms: { 38 | multiple: true, 39 | allowedValues: products 40 | } 41 | }, 42 | "products.$": { 43 | type: String 44 | } 45 | } as any); 46 | 47 | return new SimpleSchema2Bridge(volunteerActionForm); 48 | } 49 | -------------------------------------------------------------------------------- /platform/client/.graphqlrc.yml: -------------------------------------------------------------------------------- 1 | ## GraphQL Config Generated by Graphback 2 | ## Please review configuration and adjust it for your own project 3 | schema: ../server/src/schema/schema.graphql 4 | documents: ./src/graphql/**/*.graphql 5 | extensions: 6 | graphback: 7 | model: ../server/model/**/main.graphql 8 | crud: 9 | create: true 10 | update: true 11 | findOne: true 12 | find: true 13 | delete: false 14 | subCreate: false 15 | subUpdate: false 16 | subDelete: false 17 | plugins: 18 | graphback-schema: 19 | format: graphql 20 | outputPath: ../server/src/schema/schema.graphql 21 | graphback-client: 22 | format: 'graphql' 23 | outputFile: ./src/graphql/graphback.graphql 24 | ## fragmentOnly: true 25 | codegen: 26 | generates: 27 | ./src/dataFacade.tsx: 28 | config: 29 | withComponent: false 30 | withHOC: false 31 | withHooks: true 32 | skipDocumentsValidation: true 33 | scalars: 34 | GraphbackTime: string 35 | GraphbackDate: Date 36 | GraphbackDateTime: Date 37 | GraphbackTimestamp: number 38 | GraphbackObjectID: string 39 | GraphbackJSON: any 40 | GraphbackJSONObject: "{ [key: string]: any }" 41 | plugins: 42 | - add: 43 | content: '/* tslint:disable */' 44 | - typescript 45 | - typescript-operations 46 | - typescript-react-apollo -------------------------------------------------------------------------------- /platform/client-admin/.graphqlrc.yml: -------------------------------------------------------------------------------- 1 | ## GraphQL Config Generated by Graphback 2 | ## Please review configuration and adjust it for your own project 3 | schema: ../server/src/schema/schema.graphql 4 | documents: ./src/graphql/**/*.graphql 5 | extensions: 6 | graphback: 7 | model: ../server/model/main.graphql 8 | crud: 9 | create: true 10 | update: true 11 | findOne: true 12 | find: true 13 | delete: false 14 | subCreate: false 15 | subUpdate: false 16 | subDelete: false 17 | plugins: 18 | graphback-schema: 19 | format: graphql 20 | outputPath: ../server/src/schema/schema.graphql 21 | graphback-client: 22 | format: 'graphql' 23 | outputFile: ./src/graphql/graphback.graphql 24 | ## fragmentOnly: true 25 | codegen: 26 | generates: 27 | ./src/dataFacade.tsx: 28 | config: 29 | withComponent: false 30 | withHOC: false 31 | withHooks: true 32 | skipDocumentsValidation: true 33 | scalars: 34 | GraphbackTime: string 35 | GraphbackDate: Date 36 | GraphbackDateTime: Date 37 | GraphbackTimestamp: number 38 | GraphbackObjectID: string 39 | GraphbackJSON: any 40 | GraphbackJSONObject: "{ [key: string]: any }" 41 | plugins: 42 | - add: 43 | content: '/* tslint:disable */' 44 | - typescript 45 | - typescript-operations 46 | - typescript-react-apollo -------------------------------------------------------------------------------- /platform/client-admin/src/components/model/Recipient.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | IonItem, 4 | IonButton, 5 | IonLabel, 6 | IonIcon, 7 | IonButtons, 8 | IonBadge 9 | } from '@ionic/react'; 10 | import { peopleCircleSharp, open, callOutline } from 'ionicons/icons'; 11 | import { Link } from 'react-router-dom'; 12 | import { RecipientFieldsFragment } from '../../dataFacade'; 13 | 14 | export const Recipient: React.FC<{ recipient: RecipientFieldsFragment }> = ({ recipient }) => { 15 | 16 | return ( 17 | 18 | 19 | 20 |

{recipient.firstName} {recipient.lastName}

21 |

Deliveries 22 | 23 | {recipient.deliveryDays} 24 | 25 |

26 |

Actions Completed 27 | 28 | {recipient.actionsCompleted} 29 | 30 |

31 | 32 |

: {recipient.phone}

33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 | ); 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /platform/.openshift/amq.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Template 3 | labels: 4 | template: amq-online-topic-creator 5 | metadata: 6 | name: amq-online-topic-creator 7 | objects: 8 | - apiVersion: enmasse.io/v1beta1 9 | kind: AddressSpace 10 | metadata: 11 | name: ovp 12 | spec: 13 | type: brokered 14 | plan: brokered-single-broker 15 | - apiVersion: enmasse.io/v1beta1 16 | kind: Address 17 | metadata: 18 | name: ovp.${AMQ_ADDRESS} 19 | spec: 20 | address: ${AMQ_ADDRESS} 21 | type: topic 22 | plan: brokered-topic 23 | - apiVersion: user.enmasse.io/v1beta1 24 | kind: MessagingUser 25 | metadata: 26 | name: ovp.${AMQ_USERNAME} 27 | spec: 28 | username: ${AMQ_USERNAME} 29 | authentication: 30 | type: password 31 | password: ${AMQ_USER_PASSWORD} 32 | authorization: 33 | - addresses: ["*"] 34 | operations: ["send", "recv"] 35 | parameters: 36 | - description: Messaging user created in AMQ Online. The showcase server will authenticate with AMQ as this user. 37 | displayName: AMQ Messaging User Name 38 | name: AMQ_USERNAME 39 | value: messaging-user 40 | - description: Create your own password with `$ echo | base64` - the default password is Password1 41 | displayName: AMQ Messaging User Password 42 | name: AMQ_USER_PASSWORD 43 | value: UGFzc3dvcmQx # (base64 encoded) Password1 44 | - description: Address 45 | displayName: AMQ Messaging Address 46 | name: AMQ_ADDRESS 47 | value: graphql -------------------------------------------------------------------------------- /platform/.openshift/amq-topics.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Template 3 | labels: 4 | template: amq-online-topic-creator 5 | metadata: 6 | name: amq-online-topic-creator 7 | objects: 8 | - apiVersion: enmasse.io/v1beta1 9 | kind: AddressSpace 10 | metadata: 11 | name: datasync 12 | spec: 13 | type: brokered 14 | plan: brokered-single-broker 15 | - apiVersion: enmasse.io/v1beta1 16 | kind: Address 17 | metadata: 18 | name: datasync.${AMQ_ADDRESS} 19 | spec: 20 | address: ${AMQ_ADDRESS} 21 | type: topic 22 | plan: brokered-topic 23 | - apiVersion: user.enmasse.io/v1beta1 24 | kind: MessagingUser 25 | metadata: 26 | name: datasync.${AMQ_USERNAME} 27 | spec: 28 | username: ${AMQ_USERNAME} 29 | authentication: 30 | type: password 31 | password: ${AMQ_USER_PASSWORD} 32 | authorization: 33 | - addresses: ["*"] 34 | operations: ["send", "recv"] 35 | parameters: 36 | - description: Messaging user created in AMQ Online. The showcase server will authenticate with AMQ as this user. 37 | displayName: AMQ Messaging User Name 38 | name: AMQ_USERNAME 39 | value: messaging-user 40 | - description: Create your own password with `$ echo | base64` - the default password is Password1 41 | displayName: AMQ Messaging User Password 42 | name: AMQ_USER_PASSWORD 43 | value: UGFzc3dvcmQx # (base64 encoded) Password1 44 | - description: Address 45 | displayName: AMQ Messaging Address 46 | name: AMQ_ADDRESS 47 | value: graphql 48 | -------------------------------------------------------------------------------- /platform/client-admin/src/forms/volunteer.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const volunteerForm = new SimpleSchema({ 5 | firstName: { 6 | type: String, 7 | max: 120, 8 | uniforms: { 9 | readonly: true 10 | } 11 | }, 12 | lastName: { 13 | type: String, 14 | max: 120, 15 | uniforms: { 16 | readonly: true 17 | } 18 | }, 19 | email: { 20 | type: String, 21 | max: 220, 22 | uniforms: { 23 | readonly: true, 24 | type: 'email' 25 | } 26 | }, 27 | username: { 28 | type: String, 29 | max: 220, 30 | uniforms: { 31 | readonly: true 32 | } 33 | }, 34 | address1: { 35 | type: String, 36 | max: 400 37 | }, 38 | address2: { 39 | type: String, 40 | max: 400 41 | }, 42 | city: { 43 | type: String, 44 | required: false, 45 | max: 100 46 | }, 47 | postcode: { 48 | type: Number, 49 | required: false, 50 | }, 51 | dateOfBirth: { 52 | type: Date, 53 | required: false, 54 | uniforms: { 55 | label: "Date Of Birth" 56 | }, 57 | }, 58 | canDeliver: { 59 | type: Boolean, 60 | uniforms: { 61 | label: "Volunteer can do delivers to recipients" 62 | } 63 | } 64 | } as any); 65 | 66 | export default new SimpleSchema2Bridge(volunteerForm); 67 | -------------------------------------------------------------------------------- /platform/client/samples.graphql: -------------------------------------------------------------------------------- 1 | # Write your query or mutation here 2 | 3 | query findAllVolunteers { 4 | findVolunteers { 5 | items { 6 | id, 7 | firstName, 8 | lastName, 9 | email, 10 | username, 11 | address1, 12 | address2, 13 | city, 14 | postcode, 15 | canDeliver, 16 | actions { 17 | id, 18 | products { 19 | id, 20 | product { 21 | id, 22 | label 23 | } 24 | } 25 | } 26 | } 27 | } 28 | } 29 | 30 | 31 | query findAllRecipients { 32 | findRecipients { 33 | items { 34 | id, 35 | lastName, 36 | firstName, 37 | phone, 38 | address1, 39 | address2, 40 | city, 41 | postcode, 42 | prefferedProducts 43 | } 44 | } 45 | } 46 | 47 | mutation createVolunteerAction { 48 | createVolunteerAction( 49 | input: { 50 | id: "" 51 | title: "Deliver to Mr Boris" 52 | description: "Phone Number: +473020323" 53 | products: "Bread, Pasta, ToiletPaper", 54 | recieverId: "5e8f3eda92787169c1e7cd87" 55 | volunteerId: "5e9782e94b8d743f02b84e79", 56 | status: ASSIGNED 57 | } 58 | ) { 59 | id 60 | title 61 | description 62 | } 63 | } 64 | 65 | 66 | mutation createDistributionCentre { 67 | createDistributionCentre( 68 | input: { 69 | name: "NY Plaza Charity Chain" 70 | address: "Plaza Key" 71 | address2: "Brooklyn" 72 | city: "New York" 73 | lat: "0" 74 | long: "0" 75 | } 76 | ) { 77 | id 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /platform/client/src/forms/volunteer.ts: -------------------------------------------------------------------------------- 1 | import SimpleSchema from '../config/SimpleSchema'; 2 | import SimpleSchema2Bridge from 'uniforms-bridge-simple-schema-2'; 3 | 4 | const volunteerForm = new SimpleSchema({ 5 | firstName: { 6 | type: String, 7 | max: 120, 8 | uniforms: { 9 | readonly: true 10 | } 11 | }, 12 | lastName: { 13 | type: String, 14 | max: 120, 15 | uniforms: { 16 | readonly: true 17 | } 18 | }, 19 | email: { 20 | type: String, 21 | max: 220, 22 | uniforms: { 23 | readonly: true, 24 | type: 'email' 25 | } 26 | }, 27 | username: { 28 | type: String, 29 | max: 220, 30 | uniforms: { 31 | readonly: true 32 | } 33 | }, 34 | address1: { 35 | type: String, 36 | max: 400 37 | }, 38 | address2: { 39 | type: String, 40 | required: false, 41 | max: 400 42 | }, 43 | city: { 44 | type: String, 45 | max: 100 46 | }, 47 | postcode: { 48 | type: Number, 49 | required: false, 50 | }, 51 | dateOfBirth: { 52 | type: Date, 53 | required: false, 54 | uniforms: { 55 | label: "Date Of Birth" 56 | }, 57 | }, 58 | canDeliver: { 59 | type: Boolean, 60 | uniforms: { 61 | label: "I volunteer to do delivery to recipients", 62 | defaultValue: false 63 | } 64 | } 65 | } as any); 66 | 67 | export default new SimpleSchema2Bridge(volunteerForm); -------------------------------------------------------------------------------- /platform/client-admin/src/pages/VolunteersPage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | IonPage, 4 | IonFooter, 5 | IonLoading, 6 | IonContent, 7 | IonIcon, 8 | IonFab, 9 | IonFabButton, 10 | } from '@ionic/react'; 11 | import { Empty, Header } from '../components'; 12 | import { RouteComponentProps } from 'react-router'; 13 | import { useFindVolunteersQuery } from '../dataFacade'; 14 | import { VolunteersList } from '../components/model/VolunteerList'; 15 | import { add } from "ionicons/icons"; 16 | 17 | export const VolunteersPage: React.FC = ({ match }) => { 18 | let { data, loading, error } = useFindVolunteersQuery() 19 | if (error) { 20 | console.log(error); 21 | } 22 | 23 | if (loading) return ; 27 | 28 | let content; 29 | if (data?.findVolunteers?.items.length !== 0) { 30 | content = 31 | } else { 32 | content = No data!

} />; 33 | } 34 | 35 | return ( 36 | 37 |
38 | 39 | 40 | {content} 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
49 | OpenVolunteer Platform 50 |
51 |
52 | 53 | ); 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /platform/client-admin/src/pages/RecipientsPage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | IonPage, 4 | IonFooter, 5 | IonLoading, 6 | IonContent, 7 | IonIcon, 8 | IonFab, 9 | IonFabButton, 10 | } from '@ionic/react'; 11 | import { Empty, Header } from '../components'; 12 | import { RouteComponentProps } from 'react-router'; 13 | import { useFindRecipientsQuery } from '../dataFacade'; 14 | import { RecipientList } from '../components/model/RecipientList'; 15 | import { add } from 'ionicons/icons'; 16 | 17 | export const RecipientsPage: React.FC = ({ match }) => { 18 | let { data, loading, error } = useFindRecipientsQuery(); 19 | 20 | if (error) { 21 | console.log(error); 22 | } 23 | 24 | if (loading) return ; 28 | 29 | let content; 30 | if (data?.findRecipients?.items.length !== 0) { 31 | content = 32 | } else { 33 | content = No data!

} />; 34 | } 35 | 36 | 37 | return ( 38 | 39 |
40 | 41 | 42 | {content} 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
51 | OpenVolunteer Platform 52 |
53 |
54 | 55 | ); 56 | 57 | }; 58 | -------------------------------------------------------------------------------- /platform/client-admin/src/components/model/Volunteer.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | IonItem, 4 | IonButton, 5 | IonLabel, 6 | IonBadge, 7 | IonIcon, 8 | IonButtons 9 | } from '@ionic/react'; 10 | import { peopleOutline, open } from 'ionicons/icons'; 11 | import { Link } from 'react-router-dom'; 12 | import { VolunteerFieldsFragment } from '../../dataFacade'; 13 | 14 | export const Volunteer: React.FC<{ volunteer: VolunteerFieldsFragment }> = ({ volunteer }) => { 15 | 16 | return ( 17 | 18 | 19 | 20 |

{volunteer.firstName} {volunteer.lastName}

21 |
22 | {volunteer.canDeliver && 23 |

24 | Action Type 25 | 26 | Delivery 27 | 28 |

} 29 |

30 | Status 31 | 32 | {volunteer.active ? "Active" : "Inactive"} 33 | 34 |

35 | 36 |

Actions Completed 37 | 38 | {volunteer.actionsCompleted} 39 | 40 |

41 | 42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |
53 | ); 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | working_directory: ~/aerogear 5 | docker: 6 | - image: circleci/node:lts 7 | steps: 8 | - checkout 9 | - restore_cache: 10 | key: dependency-cache-{{ checksum "client/package.json" }}-{{checksum "server/package.json"}} 11 | - run: 12 | name: install-dependencies 13 | command: yarn 14 | - run: 15 | name: install-package-dependencies 16 | command: yarn 17 | - save_cache: 18 | key: dependency-cache-{{ checksum "client/package.json" }}-{{checksum "server/package.json"}} 19 | paths: 20 | - ./node_modules 21 | - run: 22 | name: run build 23 | command: "yarn build" 24 | 25 | publish_container: 26 | docker: 27 | # image for building docker containers 28 | - image: circleci/node:lts 29 | steps: 30 | - checkout 31 | - run: 32 | name: install-dependencies 33 | command: yarn 34 | # special workaround to allow running docker in docker https://circleci.com/docs/2.0/building-docker-images/ 35 | - setup_remote_docker: 36 | version: 17.05.0-ce 37 | - run: | 38 | yarn 39 | yarn prepare:client 40 | - run: | 41 | cd server 42 | TAG=$CIRCLE_TAG ../scripts/publish_container.sh 43 | workflows: 44 | version: 2 45 | build_and_release: 46 | jobs: 47 | - build: 48 | filters: 49 | tags: 50 | only: /.*/ 51 | - publish_container: 52 | filters: 53 | tags: 54 | only: /.*/ 55 | branches: 56 | only: ignored 57 | 58 | 59 | -------------------------------------------------------------------------------- /platform/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OVP-starter", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "Mono repository for OVP Starter", 6 | "main": "index.js", 7 | "devDependencies": { 8 | "del-cli": "3.0.1", 9 | "graphback-cli": "0.16.2", 10 | "graphql": "15.3.0" 11 | }, 12 | "scripts": { 13 | "start:server": "cd server && yarn start", 14 | "start:client": "cd client && yarn start", 15 | "build:server": "cd server && yarn build", 16 | "build:client": "cd client && yarn build", 17 | "removeQueries": "del ./client/src/graphql ; del ./client-admin/src/graphql", 18 | "build:clientGeneric": "cd client/ && yarn build:generic", 19 | "build:adminGeneric": "cd client-admin/ && yarn build:generic", 20 | "prepare:client": "del ./client/build ./server/website ; yarn build:clientGeneric && mv ./client/build/ ./server/website", 21 | "prepare:admin": "del ./client-admin/build ./server/admin ; yarn build:adminGeneric && mv ./client-admin/build/ ./server/admin", 22 | "build": "yarn workspaces run build", 23 | "unlock": "yarn workspaces run del package-lock.json && del yarn.lock", 24 | "clean": "yarn workspaces run del ./dist && del ./types", 25 | "walkthrough": "./scripts/create_walkthrough.sh", 26 | "generate:client": "cd client && yarn graphback generate && yarn graphql codegen", 27 | "generate:admin": "cd client-admin && yarn graphback generate && yarn graphql codegen", 28 | "generate:all": "yarn generate:client && yarn generate:admin", 29 | "prepare:all": "yarn prepare:client && yarn prepare:admin" 30 | }, 31 | "workspaces": [ 32 | "client", 33 | "client-admin", 34 | "server" 35 | ], 36 | "resolutions": { 37 | "@types/react": "16.9.49" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /platform/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ovp-server-starter", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "ts-node src/index.ts", 7 | "startMQTT": "MQTT_HOST=127.0.0.1:1883 ts-node src/index.ts", 8 | "build": "tsc", 9 | "keycloak": "docker-compose -f ./integrations/keycloak/docker-compose.yml up", 10 | "keycloak:init": "node ./integrations/keycloak/initKeycloak.js", 11 | "mqtt": "docker-compose -f ./integrations/mqtt/docker-compose.yml up", 12 | "amq:config": "node ./integrations/mqtt/configureAMQ.js" 13 | }, 14 | "license": "MIT", 15 | "devDependencies": { 16 | "@types/cors": "2.8.7", 17 | "@types/express": "4.17.0", 18 | "@types/node": "13.13.16", 19 | "keycloak-request-token": "0.1.0", 20 | "ts-node": "8.10.2", 21 | "ts-node-dev": "1.0.0-pre.62", 22 | "tslint": "6.1.3", 23 | "typescript": "3.9.7" 24 | }, 25 | "dependencies": { 26 | "@aerogear/graphql-mqtt-subscriptions": "1.1.3", 27 | "@graphback/datasync": "0.16.2", 28 | "@graphback/keycloak-authz": "0.16.2", 29 | "@graphback/runtime-mongo": "0.16.2", 30 | "@graphql-tools/graphql-file-loader": "6.2.6", 31 | "@graphql-tools/load": "6.2.5", 32 | "@types/react": "16.9.49", 33 | "apollo-server-express": "2.17.0", 34 | "cors": "2.8.5", 35 | "dotenv": "8.2.0", 36 | "express": "4.17.1", 37 | "express-session": "1.17.1", 38 | "graphback": "0.16.2", 39 | "graphql": "15.3.0", 40 | "graphql-merge-resolvers": "1.1.16", 41 | "graphql-subscriptions": "1.1.0", 42 | "graphql-tag": "2.11.0", 43 | "keycloak-connect": "10.0.2", 44 | "keycloak-connect-graphql": "0.6.1", 45 | "mongo-seeding": "3.4.1", 46 | "mongodb": "3.6.1", 47 | "mongodb-backup": "1.6.9", 48 | "mongodb-restore": "1.6.2" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /platform/client-admin/src/pages/ActionPage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | IonPage, 4 | IonFooter, 5 | IonLoading, 6 | IonContent, 7 | IonIcon, 8 | IonFab, 9 | IonFabButton 10 | } from '@ionic/react'; 11 | import { Empty, ActionsList, Header } from '../components'; 12 | import { RouteComponentProps } from 'react-router'; 13 | import { useFindVolunteerActionsQuery } from '../dataFacade'; 14 | import { add, filter } from 'ionicons/icons'; 15 | 16 | export const ActionPage: React.FC = ({ match }) => { 17 | const { data, loading, error } = useFindVolunteerActionsQuery(); 18 | 19 | if (error) { 20 | console.log(error); 21 | } 22 | 23 | if (loading) return ; 27 | 28 | let content; 29 | if (data?.findVolunteerActions?.items.length !== 0) { 30 | content = 31 | } else { 32 | content = No actions!

} />; 33 | } 34 | 35 | 36 | return ( 37 | 38 |
39 | 40 | 41 | 42 | {/* TODO add handling */} 43 | 44 | 45 | 46 | 47 | {content} 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
56 | OpenVolunteer Platform 57 |
58 |
59 | 60 | ); 61 | 62 | }; 63 | -------------------------------------------------------------------------------- /website/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * Any CSS included here will be global. The classic template 4 | * bundles Infima by default. Infima is a CSS framework designed to 5 | * work well for content-centric websites. 6 | */ 7 | 8 | /* You can override the default Infima variables here. */ 9 | :root { 10 | --ifm-color-primary: #23246f; 11 | --ifm-color-primary-dark: #1e1f5e; 12 | --ifm-color-primary-darker: #202064; 13 | --ifm-color-primary-darkest: #23246f; 14 | --ifm-color-primary-light: #27287a; 15 | --ifm-color-primary-lighter: #282980; 16 | --ifm-color-primary-lightest: #2e2f90; 17 | --ifm-code-font-size: 95%; 18 | } 19 | 20 | #__docusaurus { 21 | position: relative; 22 | } 23 | 24 | .docusaurus-highlight-code-line { 25 | background-color: rgb(72, 77, 91); 26 | display: block; 27 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 28 | padding: 0 var(--ifm-pre-padding); 29 | } 30 | 31 | .navbar { 32 | box-shadow: none; 33 | } 34 | 35 | .button--rounded { 36 | border-radius: 2rem; 37 | } 38 | 39 | .hero .hero__title { 40 | text-align: center; 41 | 42 | line-height: 3rem; 43 | font-weight: 300; 44 | 45 | /* font-size: 5rem !important; */ 46 | } 47 | 48 | .hero__subtitle { 49 | font-size: 3rem; 50 | font-weight: 600; 51 | /* font-size: 5rem !important; */ 52 | } 53 | 54 | .hide-modal { 55 | opacity: 0 !important; 56 | visibility: hidden !important; 57 | } 58 | 59 | .hidden { 60 | visibility: hidden; 61 | } 62 | 63 | .card-anchor { 64 | color: #222; 65 | } 66 | 67 | .card-ancher:hover { 68 | text-decoration: none; 69 | } 70 | 71 | a.card-anchor:hover > .card-demo > .card { 72 | border: transparent; 73 | box-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.16), 0 3px 6px 0 rgba(0, 0, 0, 0.12), 0 5px 12px 4px rgba(0, 0, 0, 0.09); 74 | } 75 | 76 | .footer.footer--dark { 77 | background: #00003C !important; 78 | } -------------------------------------------------------------------------------- /platform/client/src/theme/styles.css: -------------------------------------------------------------------------------- 1 | .list-md { 2 | padding: 0; 3 | } 4 | 5 | .task-item { 6 | padding-bottom: 0; 7 | } 8 | 9 | .item ion-label { 10 | overflow: visible; 11 | white-space: pre-wrap; 12 | } 13 | 14 | ion-note { 15 | padding: 10px; 16 | line-height: 21px; 17 | white-space: pre-wrap; 18 | } 19 | 20 | ion-badge { 21 | vertical-align: middle; 22 | white-space: pre-line; 23 | text-align: left; 24 | } 25 | 26 | ion-footer div { 27 | margin: 10px; 28 | } 29 | 30 | .create-button { 31 | margin-left:15px; 32 | z-index: 9999; 33 | } 34 | 35 | .trash-button { 36 | margin-left:5px; 37 | z-index: 9999; 38 | } 39 | 40 | .network-badge { 41 | float: right; 42 | height: calc(2.1em + 4px); 43 | font-size: 13px; 44 | text-transform: uppercase; 45 | vertical-align: middle; 46 | line-height: calc(2.1em + 4px); 47 | --padding-top: 0; 48 | --padding-bottom: 0; 49 | --padding-start: 0.9em; 50 | --padding-end: 0.9em; 51 | } 52 | 53 | .offline-queue-button { 54 | -webkit-margin-start: 0px; 55 | margin-inline-start: 0px; 56 | } 57 | 58 | .offline-queue-badge { 59 | margin-left: -7px; 60 | vertical-align: top; 61 | } 62 | 63 | .task-item { 64 | padding-bottom: 0; 65 | } 66 | 67 | .list-md { 68 | padding: 0; 69 | } 70 | 71 | .item .sc-ion-label-md-h { 72 | overflow: visible; 73 | white-space: pre-wrap; 74 | } 75 | 76 | ion-note { 77 | padding: 10px; 78 | line-height: 21px; 79 | white-space: pre-wrap; 80 | } 81 | 82 | ion-badge { 83 | vertical-align: middle; 84 | white-space: pre-line; 85 | text-align: left; 86 | } 87 | 88 | .queue-empty { 89 | height: 100%; 90 | display: flex; 91 | align-items: center; 92 | text-align: center; 93 | } 94 | 95 | .queue-empty p { 96 | line-height: 150% 97 | } 98 | 99 | .submit-btn { 100 | margin-top: 30px; 101 | } -------------------------------------------------------------------------------- /platform/client-admin/src/theme/styles.css: -------------------------------------------------------------------------------- 1 | .list-md { 2 | padding: 0; 3 | } 4 | 5 | .task-item { 6 | padding-bottom: 0; 7 | } 8 | 9 | .item ion-label { 10 | overflow: visible; 11 | white-space: pre-wrap; 12 | } 13 | 14 | ion-note { 15 | padding: 10px; 16 | line-height: 21px; 17 | white-space: pre-wrap; 18 | } 19 | 20 | ion-badge { 21 | vertical-align: middle; 22 | white-space: pre-line; 23 | text-align: left; 24 | } 25 | 26 | ion-footer div { 27 | margin: 10px; 28 | } 29 | 30 | .create-button { 31 | margin-left:15px; 32 | z-index: 9999; 33 | } 34 | 35 | .trash-button { 36 | margin-left:5px; 37 | z-index: 9999; 38 | } 39 | 40 | .network-badge { 41 | float: right; 42 | height: calc(2.1em + 4px); 43 | font-size: 13px; 44 | text-transform: uppercase; 45 | vertical-align: middle; 46 | line-height: calc(2.1em + 4px); 47 | --padding-top: 0; 48 | --padding-bottom: 0; 49 | --padding-start: 0.9em; 50 | --padding-end: 0.9em; 51 | } 52 | 53 | .offline-queue-button { 54 | -webkit-margin-start: 0px; 55 | margin-inline-start: 0px; 56 | } 57 | 58 | .offline-queue-badge { 59 | margin-left: -7px; 60 | vertical-align: top; 61 | } 62 | 63 | .task-item { 64 | padding-bottom: 0; 65 | } 66 | 67 | .list-md { 68 | padding: 0; 69 | } 70 | 71 | .item .sc-ion-label-md-h { 72 | overflow: visible; 73 | white-space: pre-wrap; 74 | } 75 | 76 | ion-note { 77 | padding: 10px; 78 | line-height: 21px; 79 | white-space: pre-wrap; 80 | } 81 | 82 | ion-badge { 83 | vertical-align: middle; 84 | white-space: pre-line; 85 | text-align: left; 86 | } 87 | 88 | .queue-empty { 89 | height: 100%; 90 | display: flex; 91 | align-items: center; 92 | text-align: center; 93 | } 94 | 95 | .queue-empty p { 96 | line-height: 150% 97 | } 98 | 99 | .submit-btn { 100 | margin-top: 30px; 101 | } -------------------------------------------------------------------------------- /website/src/components/Video/index.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import classnames from 'classnames'; 3 | import useBaseUrl from '@docusaurus/useBaseUrl'; 4 | import styles from './styles.module.css'; 5 | 6 | function VideoModal({ open, close}) { 7 | console.log(open); 8 | return ( 9 |
10 |
11 | close 12 |
13 |
14 |