From 5eb9290edf7d4b580f7f3a5cbe2b719ee12f4c13 Mon Sep 17 00:00:00 2001 From: Minu Mathew <minumpmathews@gmail.com> Date: Fri, 31 Mar 2023 10:55:56 -0500 Subject: [PATCH] Release/1.18.0 (#1114) * Master to develop after 1.17.0 (#1057) * Update CHANGELOG.md * Update version numbers in the OpenAPI documents. * Update CHANGELOG.md * Update CHANGELOG.md * Update version number in YAML file. * Point to production health and talent chooser API documentation in production. * Update CHANGELOG. * Update version number in OpenAPI spec files. * Update Building Block URL in Api Doc Dockerfile. * Minor update to CHANGELOG. * Fix Auth library dependencies versions to avoid breaking changes. * Update Events Building Block Dockerfile. * Update App Config Dockerfile. * Update Authentication Building Block Dockerfile. * Update Profile Building Block Dockerfile. * Update Contributions Building Block Dockerfile and requirements. * Update Contributions Catalog Dockerfile and requirements. * Update Logging Building Block Dockerfile. * Update version numbers in API specs. * Update CHANGELOG. * Update CHANGELOG.md * Update version number. * Update CHANGELOG.md * Update CHANGELOG.md * Update version numbers in OpenAPI specification. * turn off group authentication on image get endpoint * turn off group authentication on image get endpoint * Update Events Building Block logs and related configuration. * Update CHANGELOG. * Added more information to logs * changed the log's building block name * updated to use longDescription * updated changelog * Update CHANGELOG and verson numbers. * Update API Doc Dockerfile. * Fix CHANGELOG. * Fix CHANGELOG. * Update version numbers in SECURITY.md * Fix merge conflicts. * Update CHANGELOG.md * Update CHANGELOG. * Update Dockerfile. * Update version number in API spec files. * Updater version in SECURITY.md * Update CHANGELOG. * Update Events BB version number. * Update SECURITY.md * updated for release * resolved merge conflicts * updated version in yaml files * updated version in yaml * workaround for Oauth transport lib error * updated changelog * updated docker build with nocache option * moved ProxyFix to catalog * removed no-cache from docker build * updated version in yaml * updated security * Update contributions/api/contributions_rest_service.py remove blank line Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> * added version comparison * Update catalog_rest_service.py Comment on the proxyFix Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> * updated release version * release 1.16.0 * Update SECURITY.md Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> * release 1.16.0 * Update CHANGELOG.md Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> * release 1.16.0 * Update CHANGELOG.md Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> * release 1.16.0 * Update appconfig.yaml Updating version number in AppConfig YAML file. * added release to changelog * updated version in yaml * updated security * reverting version for unchanged blocks * reverting version for auth * update version for events * revert version logging and profile * 1048 bug edit contribution database detail (#1049) * added index to database detail field * updated changelog * updated changelog for release * Set ApibaseUrl in catalog (#1052) * set and get apibaseurl * updated changelog * 1050 multiple contribution admins field (#1051) * fixes for multiple contribution admins * updated changelog to release * added space for display in create page * comma separated display in details page * changed contributionAdmin to list * updated versionurl field * updated changelog * 1053 bug open source url field (#1055) * onclick function isopensourceurl * updated changelog * changed chmod permissions * reverting version changes to match appconfig * change to dev urls Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> Co-authored-by: Bing Zhang <bing@illinois.edu> Co-authored-by: YONG WOOK KIM <ywkim@illinois.edu> * 1034 UI change capability details page (#1035) * added css style classes * updated changelog * updated footer css * updated changelog * remove footer * unchanged footer in home * unchanging footer in home * removed footer from changelog * changed css names * added height to font css * styles for capability details and moved button outside div * added html font style * update colsm9 style * added same classes to all smallbodytext * remove unwanted classes * moved view contribution button to container div * updated small body text style * changed grid container and col classes * updated top margin * moved to unreleased * moved to unreleased section * 1036 UI changes footer in catalog (#1039) * updated footer ui * updated changelog * added image * updated padding for footer * added class link * moved to unreleased section * 1040 header UI changes (#1042) * changes to topnav * added cursor pointer to plus icon * removed inactive styles classes from style html * added contribute button * removed unwanted style classes * remove unwanted styling * added plus icon * removed extra space * changed topnav styles * updated styling for login and logout button * add navlogout display script * topnav classes and scripts * styles for topnav buttons * updated changelog * changed style of buttons * added icons stylesheet * added icons stylesheet * changed button class name * updated width of topright nav * updated margins * added blockI * style topnav right divs * moved to unreleased * removed unwanted comment * changed footer class name * updated flex div * updated header styling * removed exclamation mark * removed h1 class redundant * added typekit css * added typekit css to head * added typekit css to talent details * 1060 UI talent details page (#1061) * fixed tag div * added div and style same as capability * updated col styling * updated changelog * added col div * 1041 contribution details UI change (#1062) * added css style classes * updated changelog * updated footer css * updated changelog * remove footer * unchanged footer in home * unchanging footer in home * removed footer from changelog * changed css names * css for contribution details page * added comment * added container and changed layout * changed layout * added h5 class * updated layout and styling * updated buttons * removed input styling and updated button colors * changelog updated * removed duplicate issue * removed input type styling * deleted duplicates * fixed button styles * corrected display of contribution admins * change button styles * changed button class to match style * updated font style in button * changed button height padding and font size * updated changelog * font weight changed * 1063 catalog home page UI (#1064) * add bookshelf image asset * removed styling and added div * updated class css styling * added button styles * updated changelog * removed unwanted styling * sorted stylecss * changed class name and style * updated styling * updated contribution link class * changed view contribution div * updated card and contribution link positions * removed additional style sheet * changed styling * removed container style * updated h4 font weight * 1044 add footer for all pages (#1067) * added container margin and padding * added footer, changed filename * changed filename * removed footer from home * updated filename * updated filename * updated changelog * added image assets * added scrset to footer image * renamed topbottomnav * created footer page * removed footer margin css * added footer and renamed topnav * added spaces * moved footer to bottom * added zeplin padding * removed unwanted styles * changed footer and main div * moved box sizing style * 1059 task update codeowners file (#1068) * Update CODEOWNERS file Include CHANGELOG as a separate entry. * Update CHANGELOG.md * 1065 updated styles for create page (#1071) * updated styles for create page * changed button styling * added padding style * removed duplicate class style * removed unwanted comments * changed divs * removed class text input field * changed wordings * updated input box styling * added checkbox svg asset * added checkbox styling * added checkbox styling * rearranging input div table cell * updated cancel modal * changed close button * changed close button * changed col spaces * checkbox stlye * updated focus styling * updated changelog * close and other buttons * button active and hover styles * added form-control class and changed textarea * updated styles for form control and check classes * added font size * changed button and font style * 1066 review page UI changes (#1082) * updated styles for create page * changed button styling * added padding style * removed duplicate class style * removed unwanted comments * changed divs * removed class text input field * changed wordings * updated input box styling * added checkbox svg asset * added checkbox styling * added checkbox styling * rearranging input div table cell * updated cancel modal * changed close button * changed close button * changed col spaces * checkbox stlye * updated focus styling * updated changelog * close and other buttons * button active and hover styles * added form-control class and changed textarea * updated styles for form control and check classes * added font size * changed button and font style * change padding so that text is visible * added form group divs * added tertiary button styles * removed input reset styles * changed button classes to update styles * updated changelog * updated button focus styles * added custom dropdown div * added custom dropdown menu styles * javascript for custom dropdown menu * added border line style and removed unwanted styles * added hover style * updated font weight on hover * added border on hover * removed customized dropdown * 1079 contribute create page div rearrangement (#1093) * removed closing div tag * added container class divs * updated changelog * 1077 task fix detect secrets GitHub action (#1098) * Change to GitHub Actions version 3. * Add virtual environment to detect secrets GitHub action workflow and update run command. * Replace source with dot. * Upgrade pip. * Update run command. * Fix detect-secrets.yaml Applying the fix from https://github.com/rokwire/core-building-block/pull/627/files#diff-6be25c6f69ed96a573185fa0c1f601914a92ecd85fd9fb4cf5fb3c2e53fb6e2c * Update detect-secrets.yaml * Update .pre-commit-config.yaml * Remove virtual environment. * Update .secrets.baseline * Change scanning to staged files only. * Update baseline. * Change scanning to all tracked files. * Update local dev requirements. * Update baseline. * Update baseline. * Update CHANGELOG. * testing github precommit detect secrets * removed test changelog --------- Co-authored-by: Minu Mathew <minumpmathews@gmail.com> * 1087 vertical alignment in contribute page (#1095) * removed closing div tag * added container class divs * updated changelog * added div class col sm 10 for radio buttons * updated style for label * added radio inline class * updated cursor pointer style * input file style * added checkbox inline style label * separated label and input * removed input class * added checkbox style * added calendar hover style * changes to nav breadcrumbs * added submit div href link to breadcrumb * added col sm 10 for vertical alignment in edit page * updated styling * changed talent form edit page to match create page * updated changelog * removed inline style for add person * moved add environment variable button to row and col divs * added styling to add environment variables div row * Bump cryptography from 3.3.2 to 39.0.1 in /contributions (#1073) * Bump cryptography from 3.3.2 to 39.0.1 in /contributions Bumps [cryptography](https://github.com/pyca/cryptography) from 3.3.2 to 39.0.1. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/3.3.2...39.0.1) --- updated-dependencies: - dependency-name: cryptography dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> * updated cryptography in auth middleware * updated cryptography verison changelog --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Minu Mathew <minumpmathews@gmail.com> Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> * Bump cryptography from 3.3.2 to 39.0.1 in /appconfigservice (#1074) * Bump cryptography from 3.3.2 to 39.0.1 in /appconfigservice Bumps [cryptography](https://github.com/pyca/cryptography) from 3.3.2 to 39.0.1. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/3.3.2...39.0.1) --- updated-dependencies: - dependency-name: cryptography dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> * update gevent * update cryptography * updated changelog --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Minu Mathew <minumpmathews@gmail.com> * Bump cryptography from 3.3.2 to 39.0.1 in /eventservice (#1076) Bumps [cryptography](https://github.com/pyca/cryptography) from 3.3.2 to 39.0.1. - [Release notes](https://github.com/pyca/cryptography/releases) - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/3.3.2...39.0.1) --- updated-dependencies: - dependency-name: cryptography dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * 1084 card alignment in catalog home page (#1096) * added bookshelf images * removed styles and changed class names * updated styles for cards * updated changelog * updated max width for main container * removed search bar styling * added space before grid cards start * 1085 finalize button styles (#1097) * updated buttons in contribution details page * changed topnav buttons * topnav buton styles updated * updated illinois home page url * deleted old home page * updated changelog * updated focus styles * arranged div spacing * changed buttons * updated inline style outline * Bump werkzeug from 2.0.2 to 2.2.3 in /contributions/catalog (#1083) * Bump werkzeug from 2.0.2 to 2.2.3 in /contributions/catalog Bumps [werkzeug](https://github.com/pallets/werkzeug) from 2.0.2 to 2.2.3. - [Release notes](https://github.com/pallets/werkzeug/releases) - [Changelog](https://github.com/pallets/werkzeug/blob/main/CHANGES.rst) - [Commits](https://github.com/pallets/werkzeug/compare/2.0.2...2.2.3) --- updated-dependencies: - dependency-name: werkzeug dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> * fixed typo in prev changelog and updated changelog * upgrade flask version to match with werkzeug * upgrade flask version to match catalog * upgrade connexion version to match flask version --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Minu Mathew <minumpmathews@gmail.com> * 1090 customize dropdown menu (#1101) * updated indexing of env vars * reverted to original develop * updated styles for create page * changed button styling * added padding style * removed duplicate class style * removed unwanted comments * changed divs * removed class text input field * changed wordings * updated input box styling * added checkbox svg asset * added checkbox styling * added checkbox styling * rearranging input div table cell * updated cancel modal * changed close button * changed close button * changed col spaces * checkbox stlye * updated focus styling * updated changelog * close and other buttons * button active and hover styles * added form-control class and changed textarea * updated styles for form control and check classes * added font size * changed button and font style * change padding so that text is visible * added form group divs * added tertiary button styles * removed input reset styles * changed button classes to update styles * updated changelog * updated button focus styles * added custom dropdown div * added custom dropdown menu styles * javascript for custom dropdown menu * added border line style and removed unwanted styles * added hover style * updated font weight on hover * added border on hover * added down arrow caret * commented all javascirpt for custom dropdown * added arrow style for dropdown * undo unneccessary change * undo unwanted change * updated cahngelog * removed javascript for full customized dropdown * removed the extra styling classes for customized dropdown * remove orange underline border * 1092 fill footer at bottom of pages (#1104) * changed content page size for small contents * updated changelog * 1054 bug select contribution type buttons display (#1107) * added a right tab for div * put breadcrumbs in container class * updated moveselector placeholder function * updated changelog * 1103 validation for form fields in UI (#1106) * input type verification for capability and contribution * updated type in input tag * updated changelog * added minlength and maxlength attributes to tel * 1102 fix form texts and placeholders (#1108) * corrected div placement * div rearrangement * updated form text and plcaeholders * updated placeholders * upload icon text * removed f * phone number placeholder * updated text and placeholders * updated changelog * removed spacing of textarea * placeholder texts updated * change contributors to persons in placeholder text Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> * Update contributions/catalog/webapps/templates/contribute/contribute.html Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> --------- Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> * 1069 change wordings details page (#1109) * updated wordings for contribution view page * updated wordings for capability view page * updated wording for talent view page * capability details small case * updated changelog * siwtched to capitalize * capitalize in capability details * updated text in contribution details * Update text fields on talent_details.html Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> --------- Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> * updated changelog for release * updated yaml version for release * updated security file * update version in events yaml --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Sandeep Puthanveetil Satheesan <sandeeps@illinois.edu> Co-authored-by: Bing Zhang <bing@illinois.edu> Co-authored-by: YONG WOOK KIM <ywkim@illinois.edu> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/detect-secrets.yaml | 9 +- .pre-commit-config.yaml | 2 +- .secrets.baseline | 170 +- CHANGELOG.md | 33 + CODEOWNERS | 3 + SECURITY.md | 1 + appconfigservice/appconfig.yaml | 2 +- appconfigservice/requirements.txt | 4 +- contributions/catalog/requirements.txt | 4 +- .../webapps/static/block-i-white-orange.png | Bin 0 -> 292 bytes .../catalog/webapps/static/bookshelf.jpg | Bin 0 -> 8132 bytes .../catalog/webapps/static/bookshelf@1x.jpg | Bin 0 -> 8132 bytes .../catalog/webapps/static/bookshelf@2x.jpg | Bin 0 -> 21304 bytes .../catalog/webapps/static/bookshelf@3x.jpg | Bin 0 -> 36070 bytes .../webapps/static/checkbox-checked.svg | 7 + .../catalog/webapps/static/css/style.css | 639 ++++++-- .../static/icon-arrows-caret-down-orange.png | Bin 0 -> 153 bytes .../static/powered-by-rokwire-no-i-block.png | Bin 0 -> 1383 bytes .../powered-by-rokwire-no-i-block@2x.png | Bin 0 -> 2410 bytes .../powered-by-rokwire-no-i-block@3x.png | Bin 0 -> 3517 bytes .../catalog/webapps/templates/base.html | 1 + .../contribute/capability_details.html | 295 ++-- .../templates/contribute/contribute.html | 1372 +++++++++-------- .../contribute/contribution_details.html | 702 +++++---- .../webapps/templates/contribute/home.html | 332 ++-- .../templates/contribute/home.html.old | 468 ------ .../templates/contribute/talent_details.html | 328 ++-- .../catalog/webapps/templates/footer.html | 7 + .../catalog/webapps/templates/head.html | 2 + .../catalog/webapps/templates/style.html | 30 - .../catalog/webapps/templates/topnav.html | 37 +- .../webapps/templates/topnav_javascript.html | 12 +- contributions/contribution.yaml | 2 +- contributions/requirements.txt | 6 +- eventservice/events.yaml | 2 +- eventservice/requirements.txt | 2 +- lib/auth-middleware/setup.py | 2 +- requirements-dev.txt | 4 +- 38 files changed, 2259 insertions(+), 2219 deletions(-) create mode 100644 contributions/catalog/webapps/static/block-i-white-orange.png create mode 100644 contributions/catalog/webapps/static/bookshelf.jpg create mode 100644 contributions/catalog/webapps/static/bookshelf@1x.jpg create mode 100644 contributions/catalog/webapps/static/bookshelf@2x.jpg create mode 100644 contributions/catalog/webapps/static/bookshelf@3x.jpg create mode 100644 contributions/catalog/webapps/static/checkbox-checked.svg create mode 100644 contributions/catalog/webapps/static/icon-arrows-caret-down-orange.png create mode 100644 contributions/catalog/webapps/static/powered-by-rokwire-no-i-block.png create mode 100644 contributions/catalog/webapps/static/powered-by-rokwire-no-i-block@2x.png create mode 100644 contributions/catalog/webapps/static/powered-by-rokwire-no-i-block@3x.png delete mode 100644 contributions/catalog/webapps/templates/contribute/home.html.old create mode 100644 contributions/catalog/webapps/templates/footer.html diff --git a/.github/workflows/detect-secrets.yaml b/.github/workflows/detect-secrets.yaml index ab471b79..59029c2c 100644 --- a/.github/workflows/detect-secrets.yaml +++ b/.github/workflows/detect-secrets.yaml @@ -8,13 +8,16 @@ jobs: container: python:latest steps: - - uses: actions/checkout@v2 - + - uses: actions/checkout@v3 + + - run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + - name: Install Yelp's detect secrets run: | apt-get update && apt-get install -y jq + pip install --upgrade pip pip install yq pip install detect-secrets==$(yq -r .repos[0].rev .pre-commit-config.yaml) - name: Detect potential secrets - run: find -type f -not -path './.git/*' -printf '%P\n' | xargs detect-secrets-hook --baseline .secrets.baseline + run: git ls-files -z | xargs -0 detect-secrets-hook --baseline .secrets.baseline diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 919e6409..6ea4002c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: git@github.com:Yelp/detect-secrets - rev: v1.0.3 + rev: v1.4.0 hooks: - id: detect-secrets args: ['--baseline', '.secrets.baseline'] diff --git a/.secrets.baseline b/.secrets.baseline index a27b7e7b..3d3fccba 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -1,5 +1,5 @@ { - "version": "1.0.3", + "version": "1.4.0", "plugins_used": [ { "name": "ArtifactoryDetector" @@ -20,6 +20,12 @@ { "name": "CloudantDetector" }, + { + "name": "DiscordBotTokenDetector" + }, + { + "name": "GitHubTokenDetector" + }, { "name": "HexHighEntropyString", "limit": 3.0 @@ -46,6 +52,9 @@ { "name": "PrivateKeyDetector" }, + { + "name": "SendGridDetector" + }, { "name": "SlackDetector" }, @@ -80,6 +89,12 @@ { "path": "detect_secrets.filters.heuristic.is_likely_id_string" }, + { + "path": "detect_secrets.filters.heuristic.is_lock_file" + }, + { + "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" + }, { "path": "detect_secrets.filters.heuristic.is_potential_uuid" }, @@ -89,6 +104,9 @@ { "path": "detect_secrets.filters.heuristic.is_sequential_string" }, + { + "path": "detect_secrets.filters.heuristic.is_swagger_file" + }, { "path": "detect_secrets.filters.heuristic.is_templated_secret" } @@ -98,25 +116,39 @@ { "type": "Secret Keyword", "filename": "appconfigservice/README.md", - "hashed_secret": "055d8a847dfea9c1c840140dd0940b0a5a832565", + "hashed_secret": "3c934d2c3326a4f2d2d77be4629b074872750d76", "is_verified": false, - "line_number": 22, + "line_number": 52, "is_secret": false - }, + } + ], + "appconfigservice/api/test/test_app_config.py": [ { "type": "Secret Keyword", - "filename": "appconfigservice/README.md", - "hashed_secret": "c2d2d8a23ffdcdee0e074b02d3a076d1546dc803", + "filename": "appconfigservice/api/test/test_app_config.py", + "hashed_secret": "bb21158c733229347bd4e681891e213d94c685be", "is_verified": false, - "line_number": 28, + "line_number": 55, "is_secret": false - }, + } + ], + "appconfigservice/api/test/test_index.py": [ { "type": "Secret Keyword", - "filename": "appconfigservice/README.md", - "hashed_secret": "93b6e269c00e67237d474cb068bbfb1362ea48b8", + "filename": "appconfigservice/api/test/test_index.py", + "hashed_secret": "bb21158c733229347bd4e681891e213d94c685be", "is_verified": false, - "line_number": 52, + "line_number": 29, + "is_secret": false + } + ], + "appconfigservice/api/test/test_search_config.py": [ + { + "type": "Secret Keyword", + "filename": "appconfigservice/api/test/test_search_config.py", + "hashed_secret": "bb21158c733229347bd4e681891e213d94c685be", + "is_verified": false, + "line_number": 29, "is_secret": false } ], @@ -128,100 +160,118 @@ "is_verified": false, "line_number": 65, "is_secret": false - } - ], - "auth-middleware-test-svc/README.md": [ + }, { "type": "Secret Keyword", - "filename": "auth-middleware-test-svc/README.md", - "hashed_secret": "055d8a847dfea9c1c840140dd0940b0a5a832565", + "filename": "appconfigservice/appconfig.yaml", + "hashed_secret": "a45a360e6ff9bceaf3fcfef370a6d6e1d4ba9271", "is_verified": false, - "line_number": 30, + "line_number": 65, "is_secret": false - } - ], - "authservice/README.md": [ + }, { "type": "Secret Keyword", - "filename": "authservice/README.md", - "hashed_secret": "c2d2d8a23ffdcdee0e074b02d3a076d1546dc803", + "filename": "appconfigservice/appconfig.yaml", + "hashed_secret": "967b337f4eb99a877c1d326531d6a197b972a713", "is_verified": false, - "line_number": 73, + "line_number": 300, "is_secret": false } ], - "contributions/catalog/Dockerfile": [ + "contributions/README.md": [ { - "type": "Secret Keyword", - "filename": "contributions/catalog/Dockerfile", - "hashed_secret": "b6ee60926c0a426addcbb7e087d4274498f35b1c", + "type": "Hex High Entropy String", + "filename": "contributions/README.md", + "hashed_secret": "1da0126accdd44a043f50ae89644c355579e9008", "is_verified": false, - "line_number": 23, + "line_number": 150, "is_secret": false - } - ], - "eventservice/README.md": [ + }, { - "type": "Secret Keyword", - "filename": "eventservice/README.md", - "hashed_secret": "c2d2d8a23ffdcdee0e074b02d3a076d1546dc803", + "type": "Hex High Entropy String", + "filename": "contributions/README.md", + "hashed_secret": "923f444e304cd39f5803a8fe3a64f624837cb0a0", "is_verified": false, - "line_number": 24, + "line_number": 833, "is_secret": false }, { - "type": "Secret Keyword", - "filename": "eventservice/README.md", - "hashed_secret": "99f11f7789a5315285e569895445507118f188bd", + "type": "Hex High Entropy String", + "filename": "contributions/README.md", + "hashed_secret": "f6b110e76ea7968dbbfb44b70822238ba8d55740", + "is_verified": false, + "line_number": 873, + "is_secret": false + }, + { + "type": "Hex High Entropy String", + "filename": "contributions/README.md", + "hashed_secret": "3b5dcb0f5163198f51b25c9ac24a1e3950f23b6f", "is_verified": false, - "line_number": 30, + "line_number": 1174, "is_secret": false } ], - "loggingservice/README.md": [ + "contributions/contribution.yaml": [ { "type": "Secret Keyword", - "filename": "loggingservice/README.md", - "hashed_secret": "c2d2d8a23ffdcdee0e074b02d3a076d1546dc803", + "filename": "contributions/contribution.yaml", + "hashed_secret": "967b337f4eb99a877c1d326531d6a197b972a713", "is_verified": false, - "line_number": 22, + "line_number": 862, "is_secret": false - }, + } + ], + "eventservice/README.md": [ + { + "type": "Hex High Entropy String", + "filename": "eventservice/README.md", + "hashed_secret": "738cfd4b80282ef1adafa910355da8c0f4ba3a83", + "is_verified": false, + "line_number": 120, + "is_secret": false + } + ], + "eventservice/events.yaml": [ { "type": "Secret Keyword", - "filename": "loggingservice/README.md", - "hashed_secret": "99f11f7789a5315285e569895445507118f188bd", + "filename": "eventservice/events.yaml", + "hashed_secret": "967b337f4eb99a877c1d326531d6a197b972a713", "is_verified": false, - "line_number": 28, + "line_number": 950, "is_secret": false } ], - "profileservice/README.md": [ + "lib/auth-middleware/auth_middleware/__init__.py": [ { "type": "Secret Keyword", - "filename": "profileservice/README.md", - "hashed_secret": "055d8a847dfea9c1c840140dd0940b0a5a832565", + "filename": "lib/auth-middleware/auth_middleware/__init__.py", + "hashed_secret": "f6e3f71c77bbae9e01381e855927239c0d679530", "is_verified": false, - "line_number": 38, + "line_number": 34, "is_secret": false - }, + } + ], + "loggingservice/logging.yaml": [ { "type": "Secret Keyword", - "filename": "profileservice/README.md", - "hashed_secret": "c2d2d8a23ffdcdee0e074b02d3a076d1546dc803", + "filename": "loggingservice/logging.yaml", + "hashed_secret": "967b337f4eb99a877c1d326531d6a197b972a713", "is_verified": false, - "line_number": 44, + "line_number": 155, "is_secret": false - }, + } + ], + "profileservice/profile.yaml": [ { "type": "Secret Keyword", - "filename": "profileservice/README.md", - "hashed_secret": "99f11f7789a5315285e569895445507118f188bd", + "filename": "profileservice/profile.yaml", + "hashed_secret": "967b337f4eb99a877c1d326531d6a197b972a713", "is_verified": false, - "line_number": 50, + "line_number": 673, "is_secret": false } ] }, - "generated_at": "2021-11-17T22:48:48Z" + "generated_at": "2023-03-07T18:58:39Z" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 4eeb3023..f74850f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.18.0] - 2023-03-30 +### Added +- Footer to all pages. [#1044](https://github.com/rokwire/rokwire-building-blocks-api/issues/1044) +- Input validation for contribute create page. [#1103](https://github.com/rokwire/rokwire-building-blocks-api/issues/1103) + +### Changed +- UI for capability view page. [#1034](https://github.com/rokwire/rokwire-building-blocks-api/issues/1034) +- Updated footer UI. [#1036](https://github.com/rokwire/rokwire-building-blocks-api/issues/1036) +- UI changes to top navigation bar. [#1040](https://github.com/rokwire/rokwire-building-blocks-api/issues/1040) +- UI for talent view page. [#1060](https://github.com/rokwire/rokwire-building-blocks-api/issues/1060) +- UI changes for contribution details page. [#1041](https://github.com/rokwire/rokwire-building-blocks-api/issues/1041) +- Catalog home page UI. [#1063](https://github.com/rokwire/rokwire-building-blocks-api/issues/1063) +- CODEOWNERS file to include CHANGELOG. [#1059](https://github.com/rokwire/rokwire-building-blocks-api/issues/1059) +- Create contribution page UI. [#1065](https://github.com/rokwire/rokwire-building-blocks-api/issues/1065) +- Review block in contribution details page. [#1066](https://github.com/rokwire/rokwire-building-blocks-api/issues/1066) +- Rearranged divs in contribute page. [#1079](https://github.com/rokwire/rokwire-building-blocks-api/issues/1079) +- Element stylings in contribute page. [#1087](https://github.com/rokwire/rokwire-building-blocks-api/issues/1087) +- Cryptography version bump for contributions. [#1089](https://github.com/rokwire/rokwire-building-blocks-api/issues/1089) +- Cryptography version bump for appconfigservice. [#1089](https://github.com/rokwire/rokwire-building-blocks-api/issues/1100) +- Catalog home page card alignment. [#1084](https://github.com/rokwire/rokwire-building-blocks-api/issues/1084) +- Updated button styles to match design. [#1085](https://github.com/rokwire/rokwire-building-blocks-api/issues/1085) +- Update werkzeug version in catalog. [#1099](https://github.com/rokwire/rokwire-building-blocks-api/issues/1099) +- Custom dropdown menu style. [#1090](https://github.com/rokwire/rokwire-building-blocks-api/issues/1090) +- Fill footer at the bottom of pages. [#1092](https://github.com/rokwire/rokwire-building-blocks-api/issues/1092) +- Contribute form field labels and placeholders. [#1102](https://github.com/rokwire/rokwire-building-blocks-api/issues/1102) +- Wordings of view pages. [#1069](https://github.com/rokwire/rokwire-building-blocks-api/issues/1069) + +### Fixed +- Detect secrets GitHub action build error and updated baseline. [#1077](https://github.com/rokwire/rokwire-building-blocks-api/issues/1077) +- Overlapping divs in catalog contribute create page. [#1054](https://github.com/rokwire/rokwire-building-blocks-api/issues/1054) + ## [1.17.0] - 2022-12-06 ### Added - Cancel button in contribution edit page. [#986](https://github.com/rokwire/rokwire-building-blocks-api/issues/986) @@ -548,6 +579,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed - References to AWS keys and variables in the Events Building Block. +[Unreleased]: https://github.com/rokwire/rokwire-building-blocks-api/compare/1.18.0...HEAD +[1.18.0]: https://github.com/rokwire/rokwire-building-blocks-api/compare/1.17.0...1.18.0 [Unreleased]: https://github.com/rokwire/rokwire-building-blocks-api/compare/1.17.0...HEAD [1.17.0]: https://github.com/rokwire/rokwire-building-blocks-api/compare/1.16.0...1.17.0 [1.16.0]: https://github.com/rokwire/rokwire-building-blocks-api/compare/1.15.0...1.16.0 diff --git a/CODEOWNERS b/CODEOWNERS index 98b8ea8e..14cae5f8 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,6 +1,9 @@ # Default assignment * @sandeep-ps +# CHANGELOG +CHANGELOG.md @minump @bingzhang @sandeep-ps + # App Config Building Block /appconfigservice/ @minump diff --git a/SECURITY.md b/SECURITY.md index 73292cab..a294f728 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,6 +6,7 @@ Patches for **Rokwire Building Blocks** in this repository will only be applied | Version | Supported | |----------| ------------------ | +| 1.18.0 | :white_check_mark: | | 1.17.0 | :white_check_mark: | | 1.16.0 | :white_check_mark: | | 1.15.0 | :white_check_mark: | diff --git a/appconfigservice/appconfig.yaml b/appconfigservice/appconfig.yaml index cd3a356d..0aec144b 100755 --- a/appconfigservice/appconfig.yaml +++ b/appconfigservice/appconfig.yaml @@ -2,7 +2,7 @@ openapi: 3.0.0 info: title: Rokwire App Config Building Block API description: App Config Building Block API Documentation - version: 1.16.0 + version: 1.18.0 servers: - url: https://api.rokwire.illinois.edu description: Production server diff --git a/appconfigservice/requirements.txt b/appconfigservice/requirements.txt index e016d14c..406eb0c6 100644 --- a/appconfigservice/requirements.txt +++ b/appconfigservice/requirements.txt @@ -5,10 +5,10 @@ pymongo[tls,srv]==3.7.2 pytest==5.0.1 requests==2.22.0 pyjwt==2.4.0 -cryptography==3.3.2 +cryptography==39.0.1 gunicorn==20.0.4 python-dotenv==0.10.3 -gevent==20.9.0 +gevent==21.12.0 diskcache==4.0.0 connexion[swagger-ui]==2.9.0 diff --git a/contributions/catalog/requirements.txt b/contributions/catalog/requirements.txt index ffd96d4c..366e4339 100644 --- a/contributions/catalog/requirements.txt +++ b/contributions/catalog/requirements.txt @@ -1,5 +1,5 @@ -Flask==1.1.1 -werkzeug==2.0.2 +Flask==2.2.3 +werkzeug==2.2.3 itsdangerous==2.0.1 Jinja2==3.0.3 pymongo==3.7.2 diff --git a/contributions/catalog/webapps/static/block-i-white-orange.png b/contributions/catalog/webapps/static/block-i-white-orange.png new file mode 100644 index 0000000000000000000000000000000000000000..cf7693863e32db99d2ed515e257adabf88830f20 GIT binary patch literal 292 zcmeAS@N?(olHy`uVBq!ia0vp^ia@N-!VDzmAK0e@q*&4&eH|GXHuiJ>Nn{1`8H<D5 zofy`glX(f`7zFr)xVjhk{J(ti|A*KAf#B}7|4k_%1{~~N|9|s>|C#Rpqf9_zp?Wnr z)wh6p`AUNPf*CHq`g-et{QWA06UR<IkZ!zR1C*)oba4#PIG<e6&L$xt$GwQbmaVP* zf8c>#jbfEW&(1_jd_OnSxQK^GVft}rmVHh&7lB|6zu?awOeYc<7|T|i5NBr7kPuzC z>%^Iv#>)@8=rqcBygA|QQs<oX{NlU2yWcyz{BwJM&z9rzjl}^X57<AlX8CzKGxIPk X|H%4MgQu|>=mrK)S3j3^P6<r_HQ0aQ literal 0 HcmV?d00001 diff --git a/contributions/catalog/webapps/static/bookshelf.jpg b/contributions/catalog/webapps/static/bookshelf.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a52defd673b0b438d4410f1d280c7b3ee793f18d GIT binary patch literal 8132 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 Q@c4mvFeArZ<o){p0k5`xW&i*H literal 0 HcmV?d00001 diff --git a/contributions/catalog/webapps/static/bookshelf@1x.jpg b/contributions/catalog/webapps/static/bookshelf@1x.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a52defd673b0b438d4410f1d280c7b3ee793f18d GIT binary patch literal 8132 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 Q@c4mvFeArZ<o){p0k5`xW&i*H literal 0 HcmV?d00001 diff --git a/contributions/catalog/webapps/static/bookshelf@2x.jpg b/contributions/catalog/webapps/static/bookshelf@2x.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f3aba2c2325945647bb805020250a965b34093e6 GIT binary patch literal 21304 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 literal 0 HcmV?d00001 diff --git a/contributions/catalog/webapps/static/bookshelf@3x.jpg b/contributions/catalog/webapps/static/bookshelf@3x.jpg new file mode 100644 index 0000000000000000000000000000000000000000..79e62b7d78a137e832e70207016dc32c59e35572 GIT binary patch literal 36070 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 literal 0 HcmV?d00001 diff --git a/contributions/catalog/webapps/static/checkbox-checked.svg b/contributions/catalog/webapps/static/checkbox-checked.svg new file mode 100644 index 00000000..e39fdfa7 --- /dev/null +++ b/contributions/catalog/webapps/static/checkbox-checked.svg @@ -0,0 +1,7 @@ +<svg width="21" height="22" viewBox="0 0 21 22" xmlns="http://www.w3.org/2000/svg"> + <g transform="translate(0 .94)" fill="none" fill-rule="evenodd"> + <ellipse stroke="#002855" stroke-width=".668" fill="#002855" cx="10.025" cy="10.036" rx="9.691" ry="9.702"/> + <rect fill="#002855" width="20.05" height="20.072" rx=".668"/> + <path stroke="#FFF" stroke-width="1.337" stroke-linecap="round" stroke-linejoin="round" d="m5.848 10.036 2.785 3.345 5.57-6.69"/> + </g> +</svg> diff --git a/contributions/catalog/webapps/static/css/style.css b/contributions/catalog/webapps/static/css/style.css index abff5451..11700664 100644 --- a/contributions/catalog/webapps/static/css/style.css +++ b/contributions/catalog/webapps/static/css/style.css @@ -1,32 +1,116 @@ -/* Add a black background color to the top navigation */ +html * { + font-family: proxima-nova,sans-serif; +} + +* { + box-sizing: border-box; +} + +/* Style the navigation bar */ .topnav { overflow: hidden; - background-color: #2a4b45; + background-color: #13294b; width: 100%; order: 1; + margin: 0 0 10px; + padding: 32px 32px 32px 32px; } - -/* Style the links inside the navigation bar */ -.topnav a { +/* Left-aligned section inside the top navigation */ +.topnav-left { + display: flex; float: left; - display: inline-block; - color: #f2f2f2; - text-align: center; - padding: 14px 16px; - text-decoration: none; - font-size: 17px; + align-items: center; +} +.topnav-left div { + flex:auto; } -/* Change the color of links on hover */ -.topnav a:hover { - background-color: #ddd; - color: #4c4c4c; +/* Right-aligned section inside the top navigation */ +.topnav-right { + display: flex; + float: right; + align-items: center; + color: #ffffff; +} +.topnav-right div { + flex:2 min-content auto; } -/* Add an active class to highlight the current page */ -.topnav a.active { - background-color: #88aeaf; - color: white; +.topnav-contribute button{ + margin-left: 10px; + outline: none; + border-radius: 24px; + color: #002855; + font-weight: bold; + border: solid 2px #e84a27; + background-color: #ffffff; +} +.topnav-contribute i{ + cursor: pointer; + color: #e84a27; +} + +.topnav-contribute:hover button{ + margin-left: 10px; + outline: none; + border-radius: 24px; + color: #fff; + font-weight: bold; + border: solid 2px #e84a27; + background-color: #e84a27; +} +.topnav-contribute:hover i{ + cursor: pointer; + color: #fff; +} + +.topnav-contribute button:active, .topnav-contribute button:focus{ + margin-left: 10px; + outline: none; + border-radius: 24px; + color: #002855; + font-weight: bold; + border: solid 2px #009fd4; + background-color: #ffffff; +} +.topnav-contribute:active i, .topnav-contribute:focus i{ + cursor: pointer; + color: #009fd4; +} + + +.topnav-login-logout-button{ + float: right; + margin: 15px 15px 5px 15px; + width:100px; + outline: none; + border-radius: 24px; + color: #002855; + font-weight: bold; + border: solid 2px #e84a27; + background-color: #ffffff; +} +.topnav-login-logout-button:hover{ + float: right; + margin: 15px 15px 5px 15px; + width:100px; + outline: none; + border-radius: 24px; + color: #fff; + font-weight: bold; + border: solid 2px #e84a27; + background-color: #e84a27; +} +.topnav-login-logout-button:active, .topnav-login-logout-button:focus{ + float: right; + margin: 15px 15px 5px 15px; + width:100px; + outline: none; + border-radius: 24px; + color: #002855; + font-weight: bold; + border: solid 2px #009fd4; + background-color: #ffffff; } /* Hide the link that should open and close the topnav on small screens */ @@ -34,75 +118,180 @@ display: none; } -/* Right-aligned section inside the top navigation */ -.topnav-right { +.user-greeting{ + font-size: 16px; + margin-top: 20px; float: right; +} + +.rokwire-footer { + width: 100%; + color: #ffffff; + text-align: center; + padding: 85px 363px 26px; + transform: rotate(-360deg); + background-color: #13294b; + clip-path: polygon(0 50%, 100% 0, 100% 100%, 0% 100%); +} + +/* home page main container */ +.main { + margin: auto; + position: relative; + max-width: 1010px; + min-height: 70%; + min-height: -webkit-calc(100vh - 176px); + min-height: -moz-calc(100vh - 176px); + min-height: calc(100vh - 176px); +} + +.row { + display: flex; + flex-wrap: wrap; + margin: 10px -16px; +} + +/* Add padding between each column in catalog home page*/ +.row, +.row > .column { + padding: 10px; +} + +/* Create three equal columns that floats next to each other */ +.column { + float: left; + width: 33.33%; /* if 5 cards in a row, put 20%. to change the width, adjust max-width in main class */ +} + +/* Clear floats after rows */ +.row:after { + content: ""; + display: table; + clear: both; +} + +label { + font-size: 16px; + font-weight: 500; + font-stretch: normal; + font-style: normal; + letter-spacing: normal; + line-height: 30px; + color: #13294b; +} + +.form-control { + height: 48px; + font-size: 16px; + padding: 10px 8px 10px; + border: 1px solid #002855; + border-radius: 0; + background-color: #fff; + color: #404040; +} + +.form-check-input { + height: 20px; + font-size: 16px; + border: 1px solid #002855; + border-radius: 0; + background-color: #fff; + color: #404040; cursor: pointer; } -* { - box-sizing: border-box; +.form-check-label{ + height: 48px; + font-size: 16px; } -input[type=text], select, textarea { - color: #090000; +select, textarea { + height: 48px; width: 100%; - padding: 12px; - border: 1px solid #ccc; - border-radius: 4px; - resize: vertical; + font-size: 16px; + padding: 12px 8px; + border: 1px solid #002855; + border-radius: 0; + background-color: #fff; + color: #404040; } -label { - padding: 12px 12px 12px 0; - display: inline-block; +input[type=text], input[type=url], select, textarea { + width: 100%; } +input[type=number]{ + width:auto; + resize: vertical; +} -input[type=submit] { - background-color: #84af9d; - color: #090000; - padding: 15px 25px; - text-align: center; - margin: 5px 5px; - transition-duration: 0.2s; - border: none; - border-radius: 4px; +input[type=date]{ + height: 34px; + width:auto; + resize: vertical; + border: 1px solid #002855; + border-radius: 0; +} +input[type=date]::-webkit-calendar-picker-indicator:hover { cursor: pointer; - float: right; + } + +input[type=text]:focus, input[type=number]:focus, input[type=date]:focus, input[type=submit]:focus, select:focus, textarea:focus, .form-check-input:focus{ + box-shadow: none; } -input[type=submit]:hover { - background-color: #45a049; - /*color: white;*/ +input[type=file]{ + height: 48px; + color: #404040; + padding: 10px 0px; + font-size: 16px; + letter-spacing: normal; + line-height: 30px; + } -input[type=reset] { - background-color: #6b9ec0; - color: #090000; - padding: 15px 25px; - text-align: center; - margin: 5px 5px; - transition-duration: 0.2s; - border: none; - border-radius: 4px; - cursor: pointer; - float: right; +input[type=checkbox]{ + vertical-align: middle; + width: 20px; + height: 20px; + display: inline-grid; + place-content: center; + position: inherit; } -input[type=reset]:hover { - background-color: #378bc4; - /*color: white;*/ +input[type=checkbox]::before { + content: ""; + width: inherit; + height: inherit; + background-image: url("../checkbox-checked.svg"); + transform: scale(0); + transform-origin: center; + transition: 20ms transform ease-in-out; } -/*input:hover {*/ -/* color: white;*/ -/*}*/ +input[type=checkbox]:checked::before { + transform: scale(1); + background-color: #20375c; +} + +input[type=checkbox]:checked:focus, input[type=checkbox]:not(:checked):focus{ + box-shadow: none; +} .container { border-radius: 5px; background-color: #ffffff; - padding: 20px; + padding: 5px; +} +.details-container{ + min-height: 70%; + min-height: -webkit-calc(100vh - 300px); + min-height: -moz-calc(100vh - 300px); + min-height: calc(100vh - 300px); +} + +.col-sm-2 { + padding-left: 1px; } .col-25 { @@ -117,13 +306,6 @@ input[type=reset]:hover { margin-top: 6px; } -/* Clear floats after the columns */ -.row:after { - content: ""; - display: table; - clear: both; -} - .key-val { -ms-flex: 0 0 83.333333%; flex: 0 0 83.333333%; @@ -139,80 +321,149 @@ input[type=reset]:hover { } .button { - background-color: #4CAF50; /* Green */ border: none; border-radius: 4px; color: white; - padding: 10px 10px; + padding: 5px 15px 5px 15px; text-align: center; display: inline-block; - font-size: 15px; + font-size: 14px; margin: 5px 5px; transition-duration: 0.2s; cursor: pointer; float: none; + height: 36px; + line-height: 20px; + font-weight: bold; } -.button1 { - background-color: white; - color: black; - border: 1px solid #4CAF50; - display: inline-block; -} - -.button1:hover { - background-color: #4CAF50; - color: white; +.button1, .button1:hover { display: inline-block; + color: #002855; + border-radius: 24px; + border: solid 2px #e84a27; + background-color: #fff; } .button2 { - background-color: white; - color: black; - border: 1px solid #008CBA; + color: #002855; display: inline-block; + border-radius: 24px; + border: solid 2px #e84a27; + background-color: #fff; + text-decoration: none; } - -.button2:hover { - background-color: #008CBA; +.button2:hover{ color: white; display: inline-block; + border-radius: 24px; + border: solid 2px #e84a27; + background-color: #e84a27; + text-decoration: none; +} +.button2:active, .button2:focus{ + color: #002855; + display: inline-block; + border-radius: 24px; + border: solid 2px #009fd4; + background-color: #fff; + text-decoration: none; } + .button3 { - background-color: white; - color: black; - border: 1px solid #f44336; + color: white; display: inline-block; + border-radius: 24px; + border: solid 2px #e84a27; + background-color: #e84a27; + text-decoration: none; } - .button3:hover { - background-color: #f44336; color: white; display: inline-block; + border-radius: 24px; + border: solid 2px #f5821e; + background-color: #f5821e; + text-decoration: none; +} +.button3:active, .button3:focus { + color: white; + display: inline-block; + border-radius: 24px; + border: solid 2px #009fd4; + background-color: #e84a27; + text-decoration: none; } .button4 { background-color: white; - color: black; - border: 1px solid #e7e7e7; + color: #002855; display: inline-block; + border-radius: 24px; + border: solid 2px #002855; + text-decoration: none; } - .button4:hover { - background-color: #e7e7e7; + background-color: #002855; + color: white; + display: inline-block; + border-radius: 24px; + border: solid 2px #002855; + text-decoration: none; +} +.button4:active, .button4:focus { + background-color: white; + color: #002855; + display: inline-block; + border-radius: 24px; + border: solid 2px #009fd4; + text-decoration: none; } .button5 { background-color: white; - color: black; - border: 1px solid #555555; + color: #002855; display: inline-block; + border: solid 2px #e84a27; + border-radius: 24px; + font-size: 14px; + line-height: 1.14; + letter-spacing: normal; + text-align: center; + padding: 5px 15px 5px 15px; } -.button5:hover { - background-color: #555555; +.button5:hover { color: white; + border: solid 2px #e84a27; + background-color: #e84a27; +} + +/* Dropdown menu style */ +.catalog-dropdown-menu { + position: relative; + border: 1px solid #002855; + border-radius: 0; +} +.catalog-dropdown-menu:hover { + border: 1px solid #dadde1; + border-radius: 0; +} +.catalog-dropdown-menu select { + /*display: none; !* hide original select element *!*/ + background-image: url("../icon-arrows-caret-down-orange.png"); + background-repeat: no-repeat; + background-position: right .7em top 50%, 0 0; + background-size: auto; + position: relative; + object-fit: contain; + -moz-appearance: none; + -webkit-appearance: none; + -webkit-border-radius: 0px; + appearance: none; + outline-width: 0; + border: none; } /* Style the buttons */ @@ -237,22 +488,26 @@ input[type=reset]:hover { #header { border: none; + margin: auto; padding: 30px; - background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url("https://images.unsplash.com/photo-1521587760476-6c12a4b040da?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80"); + max-width: 1500px; + background-image: url("../bookshelf.jpg"); + background-image: -webkit-image-set(url("../bookshelf@1x.jpg") 1x, url("../bookshelf@2x.jpg") 2x, url("../bookshelf@3x.jpg") 3x); + background-image: image-set(url("../bookshelf@1x.jpg") 1x, url("../bookshelf@2x.jpg") 2x, url("../bookshelf@3x.jpg") 3x); background-repeat: no-repeat; - height: 20%; + height: 200px; background-position: center; background-size: auto; - position: fixed; + position: relative; + object-fit: contain; } #title { text-align: center; position: relative; top: 25%; - /*left: 50%;*/ - transform: translate(-25%, -25%); color: white; + font-size: 32px; } .search { @@ -272,21 +527,21 @@ input[type=reset]:hover { } /* the card feature */ -.content { - background-color: #eaefee; - /*background: url("https://images.unsplash.com/photo-1463947628408-f8581a2f4aca?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80");*/ +.card { + position: relative; + background-color: #FFFFFF; height: 160px; - box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); - padding: 10px; + box-shadow: 0 0 4px 0 #d2d2d2; + padding: 10px 10px 10px 16px; transition-duration: 0.2s; - border: none; - border-radius: 4px; + border: solid 1px #dadde1; + border-radius: 8px; overflow-wrap: break-word; word-wrap: break-word; } -.content:hover { - box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); +.card:hover { + box-shadow: 0 0 4px 0 #d2d2d2; } .required:after { @@ -333,10 +588,8 @@ hr.dotted { /* The Close Button */ .close { - color: #aaaaaa; - float: right; - font-size: 28px; - font-weight: bold; + color: #888; + /*color: #aaaaaa;*/ } .close:hover, @@ -352,6 +605,28 @@ hr.dotted { background-color: #2a4b45; } +.catalog-home { + white-space: nowrap; + margin-left: 20px; + margin-right: 20px; + /*float: left;*/ + display: inline-block; + font-size: 32px; + font-weight: 800; + font-stretch: normal; + font-style: normal; + letter-spacing: normal; + line-height: 1.13; + color: #FFFFFF; +} + +.block-i { + margin-left: 30px; + margin-right: 10px; + margin-bottom: 10px; + align-items: center; +} + .dropdown-content { display: none; position: relative; @@ -384,6 +659,30 @@ hr.dotted { display: block; } +.link { + color: #e84a27; +} + +.contribution-link { + position: absolute; + bottom: 20px; + font-size: 16px; + font-weight: normal; + font-stretch: normal; + font-style: normal; + line-height: 1.38; + letter-spacing: normal; + text-align: left; + color: #002855; + text-decoration: underline; + text-decoration-color: #e84a27; + text-underline-offset: 5px; +} + +.contribution-link:hover, .contribution-link:active { + color: #e84a27; +} + #togglePassword { cursor: pointer; position: relative; @@ -395,16 +694,24 @@ hr.dotted { margin-left: 1%; } +.env-var-div-row{ + margin-bottom: 15px; +} + input.envvar-key[type=text] { width: 47%; display: table-cell; + margin-bottom: 5px; } input.envvar-value { width: 47%; margin-left: 1%; margin-right: 1%; + margin-bottom: 5px; display: table-cell; + resize: vertical; + } input.datadel-endpoint[type=text] { @@ -417,7 +724,97 @@ input.datadel-api { margin-left: 1%; margin-right: 1%; display: inline-block; + margin-bottom: 5px; + } .hidetext { -webkit-text-security: disc; } -.showtext { -webkit-text-security: none; } \ No newline at end of file +.showtext { -webkit-text-security: none; } + +.table-row-inputs { + display: table-cell; +} + +.checkbox-inline { + padding-top: 5px; + padding-left: 2px; + cursor: default; +} + +h1 { + font-size: 32px; + height: 36px; + font-weight: 800; + font-stretch: normal; + font-style: normal; + letter-spacing: normal; + text-align: center; + color: #13294b; +} + +h2 { + font-size: 24px; + font-weight: 800; + font-stretch: normal; + font-style: normal; + line-height: 1.17; + letter-spacing: normal; + color: #13294b; +} + +h3 { + font-size: 20px; + font-weight: 800; + font-stretch: normal; + font-style: normal; + line-height: 1.2; + letter-spacing: normal; + color: #ff552e; +} + +h4{ + font-size: 16px; + height: 20px; + font-weight: bold; + font-stretch: normal; + font-style: normal; + letter-spacing: normal; + color: #13294b; +} + +h5 { + font-size: 16px; + font-weight: normal; + font-stretch: normal; + font-style: normal; + line-height: 1.25; + letter-spacing: normal; + color: #404040; +} + +p { + /* Both of the following are required for text-overflow */ + white-space: nowrap; + overflow: hidden; +} + +.small-body-text { + font-size: 14px; + font-weight: normal; + font-stretch: normal; + font-style: normal; + letter-spacing: normal; + margin: 7px auto; + text-align: left; + color: #404040; + text-overflow: ellipsis; +} + +.capability-name, .capability-name:hover { + font-weight: bold; +} + +.talent-name, .talent-name:hover { + font-weight: bold; +} + diff --git a/contributions/catalog/webapps/static/icon-arrows-caret-down-orange.png b/contributions/catalog/webapps/static/icon-arrows-caret-down-orange.png new file mode 100644 index 0000000000000000000000000000000000000000..012cb2d24ff29b7e1d9d28a61b45c4b78ad055e1 GIT binary patch literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^JV4CG#0(_68m0>YDVB6cUq=Rpjs4tz5?O(K#^NA% zCx&(BWL^R}oB=)|t}lHw+zWhOc&RVlcEKAc$W#*K7u>+$D-c=?<SBT%IEHXsPreYf vwdr8?Rj0NEp=)^*SG!0$nL0^2$vQJ8{bx^RNO#Qxs%7wW^>bP0l+XkKs{<&j literal 0 HcmV?d00001 diff --git a/contributions/catalog/webapps/static/powered-by-rokwire-no-i-block.png b/contributions/catalog/webapps/static/powered-by-rokwire-no-i-block.png new file mode 100644 index 0000000000000000000000000000000000000000..15ed3deeefd54226bd93a8f549dcae25b1271b14 GIT binary patch literal 1383 zcmb_c`#Tc~0G%t3Z06O&t8nGgh|qR7H_BtpqHW*I`%Q(oYs>NoB@yx}c~quoc7>Y9 zmSIHAm3cMOhas;e7P%T-GUe`%xaa%MIp6u^eCMZ=jl-Z+RdiJV0Dvmm)der}d>M}^ z%gYp7N4qAoJrR!Q907pF0^m-lf-K9$;!#cj#*n^P7Tj>|1SE>&zWYBxaHWSNtJS99 zF&=;$XD04SEQtIa@qw_ac)XHYN24L)QO~{W?O55Y610mW!H4_hfv`{n0iAxW4NBm0 ze(t)Vfa92pwWhq3R_K0v3P<5~INJ4T@phm0&rq>yAAUGokO}>92g`IsqE6{D%@?Bb zhtEcB+sDIcVa38CJ6F&80^ni0n&AO-4Nq@VaR_AXmzo!pK5OigJXPs+snWpq#90NZ zmhn%|TXfztU8B3;o5o<phH&4t)JPDYqXc3R>Zjib3G?xBaK96P2YY{ChxmS<Q#Qpi zvd^EkAM$CkbgIK^tz4U*-K3Dr7I3W@@QxgsuHV!z^-Gm_59JX>C6=Bx5^mmCM1}~A zz~aJLJ{x2@G|qrl6lf%WJzl#>DrsZ4460cBhZz1zcUBN}^(z_<pMZ@e9r@4;u_>RW zRAa%1eKZwlnIl<NqKZ8m6ky4I4&24SL6|aE0OZqh)1B{2vq>QFXxhke_N;}J*zE&$ zl3HRG0}2f*)}ctrWBG!toW@YRS|jaH!KuH&!b;BDA;=7D0h??a=VRAUUe~^&B{!#- z>T8Y3m_HI{cjtWfL-d$npz-s`Ey_G)(ko|i7nm>5H;y&8bmqX-%iLBr5Jf_DMBG-z zx_{lZtV4-kQ>d6=odGC^A)yhKaf(o24~Bj(g=S=Gr%zn-UR(t}1xfPIYBNsj#r4Vb z-tm1pfo<=JOQk{HzRbCXD!Pm9(T5*(Sy32wY9uM$lx4Hr{8uzl5`M6`%cOG1o>$@l z(T)NtqT3Vgpz&?5f)4Wcw-n_PrYEBZ$H}1`=uHTi_|D)%x*N0lkD+|Ew=OE&%h<~I za?_gepP!IgUM9$AvcYC_!%*`1V)mO@?(o(m)`nYS^Uds#N}R?x>;Sdt$SM}z?7A7d z5pucv0-HV<f;WE=24nSoLfbxupKA>Ej`_7YkXhdCt&{0s(V9Un8xh_pP2=9~X`7D7 z<X>SuvV!l?K;R|}Vd$`~GkZ~{dBTiawhjDAHFD(Gy=G;TZU6p$TTBLMxTY-P!D|&? zt49&~t2Wi|NWBLbX;U#ZnjBS8<kVOj6KPJ4zBHF58MOt&id*dFEM8_M$wfGkSp;{M zM+z9WGlsKqj2iCs2TE(FwG;YLpWgVAcyVPqE7zN9J4FG4wYu#~PY;upR<CY%{g&<T z9LIyT%>@VtQgS`qP6n{m2P3k`&pY$fFCt&fAFYH6xt*ePYXh`ZQ%9~An;KZJN6Vbz zI6s?6FtL`55{3Esf<&F~s*66%{u$*9{+{6$^;=Zw9gUbU>QwdQq_B_2U!zS`S?afk zsv~1&-ex1n4W3(9aIxa(=N~zR#bWA0SxyzvL*EZ067eRONv9A?Ziw<^Bj^ttQ!h%I zc7GsoWddOG>BEbC_Vez-4$A<g4n~lLrWfRwAE*T{!dTK?`qlM?8@KT-;~n2erA6^( z*}`URb->~LFYlrn%o!M|ub@=i_!`c=86jQX8vKlf2ax%J;sl-Q&Fc<N+9^N=jG*~% zGK907D$tMf)_XBn+WM__L>^op8T`+MF>x1aM{^M?c39S$-1t)5Dd{W;MjX4TDcyY% QCVMde8i{dXIEAGB2Qx#!SpWb4 literal 0 HcmV?d00001 diff --git a/contributions/catalog/webapps/static/powered-by-rokwire-no-i-block@2x.png b/contributions/catalog/webapps/static/powered-by-rokwire-no-i-block@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..7609afd5f8432a898e4d1b1c47ef6c452a25fb5b GIT binary patch literal 2410 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 literal 0 HcmV?d00001 diff --git a/contributions/catalog/webapps/static/powered-by-rokwire-no-i-block@3x.png b/contributions/catalog/webapps/static/powered-by-rokwire-no-i-block@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..d2958cf5ed77d2a3c2892df2c64d9a3acb8a0b7c GIT binary patch literal 3517 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 XguElE$L)LiEdk6-t)OKl=x6@}+GXtH literal 0 HcmV?d00001 diff --git a/contributions/catalog/webapps/templates/base.html b/contributions/catalog/webapps/templates/base.html index 464b1d71..7bef3039 100644 --- a/contributions/catalog/webapps/templates/base.html +++ b/contributions/catalog/webapps/templates/base.html @@ -5,6 +5,7 @@ <h4>Contribution Catalog / Packager</h4> <link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet"> <link href="{{ url_for('static', filename='/css/bar.css') }}" rel="stylesheet" type="text/css"> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> +<link rel="stylesheet" href="https://use.typekit.net/qjr3liq.css"> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> <link href="../css/style.css" rel="stylesheet"> <link href="../css/bar.css" rel="stylesheet"> diff --git a/contributions/catalog/webapps/templates/contribute/capability_details.html b/contributions/catalog/webapps/templates/contribute/capability_details.html index fc8d0628..fc6dd6f5 100644 --- a/contributions/catalog/webapps/templates/contribute/capability_details.html +++ b/contributions/catalog/webapps/templates/contribute/capability_details.html @@ -3,8 +3,10 @@ <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1" name="viewport"> + <link rel="stylesheet" href="https://use.typekit.net/qjr3liq.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css"> - <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> + <link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> + <link rel="stylesheet" href="https://use.typekit.net/qjr3liq.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> <link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet" type="text/css"> @@ -15,11 +17,6 @@ <title>Capability Details</title> </head> -<style> - .hidetext { -webkit-text-security: disc; } - .showtext { -webkit-text-security: none; } -</style> - <body onload=start()> <div class="header"> @@ -30,161 +27,177 @@ <h1>Capability Details</h1> <hr class="divider"/> - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Capability Name </h4> - </div> - <p class="col-sm-9">{{post.name}}</p> - </div> - - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Capability description </h4> - </div> - <p class="col-sm-9">{{post.description}}</p> - </div> - - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Is code open source?</h4> - </div> - <p class="col-sm-9">{{post.isOpenSource}}</p> - </div> - - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Source code repository URL</h4> - </div> - <p class="col-sm-9">{{post.sourceRepoUrl}}</p> - </div> - - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Api Documentation URL</h4> - </div> - <p class="col-sm-9">{{post.apiDocUrl}}</p> - </div> - - {% if post.deploymentDetails%} - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Deployment status (Internal vs External)</h4> + <div class="container details-container"> + <!-- capability details container --> + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Capability Name </h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.name}}</div> + </div> </div> - <p class="col-sm-9">{{post.deploymentDetails.location}}</p> - </div> - {% endif %} - {% if reviewer %} - {% if post.version %} <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Version</h4> + <div class="col-12 col-md-3"> + <h4>Capability Description </h4> + </div> + <div class="col-12 col-md-9 "> + <div class="small-body-text">{{post.description}}</div> </div> - <p class="col-sm-9">{{post.version}}</p> </div> - {% endif %} - {% if post.healthCheckUrl %} + <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Health Check URL</h4> + <div class="col-12 col-md-3"> + <h4>Is Code Open Source? </h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.isOpenSource}}</div> </div> - <p class="col-sm-9">{{post.healthCheckUrl}}</p> </div> - {% endif %} - {% if post.dataDeletionEndpointDetails %} + <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Data Deletion Endpoint Details</h4> + <div class="col-12 col-md-3"> + <h4>Source Code Repository URL </h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.sourceRepoUrl}}</div> </div> - <p class="col-sm-9"> - <table> - {% if post.dataDeletionEndpointDetails.apiKey %} - <tr id="datadeletion_row"> - <td><b>Api Key </b></td> - <td class="hidetext">{{post.dataDeletionEndpointDetails.apiKey}}</td> - <td>     <i class="bi bi-eye-slash field_icon" id="toggleText" style="cursor: pointer;"></i></td> - </tr> - {% endif %} - {% if post.dataDeletionEndpointDetails.deletionEndpoint %} - <tr> - <td><b>Deletion Endpoint </b></td> - <td>{{post.dataDeletionEndpointDetails.deletionEndpoint}}</td> - </tr> - {% endif %} - {% if post.dataDeletionEndpointDetails.description %} - <tr> - <td><b>Description </b></td> - <td>{{post.dataDeletionEndpointDetails.description}}</td> - </tr> - {% endif %} - </table> - </p> </div> - {% endif %} - {% if post.deploymentDetails %} + <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Deployment Details</h4> + <div class="col-12 col-md-3"> + <h4>API Documentation URL </h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.apiDocUrl}}</div> </div> - <p class="col-sm-9"> - <table> - {% if post.deploymentDetails.authMethod %} - <tr> - <td><b>Auth Method </b></td> - <td>{{post.deploymentDetails.authMethod}}</td> - </tr> - {% endif %} - {% if post.deploymentDetails.databaseDetails %} - <tr> - <td><b>Database Details </b></td> - <td>{{post.deploymentDetails.databaseDetails}}</td> - </tr> - {% endif %} - {% if post.deploymentDetails.environmentVariables %} - <tr> - <td valign="top"><b>Environment Variables </b></td> - <td> - {% for envvar in post.deploymentDetails.environmentVariables %} - <table> - {% for key_val in envvar.items() | batch(4) %} - <tr id="envvar_row"> - {% for item in key_val %} - {% if loop.index %2 == 0 %} - <td style="padding:0 5px 0 15px;">{{item[0]}}: </td> - <td class="hidetext">{{item[1]}}</td> - <td>     <i class="bi bi-eye-slash field_icon" id="toggleText" style="cursor: pointer;"></i></td> - {% else %} - <td style="padding:0 5px 0 5px;">{{item[0]}}: </td> - <td>{{item[1]}}</td> - {% endif %} - {% endfor %} - </tr> - {% endfor %} - </table> - {% endfor %} - </td> - </tr> - {% endif %} - {% if post.deploymentDetails.location %} - <tr> - <td><b>Location </b></td> - <td>{{post.deploymentDetails.location}}</td> - </tr> - {% endif %} - </table> - </p> </div> - {% endif %} - {% endif %} - <button class="button button3" onclick="get_url()">View Contribution</button> -</div> + {% if post.deploymentDetails%} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Deployment Location </h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.deploymentDetails.location}}</div> + </div> + </div> + {% endif %} + {% if reviewer %} + {% if post.version %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Version </h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.version}}</div> + </div> + </div> + {% endif %} + {% if post.healthCheckUrl %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Health Check URL </h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.healthCheckUrl}}</div> + </div> + </div> + {% endif %} + {% if post.dataDeletionEndpointDetails %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Data Deletion Endpoint Details </h4> + </div> + <div class="col-12 col-md-9"> + <table> + {% if post.dataDeletionEndpointDetails.apiKey %} + <tr id="datadeletion_row"> + <td><b>API Key </b></td> + <td class="hidetext">{{post.dataDeletionEndpointDetails.apiKey}}</td> + <td>     <i class="bi bi-eye-slash field_icon" id="toggleText" style="cursor: pointer;"></i></td> + </tr> + {% endif %} + {% if post.dataDeletionEndpointDetails.deletionEndpoint %} + <tr> + <td><b>Deletion Endpoint </b></td> + <td>{{post.dataDeletionEndpointDetails.deletionEndpoint}}</td> + </tr> + {% endif %} + {% if post.dataDeletionEndpointDetails.description %} + <tr> + <td><b>Description </b></td> + <td>{{post.dataDeletionEndpointDetails.description}}</td> + </tr> + {% endif %} + </table> + </div> + </div> + {% endif %} + {% if post.deploymentDetails %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Deployment Details </h4> + </div> + <div class="col-12 col-md-9"> + <table> + {% if post.deploymentDetails.authMethod %} + <tr> + <td><b>Auth Method </b></td> + <td>{{post.deploymentDetails.authMethod}}</td> + </tr> + {% endif %} + {% if post.deploymentDetails.databaseDetails %} + <tr> + <td><b>Database Details </b></td> + <td>{{post.deploymentDetails.databaseDetails}}</td> + </tr> + {% endif %} + {% if post.deploymentDetails.environmentVariables %} + <tr> + <td valign="top"><b>Environment Variables </b></td> + <td> + {% for envvar in post.deploymentDetails.environmentVariables %} + <table> + {% for key_val in envvar.items() | batch(4) %} + <tr id="envvar_row"> + {% for item in key_val %} + {% if loop.index %2 == 0 %} + <td style="padding:0 5px 0 15px;">{{item[0]}}: </td> + <td class="hidetext">{{item[1]}}</td> + <td>     <i class="bi bi-eye-slash field_icon" id="toggleText" style="cursor: pointer;"></i></td> + {% else %} + <td style="padding:0 5px 0 5px;">{{item[0]}}: </td> + <td>{{item[1]}}</td> + {% endif %} + {% endfor %} + </tr> + {% endfor %} + </table> + {% endfor %} + </td> + </tr> + {% endif %} + {% if post.deploymentDetails.location %} + <tr> + <td><b>Location </b></td> + <td>{{post.deploymentDetails.location}}</td> + </tr> + {% endif %} + </table> + </div> + </div> + {% endif %} + {% endif %} + </div> -<div class="action"> + <button class="button button2" onclick="get_url()">View Contribution</button> </div> +{% include 'footer.html' %} {% include 'topnav_javascript.html' %} <script> diff --git a/contributions/catalog/webapps/templates/contribute/contribute.html b/contributions/catalog/webapps/templates/contribute/contribute.html index 71a1681c..1132d885 100644 --- a/contributions/catalog/webapps/templates/contribute/contribute.html +++ b/contributions/catalog/webapps/templates/contribute/contribute.html @@ -4,6 +4,7 @@ <title> Capability Catalog </title> <meta charset="utf-8"> <meta content="width=device-width, initial-scale=1" name="viewport"> + <link rel="stylesheet" href="https://use.typekit.net/qjr3liq.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css"> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> @@ -75,24 +76,22 @@ <nav> <ol class="cd-multi-steps text-top"> <li class="current"><a href="#contribute">Contribution Details</a></li> - <li><em><a href="#capability-parent">Capability and/or Talent Details </a></em></li> - <li><em><a href="#contact">Contact & Self-certification</a></em></li> - <li><em>Submit</em></li> + <li><em><a href="#capability-parent">Capability / Talent Details </a></em></li> + <li><em><a href="#contact">Contact Details</a></em></li> + <li><em><a href="#submit">Submit</a></em></li> </ol> </nav> </div> <form enctype=multipart/form-data class="form-horizontal" method="POST" onsubmit="return data_validation()"> - <div> - <!-- not currently used --> - {% for member in teammembers %} - {{ member['name'] }} - {% endfor %} - </div> <div class="container"> <h2 id="contribute">Contribution Details</h2> - + <div class="form-group"> + <div> + <input id="contribution_details" name="contribution_details" type="hidden" value="contribution"> + </div> + </div> {% if is_editable %} <input class="form-control" type="hidden" name="contribution_id" value={{ post.id }} > {% endif %} @@ -108,7 +107,6 @@ <h2 id="contribute">Contribution Details</h2> <input class="form-control" id="contribution_name" name="contribution_name" placeholder="Give a name for your contribution" type="text"> {% endif %} - <p class="error_message"></p> </div> </div> <div class="form-group"> @@ -144,360 +142,362 @@ <h2 id="contribute">Contribution Details</h2> {% if is_editable %} <input class="form-control" id="contribution_Admins" name="contribution_contributionAdmins" - placeholder="Give a list of admin names, separated by comma" - type="text" value="{{ post.contributionAdmins|join(', ') }}"></div> + placeholder="Give a list of GitHub usernames, separated by comma, to be selected as admins of this contribution" + type="text" value="{{ post.contributionAdmins|join(', ') }}"> {% else %} <input class="form-control" id="contribution_Admins" name="contribution_contributionAdmins" - placeholder="Give a list of admin names, separated by comma" - type="text"></div> + placeholder="Give a list of GitHub usernames, separated by comma, to be selected as admins of this contribution" + type="text"> {% endif %} - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Contributor Details</label> - <!-- <label class="radio-inline"><input type="radio" name="optradio" onclick="show_person()"> Person</label>--> - <!-- <label class="radio-inline"><input type="radio" name="optradio" onclick="show_org()"checked> Organization</label>--> - <div> - <button class="button button1" id="add-contributor-person">Add Person</button> - <button class="button button2" id="add-contributor-org">Add Organization</button> + </div> </div> - <!-- <div>--> - <!-- <button class="button button2" id="add-contributor-org">Add Contributor as Organization</button>--> - <!-- </div>--> - </div> + + <div class="form-group"> + <label class="control-label col-sm-2">Contributor Details</label> + <div class="col-sm-10"> + <button class="button button2" id="add-contributor-person">Add Person</button> + <button class="button button2" id="add-contributor-org">Add Organization</button> + </div> + </div> + </div> {# end of contribution-details container div #} <!-------------- contributor block parent --------------------------> - <div id="contributor-parent"> - <!-------------------- organization block clean --------------------> - <div id="organization-clean" style="display: none"> - <hr class="dotted"> - <h3 id="capability">Add an Organization to this Contribution</h3> - <div class="form-group"> - <label class="control-label col-sm-2">Organization Name</label> - <div class="col-sm-10"> - <input class="form-control" id="org_name" name="org_name" placeholder="" type="text"> + <div class="container"> + <div id="contributor-parent"> + <!-------------------- organization block clean --------------------> + <div id="organization-clean" style="display: none"> + <hr class="dotted"> + <h3 id="capability">Add an Organization to this Contribution</h3> + <div class="form-group"> + <div> + <input id="contributor_type" name="contributor_type" type="hidden" value="organization"> + </div> </div> - </div> - <div class="form-group"> - <div> - <input id="contributor_type" name="contributor_type" type="hidden" value="organization"> + <div class="form-group"> + <label class="control-label col-sm-2">Name</label> + <div class="col-sm-10"> + <input class="form-control" id="org_name" name="org_name" placeholder="Organization name" type="text"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Organization Address</label> - <div class="col-sm-10"> - <input class="form-control" id="org_address" name="org_address" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">Address</label> + <div class="col-sm-10"> + <input class="form-control" id="org_address" name="org_address" placeholder="Organization address" type="text"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Organization Email</label> - <div class="col-sm-10"> - <input class="form-control" id="org_email" name="org_email" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">Email</label> + <div class="col-sm-10"> + <input class="form-control" id="org_email" name="org_email" placeholder="Organization email" type="email"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Organization Phone</label> - <div class="col-sm-10"> - <input class="form-control" id="org_phone" name="org_phone" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">Phone</label> + <div class="col-sm-10"> + <input class="form-control" id="org_phone" name="org_phone" placeholder="Organization phone number (9 to 14 digits)" type="tel" minlength="9" maxlength="14"> + </div> </div> - </div> - </div> + </div> <!--- end of organization block clean --> - <!-------------------- person block clean --------------------> - <div id="person-clean" style="display: none"> - <hr class="dotted"> - <h3 id="capability">Add a Person to this Contribution</h3> - <div class="form-group"> - <div> - <input id="contributor_type" name="contributor_type" type="hidden" value="person"> + <!-------------------- person block clean --------------------> + <div id="person-clean" style="display: none"> + <hr class="dotted"> + <h3 id="capability">Add a Person to this Contribution</h3> + <div class="form-group"> + <div> + <input id="contributor_type" name="contributor_type" type="hidden" value="person"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Contributor's first name</label> - <div class="col-sm-10"> - <input class="form-control" id="contributor_fname" name="person_firstName" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">First Name</label> + <div class="col-sm-10"> + <input class="form-control" id="contributor_fname" name="person_firstName" placeholder="Person's first name" type="text"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Contributor's middle name</label> - <div class="col-sm-10"> - <input class="form-control" id="contributor_mname" name="person_middleName" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">Middle Name</label> + <div class="col-sm-10"> + <input class="form-control" id="contributor_mname" name="person_middleName" placeholder="Person's middle name" type="text"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Contributor's last name</label> - <div class="col-sm-10"> - <input class="form-control" id="contributor_lname" name="person_lastName" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">Last Name</label> + <div class="col-sm-10"> + <input class="form-control" id="contributor_lname" name="person_lastName" placeholder="Person's last name" type="text"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Contributor Email</label> - <div class="col-sm-10"> - <input class="form-control" name="person_email" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">Email</label> + <div class="col-sm-10"> + <input class="form-control" name="person_email" placeholder="Person's email address" type="email"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Contributor Phone</label> - <div class="col-sm-10"> - <input class="form-control" name="person_phone" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">Phone Number</label> + <div class="col-sm-10"> + <input class="form-control" name="person_phone" placeholder="Person's phone number (9 to 14 digits)" type="tel" minlength="9" maxlength="14"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Affiliation Name</label> - <div class="col-sm-10"> - <input class="form-control" name="affiliation_name" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">Affiliation Name</label> + <div class="col-sm-10"> + <input class="form-control" name="affiliation_name" placeholder="" type="text"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Affiliation Address</label> - <div class="col-sm-10"> - <input class="form-control" name="affiliation_address" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">Affiliation Address</label> + <div class="col-sm-10"> + <input class="form-control" name="affiliation_address" placeholder="" type="text"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Affiliation Email</label> - <div class="col-sm-10"> - <input class="form-control" name="affiliation_email" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">Affiliation Email</label> + <div class="col-sm-10"> + <input class="form-control" name="affiliation_email" placeholder="" type="email"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Affiliation Phone</label> - <div class="col-sm-10"> - <input class="form-control" name="affiliation_phone" placeholder="" type="text"> + <div class="form-group"> + <label class="control-label col-sm-2">Affiliation Phone</label> + <div class="col-sm-10"> + <input class="form-control" name="affiliation_phone" placeholder="Phone number (9 to 14 digits)" type="tel" minlength="9" maxlength="14"> + </div> </div> - </div> - </div> - - {% if post.contributors %} - {% for contributor in post.contributors %} - {% if contributor["contributorType"] == 'organization' %} - <!-------------------- organization block existing records --------------------> - <div id="organization-existing-records" style="display: block"> - <hr class="dotted"> - <h3 id="capability">Add an Organization to this Contribution</h3> - <div class="form-group"> - <div> - <input id="contributor_type_{{loop.index0}}" - name="contributor_type_{{loop.index0}}" - type="hidden" value="organization"> + </div> <!-- end of person block clean --> + + {% if post.contributors %} + {% for contributor in post.contributors %} + {% if contributor["contributorType"] == 'organization' %} + <!-------------------- organization block existing records --------------------> + <div id="organization-existing-records" style="display: block"> + <hr class="dotted"> + <h3 id="capability">Add an Organization to this Contribution</h3> + <div class="form-group"> + <div> + <input id="contributor_type_{{loop.index0}}" + name="contributor_type_{{loop.index0}}" + type="hidden" value="organization"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Organization Name</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" id="org_name_{{loop.index0}}" - name="org_name_{{loop.index0}}" placeholder="" - type="text" value="{{ contributor|filter_nested_dict(["name"]) }}"> - {% else %} - <input class="form-control" id="org_name_{{loop.index0}}" - name="org_name_{{loop.index0}}" placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Name</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" id="org_name_{{loop.index0}}" + name="org_name_{{loop.index0}}" placeholder="Organization name" + type="text" value="{{ contributor|filter_nested_dict(["name"]) }}"> + {% else %} + <input class="form-control" id="org_name_{{loop.index0}}" + name="org_name_{{loop.index0}}" placeholder="Organization name" type="text"> + {% endif %} + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Organization Address</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" id="org_address_{{loop.index0}}" - name="org_address_{{loop.index0}}" placeholder="" - type="text" value="{{ contributor|filter_nested_dict(["address"]) }}"> - {% else %} - <input class="form-control" id="org_address_{{loop.index0}}" - name="org_address_{{loop.index0}}" placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Address</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" id="org_address_{{loop.index0}}" + name="org_address_{{loop.index0}}" placeholder="" + type="text" value="{{ contributor|filter_nested_dict(["address"]) }}"> + {% else %} + <input class="form-control" id="org_address_{{loop.index0}}" + name="org_address_{{loop.index0}}" placeholder="" type="text"> + {% endif %} + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Organization Email</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" id="org_email_{{loop.index0}}" - name="org_email_{{loop.index0}}" placeholder="" - type="text" value="{{ contributor|filter_nested_dict(["email"]) }}"> - {% else %} - <input class="form-control" id="org_email_{{loop.index0}}" - name="org_email_{{loop.index0}}" placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Email</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" id="org_email_{{loop.index0}}" + name="org_email_{{loop.index0}}" placeholder="" + type="email" value="{{ contributor|filter_nested_dict(["email"]) }}"> + {% else %} + <input class="form-control" id="org_email_{{loop.index0}}" + name="org_email_{{loop.index0}}" placeholder="" type="email"> + {% endif %} + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Organization Phone</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" id="org_phone_{{loop.index0}}" - name="org_phone_{{loop.index0}}" placeholder="" - type="text" value="{{ contributor|filter_nested_dict(["phone"]) }}"> - {% else %} - <input class="form-control" id="org_phone_{{loop.index0}}" - name="org_phone_{{loop.index0}}" placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Phone</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" id="org_phone_{{loop.index0}}" + name="org_phone_{{loop.index0}}" placeholder="Organization phone number (9 to 14 digits)" + type="tel" value="{{ contributor|filter_nested_dict(["phone"]) }}" minlength="9" maxlength="14"> + {% else %} + <input class="form-control" id="org_phone_{{loop.index0}}" + name="org_phone_{{loop.index0}}" placeholder="Organization phone number (9 to 14 digits)" type="tel" minlength="9" maxlength="14"> + {% endif %} + </div> </div> - </div> - </div> - {% endif %} - {% if contributor["contributorType"] == 'person' %} - <!-------------------- person block existing records --------------------> - <div id="person-existing-records" style="display: block"> - <hr class="dotted"> - <h3 id="capability">Add a Person to this Contribution</h3> - <div class="form-group"> - <div> - <input id="contributor_type_{{loop.index0}}" - name="contributor_type_{{loop.index0}}" type="hidden" value="person"> + </div> <!-- end of organization existing records --> + {% endif %} + {% if contributor["contributorType"] == 'person' %} + <!-------------------- person block existing records --------------------> + <div id="person-existing-records" style="display: block"> + <hr class="dotted"> + <h3 id="capability">Add a Person to this Contribution</h3> + <div class="form-group"> + <div> + <input id="contributor_type_{{loop.index0}}" + name="contributor_type_{{loop.index0}}" type="hidden" value="person"> + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Contributor's first name</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" id="contributor_fname_{{loop.index0}}" - name="person_firstName_{{loop.index0}}" placeholder="" - type="text" value="{{ contributor | filter_nested_dict(["firstName"]) }}"> - {% else %} - <input class="form-control" id="contributor_fname_{{loop.index0}}" - name="person_firstName_{{loop.index0}}" placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">First Name</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" id="contributor_fname_{{loop.index0}}" + name="person_firstName_{{loop.index0}}" placeholder="Person's first name" + type="text" value="{{ contributor | filter_nested_dict(["firstName"]) }}"> + {% else %} + <input class="form-control" id="contributor_fname_{{loop.index0}}" + name="person_firstName_{{loop.index0}}" placeholder="Person's first name" type="text"> + {% endif %} + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Contributor's middle name</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" id="contributor_mname_{{loop.index0}}" - name="person_middleName_{{loop.index0}}" placeholder="" - type="text" value="{{ contributor | filter_nested_dict(["middleName"]) }}"> - {% else %} - <input class="form-control" id="contributor_mname_{{loop.index0}}" - name="person_middleName_{{loop.index0}}" placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Middle Name</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" id="contributor_mname_{{loop.index0}}" + name="person_middleName_{{loop.index0}}" placeholder="Person's middle name" + type="text" value="{{ contributor | filter_nested_dict(["middleName"]) }}"> + {% else %} + <input class="form-control" id="contributor_mname_{{loop.index0}}" + name="person_middleName_{{loop.index0}}" placeholder="Person's middle name" type="text"> + {% endif %} + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Contributor's last name</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" id="contributor_lname_{{loop.index0}}" - name="person_lastName_{{loop.index0}}" placeholder="" - type="text" value="{{ contributor | filter_nested_dict(["lastName"]) }}"> - {% else %} - <input class="form-control" id="contributor_lname_{{loop.index0}}" - name="person_lastName_{{loop.index0}}" placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Last Name</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" id="contributor_lname_{{loop.index0}}" + name="person_lastName_{{loop.index0}}" placeholder="Person's last name" + type="text" value="{{ contributor | filter_nested_dict(["lastName"]) }}"> + {% else %} + <input class="form-control" id="contributor_lname_{{loop.index0}}" + name="person_lastName_{{loop.index0}}" placeholder="Person's last name" type="text"> + {% endif %} + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Contributor Email</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" name="person_email_{{loop.index0}}" - id="person_email_{{loop.index0}}" placeholder="" - type="text" value="{{ contributor| filter_nested_dict(["email"]) }}"> - {% else %} - <input class="form-control" name="person_email_{{loop.index0}}" - id="person_email_{{loop.index0}}" placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Email</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" name="person_email_{{loop.index0}}" + id="person_email_{{loop.index0}}" placeholder="Person's email" + type="email" value="{{ contributor| filter_nested_dict(["email"]) }}"> + {% else %} + <input class="form-control" name="person_email_{{loop.index0}}" + id="person_email_{{loop.index0}}" placeholder="Person's email" type="email"> + {% endif %} + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Contributor Phone</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" name="person_phone_{{loop.index0}}" - id="person_phone_{{loop.index0}}" placeholder="" - type="text" value="{{ contributor | filter_nested_dict(["phone"]) }}"> - {% else %} - <input class="form-control" name="person_phone_{{loop.index0}}" - id="person_phone_{{loop.index0}}" placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Phone Number</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" name="person_phone_{{loop.index0}}" + id="person_phone_{{loop.index0}}" placeholder="Person's phone number (9 to 14 digits)" + type="tel" value="{{ contributor | filter_nested_dict(["phone"]) }}" minlength="9" maxlength="14"> + {% else %} + <input class="form-control" name="person_phone_{{loop.index0}}" + id="person_phone_{{loop.index0}}" placeholder="Person's phone number (9 to 14 digits)" type="tel" minlength="9" maxlength="14"> + {% endif %} + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Affiliation Name</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" name="affiliation_name_{{loop.index0}}" - id="affiliation_name_{{loop.index0}}" placeholder="" - type="text" value="{{ contributor | filter_nested_dict(["affiliation", "name"]) }}"> - {% else %} - <input class="form-control" name="affiliation_name_{{loop.index0}}" - id="affiliation_name_{{loop.index0}}" placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Affiliation Name</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" name="affiliation_name_{{loop.index0}}" + id="affiliation_name_{{loop.index0}}" placeholder="" + type="text" value="{{ contributor | filter_nested_dict(["affiliation", "name"]) }}"> + {% else %} + <input class="form-control" name="affiliation_name_{{loop.index0}}" + id="affiliation_name_{{loop.index0}}" placeholder="" type="text"> + {% endif %} + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Affiliation Address</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" name="affiliation_address_{{loop.index0}}" - id="affilication_address_{{loop.index0}}" - placeholder="" type="text" - value="{{ contributor | filter_nested_dict(["affiliation", "address"]) }}"> - {% else %} - <input class="form-control" name="affiliation_address_{{loop.index0}}" - id="affiliation_address_{{loop.index0}}" - placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Affiliation Address</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" name="affiliation_address_{{loop.index0}}" + id="affilication_address_{{loop.index0}}" + placeholder="" type="text" + value="{{ contributor | filter_nested_dict(["affiliation", "address"]) }}"> + {% else %} + <input class="form-control" name="affiliation_address_{{loop.index0}}" + id="affiliation_address_{{loop.index0}}" + placeholder="" type="text"> + {% endif %} + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Affiliation Email</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" name="affiliation_email_{{loop.index0}}" - id="affiliation_email_{{loop.index0}}" placeholder="" - type="text" value="{{ contributor | filter_nested_dict(["affiliation", "email"]) }}"> - {% else %} - <input class="form-control" name="affiliation_email_{{loop.index0}}" - id="affiliation_email_{{loop.index0}}" placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Affiliation Email</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" name="affiliation_email_{{loop.index0}}" + id="affiliation_email_{{loop.index0}}" placeholder="" + type="email" value="{{ contributor | filter_nested_dict(["affiliation", "email"]) }}"> + {% else %} + <input class="form-control" name="affiliation_email_{{loop.index0}}" + id="affiliation_email_{{loop.index0}}" placeholder="" type="email"> + {% endif %} + </div> </div> - </div> - <div class="form-group"> - <label class="control-label col-sm-2">Affiliation Phone</label> - <div class="col-sm-10"> - {% if is_editable %} - <input class="form-control" name="affiliation_phone_{{loop.index0}}" - id="affiliation_phone_{{loop.index0}}" - placeholder="" type="text" - value="{{ contributor | filter_nested_dict(["affiliation", "phone"]) }}"> - {% else %} - <input class="form-control" name="affiliation_phone_{{loop.index0}}" - id="affiliation_phone_{{loop.index0}}" - placeholder="" type="text"> - {% endif %} + <div class="form-group"> + <label class="control-label col-sm-2">Affiliation Phone</label> + <div class="col-sm-10"> + {% if is_editable %} + <input class="form-control" name="affiliation_phone_{{loop.index0}}" + id="affiliation_phone_{{loop.index0}}" + placeholder="Phone number (9 to 14 digits)" type="tel" minlength="9" maxlength="14" + value="{{ contributor | filter_nested_dict(["affiliation", "phone"]) }}"> + {% else %} + <input class="form-control" name="affiliation_phone_{{loop.index0}}" + id="affiliation_phone_{{loop.index0}}" + placeholder="Phone number (9 to 14 digits)" type="tel" minlength="9" maxlength="14"> + {% endif %} + </div> </div> - </div> - </div> - {% endif %} - <script>contributor_count++;</script> - {% endfor %} - {% endif %} - </div> + </div> <!-- end of person existing records --> + {% endif %} + <script>contributor_count++;</script> + {% endfor %} + {% endif %} + </div> {# end of contributor block parent div #} + </div> {# end of contributor block parent container div #} - <div id="cd-multi-steps-text-top"> + <div class="container" id="cd-multi-steps-text-top"> <nav> <ol class="cd-multi-steps text-top"> <li class="visited"><em><a href="#contribute">Contribution Details</a></em></li> - <li class="current"><em><a href="#capability-parent">Capability and/or Talent Details </a></em> - </li> - <li><em><a href="#contact">Contact & Self-certification</a></em></li> - <li><em>Submit</em></li> + <li class="current"><em><a href="#capability-parent">Capability / Talent Details </a></em></li> + <li><em><a href="#contact">Contact Details</a></em></li> + <li><em><a href="#submit">Submit</a></em></li> </ol> </nav> </div> - <div class="form-group" id="select-contribution-div"> - <label class="required control-label col-sm-2" id="select-contribution">Select the Contribution Type</label> - <div id="select-contribution-button"> - <button class="button button2" id="add-capability" onclick="AddCapability(event); MoveSelector(event);">Add a Capability</button> - OR - <button class="button button1" id="add-talent" onclick="AddTalent(event); MoveSelector(event);">Add a Talent</button> + <div class="container"> + <div class="form-group" id="select-contribution-div"> + <label class="required control-label col-sm-2" id="select-contribution">Select the Contribution Type</label> + <div class="col-sm-10" id="select-contribution-button"> + <button class="button button2" id="add-capability" onclick="AddCapability(event); MoveSelector(event);">Add a Capability</button> + OR + <button class="button button2" id="add-talent" onclick="AddTalent(event); MoveSelector(event);">Add a Talent</button> + </div> </div> - </div> + </div> {# end of select-contribution-div container div #} <!-----------------------------------------capability block ------------------------------------> - <div id="capability-parent" style="display: block; background-color:white"> + <div class="container"> + <div id="capability-parent" style="display: block; background-color:white"> <!--------------------------- capability clean block ---------------------------------> <div id="capability-div-clean" style="display: none; background-color:white"> @@ -522,22 +522,27 @@ <h3 id="capability">Add a Capability to this Contribution</h3> </div> <div class="form-group"> - <label class="control-label col-sm-2" for="capability_icon">Upload an ICON for - capability</label> - <input accept="image/*" id="capability_icon" name="capability_icon" type="file"> + <label class="control-label col-sm-2" for="capability_icon">Upload an Icon</label> + <div class="col-sm-10"> + <input accept="image/*" id="capability_icon" name="capability_icon" type="file"> + </div> </div> <div class="form-group" id="open-source-check-div"> - <label class="required control-label col-sm-2"> Is the Code Open Sourced? </label> - <!-- open source yes no block --> - <label class="form-check-label"> - <input class="form-check-input" id="open_source_yes" - name="capability_isOpenSource" type="radio" value="y"> - yes</label> - <label class="form-check-label"> - <input class="form-check-input" id="open_source_no" - name="capability_isOpenSource" type="radio" value="n"> - no</label> + <label class="required control-label col-sm-2"> Is Code Open Sourced? </label> + <div class="col-sm-10"> + <!-- open source yes no block --> + <label class="form-check-label radio-inline"> + <input class="form-check-input" id="open_source_yes" + name="capability_isOpenSource" type="radio" value="y"> + Yes + </label> + <label class="form-check-label radio-inline"> + <input class="form-check-input" id="open_source_no" + name="capability_isOpenSource" type="radio" value="n"> + No + </label> + </div> </div> <div class="form-group" id="sourceurl"> @@ -551,20 +556,24 @@ <h3 id="capability">Add a Capability to this Contribution</h3> <label class="control-label col-sm-2">API Doc URL</label> <div class="col-sm-10"> <input class="form-control" id="api_url" name="capability_apiDocUrl" - placeholder="API documentation URL" type="text"> + placeholder="API documentation URL" type="url"> </div> </div> <div class="form-group"> <label class="required control-label col-sm-2">Deployment location</label> - <label class="form-check-label"> - <input class="form-check-input" id="deploy_internal" name="deploymentDetails_location" - type="radio" value="internal"> internal - </label> - <label class="form-check-label"> - <input class="form-check-input" id="deploy_external" - name="deploymentDetails_location" type="radio" - value="external"> external - </label> + <div class="col-sm-10"> + <label class="form-check-label radio-inline"> + <input class="form-check-input" id="deploy_internal" name="deploymentDetails_location" + type="radio" value="internal"> + Internal + </label> + <label class="form-check-label radio-inline"> + <input class="form-check-input" id="deploy_external" + name="deploymentDetails_location" type="radio" + value="external"> + External + </label> + </div> </div> <div class="form-group"> @@ -595,15 +604,20 @@ <h3 id="capability">Add a Capability to this Contribution</h3> <i class="bi bi-x-lg" id="env-var-close-btn"></i> </div> </div> - <div id="add-env-var-button-div" class="row"> - <!-- place holder for dynamic button for add environment variables" --> + <div id="add-env-var-div" class="row env-var-div-row"> + <div class="col-sm-2"> + <!-- empty column" --> + </div> + <div class="col-sm-10" id="add-env-var-button-div"> + <!-- place holder for dynamic button for add environment variables" --> + </div> </div> <div class="form-group"> <label class="required control-label col-sm-2">Database Detail</label> <div class="col-sm-10"> <input class="form-control" id="db-detail" name="deploymentDetails_databaseDetails" - placeholder="Details of API endpoint to delete user info given the user UUID" + placeholder="Provide the name, version, and other details of the database server used." type="text"> </div> </div> @@ -611,7 +625,7 @@ <h3 id="capability">Add a Capability to this Contribution</h3> <label class="required control-label col-sm-2">Version</label> <div class="col-sm-10"> <input class="form-control" id="version" name="capability_version" - placeholder="latest version number" + placeholder="Latest Capability version number" type="text"> </div> </div> @@ -620,7 +634,7 @@ <h3 id="capability">Add a Capability to this Contribution</h3> <div class="col-sm-10"> <input class="form-control" id="version_url" name="capability_versionUrl" placeholder="" - type="text"> + type="url"> </div> </div> @@ -628,7 +642,7 @@ <h3 id="capability">Add a Capability to this Contribution</h3> <label class="required control-label col-sm-2">Health Check URL</label> <div class="col-sm-10"> <input class="form-control" id="health" name="capability_healthCheckUrl" - placeholder="health check url" type="text"> + placeholder="Add a health check URL to check the Capability status continuously." type="url"> </div> </div> @@ -696,52 +710,62 @@ <h3 id="capability_{{loop.index0}}">Capability - {{ capability | filter_nested_d </div> </div> <div class="form-group"> - <label class="control-label col-sm-2" for="capability_icon">Upload an ICON for capability</label> - <input accept="image/*" id="capability_icon_{{loop.index0}}" - name="capability_icon_{{loop.index0}}" type="file"> + <label class="control-label col-sm-2" for="capability_icon">Upload an Icon</label> + <div class="col-sm-10"> + <input accept="image/*" id="capability_icon_{{loop.index0}}" + name="capability_icon_{{loop.index0}}" type="file"> + </div> </div> <div class="form-group" id="open-source-check-div"> - <label class="required control-label col-sm-2">Is the Code Open Sourced? </label> - <!-- open source yes no block --> - {% if is_editable %} - {% if capability | filter_nested_dict(["isOpenSource"]) == True %} - <label class="form-check-label"> - <input class="form-check-input" id="open_source_yes_{{loop.index0}}" - name="capability_isOpenSource_{{loop.index0}}" type="radio" - checked="checked" value="y"> - yes</label> + <label class="required control-label col-sm-2">Is Code Open Sourced? </label> + <div class="col-sm-10"> + <!-- open source yes no block --> + {% if is_editable %} + {% if capability | filter_nested_dict(["isOpenSource"]) == True %} + <label class="form-check-label radio-inline"> + <input class="form-check-input" id="open_source_yes_{{loop.index0}}" + name="capability_isOpenSource_{{loop.index0}}" type="radio" + checked="checked" value="y"> + Yes + </label> + {% else %} + <label class="form-check-label radio-inline"> + <input class="form-check-input" id="open_source_yes_{{loop.index0}}" + name="capability_isOpenSource_{{loop.index0}}" + type="radio" value="y"> + Yes + </label> + {% endif %} + {% if capability | filter_nested_dict(["isOpenSource"]) == False %} + <label class="form-check-label radio-inline"> + <input class="form-check-input" id="open_source_no_{{loop.index0}}" + name="capability_isOpenSource_{{loop.index0}}" + type="radio" checked="checked" value="n"> + No + </label> + {% else %} + <label class="form-check-label radio-inline"> + <input class="form-check-input" id="open_source_no_{{loop.index0}}" + name="capability_isOpenSource_{{loop.index0}}" + type="radio" value="n"> + No + </label> + {% endif %} {% else %} - <label class="form-check-label"> + <label class="form-check-label radio-inline"> <input class="form-check-input" id="open_source_yes_{{loop.index0}}" - name="capability_isOpenSource_{{loop.index0}}" - type="radio" value="y"> - yes</label> - {% endif %} - {% if capability | filter_nested_dict(["isOpenSource"]) == False %} - <label class="form-check-label"> - <input class="form-check-input" id="open_source_no_{{loop.index0}}" name="capability_isOpenSource_{{loop.index0}}" - type="radio" checked="checked" value="n"> - no</label> - {% else %} - <label class="form-check-label"> + type="radio" value="y"> + Yes + </label> + <label class="form-check-label radio-inline"> <input class="form-check-input" id="open_source_no_{{loop.index0}}" name="capability_isOpenSource_{{loop.index0}}" type="radio" value="n"> - no</label> - {% endif %} - {% else %} - <label class="form-check-label"> - <input class="form-check-input" id="open_source_yes_{{loop.index0}}" - name="capability_isOpenSource_{{loop.index0}}" - type="radio" value="y"> - yes</label> - <label class="form-check-label"> - <input class="form-check-input" id="open_source_no_{{loop.index0}}" - name="capability_isOpenSource_{{loop.index0}}" - type="radio" value="n"> - no</label> - {% endif %} + No + </label> + {% endif %} + </div> </div> <!-- end of open source yes no check div --> <!-- display opensource url if yes --> {% if is_editable %} @@ -804,51 +828,53 @@ <h3 id="capability_{{loop.index0}}">Capability - {{ capability | filter_nested_d <input class="form-control" id="api_url_{{loop.index0}}" name="capability_apiDocUrl_{{loop.index0}}" placeholder="API documentation URL" - type="text" + type="url" value="{{ capability | filter_nested_dict(["apiDocUrl"]) }}"> {% else %} <input class="form-control" id="api_url_{{loop.index0}}" name="capability_apiDocUrl_{{loop.index0}}" - placeholder="API documentation URL" type="text"> + placeholder="API documentation URL" type="url"> {% endif %} </div> </div> <div class="form-group"> <label class="required control-label col-sm-2">Deployment location</label> - <label class="form-check-label"> - {% if is_editable %} - {% if capability | filter_nested_dict(["deploymentDetails","location"]) == "internal" %} - <input class="form-check-input" id="deploy_internal_{{loop.index0}}" - name="deploymentDetails_location_{{loop.index0}}" - type="radio" value="internal" checked="checked"> internal + <div class="col-sm-10"> + <label class="form-check-label radio-inline"> + {% if is_editable %} + {% if capability | filter_nested_dict(["deploymentDetails","location"]) == "internal" %} + <input class="form-check-input" id="deploy_internal_{{loop.index0}}" + name="deploymentDetails_location_{{loop.index0}}" + type="radio" value="internal" checked="checked"> Internal + {% else %} + <input class="form-check-input" id="deploy_internal_{{loop.index0}}" + name="deploymentDetails_location_{{loop.index0}}" + type="radio" value="internal"> Internal + {% endif %} {% else %} <input class="form-check-input" id="deploy_internal_{{loop.index0}}" name="deploymentDetails_location_{{loop.index0}}" type="radio" value="internal"> internal {% endif %} - {% else %} - <input class="form-check-input" id="deploy_internal_{{loop.index0}}" - name="deploymentDetails_location_{{loop.index0}}" - type="radio" value="internal"> internal - {% endif %} - </label> - <label class="form-check-label"> - {% if is_editable %} - {% if capability | filter_nested_dict(["deploymentDetails","location"]) == "external" %} - <input class="form-check-input" id="deploy_external_{{loop.index0}}" - name="deploymentDetails_location_{{loop.index0}}" type="radio" - value="external" checked="checked"> external + </label> + <label class="form-check-label radio-inline"> + {% if is_editable %} + {% if capability | filter_nested_dict(["deploymentDetails","location"]) == "external" %} + <input class="form-check-input" id="deploy_external_{{loop.index0}}" + name="deploymentDetails_location_{{loop.index0}}" type="radio" + value="external" checked="checked"> External + {% else %} + <input class="form-check-input" id="deploy_external_{{loop.index0}}" + name="deploymentDetails_location_{{loop.index0}}" type="radio" + value="external"> external + {% endif %} {% else %} <input class="form-check-input" id="deploy_external_{{loop.index0}}" name="deploymentDetails_location_{{loop.index0}}" type="radio" - value="external"> external + value="external"> External {% endif %} - {% else %} - <input class="form-check-input" id="deploy_external_{{loop.index0}}" - name="deploymentDetails_location_{{loop.index0}}" type="radio" - value="external"> external - {% endif %} - </label> + </label> + </div> </div> <div class="form-group"> @@ -930,59 +956,65 @@ <h3 id="capability_{{loop.index0}}">Capability - {{ capability | filter_nested_d {% endif %} </div> <!-- end of div key-val_loop.index0 --> </div> <!-- end of div add-env-var-div --> - <div id="add-env-var-button-div_{{ loop.index0 }}" class="row"> - <script> - var env_var_button = '<button class="button button5" type="submit" id="add_env_var_{{ loop.index0 }}">' + - 'Add environment variables</button>' - $('#add-env-var-button-div_{{ loop.index0 }}').append(env_var_button); - // get all envvar pairs in the key-val div. - var envvar_list = $("#key-val_{{ loop.index0 }}").children(`input[id^="environmentVariables_key_"]`); - // start the envvar counter with the number of envvar pairs in the key-val div - var add_env_var_button_click_count = envvar_list.length; - $('#add_env_var_{{ loop.index0 }}').click(function (e) { - e.preventDefault(); - // environment variables match the pattern environmentVariables_key_envindex_capindex - $("#key-val_{{ loop.index0 }}").append("<input class=\"form-control envvar-key\" name=\"environmentVariables_key_" + add_env_var_button_click_count + "_{{ loop.index0 }}\" " + - "id=\"environmentVariables_key_" + add_env_var_button_click_count + "_{{ loop.index0 }}\" type=\"text\" placeholder=\"Key\">"); - $("#key-val_{{ loop.index0 }}").append("<input class=\"form-control envvar-value\" name=\"environmentVariables_value_" + add_env_var_button_click_count + "_{{ loop.index0 }}\" " + - "id=\"environmentVariables_value_" + add_env_var_button_click_count + "_{{ loop.index0 }}\" type=\"password\" placeholder=\"Value\">"); - $("#key-val_{{ loop.index0 }}").append($("<i class=\"bi bi-eye-slash field_icon\" id=\"togglePassword\">").on('click', function () { - $(this).toggleClass("bi-eye"); - let input = $(this).prev(); - if (input.attr("type") === "password") { - input.attr("type", "text"); - } else { - input.attr("type", "password"); - } - })); - var i_envvarclose = '<i class=\"bi bi-x-lg\" id=\"env-var-close-btn\"></i>'; - $("#key-val_{{ loop.index0 }}").append($(i_envvarclose).on('click', function () { - let closebtn = $(this); - let eyebtn = closebtn.prev(); - let input_envval = eyebtn.prev(); - let input_envkey = input_envval.prev(); - eyebtn.remove() - input_envval.remove(); - input_envkey.remove(); - closebtn.remove(); - MoveSelector(event); - })); - // once new envvar pairs are added, increment the counter - add_env_var_button_click_count++; - }); - </script> - </div> <!-- end of add-env-var-button-div --> + <div id="add-env-var-div" class="row env-var-div-row"> + <div class="col-sm-2"> + <!-- empty column" --> + </div> + <div id="add-env-var-button-div_{{ loop.index0 }}" class="col-sm-10"> + <script> + var env_var_button = '<button class="button button5" type="submit" id="add_env_var_{{ loop.index0 }}">' + + 'Add environment variables</button>' + $('#add-env-var-button-div_{{ loop.index0 }}').append(env_var_button); + // get all envvar pairs in the key-val div. + var envvar_list = $("#key-val_{{ loop.index0 }}").children(`input[id^="environmentVariables_key_"]`); + // start the envvar counter with the number of envvar pairs in the key-val div + var add_env_var_button_click_count = envvar_list.length; + $('#add_env_var_{{ loop.index0 }}').click(function (e) { + e.preventDefault(); + // environment variables match the pattern environmentVariables_key_envindex_capindex + $("#key-val_{{ loop.index0 }}").append("<input class=\"form-control envvar-key\" name=\"environmentVariables_key_" + add_env_var_button_click_count + "_{{ loop.index0 }}\" " + + "id=\"environmentVariables_key_" + add_env_var_button_click_count + "_{{ loop.index0 }}\" type=\"text\" placeholder=\"Key\">"); + $("#key-val_{{ loop.index0 }}").append("<input class=\"form-control envvar-value\" name=\"environmentVariables_value_" + add_env_var_button_click_count + "_{{ loop.index0 }}\" " + + "id=\"environmentVariables_value_" + add_env_var_button_click_count + "_{{ loop.index0 }}\" type=\"password\" placeholder=\"Value\">"); + $("#key-val_{{ loop.index0 }}").append($("<i class=\"bi bi-eye-slash field_icon\" id=\"togglePassword\">").on('click', function () { + $(this).toggleClass("bi-eye"); + let input = $(this).prev(); + if (input.attr("type") === "password") { + input.attr("type", "text"); + } else { + input.attr("type", "password"); + } + })); + var i_envvarclose = '<i class=\"bi bi-x-lg\" id=\"env-var-close-btn\"></i>'; + $("#key-val_{{ loop.index0 }}").append($(i_envvarclose).on('click', function () { + let closebtn = $(this); + let eyebtn = closebtn.prev(); + let input_envval = eyebtn.prev(); + let input_envkey = input_envval.prev(); + eyebtn.remove() + input_envval.remove(); + input_envkey.remove(); + closebtn.remove(); + MoveSelector(event); + })); + // once new envvar pairs are added, increment the counter + add_env_var_button_click_count++; + }); + </script> + </div> <!-- end of add-env-var-button-div --> + </div> + <div class="form-group"> <label class="required control-label col-sm-2">Database Detail</label> <div class="col-sm-10"> {% if is_editable %} <input class="form-control" id="db-detail_{{loop.index0}}" name="deploymentDetails_databaseDetails_{{loop.index0}}" - placeholder="Details of API endpoint to delete user info given the user UUID" + placeholder="Provide the name, version, and other details of the database server used." type="text" value="{{ capability | filter_nested_dict(["deploymentDetails","databaseDetails"]) }}"> {% else %} <input class="form-control" id="db-detail_{{loop.index0}}" name="deploymentDetails_databaseDetails_{{loop.index0}}" - placeholder="Details of API endpoint to delete user info given the user UUID" + placeholder="Provide the name, version, and other details of the database server used." type="text"> {% endif %} </div> @@ -994,13 +1026,13 @@ <h3 id="capability_{{loop.index0}}">Capability - {{ capability | filter_nested_d <input class="form-control" id="version_{{loop.index0}}" name="capability_version_{{loop.index0}}" - placeholder="latest version number" + placeholder="Latest Capability version number" type="text" value="{{ capability | filter_nested_dict(["version"]) }}"> {% else %} <input class="form-control" id="version_{{loop.index0}}" name="capability_version_{{loop.index0}}" - placeholder="latest version number" + placeholder="Latest Capability version number" type="text"> {% endif %} </div> @@ -1013,13 +1045,13 @@ <h3 id="capability_{{loop.index0}}">Capability - {{ capability | filter_nested_d id="version_url_{{loop.index0}}" name="capability_versionUrl_{{loop.index0}}" placeholder="" - type="text" value="{{ capability | filter_nested_dict(["versionUrl"]) }}"> + type="url" value="{{ capability | filter_nested_dict(["versionUrl"]) }}"> {% else %} <input class="form-control" id="version_url_{{loop.index0}}" name="capability_versionUrl_{{loop.index0}}" placeholder="" - type="text"> + type="url"> {% endif %} </div> </div> @@ -1030,13 +1062,13 @@ <h3 id="capability_{{loop.index0}}">Capability - {{ capability | filter_nested_d <input class="form-control" id="health_{{loop.index0}}" name="capability_healthCheckUrl_{{loop.index0}}" - placeholder="health check url" - type="text" value="{{ capability | filter_nested_dict(["healthCheckUrl"]) }}"> + placeholder="Add a health check URL to check the Capability status continuously." + type="url" value="{{ capability | filter_nested_dict(["healthCheckUrl"]) }}"> {% else %} <input class="form-control" id="health_{{loop.index0}}" name="capability_healthCheckUrl_{{loop.index0}}" - placeholder="health check url" type="text"> + placeholder="Add a health check URL to check the Capability status continuously." type="url"> {% endif %} </div> </div> @@ -1095,9 +1127,11 @@ <h3 id="capability_{{loop.index0}}">Capability - {{ capability | filter_nested_d {% endfor %} <!-- end of for loop iterating through existing capabilities --> {% endif %} <!-- end of if existing capabilities exist --> </div> <!-- end of div capability-parent --> + </div> {# end of capability-parent container div #} <!--------------------------------------------talent block ------------------------------------------> - <div id="talent-parent" style="display: block; background-color:white"> + <div class="container"> + <div id="talent-parent" style="display: block; background-color:white"> <!----------------------------------------talent clean block ----------------------------------------> <div id="talent-div-clean" style="display: none"> <!-- all field id in talent clean block will be appended with _0 --> @@ -1148,49 +1182,73 @@ <h3 id="talent">Add a Talent to this Contribution</h3> <div class="form-group"> <label class="control-label col-sm-2">User Privacy Level</label> <div class="col-sm-10"> - <input max="5" min="1" name="talent_minUserPrivacyLevel" + <input class="form-control" max="5" min="1" name="talent_minUserPrivacyLevel" step="1" type="number" value="1"> </div> </div> <div class="form-group"> <label class="control-label col-sm-2">End User Role</label> - <label class="form-check-label"><input class="form-check-input" id="student" - name="talent_minEndUserRoles" - type="checkbox" value="student"> student</label> - <label class="form-check-label"><input class="form-check-input" id="visitor" - name="talent_minEndUserRoles" - type="checkbox" value="visitor"> visitor</label> - <label class="form-check-label"><input class="form-check-input" id="alumni" - name="talent_minEndUserRoles" - type="checkbox" - value="alumni"> alumni</label> - <label class="form-check-label"><input class="form-check-input" id="employee" - name="talent_minEndUserRoles" type="checkbox" - value="employee"> employee</label> - <label class="form-check-label"><input class="form-check-input" id="parent" - name="talent_minEndUserRoles" - type="checkbox" - value="parent"> parent</label> - <label class="form-check-label"><input class="form-check-input" id="fan" - name="talent_minEndUserRoles" - type="checkbox" value="fan"> fan</label> + <div class="col-sm-7" style="display: table"> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" id="student" + name="talent_minEndUserRoles" + type="checkbox" value="student"> + <label class="checkbox-inline" for="student"> Student </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" id="visitor" + name="talent_minEndUserRoles" + type="checkbox" value="visitor"> + <label class="checkbox-inline" for="visitor"> Visitor </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" id="alumni" + name="talent_minEndUserRoles" + type="checkbox" + value="alumni"> + <label class="checkbox-inline" for="alumni"> Alumni </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" id="employee" + name="talent_minEndUserRoles" type="checkbox" + value="employee"> + <label class="checkbox-inline" for="employee"> Employee </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" id="parent" + name="talent_minEndUserRoles" type="checkbox" + value="parent"> + <label class="checkbox-inline" for="parent"> Parent </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" id="fan" + name="talent_minEndUserRoles" + type="checkbox" value="fan"> + <label class="checkbox-inline" for="fan"> Fan </label> + </div> + </div> </div> <div class="form-group"> <label class="control-label col-sm-2">Select active date range</label> - <label class="form-check-label">start</label> - <input class="form-check-input" id="start_day" name="talent_startDate" type="date"> - <label class="form-check-label"> end</label> - <input class="form-check-input" id="end_day" name="talent_endDate" type="date"> + <div class="col-sm-5" style="display: table"> + <div class="form-check-label table-row-inputs"> + Start + <input id="start_day" name="talent_startDate" type="date"> + </div> + <div class="form-check-label table-row-inputs"> + End + <input id="end_day" name="talent_endDate" type="date"> + </div> + </div> </div> <div class="form-group"> <label class="control-label col-sm-2">Data Description</label> <div class="col-sm-10"> - <input id="data_des" name="talent_dataDescription" - placeholder="Detailed description of the data that is collected by this Talent, how it is used, and how this relates to the privacy level." - style="height:150px" - type="text"> + <textarea id="data_des" name="talent_dataDescription" + placeholder="Provide a detailed description of the data that is collected by this Talent, how it is used, and how it relates to the Rokwire privacy levels" + style="height:150px"></textarea> </div> </div> <!---------- self certification block --------------------> @@ -1201,28 +1259,28 @@ <h3>Self-certification</h3> <label class="control-label col-sm-2">Deleting data upon request</label> <div class="col-sm-10"> <input class="form-control" name="selfcertificate_dataDeletionUponRequest" - placeholder="Deleting data upon request" type="text"> + placeholder="Declaration of deleting data upon request" type="text"> </div> </div> <div class="form-group"> <label class="control-label col-sm-2">Respecting privacy setting</label> <div class="col-sm-10"> <input class="form-control" name="selfcertificate_respectingUserPrivacySetting" - placeholder="Respecting privacy setting" type="text"> + placeholder="Declaration to respect privacy setting" type="text"> </div> </div> <div class="form-group"> <label class="control-label col-sm-2">Disclose sponsors / ads</label> <div class="col-sm-10"> <input class="form-control" name="selfcertificate_discloseAds" - placeholder="Disclose sponsors / ads" type="text"> + placeholder="Disclose sponsors / ads in this contribution" type="text"> </div> </div> <div class="form-group"> <label class="control-label col-sm-2">Disclose right to use images</label> <div class="col-sm-10"> <input class="form-control" name="selfcertificate_discloseImageRights" - placeholder="Disclose right to use images" type="text"> + placeholder="Disclose right to use images in this contribution" type="text"> </div> </div> </div> <!-- end of self certification block --> @@ -1343,7 +1401,8 @@ <h3 id="talent_{{loop.index0}}">Talent - {{ talent|filter_nested_dict(["name"]) <div class="form-group"> <label class="control-label col-sm-2">User Privacy Level</label> <div class="col-sm-10"> - <input max="5" min="1" + <input class="form-control" + max="5" min="1" name="talent_minUserPrivacyLevel_{{loop.index0}}" id="minUserPrivacyLevel_{{loop.index0}}" step="1" @@ -1353,112 +1412,139 @@ <h3 id="talent_{{loop.index0}}">Talent - {{ talent|filter_nested_dict(["name"]) </div> <div class="form-group"> <label class="control-label col-sm-2">End User Role</label> - {% if talent["minEndUserRoles"] %} - {% set student_ns = namespace(is_on=false) %} - {% set visitor_ns = namespace(is_on=false) %} - {% set alumni_ns = namespace(is_on=false) %} - {% set employee_ns = namespace(is_on=false) %} - {% set parent_ns = namespace(is_on=false) %} - {% set fan_ns = namespace(is_on=false) %} - {% for role in talent["minEndUserRoles"] %} - {% if role == "student" %} - {% set student_ns.is_on = True %} - {% elif role == "visitor" %} - {% set visitor_ns.is_on = True %} - {% elif role == "alumni" %} - {% set alumni_ns.is_on = True %} - {% elif role == "employee" %} - {% set employee_ns.is_on = True %} - {% elif role == "parent" %} - {% set parent_ns.is_on = True %} - {% elif role == "fan" %} - {% set fan_ns.is_on = True %} - {% endif %} - {% endfor %} - <label class="form-check-label"> - <input class="form-check-input" - id="student_{{loop.index0}}" - name="talent_minEndUserRolesname_{{loop.index0}}" - type="checkbox" value="student" - {% if student_ns.is_on %} checked {% endif %}> student</label> - <label class="form-check-label"> - <input class="form-check-input" - id="visitor_{{loop.index0}}" - name="talent_minEndUserRoles_{{loop.index0}}" - type="checkbox" value="visitor" - {% if visitor_ns.is_on %} checked {% endif %}> visitor</label> - <label class="form-check-label"> - <input class="form-check-input" - id="alumni_{{loop.index0}}" - name="talent_minEndUserRoles_{{loop.index0}}" - type="checkbox" value="alumni" - {% if alumni_ns.is_on %} checked {% endif %}> alumni</label> - <label class="form-check-label"> - <input class="form-check-input" - id="employee_{{loop.index0}}" - name="talent_minEndUserRoles_{{loop.index0}}" - type="checkbox" - value="employee" - {% if employee_ns.is_on %} checked {% endif %}> employee</label> - <label class="form-check-label"> - <input class="form-check-input" - id="parent_{{loop.index0}}" - name="talent_minEndUserRoles_{{loop.index0}}" - type="checkbox" - value="parent" - {% if parent_ns.is_on %} checked {% endif %}> parent</label> - <label class="form-check-label"> - <input class="form-check-input" - id="fan_{{loop.index0}}" - name="talent_minEndUserRoles_{{loop.index0}}" - type="checkbox" value="fan" - {% if fan_ns.is_on %} checked {% endif %}> fan</label> - {% else %} - <label class="form-check-label"> - <input class="form-check-input" - id="student_{{loop.index0}}" - name="talent_minEndUserRoles_{{loop.index0}}" - type="checkbox" value="student"> student</label> - <label class="form-check-label"> - <input class="form-check-input" id="visitor_{{loop.index0}}" - name="talent_minEndUserRoles_{{loop.index0}}" - type="checkbox" value="visitor"> visitor</label> - <label class="form-check-label"> - <input class="form-check-input" - id="alumni_{{loop.index0}}" - name="talent_minEndUserRoles_{{loop.index0}}" - type="checkbox" value="alumni"> alumni</label> - <label class="form-check-label"> - <input class="form-check-input" - id="employee_{{loop.index0}}" - name="talent_minEndUserRoles_{{loop.index0}}" - type="checkbox" - value="employee"> employee</label> - <label class="form-check-label"> - <input class="form-check-input" - id="parent_{{loop.index0}}" - name="talent_minEndUserRoles_{{loop.index0}}" - type="checkbox" - value="parent"> parent</label> - <label class="form-check-label"> - <input class="form-check-input" id="fan" name="talent_minEndUserRoles" - type="checkbox" value="fan"> fan</label> - {% endif %} + <div class="col-sm-7" style="display: table"> + {% if talent["minEndUserRoles"] %} + {% set student_ns = namespace(is_on=false) %} + {% set visitor_ns = namespace(is_on=false) %} + {% set alumni_ns = namespace(is_on=false) %} + {% set employee_ns = namespace(is_on=false) %} + {% set parent_ns = namespace(is_on=false) %} + {% set fan_ns = namespace(is_on=false) %} + {% for role in talent["minEndUserRoles"] %} + {% if role == "student" %} + {% set student_ns.is_on = True %} + {% elif role == "visitor" %} + {% set visitor_ns.is_on = True %} + {% elif role == "alumni" %} + {% set alumni_ns.is_on = True %} + {% elif role == "employee" %} + {% set employee_ns.is_on = True %} + {% elif role == "parent" %} + {% set parent_ns.is_on = True %} + {% elif role == "fan" %} + {% set fan_ns.is_on = True %} + {% endif %} + {% endfor %} + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" + id="student_{{loop.index0}}" + name="talent_minEndUserRolesname_{{loop.index0}}" + type="checkbox" value="student" + {% if student_ns.is_on %} checked {% endif %}> + <label class="checkbox-inline" for="student"> Student </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" + id="visitor_{{loop.index0}}" + name="talent_minEndUserRoles_{{loop.index0}}" + type="checkbox" value="visitor" + {% if visitor_ns.is_on %} checked {% endif %}> + <label class="checkbox-inline" for="visitor"> Visitor </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" + id="alumni_{{loop.index0}}" + name="talent_minEndUserRoles_{{loop.index0}}" + type="checkbox" value="alumni" + {% if alumni_ns.is_on %} checked {% endif %}> + <label class="checkbox-inline" for="alumni"> Alumni </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" + id="employee_{{loop.index0}}" + name="talent_minEndUserRoles_{{loop.index0}}" + type="checkbox" + value="employee" + {% if employee_ns.is_on %} checked {% endif %}> + <label class="checkbox-inline" for="employee"> Employee </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" + id="parent_{{loop.index0}}" + name="talent_minEndUserRoles_{{loop.index0}}" + type="checkbox" + value="parent" + {% if parent_ns.is_on %} checked {% endif %}> + <label class="checkbox-inline" for="parent"> Parent</label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" + id="fan_{{loop.index0}}" + name="talent_minEndUserRoles_{{loop.index0}}" + type="checkbox" value="fan" + {% if fan_ns.is_on %} checked {% endif %}> + <label class="checkbox-inline" for="fan"> Fan</label> + </div> + {% else %} + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" + id="student_{{loop.index0}}" + name="talent_minEndUserRoles_{{loop.index0}}" + type="checkbox" value="student"> + <label class="checkbox-inline" for="student"> Student </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" id="visitor_{{loop.index0}}" + name="talent_minEndUserRoles_{{loop.index0}}" + type="checkbox" value="visitor"> + <label class="checkbox-inline" for="visitor"> Visitor </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" + id="alumni_{{loop.index0}}" + name="talent_minEndUserRoles_{{loop.index0}}" + type="checkbox" value="alumni"> + <label class="checkbox-inline" for="alumni"> Alumni </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" + id="employee_{{loop.index0}}" + name="talent_minEndUserRoles_{{loop.index0}}" + type="checkbox" + value="employee"> + <label class="checkbox-inline" for="employee"> Employee </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" + id="parent_{{loop.index0}}" + name="talent_minEndUserRoles_{{loop.index0}}" + type="checkbox" + value="parent"> + <label class="checkbox-inline" for="parent"> Parent </label> + </div> + <div class="form-check-label table-row-inputs"> + <input class="form-check-input" + id="fan_{{loop.index0}}" name="talent_minEndUserRoles_{{loop.index0}}" + type="checkbox" value="fan"> + <label class="checkbox-inline" for="fan"> Fan</label> + </div> + {% endif %} + </div> </div> <div class="form-group"> <label class="control-label col-sm-2">Select active date range</label> - <label class="form-check-label">start</label> - <input class="form-check-input" - id="start_day_{{loop.index0}}" - name="talent_startDate_{{loop.index0}}" - type="date" - value="{{ talent|filter_nested_dict(["startDate"]) }}"> - <label class="form-check-label"> end</label> - <input class="form-check-input" - id="end_day_{{loop.index0}}" - name="talent_endDate_{{loop.index0}}" - type="date" - value="{{ talent|filter_nested_dict(["endDate"]) }}"> + <div class="col-sm-5" style="display: table"> + <div class="form-check-label table-row-inputs"> + Start + <input id="start_day_{{loop.index0}}" name="talent_startDate_{{loop.index0}}" + type="date" value="{{ talent|filter_nested_dict(["startDate"]) }}"> + </div> + <div class="form-check-label table-row-inputs"> + End + <input id="end_day_{{loop.index0}}" name="talent_endDate_{{loop.index0}}" + type="date" value="{{ talent|filter_nested_dict(["endDate"]) }}"> + </div> + </div> <script> $('#start_day_{{loop.index0}}').change(function(){ let start_val = $(this).val(); @@ -1474,12 +1560,12 @@ <h3 id="talent_{{loop.index0}}">Talent - {{ talent|filter_nested_dict(["name"]) <div class="form-group"> <label class="control-label col-sm-2">Data Description</label> <div class="col-sm-10"> - <input id="data_des_{{loop.index0}}" + <textarea id="data_des_{{loop.index0}}" name="talent_dataDescription_{{loop.index0}}" - placeholder="Detailed description of the data that is collected by this Talent, how it is used, and how this relates to the privacy level." + placeholder="Provide a detailed description of the data that is collected by this Talent, how it is used, and how it relates to the Rokwire privacy levels" style="height:150px" type="text" - value="{{ talent|filter_nested_dict(["dataDescription"]) }}"> + value="{{ talent|filter_nested_dict(["dataDescription"]) }}"></textarea> </div> </div> <!---------- self certification block --------------------> @@ -1491,7 +1577,7 @@ <h3>Self-certification</h3> <input class="form-control" id="dataDeletionUponRequest_{{loop.index0}}" name="selfcertificate_dataDeletionUponRequest_{{loop.index0}}" - placeholder="Deleting data upon request" + placeholder="Declaration for deleting data upon request" type="text" value="{{ talent|filter_nested_dict(["selfCertification", "dataDeletionUponRequest"]) }}"> </div> @@ -1502,7 +1588,7 @@ <h3>Self-certification</h3> <input class="form-control" id="respectingUserPrivacySetting_{{loop.index0}}" name="selfcertificate_respectingUserPrivacySetting_{{loop.index0}}" - placeholder="Respecting privacy setting" + placeholder="Declaration and steps for respecting privacy setting" type="text" value="{{ talent|filter_nested_dict(["selfCertification", "respectingUserPrivacySetting"]) }}"> </div> @@ -1513,7 +1599,7 @@ <h3>Self-certification</h3> <input class="form-control" id="discloseAds_{{loop.index0}}" name="selfcertificate_discloseAds_{{loop.index0}}" - placeholder="Disclose sponsors / ads" + placeholder="Disclose sponsors / ads in the contribution" type="text" value="{{ talent|filter_nested_dict(["selfCertification", "discloseAds"]) }}"> </div> @@ -1524,7 +1610,7 @@ <h3>Self-certification</h3> <input class="form-control" id="discloseImageRights_{{loop.index0}}" name="selfcertificate_discloseImageRights_{{loop.index0}}" - placeholder="Disclose right to use images" + placeholder="Disclose right to use images in the contribution" type="text" value="{{ talent|filter_nested_dict(["selfCertification", "discloseImageRights"]) }}"> </div> @@ -1537,22 +1623,24 @@ <h3>Self-certification</h3> {% endfor %} <!-- end of for loop iterating through existing talents --> {% endif %} <!-- end of if existing talents exist --> </div> <!-- end of div talent-parent --> + </div> {# end of talent-parent container div #} - <div id="select-contribution-div-placeholder" class="row"> - <!-- place holder for dynamic add capability / talent buttons" --> + <div class="container"> + <div id="select-contribution-div-placeholder" class="row" style="margin-bottom:1cm"> + <!-- place holder for dynamic add capability / talent buttons" --> + </div> {# end of place holder for dynamic add capability / talent buttons container div #} </div> + <!--------------------------------------------contact/privacy check ------------------------------------------> - <div id="cd-multi-steps-text-bottom"> + <div id="cd-multi-steps-text-bottom" class="container"> <nav> <ol class="cd-multi-steps text-top"> <li class="visited"><a href="#contribute">Contribution Details</a></li> - <li class="visited"><em><a href="#capability-parent">Capability and/or Talent Details </a></em> - </li> - <li class="current"><em><a href="#contact">Contact</a></em></li> - <li><em>Submit</em></li> + <li class="visited"><em><a href="#capability-parent">Capability / Talent Details </a></em></li> + <li class="current"><em><a href="#contact">Contact Details</a></em></li> + <li><em><a href="#submit">Submit</a></em></li> </ol> </nav> - </div> <div class="container"> @@ -1581,7 +1669,7 @@ <h3 id="contact">Contact Details</h3> <label class="required control-label col-sm-2">Contact Email</label> <div class="col-sm-10"> <input class="form-control" id="contact_email" name="contact_email" - placeholder="" type="text" value="{{ contact.email }}"> + placeholder="" type="email" value="{{ contact.email }}"> </div> </div> {% else %} @@ -1589,7 +1677,7 @@ <h3 id="contact">Contact Details</h3> <label class="required control-label col-sm-2">Contact Email</label> <div class="col-sm-10"> <input class="form-control" id="contact_email" name="contact_email" - placeholder="" type="text"> + placeholder="" type="email"> </div> </div> {% endif %} @@ -1598,8 +1686,8 @@ <h3 id="contact">Contact Details</h3> <label class="required control-label col-sm-2">Contact Phone</label> <div class="col-sm-10"> <input class="form-control" id="contact_phone" - name="contact_phone" placeholder="" type="text" - value="{{ contact.phone }}"> + name="contact_phone" placeholder="Phone number (9 to 14 digits)" type="tel" + value="{{ contact.phone }}" minlength="9" maxlength="14"/> </div> </div> {% else %} @@ -1607,7 +1695,7 @@ <h3 id="contact">Contact Details</h3> <label class="required control-label col-sm-2">Contact Phone</label> <div class="col-sm-10"> <input class="form-control" id="contact_phone" name="contact_phone" - placeholder="" type="text"> + placeholder="Phone number (9 to 14 digits)" type="tel" minlength="9" maxlength="14"/> </div> </div> {% endif %} @@ -1658,14 +1746,14 @@ <h3 id="contact">Contact Details</h3> <div class="form-group"> <label class="required control-label col-sm-2">Contact Email</label> <div class="col-sm-10"> - <input class="form-control" id="contact_email" name="contact_email" placeholder="" type="text"> + <input class="form-control" id="contact_email" name="contact_email" placeholder="" type="email"> </div> </div> <div class="form-group"> <label class="required control-label col-sm-2">Contact Phone</label> <div class="col-sm-10"> <input class="form-control" id="contact_phone" name="contact_phone" - placeholder="" type="text"> + placeholder="" type="tel" minlength="9" maxlength="14" /> </div> </div> <div class="form-group"> @@ -1686,22 +1774,22 @@ <h3 id="contact">Contact Details</h3> </div> <!-- end of class container Contact Details div --> <!-------------------------------------------- submit ------------------------------------------> - <div class="row"> - <button type="button" class="button button3" id="cancel_button" data-toggle="modal" data-target="#cancel-modal">Cancel</button> - <input href="{{ url_for('contribute.home') }}" - id="submit_button" - onsubmit="return data_validation()" - type="submit" - value="Submit"> + <div class="container" id="submit"> + <div class="row"> + <button type="button" class="button button2" id="cancel_button" data-toggle="modal" data-target="#cancel-modal">Cancel </button> + <input href="{{ url_for('contribute.home') }}" id="submit_button" class="button button3" + onsubmit="return data_validation()" type="submit" value="Submit"> + </div> </div> <!-- Submit modal --> <div class="modal" id="submit-modal"> <!-- Modal content --> <div class="modal-content"> - <span class="close">×</span> - <p id="submit-pop">Please finish the form!</p> - <br> + <div class="modal-body"> + <span class="close"><i class="bi bi-x-lg" id="close-btn"></i></span> + <p id="submit-pop" >Please finish the form!</p> + </div> </div> </div> @@ -1710,19 +1798,21 @@ <h3 id="contact">Contact Details</h3> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> - <h5 class="modal-title" id="exampleModalLabel"> + <h3 class="cancel-modal-title" id="cancel-modal-title" style="display: inline-block"> Cancel submission - </h5> + </h3> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> - <span aria-hidden="true">×</span> + <i class="bi bi-x-lg" id="close-btn"></i> </button> </div> <div class="modal-body"> - Are you sure you want to Cancel this submission? + <h5>Are you sure you want to Cancel this submission?</h5> </div> <div class="modal-footer"> - <button type="button" class="btn btn-secondary mr-2" data-dismiss="modal">No</button> - <a class="btn btn-primary ml-1" role="button" id="cancel-modal-btn-yes" href="{{ url_for('contribute.home') }}">Yes</a> + <button type="button" class="button button2" data-dismiss="modal">No</button> + <a class="button button3" role="button" id="cancel-modal-btn-yes" href="{{ url_for('contribute.home') }}" style="text-decoration: none"> + Yes + </a> </div> </div> </div> @@ -1731,6 +1821,8 @@ <h5 class="modal-title" id="exampleModalLabel"> </form> <!-- end of form --> </div> <!-- end --> +{% include 'footer.html' %} +{% include 'topnav_javascript.html' %} </body> <script src="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@9.0.0/dist/js/autoComplete.min.js"></script> @@ -2196,9 +2288,9 @@ <h5 class="modal-title" id="exampleModalLabel"> // adjust button position event.preventDefault(); $('#select-contribution-div').position({ - my: "top", - at: "bottom", - of: $("#select-contribution-div-placeholder"), + my: "bottom", + at: "top", + of: $("#cd-multi-steps-text-bottom"), collision: "none none" }); } diff --git a/contributions/catalog/webapps/templates/contribute/contribution_details.html b/contributions/catalog/webapps/templates/contribute/contribution_details.html index f566b174..0231f678 100644 --- a/contributions/catalog/webapps/templates/contribute/contribution_details.html +++ b/contributions/catalog/webapps/templates/contribute/contribution_details.html @@ -3,6 +3,8 @@ <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1" name="viewport"> + <link rel="stylesheet" href="https://use.typekit.net/qjr3liq.css"> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css"> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> @@ -13,384 +15,415 @@ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> <title>Contribution Details</title> </head> -<style> - /* Style the buttons */ - .btn { - position: relative; - margin-top: 20px; - border: none; - outline: none; - padding: 12px 16px; - background-color: white; - cursor: pointer; - } - - .btn:hover { - background-color: #ddd; - color: white; - } - - .btn.active { - background-color: #666; - color: white; - } - .modal-backdrop { - z-index: 0; - } -</style> <body onload=start()> <div class="header"> {% include 'topnav.html' %} </div> -<div class="container"> - <h1 id="contribute">Contribution Details</h1> +<div class="container details-container"> + <h1 id="contribute">Contribution Details</h1> <hr class="divider"/> - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Contribution Name</h4> - </div> - <p class="col-sm-2" style="text-align: justify;">{{post.name}}</p> - </div> - - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Contribution short description</h4> + <div class="container"> + <!-- contribution details container --> + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Contribution Name</h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.name}}</div> + </div> </div> - <p class="col-sm-9">{{post.shortDescription}}</p> - </div> - {% if post.longDescription %} <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Contribution long description</h4> + <div class="col-12 col-md-3"> + <h4>Short Description</h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.shortDescription}}</div> </div> - <p class="col-sm-9">{{post.longDescription}}</p> </div> - {% endif %} + {% if post.longDescription %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Long Description</h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.longDescription}}</div> + </div> + </div> + {% endif %} + + {% if post.contributors %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Contributor Details</h4> + </div> + </div> - {% if post.contributors %} - <h4>Contributor details</h4> - {% for c in post.contributors %} - {% set contributor_ns = namespace(firstName='', lastName='', middleName='', address='', phone='', email='', - name='', contributorType='', affil_name='', affil_address='', affil_phone='', affil_email='') %} - {% for key,val in c.items() %} - {% if key == "affiliation" %} - {% for k,vk in val.items() %} - {% if vk %} - {% if k == 'name' %} - {% set contributor_ns.affil_name = vk %} - {% elif k == 'address' %} - {% set contributor_ns.affil_address = vk %} - {% elif k == 'phone' %} - {% set contributor_ns.affil_phone = vk %} - {% elif k == 'email' %} - {% set contributor_ns.affil_email = vk %} + {% for c in post.contributors %} + {% set contributor_ns = namespace(firstName='', lastName='', middleName='', address='', phone='', email='', + name='', contributorType='', affil_name='', affil_address='', affil_phone='', affil_email='') %} + {% for key,val in c.items() %} + {% if key == "affiliation" %} + {% for k,vk in val.items() %} + {% if vk %} + {% if k == 'name' %} + {% set contributor_ns.affil_name = vk %} + {% elif k == 'address' %} + {% set contributor_ns.affil_address = vk %} + {% elif k == 'phone' %} + {% set contributor_ns.affil_phone = vk %} + {% elif k == 'email' %} + {% set contributor_ns.affil_email = vk %} + {% endif %} {% endif %} + {% endfor %} + {% else %} + {% if key == 'contributorType' %} + {% set contributor_ns.contributorType = val %} + {% elif key == 'firstName' %} + {% set contributor_ns.firstName = val %} + {% elif key == 'lastName' %} + {% set contributor_ns.lastName = val %} + {% elif key == 'middleName' %} + {% set contributor_ns.middleName = val %} + {% elif key == 'phone' %} + {% set contributor_ns.phone = val %} + {% elif key == 'email' %} + {% set contributor_ns.email = val %} + {% elif key == 'address' %} + {% set contributor_ns.address = val %} + {% elif key == 'name' %} + {% set contributor_ns.name = val %} {% endif %} - {% endfor %} - {% else %} - {% if key == 'contributorType' %} - {% set contributor_ns.contributorType = val %} - {% elif key == 'firstName' %} - {% set contributor_ns.firstName = val %} - {% elif key == 'lastName' %} - {% set contributor_ns.lastName = val %} - {% elif key == 'middleName' %} - {% set contributor_ns.middleName = val %} - {% elif key == 'phone' %} - {% set contributor_ns.phone = val %} - {% elif key == 'email' %} - {% set contributor_ns.email = val %} - {% elif key == 'address' %} - {% set contributor_ns.address = val %} - {% elif key == 'name' %} - {% set contributor_ns.name = val %} {% endif %} - {% endif %} - {% endfor %} - {% if contributor_ns.contributorType == "person" %} - <h5><b>Person</b></h5> - <div class="row"> - <div class="col-12 col-sm-2"> - First Name - </div> - <p class="col-sm-2">{{contributor_ns.firstName}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Middle Name - </div> - <p class="col-sm-2">{{contributor_ns.middleName}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Last Name - </div> - <p class="col-sm-2">{{contributor_ns.lastName}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Phone - </div> - <p class="col-sm-2">{{contributor_ns.phone}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Email - </div> - <p class="col-sm-2">{{contributor_ns.email}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Affiliation Name - </div> - <p class="col-sm-2">{{contributor_ns.affil_name}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Affiliation Address - </div> - <p class="col-sm-2">{{contributor_ns.affil_address}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Affiliation Phone + {% endfor %} + + {% if contributor_ns.contributorType == "person" %} + <div class="row"> + <div class="col-12 col-md-3"> + <h5>Person</h5> + </div> + <div class="col-12 col-md-9"> + <table> + <tr> + <td><b>First Name </b></td> + <td>{{contributor_ns.firstName}}</td> + </tr> + + <tr> + <td><b>Middle Name </b></td> + <td>{{contributor_ns.middleName}}</td> + </tr> + + <tr> + <td><b>Last Name </b></td> + <td>{{contributor_ns.lastName}}</td> + </tr> + + <tr> + <td><b>Phone </b></td> + <td>{{contributor_ns.phone}}</td> + </tr> + + <tr> + <td><b>Email </b></td> + <td>{{contributor_ns.email}}</td> + </tr> + + <tr> + <td><b>Affiliation Name </b></td> + <td>{{contributor_ns.affil_name}}</td> + </tr> + + <tr> + <td><b>Affiliation Address </b></td> + <td>{{contributor_ns.affil_address}}</td> + </tr> + + <tr> + <td><b>Affiliation Phone </b></td> + <td>{{contributor_ns.affil_phone}}</td> + </tr> + + <tr> + <td><b>Affiliation Email </b></td> + <td>{{contributor_ns.affil_email}}</td> + </tr> + </table> + </div> </div> - <p class="col-sm-2">{{contributor_ns.affil_phone}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Affiliation Email + {% endif %} + {% if contributor_ns.contributorType == "organization" %} + <div class="row" style="margin-top: 5px"> + <div class="col-12 col-md-3"> + <h5>Organization</h5> + </div> + <div class="col-12 col-md-9"> + <table> + <tr> + <td><b>Name </b></td> + <td>{{contributor_ns.name}}</td> + </tr> + + <tr> + <td><b>Address </b></td> + <td>{{contributor_ns.address}}</td> + </tr> + + <tr> + <td><b>Email </b></td> + <td>{{contributor_ns.email}}</td> + </tr> + + <tr> + <td><b>Phone </b></td> + <td>{{contributor_ns.phone}}</td> + </tr> + </table> + </div> </div> - <p class="col-sm-2">{{contributor_ns.affil_email}}</p> + {% endif %} + + {% endfor %} + + {% endif %} + + {% if post.contacts %} + <div class="row" style="margin-top: 5px"> + <div class="col-12 col-md-3"> + <h4>Contact Details</h4> </div> - {% endif %} - {% if contributor_ns.contributorType == "organization" %} - <h5><b>Organization</b></h5> - <div class="row"> - <div class="col-12 col-sm-2"> - Name + + {% for contact in post["contacts"] %} + {% set contact_ns = namespace(name='', officialAddress='', phone='', email='', organization='') %} + {% for key,val in contact.items() %} + {% if key == 'name' %} + {% set contact_ns.name = val %} + {% elif key == 'phone' %} + {% set contact_ns.phone = val %} + {% elif key == 'email' %} + {% set contact_ns.email = val %} + {% elif key == 'officialAddress' %} + {% set contact_ns.officialAddress = val %} + {% elif key == 'organization' %} + {% set contact_ns.organization = val %} + {% endif %} + {% endfor %} + + <div class="col-12 col-md-9"> + <table> + <tr> + <td><b>Name </b></td> + <td>{{contact_ns.name}}</td> + </tr> + <tr> + <td><b>Official Address </b></td> + <td>{{contact_ns.officialAddress}}</td> + </tr> + <tr> + <td><b>Email </b></td> + <td>{{contact_ns.email}}</td> + </tr> + <tr> + <td><b>Phone </b></td> + <td>{{contact_ns.phone}}</td> + </tr> + <tr> + <td><b>Organization </b></td> + <td>{{contact_ns.organization}}</td> + </tr> + + </table> </div> - <p class="col-sm-2">{{contributor_ns.name}}</p> + {% endfor %} + </div> + {% endif %} + + {% if post.capabilities %} + <div class="row justify-content-center"> + <div class="col-12 col-md-3"> + <h4>Capabilities</h4> </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Address - </div> - <p class="col-sm-2">{{contributor_ns.address}}</p> + <div class="col-12 col-md-9"> + <table> + {% for c in post.capabilities %} + <tr> + <td style="padding-right: 10px"> + <h4>{{c.name}}</h4> + </td> + <td> + {% if is_review %} + <button class="button button4" onclick="cap_url_review('{{c.id}}')" > View </button> + {% else %} + <button class="button button4" onclick="cap_url('{{c.id}}')" > View </button> + {% endif %} + </td> + </tr> + {% endfor %} + </table> </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Email - </div> - <p class="col-sm-2">{{contributor_ns.email}}</p> + </div> + {% endif %} + + {% if post.talents %} + <div class="row justify-content-center"> + <div class="col-12 col-md-3"> + <h4>Talents</h4> </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Phone - </div> - <p class="col-sm-2">{{contributor_ns.phone}}</p> + <div class="col-12 col-md-9"> + <table> + {% for t in post.talents %} + <tr> + <td style="padding-right: 10px"> + <h4>{{t.name}}</h4> + </td> + <td> + {% if is_review %} + <button class="button button4" onclick="tal_url_review('{{t.id}}')" > View </button> + {% else %} + <button class="button button4" onclick="tal_url('{{t.id}}')" > View </button> + {% endif %} + </td> + </tr> + {% endfor %} + </table> </div> - {% endif %} - {% endfor %} - {% endif %} + </div> + {% endif %} - {% if post.contacts %} - <h4>Contact details</h4> - {% for contact in post["contacts"] %} - {% set contact_ns = namespace(name='', officialAddress='', phone='', email='', organization='') %} - {% for key,val in contact.items() %} - {% if key == 'name' %} - {% set contact_ns.name = val %} - {% elif key == 'phone' %} - {% set contact_ns.phone = val %} - {% elif key == 'email' %} - {% set contact_ns.email = val %} - {% elif key == 'officialAddress' %} - {% set contact_ns.officialAddress = val %} - {% elif key == 'organization' %} - {% set contact_ns.organization = val %} - {% endif %} - {% endfor %} + {% if (is_reviewer or is_editable or is_review) %} <div class="row"> - <div class="col-12 col-sm-2"> - Name + <div class="col-12 col-md-3"> + <h4>Admins</h4> </div> - <p class="col-sm-2">{{contact_ns.name}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Official Address + <div class="col-12 col-md-9"> + <div class="small-body-text"> + {% for x in post.contributionAdmins %} + {{x}} {% if not loop.last %},{% endif %} + {% endfor %} + </div> </div> - <p class="col-sm-2">{{contact_ns.officialAddress}}</p> </div> <div class="row"> - <div class="col-12 col-sm-2"> - Email + <div class="col-12 col-md-3"> + <h4>Status</h4> </div> - <p class="col-sm-2">{{contact_ns.email}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - Phone + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.status}}</div> </div> - <p class="col-sm-2">{{contact_ns.phone}}</p> </div> <div class="row"> - <div class="col-12 col-sm-2"> - Organization + <div class="col-12 col-md-3"> + <h4>Date Created</h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.dateCreated}}</div> </div> - <p class="col-sm-2">{{contact_ns.organization}}</p> </div> - {% endfor %} - {% endif %} - - {% if post.capabilities %} - <h4>Capabilities in this contribution</h4> - {% for c in post.capabilities %} <div class="row"> - <div class="col-12 col-sm-2"> - <ol><h4>{{c.name}}</h4></ol> + <div class="col-12 col-md-3"> + <h4>Date Modified</h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.dateModified}}</div> </div> - {% if is_review %} - <button class="button button1" onclick="cap_url_review('{{c.id}}')" > View </button> - {% else %} - <button class="button button1" onclick="cap_url('{{c.id}}')" > View </button> - {% endif %} - </div> - {% endfor %} - {% endif %} - - {% if post.talents %} - <h4>Talents in this contribution</h4> - {% for t in post.talents %} - <div class="row"> - <div class="col-12 col-sm-2"> - <ol><h4>{{t.name}}</h4></ol> </div> - {% if is_review %} - <button class="button button2" onclick="tal_url_review('{{t.id}}')" > View </button> - {% else %} - <button class="button button2" onclick="tal_url('{{t.id}}')" > View </button> - {% endif %} - </div> - {% endfor %} - {% endif %} + {% endif %} + </div> <!-- end of contribution details container --> - {% if (is_reviewer or is_editable or is_review) %} - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Contribution admins</h4> - </div> - <p class="col-sm-9"> - {% for x in post.contributionAdmins %} - {{x}} - {% if not loop.last %},{% endif %} - {% endfor %} - </p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Status</h4> - </div> - <p class="col-sm-9">{{post.status}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Date created</h4> - </div> - <p class="col-sm-9">{{post.dateCreated}}</p> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Date modified</h4> - </div> - <p class="col-sm-9">{{post.dateModified}}</p> - </div> - {% endif %} + <div class="container"> + <!-- buttons container --> + {% if is_editable %} + <button class="button button2" onclick="location.href = '{{ url_for('contribute.contribution_edit', contribution_id=post.id) }}';" >Edit</button> + <!-- Button trigger modal --> + <button type="button" class="button button3" data-toggle="modal" data-target="#confirmDelete">Delete</button> + {% endif %} - {% if is_editable %} - <a class="button button5" role="button" href="{{ url_for('contribute.contribution_edit', contribution_id=post.id) }}">Edit Contribution</a> - <!-- Button trigger modal --> - <button type="button" class="button button3" data-toggle="modal" data-target="#confirmDelete">Delete Contribution</button> - {% endif %} + {% if is_reviewer %} + <button class="button button4" onclick="location.href = '{{ url_for('contribute.contribution_review', contribution_id=post.id) }}';">Review</button> + {% endif %} + </div> <!-- end of buttons container --> - {% if is_reviewer %} - <a class="button button4" role="button" href="{{ url_for('contribute.contribution_review', contribution_id=post.id) }}">Review Contribution</a> - {% endif %} -</div> + {% if is_review %} + <div class="container"> + <!-- review container --> + <h1>Review</h1> + <hr class="divider"/> + <form class="form-horizontal" method="POST" onsubmit="return data_validation()"> + <div class="form-group"> + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Status</h4> + </div> + <div class="col-sm-10" style="width: 250px"> + <div class="catalog-dropdown-menu"> + <select id="status" name="contribution_status"> + {% if post["status"].lower() == "submitted" %} + <option value="Submitted" selected>Submitted</option> + {% else %} + <option value="Submitted">Submitted</option> + {% endif %} + {% if post["status"].lower() == "reviewing" %} + <option value="Reviewing" selected>Reviewing</option> + {% else %} + <option value="Reviewing" >Reviewing</option> + {% endif %} + {% if post["status"].lower() == "approved" %} + <option value="Approved" selected>Approved</option> + {% else %} + <option value="Approved">Approved</option> + {% endif %} + {% if post["status"].lower() == "disapproved" %} + <option value="Disapproved" selected>Disapproved</option> + {% else %} + <option value="Disapproved">Disapproved</option> + {% endif %} + {% if post["status"].lower() == "published" %} + <option value="Published" selected>Published</option> + {% else %} + <option value="Published">Published</option> + {% endif %} + </select> + </div> -{% if is_review %} - <div class="container"> - <h1>Review</h1> - <hr class="divider"/> - <form class="form-horizontal" method="POST" onsubmit="return data_validation()"> - <div class="form-group"> - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Status</h4> + </div> </div> - <div class="col-sm-10" style="width: 250px"> - <select class="form-control" id="status" name="contribution_status"> - {% if post["status"].lower() == "submitted" %} - <option value="Submitted" selected>Submitted</option> - {% else %} - <option value="Submitted">Submitted</option> - {% endif %} - {% if post["status"].lower() == "reviewing" %} - <option value="Reviewing" selected>Reviewing</option> - {% else %} - <option value="Reviewing" >Reviewing</option> - {% endif %} - {% if post["status"].lower() == "approved" %} - <option value="Approved" selected>Approved</option> - {% else %} - <option value="Approved">Approved</option> - {% endif %} - {% if post["status"].lower() == "disapproved" %} - <option value="Disapproved" selected>Disapproved</option> - {% else %} - <option value="Disapproved">Disapproved</option> - {% endif %} - {% if post["status"].lower() == "published" %} - <option value="Published" selected>Published</option> + </div> + <div class="form-group"> + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Comment</h4> + </div> + <div class="col-md-9"> + {% if 'review' in post %} + <textarea id="reviewer_comment" name="contribution_reviewer_comment" + placeholder="Give a comment" + style="height:150px">{{ post | filter_nested_dict(["review", "reviewerComment"]) }}</textarea> {% else %} - <option value="Published">Published</option> + <textarea id="contribution_detail" name="contribution_reviewer_comment" + placeholder="Give a comment" + style="height:150px"></textarea> {% endif %} - </select> - </div> - </div> - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Comment</h4> - </div> - <div class="col-sm-10"> - {% if 'review' in post %} - <textarea id="reviewer_comment" name="contribution_reviewer_comment" - placeholder="Give a comment" - style="height:150px">{{ post | filter_nested_dict(["review", "reviewerComment"]) }}</textarea> - {% else %} - <textarea id="contribution_detail" name="contribution_reviewer_comment" - placeholder="Give a comment" - style="height:150px"></textarea> - {% endif %} + </div> </div> </div> - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Last Updated</h4> - </div> - <div class="col-sm-10"> - {% if 'review' in post %} - {{ post | filter_nested_dict(["review", "lastUpdated"]) }} - {% endif %} + <div class="form-group"> + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Last Updated</h4> + </div> + <div class="col-md-9"> + {% if 'review' in post %} + {{ post | filter_nested_dict(["review", "lastUpdated"]) }} + {% endif %} + </div> + <input class="hidden" id="contribution_id" name="contribution_id" value="{{ post["id"] }}"> </div> - <input class="hidden" id="contribution_id" name="contribution_id" value="{{ post["id"] }}"> </div> <div class="row"> <div class="col-12 col-sm-2"> @@ -398,22 +431,24 @@ <h4>Last Updated</h4> <tr> <td> <input href="{{ url_for('contribute.home') }}" - id="button_submit" + class="button button3" type="submit" value="Submit"> </td> <td> - <input id="button_reset", type="reset" value="Reset"> + <input class="button button4" type="reset" value="Reset"> </td> </tr> </table> </div> </div> - </div> - </form> - </div> -{% endif %} + </form> + </div> <!-- end of review container --> + {% endif %} +</div> <!-- end of main container --> + +{% include 'footer.html' %} {% include 'topnav_javascript.html' %} <!-- Modal --> @@ -427,7 +462,7 @@ <h4>Last Updated</h4> <h4 class="modal-title" id="confirmDeleteTitle">Delete Contribution</h4> </div> <div class="modal-body"> - Are you sure you want to delete the Contribution {{post.name}}? + Are you sure you want to delete the contribution {{post.name}}? </div> <div class="modal-footer"> <button type="button" class="button button2" data-dismiss="modal">Cancel</button> @@ -477,7 +512,6 @@ <h4 class="modal-title" id="confirmDeleteTitle">Delete Contribution</h4> } }) - </script> </body> </html> diff --git a/contributions/catalog/webapps/templates/contribute/home.html b/contributions/catalog/webapps/templates/contribute/home.html index 3505b190..8f49e119 100644 --- a/contributions/catalog/webapps/templates/contribute/home.html +++ b/contributions/catalog/webapps/templates/contribute/home.html @@ -2,6 +2,8 @@ <html> <head> <meta content="width=device-width, initial-scale=1" name="viewport"> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css"> + <!-- <link rel="stylesheet" href="https://use.typekit.net/qjr3liq.css"> --> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> @@ -14,106 +16,7 @@ </head> <style> - /* Center website */ - .main { - margin: auto; - position: relative; - max-width: 1000px; - } - - .row { - margin: 10px -16px; - } - - /* Add padding BETWEEN each column */ - .row, - .row > .column { - padding: 10px; - } - - /* Create three equal columns that floats next to each other */ - .column { - float: left; - width: 33.33%; - } - - /* Clear floats after rows */ - .row:after { - content: ""; - display: table; - clear: both; - } - - /* Style the buttons */ - .btn { - position: relative; - margin-top: 20px; - border: none; - outline: none; - padding: 12px 16px; - background-color: white; - cursor: pointer; - } - - .btn:hover { - background-color: #ddd; - color: white; - } - - .btn.active { - background-color: #666; - color: white; - } - - .i { - cursor: pointer; - } - - - h1 { - font-size: 50px; - word-break: break-all; - } - - #header { - margin: auto; - position: relative; - max-width: 1000px; - - left: auto; - right: auto; - border: none; - /*padding: 30px;*/ - background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url("https://images.unsplash.com/photo-1521587760476-6c12a4b040da?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80"); - background-repeat: no-repeat; - /*height: 30%;*/ - /*width: 52%;*/ - height: 250px; - width: 1000px; - background-position: center; - background-size: auto; - } - - #title { - margin: auto; - text-align: center; - position: relative; - top: 50%; - left: 15%; - transform: translate(-25%, -25%); - color: white; - } - - @import url(https://fonts.googleapis.com/css?family=Open+Sans); - .search { - width: 100%; - position: relative; - display: flex; - } - .navbar a:hover, .dropdown:hover .dropbtn, .dropbtn:focus { - background-color: #2a4b45; - } .dropdown-content { display: none; @@ -143,158 +46,123 @@ border-radius: 5%; } - .show { - display: block; - } - - /* the card feature */ - .content { - background-color: #f7f3f3; - /*background: url("https://images.unsplash.com/photo-1463947628408-f8581a2f4aca?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80");*/ - height: 160px; - box-shadow: 0 4px 8px 0 rgba(98, 66, 66, 0.2); - padding: 10px; - transition-duration: 0.2s; - border: none; - border-radius: 4px; - overflow-wrap: break-word; - word-wrap: break-word; - - } - - .content:hover { - box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); - cursor: pointer; - text-decoration: #8fd19e; - } - - .footer { - position: fixed; - left: 0; - bottom: 0; - width: 100%; - text-align: center; - background-color: #2a4b45; - color: #ffffff; - -} - </style> {#<body>#} <body onload=start()> -{% include 'topnav.html' %} - -<div id="header"> - <h2 id="title"> Contributions Catalog/Packager </h2> -</div> -<!-- MAIN (Center website) --> -<div class="main"> - - - <div id="myBtnContainer"> - {% if show_sel == "capability" %} - <button class="btn" id="all_btn" onclick="get_url('all')"> Show All</button> - <button class="btn active" id="capability_btn" onclick="get_url('capability')"> Capabilities</button> - <button class="btn" id="talent_btn" onclick="get_url('talent')"> Talents</button> - {% elif show_sel == "talent" %} - <button class="btn" id="all_btn" onclick="get_url('all')"> Show All</button> - <button class="btn" id="capability_btn" onclick="get_url('capability')"> Capabilities</button> - <button class="btn active" id="talent_btn" onclick="get_url('talent')"> Talents</button> - {% else %} - <button class="btn active" id="all_btn" onclick="get_url('all')"> Show All</button> - <button class="btn" id="capability_btn" onclick="get_url('capability')"> Capabilities</button> - <button class="btn" id="talent_btn" onclick="get_url('talent')"> Talents</button> - {% endif %} - - <div class="footer"> - <p>Version: {{ git_tag }}   SHA: {{ git_sha }}   |   © University of Illinois Board of Trustees   |   <a href="https://www.vpaa.uillinois.edu/resources/web_privacy">Privacy Policy</a> </p> - </div> + {% include 'topnav.html' %} - <div class="form-group pull-right"> - <form action="{{ url_for('contribute.result')}}" method="POST"> - <input class="search form-control bar" name="search" placeholder="Search" type="searchbar"> - <input id="myBtn" style="display:none;" type="submit" value="Submit"> - </form> - </div> - - <div class="row" id="grid-view"> - {% if cap_json|length > 0 %} - {% for capability in cap_json %} - <div class="column capability"> - <div class="content"> - <a class="card=link" href="{{ url_for('contribute.capability_details', contribution_id=capability['cont_id'], id=capability['id']) }}"> - <h4 class="capability_name">{{ capability|filter_nested_dict(["name"]) }}</h4> - <p class="capability_description">{{ capability|filter_nested_dict(["description"]) }}</p> - <p class="contributors">{{ capability|filter_nested_dict(["contributors"]) }}</p> - </a> - <a class="link" href="{{ url_for('contribute.contribution_details', contribution_id=capability['cont_id']) }}"> View Contribution >>> </a> - </div> - </div> - {% endfor %} + <div id="header"> + <h2 id="title"> Contributions Catalog/Packager </h2> + </div> + <!-- MAIN (Center website) --> + <div class="main"> + + <div id="mainContainer" class="container-fluid"> + {% if show_sel == "capability" %} + <button class="button button2" id="all_btn" onclick="get_url('all')"> Show All</button> + <button class="button button2" id="capability_btn" onclick="get_url('capability')"> Capabilities</button> + <button class="button button2" id="talent_btn" onclick="get_url('talent')"> Talents</button> + {% elif show_sel == "talent" %} + <button class="button button2" id="all_btn" onclick="get_url('all')"> Show All</button> + <button class="button button2" id="capability_btn" onclick="get_url('capability')"> Capabilities</button> + <button class="button button2" id="talent_btn" onclick="get_url('talent')"> Talents</button> + {% else %} + <button class="button button2" id="all_btn" onclick="get_url('all')"> Show All</button> + <button class="button button2" id="capability_btn" onclick="get_url('capability')"> Capabilities</button> + <button class="button button2" id="talent_btn" onclick="get_url('talent')"> Talents</button> {% endif %} - {% if tal_json|length > 0 %} - {% for talent in tal_json %} - <div class="column talent"> - <div class="content"> - <a class="card-link" href="{{ url_for('contribute.talent_details', contribution_id=talent['cont_id'], id=talent['id']) }}"> - <h4 class="talent_name">{{ talent|filter_nested_dict(["name"]) }}</h4> - <p class="talent_description">{{ talent|filter_nested_dict(["shortDescription"]) }}</p> - <p class="contributors">{{ talent|filter_nested_dict(["contributors"]) }}</p> - </a> - <a class="link" href="{{ url_for('contribute.contribution_details', contribution_id=talent['cont_id']) }}"> View Contribution >>> </a> + <div class="form-group pull-right"> + <form action="{{ url_for('contribute.result')}}" method="POST"> + <input class="search form-control bar" name="search" placeholder="Search" type="searchbar"> + <input id="myBtn" style="display:none;" type="submit" value="Submit"> + </form> + </div> + <div class="form-group"> + <p style="margin-bottom:25px;"> <!-- empty div to add space --> </p> + </div> + + <div class="row" id="grid-view"> + {% if cap_json|length > 0 %} + {% for capability in cap_json %} + <div class="column capability"> + <div class="card"> + <a class="card-link" href="{{ url_for('contribute.capability_details', contribution_id=capability['cont_id'], id=capability['id']) }}" style="text-decoration: none;"> + <h3 class="capability-name">{{ capability|filter_nested_dict(["name"]) }}</h3> + </a> + <p class="small-body-text">{{ capability|filter_nested_dict(["description"]) }}</p> + <p class="contributors">{{ capability|filter_nested_dict(["contributors"]) }}</p> + <a class="contribution-link" href="{{ url_for('contribute.contribution_details', contribution_id=capability['cont_id']) }}"> View Contribution </a> + </div> </div> - </div> - {% endfor %} - {% endif %} + {% endfor %} + {% endif %} + + {% if tal_json|length > 0 %} + {% for talent in tal_json %} + <div class="column talent"> + <div class="card"> + <a class="card-link" href="{{ url_for('contribute.talent_details', contribution_id=talent['cont_id'], id=talent['id']) }}" style="text-decoration: none;"> + <h3 class="talent-name">{{ talent|filter_nested_dict(["name"]) }}</h3> + </a> + <p class="small-body-text">{{ talent|filter_nested_dict(["shortDescription"]) }}</p> + <p class="contributors">{{ talent|filter_nested_dict(["contributors"]) }}</p> + <a class="contribution-link" href="{{ url_for('contribute.contribution_details', contribution_id=talent['cont_id']) }}"> View Contribution </a> + </div> + </div> + {% endfor %} + {% endif %} - {% if (tal_json|length == 0) and (cap_json|length == 0) %} - <div> - <h4 class="talent_name">There are no published contributions.</h4> - </div> - {% endif %} - </div><!-- END GRID --> + {% if (tal_json|length == 0) and (cap_json|length == 0) %} + <div> + <h4 class="talent_name">There are no published contributions.</h4> + </div> + {% endif %} + </div><!-- END GRID --> + </div><!-- END mainContainer --> + </div><!-- END Main --> + {% include 'footer.html' %} {% include 'topnav_javascript.html' %} + <script> - window.onclick = function (event) { - if (!event.target.matches('.dropbtn')) { - var dropdowns = document.getElementsByClassName("dropdown-content"); - for (let i = 0; i < dropdowns.length; i++) { - var openDropdown = dropdowns[i]; - if (openDropdown.classList.contains('show')) { - openDropdown.classList.remove('show'); - } + window.onclick = function (event) { + if (!event.target.matches('.dropbtn')) { + var dropdowns = document.getElementsByClassName("dropdown-content"); + for (let i = 0; i < dropdowns.length; i++) { + var openDropdown = dropdowns[i]; + if (openDropdown.classList.contains('show')) { + openDropdown.classList.remove('show'); } } } + } - function get_url(c) { - var cur_url = window.location.href.split('/'); - if (c === "all") - window.location.href = cur_url[0] + "?show=all" - if (c === "capability") - window.location.href = cur_url[0] + "?show=capability" - if (c === "talent") - window.location.href = cur_url[0] + "?show=talent" - } + function get_url(c) { + var cur_url = window.location.href.split('/'); + if (c === "all") + window.location.href = cur_url[0] + "?show=all" + if (c === "capability") + window.location.href = cur_url[0] + "?show=capability" + if (c === "talent") + window.location.href = cur_url[0] + "?show=talent" + } - // Add active class to the current button (highlight it) - var btnContainer = document.getElementById("myBtnContainer"); - var btns = btnContainer.getElementsByClassName("btn"); - for (var i = 0; i < btns.length; i++) { - btns[i].addEventListener("click", function () { - var current = document.getElementsByClassName("active"); - current[0].className = current[0].className.replace(" active", ""); - this.className += " active"; - }); - } + // Add active class to the current button (highlight it) + var mainContainer = document.getElementById("mainContainer"); + var btns = mainContainer.getElementsByClassName("btn"); + for (var i = 0; i < btns.length; i++) { + btns[i].addEventListener("click", function () { + var current = document.getElementsByClassName("active"); + current[0].className = current[0].className.replace(" active", ""); + this.className += " active"; + }); + } - </script> - </div> +</script> -</div> </body> + </html> diff --git a/contributions/catalog/webapps/templates/contribute/home.html.old b/contributions/catalog/webapps/templates/contribute/home.html.old deleted file mode 100644 index 195fc445..00000000 --- a/contributions/catalog/webapps/templates/contribute/home.html.old +++ /dev/null @@ -1,468 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - <meta content="width=device-width, initial-scale=1" name="viewport"> - <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> - <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> - <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> - <!-- <link href="{{ url_for('static', filename='css/filter.css') }}" rel="stylesheet">--> - <link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet" type="text/css"> - <link href="{{ url_for('static', filename='css/bar.css') }}" rel="stylesheet" type="text/css"> - <link href="{{ url_for('static', filename='js/modernizr.js') }}" rel="javascript"> - <script src="../../static/js/modernizr.js"></script> <!-- Modernizr --> - <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> -</head> - -<style> - /* Center website */ - .main { - margin: auto; - position: relative; - max-width: 1000px; - } - - .row { - margin: 10px -16px; - } - - /* Add padding BETWEEN each column */ - .row, - .row > .column { - padding: 10px; - } - - /* Create three equal columns that floats next to each other */ - .column { - float: left; - width: 33.33%; - display: none; /* Hide all elements by default */ - } - - /* Clear floats after rows */ - .row:after { - content: ""; - display: table; - clear: both; - } - - /* Style the buttons */ - .btn { - position: relative; - margin-top: 20px; - border: none; - outline: none; - padding: 12px 16px; - background-color: white; - cursor: pointer; - } - - .btn:hover { - background-color: #ddd; - color: white; - } - - .btn.active { - background-color: #666; - color: white; - } - - .i { - cursor: pointer; - } - - - h1 { - font-size: 50px; - word-break: break-all; - } - - #header { - margin: auto; - position: relative; - max-width: 1000px; - - left: auto; - right: auto; - border: none; - /*padding: 30px;*/ - background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url("https://images.unsplash.com/photo-1521587760476-6c12a4b040da?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80"); - background-repeat: no-repeat; - /*height: 30%;*/ - /*width: 52%;*/ - height: 250px; - width: 1000px; - background-position: center; - background-size: auto; - } - - #title { - margin: auto; - text-align: center; - position: relative; - top: 50%; - left: 15%; - transform: translate(-25%, -25%); - color: white; - } - - @import url(https://fonts.googleapis.com/css?family=Open+Sans); - .search { - width: 100%; - position: relative; - display: flex; - } - - .navbar a:hover, .dropdown:hover .dropbtn, .dropbtn:focus { - background-color: #2a4b45; - } - - .dropdown-content { - display: none; - position: relative; - background-color: #2a4b45; - min-width: 160px; - box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); - /*z-index: 1;*/ - cursor: pointer; - } - - .dropdown-content a { - float: right; - color: black; - padding: 12px 16px; - text-decoration: none; - display: block; - padding-right: 50px; - padding-left: 50px; - text-align: right; - cursor: pointer; - } - - .dropdown-content a:hover { - background-color: #f4f7f5; - border: grey; - border-radius: 5%; - } - - .show { - display: block; - } - - /* the card feature */ - .content { - background-color: #f7f3f3; - /*background: url("https://images.unsplash.com/photo-1463947628408-f8581a2f4aca?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80");*/ - height: 160px; - box-shadow: 0 4px 8px 0 rgba(98, 66, 66, 0.2); - padding: 10px; - transition-duration: 0.2s; - border: none; - border-radius: 4px; - overflow-wrap: break-word; - word-wrap: break-word; - - } - - .content:hover { - box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); - cursor: pointer; - text-decoration: #8fd19e; - } - -</style> - -<body onload=start()> -<div class="topnav" id="myTopnav"> - <a href="{{ url_for('contribute.home') }}"><i class="fa fa fa-home fa-lg"></i> Contributions Catalog</a> - <div id="submit_contribution" style="display: none;"> - <a href="{{ url_for('contribute.create') }}"><i class="fa fa-plus-square fa-lg"></i> Contribute</a> - </div> - - - <div class="topnav-right" id="nav_login" style="display: none; float: right; margin-right: 15px;"> - <a href="{{ url_for('contribute.login') }}"><i class="fa fa-sign-in fa-lg"></i> Login</a> - </div> - - <div class="topnav-right" id="nav_greeting" style="display: none; float: right; margin-right: 15px;"> - <meta id="nav-user-data" user="{{user}}"> - <a class="dropbtn" id="user_profile"><i class="fa fa-fw fa-user fa-lg"></i> Hello, {{ user }}! </a> - </div> -</div> - -<div class="dropdown-content" id="myDropdown" style="display: none"> - <a href="{{ url_for('contribute.logout') }}">Logout</a> -</div> - -<div id="header"> - <h2 id="title"> Contributions Catalog/Packager </h2> -</div> -<!-- MAIN (Center website) --> -<div class="main"> - - - <div id="myBtnContainer"> - - <button class="btn active" id="all_btn" onclick="filterSelection('all')"> Show All</button> - <button class="btn" id="capability_btn" onclick="filterSelection('capability')"> Capabilities</button> - <button class="btn" id="talent_btn" onclick="filterSelection('talent')"> Talents</button> - <div class="form-group pull-right"> - <form action="http://localhost:5050/contribute/results" method="POST"> - <input class="search form-control bar" name="search" placeholder="Search" type="searchbar"> - <input id="myBtn" style="display:none;" type="submit" value="Submit"> - </form> - </div> - - <div class="row" id="grid-view"> - <!-- Template for cards --> - <script id="capability_template" type="text/template"> - <a href="" class="card-link"> - <div class="column capability"> - <div class="content"> - <h4 class="capability_name"></h4> - <p class="capability_description"></p> - <p class="contributors"></p> - <a class="link"> View Contribution >>> </a> - <!-- <span class="label label-default">App Config</span>--> - </div> - </div> - </a> - </script> - - <script id="talent_template" type="text/template"> - <a href="" class="card-link"> - <div class="column talent"> - <div class="content"> - <h4 class="talent_name"></h4> - <p class="talent_description"></p> - <p class="contributors"></p> - <a class="link" > View Contribution >>> </a> - <!-- <span class="label label-default">App Config</span>--> - </div> - </div> - </a> - </script> - <!-- END GRID --> - </div> - - <!-- END MAIN --> - </div> - - <script> - - function start() { - var user_name = "{{user}}"; - // var user_name = $('#nav-user-data').data("user"); - //console.log(user_name) - // alert(user_name) - var nav_login = document.getElementById('nav_login'); - var nav_greet = document.getElementById('nav_greeting') - var nav_user = document.getElementById('user_profile') - var submit_btn = document.getElementById('submit_contribution') - if (user_name.length > 0) { - nav_login.style.display = 'none'; - nav_greet.style.display = 'block'; - nav_user.style.display = 'block'; - submit_btn.style.display = 'block'; - } else { - nav_login.style.display = 'block'; - nav_greet.style.display = 'none'; - nav_user.style.display = 'block'; - submit_btn.style.display = 'none'; - } - ajax('GET', get_cap_url, null, - function (res) { - var items = JSON.parse(res); - all_capability = items; - append_capability(all_capability) - filterSelection('all'); - - }, - function () { - console.log("error occured - capability"); - }); - - ajax('GET', get_talent_url, null, - function (res) { - var items = JSON.parse(res); - - all_talents = items; - append_talent(all_talents) - filterSelection('all'); - }, - function () { - console.log("error occured talent"); - }); - - window.onload = append_capability(all_capability); - window.onload = append_talent(all_talents); - } - - var user_icon = document.getElementById('user_profile'); - user_icon.addEventListener('click', function () { - if (user_icon.style.display === 'block') { - document.getElementById("myDropdown").classList.toggle("show"); - } - }) - - window.onclick = function (event) { - if (!event.target.matches('.dropbtn')) { - var dropdowns = document.getElementsByClassName("dropdown-content"); - for (let i = 0; i < dropdowns.length; i++) { - var openDropdown = dropdowns[i]; - if (openDropdown.classList.contains('show')) { - openDropdown.classList.remove('show'); - } - } - } - } - var all_capability = []; - var all_talents = [] - - var get_talent_url = "http://" + "localhost:5000/contributions/talents"; - var get_cap_url = "http://" + "localhost:5000/contributions/capabilities"; - var get_contribution_url = "http://" + "localhost:5000/contributions"; - - - - function get_contributors(data) { - return "abc@abc.com" + " NCSA" - } - - function append_capability(data) { - //Set Up the template - var s = $("#capability_template")[0].innerHTML.trim(); - var holder = document.createElement('div'); - holder.innerHTML = s; - var template = holder.childNodes; - - var member = document.getElementById('grid-view'); - data.forEach(function (object) { - - //Clone Template - var newItem = $(template).clone(); - var contributionid = object.contributionId; - var id = object.id; - - - console.log(contributionid, id) - //Populate it - $(newItem).find(".card-link").attr('href', "http://localhost:5050/contribute/details/" + contributionid + "/capabilities/" + id) - - $(newItem).find(".capability_name").html(object.name); - $(newItem).find(".capability_description").html(object.description); - $(newItem).find(".contributors").html(get_contributors(data)); - // $(newItem).click(function(){ - // // $(newItem).load("http://localhost:5050/contribute/details/" + contributionid) - // $(newItem).attr('href', "http://localhost:5050/contribute/details/" + contributionid ) - // - // }) - $(newItem).find(".link").attr('href', "http://localhost:5050/contribute/details/" + contributionid) - $("#grid-view").append(newItem); - - // newItem.onclick = function (){ - // console.log('haha') - // } - - }); - } - - function append_talent(data) { - //Set Up the template - var s = $("#talent_template")[0].innerHTML.trim(); - var holder = document.createElement('div'); - holder.innerHTML = s; - - var template = holder.childNodes; - - var member = document.getElementById('grid-view'); - data.forEach(function (object) { - var contributionid = object.contributionId; - var id = object.id; - console.log(contributionid, id) - //Clone Template - var newItem = $(template).clone(); - - //Populate it - $(newItem).find(".card-link").attr('href', "http://localhost:5050/contribute/details/" + contributionid + "/talents/" + id) - - $(newItem).find(".talent_name").html(object.name); - $(newItem).find(".talent_description").html(object.shortDescription); - $(newItem).find(".contributors").html(get_contributors(data)); - $(newItem).find(".link").attr('href', "http://localhost:5050/contribute/details/" + contributionid) - - $("#grid-view").append(newItem); - - }); - } - - function ajax(method, url, data, okcallback, errorcallback) { - var xhr = new XMLHttpRequest(); - - xhr.open(method, url, true); - xhr.setRequestHeader("Authorization", 'bearer ' + '{{token}}'); - xhr.onload = function () { - if (xhr.status == 200) { - okcallback(xhr.responseText); - } else { - errorcallback(); - } - } - - if (data == null) { - xhr.send(); - } else { - - xhr.setRequestHeader("Content-Type", "application/json;charset=utf-8"); - xhr.send(data); - } - } - - - function filterSelection(c) { - var x, i; - x = document.getElementsByClassName("column"); - if (c === "all") c = ""; - for (i = 0; i < x.length; i++) { - w3RemoveClass(x[i], "show"); - if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "show"); - } - } - - function w3AddClass(element, name) { - var i, arr1, arr2; - arr1 = element.className.split(" "); - arr2 = name.split(" "); - for (i = 0; i < arr2.length; i++) { - if (arr1.indexOf(arr2[i]) == -1) { - element.className += " " + arr2[i]; - } - } - } - - function w3RemoveClass(element, name) { - var i, arr1, arr2; - arr1 = element.className.split(" "); - arr2 = name.split(" "); - for (i = 0; i < arr2.length; i++) { - while (arr1.indexOf(arr2[i]) > -1) { - arr1.splice(arr1.indexOf(arr2[i]), 1); - } - } - element.className = arr1.join(" "); - } - - // Add active class to the current button (highlight it) - var btnContainer = document.getElementById("myBtnContainer"); - var btns = btnContainer.getElementsByClassName("btn"); - for (var i = 0; i < btns.length; i++) { - btns[i].addEventListener("click", function () { - var current = document.getElementsByClassName("active"); - current[0].className = current[0].className.replace(" active", ""); - this.className += " active"; - }); - } - - </script> - -</body> -</html> diff --git a/contributions/catalog/webapps/templates/contribute/talent_details.html b/contributions/catalog/webapps/templates/contribute/talent_details.html index 4d67f537..3652b058 100644 --- a/contributions/catalog/webapps/templates/contribute/talent_details.html +++ b/contributions/catalog/webapps/templates/contribute/talent_details.html @@ -3,7 +3,10 @@ <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1" name="viewport"> + <link rel="stylesheet" href="https://use.typekit.net/qjr3liq.css"> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css"> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> + <link rel="stylesheet" href="https://use.typekit.net/qjr3liq.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> <link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet" type="text/css"> @@ -20,210 +23,227 @@ {% include 'topnav.html' %} </div> - - <div class="container"> <h1>Talent Details</h1> <hr class="divider"/> - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Talent Name </h4> - </div> - <p class="col-sm-9">{{post.name}}</p> - </div> - - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Talent description </h4> + <div class="container details-container"> + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Talent Name </h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.name}}</div> + </div> </div> - <p class="col-sm-9">{{post.shortDescription}}</p> - </div> - {% if post.dataDescription %} <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Data Description</h4> + <div class="col-12 col-md-3"> + <h4>Talent Description </h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.shortDescription}}</div> </div> - <p class="col-sm-9">{{post.dataDescription}}</p> </div> - {% endif %} - {% if post.icon %} - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Icon</h4> - </div> - <p class="col-sm-9">{{post.icon}}</p> - </div> - {% endif %} + {% if post.dataDescription %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Data Description</h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.dataDescription}}</div> + </div> + </div> + {% endif %} - {% if post.requiredCapabilities %} - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Required Capabilities</h4> + {% if post.icon %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Icon</h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.icon}}</div> + </div> </div> - <table> - {% for x in post.requiredCapabilities %} - <tr> - <td><a href="{{ url_for('contribute.capability_details', contribution_id=x['contributionId'], id=x['capabilityId']) }}">{{x['capabilityName']}}</a></td> - </tr> - {% endfor %} - <!-- extra row for the separation to next field --> - <tr> - <td> </td> - </tr> - </table> - </div> - {% endif %} + {% endif %} - {% if post.requiredBuildingBlocks %} - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Required Building Blocks</h4> - </div> - <table> - {% for x in post.requiredBuildingBlocks %} + {% if post.requiredCapabilities %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Required Capabilities</h4> + </div> + <div class="col-12 col-md-9"> + <table> + {% for x in post.requiredCapabilities %} + <tr> + <td><a href="{{ url_for('contribute.capability_details', contribution_id=x['contributionId'], id=x['capabilityId']) }}">{{x['capabilityName']}}</a></td> + </tr> + {% endfor %} + <!-- extra row for the separation to next field --> <tr> - <td>{{x}}</td> + <td> </td> </tr> - {% endfor %} - <!-- extra row for the separation to next field --> - <tr> - <td> </td> - </tr> - </table> - </div> - {% endif %} - - {% if post.minUserPrivacyLevel %} - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Minimum user privacy level</h4> - </div> - <p class="col-sm-9">{{post.minUserPrivacyLevel}}</p> - </div> - {% endif %} - - {% if post.minEndUserRoles %} - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Minimum set of end-user roles</h4> + </table> + </div> </div> - <p class="col-sm-9"> - {% for role in post.minEndUserRoles %} - {{role}}<br> - {% endfor %}</p> - </div> - {% endif %} + {% endif %} - {% if reviewer %} - {% if post.startDate %} + {% if post.requiredBuildingBlocks %} <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Start Date</h4> + <div class="col-12 col-md-3"> + <h4>Required Building Blocks</h4> + </div> + <div class="col-12 col-md-9"> + <table> + {% for x in post.requiredBuildingBlocks %} + <tr> + <td>{{x}}</td> + </tr> + {% endfor %} + <!-- extra row for the separation to next field --> + <tr> + <td> </td> + </tr> + </table> </div> - <p class="col-sm-9">{{post.startDate}}</p> </div> {% endif %} - {% if post.endDate %} + {% if post.minUserPrivacyLevel %} <div class="row"> - <div class="col-12 col-sm-2"> - <h4>End Date</h4> + <div class="col-12 col-md-3"> + <h4>Minimum User Privacy Level</h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.minUserPrivacyLevel}}</div> </div> - <p class="col-sm-9">{{post.endDate}}</p> </div> {% endif %} - {% if post.longDescription %} + {% if post.minEndUserRoles %} <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Long Description</h4> + <div class="col-12 col-md-3"> + <h4>End-user Roles</h4> + </div> + <div class="col-12 col-md-9"> + {% for role in post.minEndUserRoles %} + <div class="small-body-text">{{role}}<br> </div> + {% endfor %} </div> - <p class="col-sm-9">{{post.longDescription}}</p> </div> {% endif %} - {% if post.selfCertification %} - <div class="row"> - <div class="col-12 col-sm-2"> - <h4>Self Certification</h4> + {% if reviewer %} + {% if post.startDate %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Start Date</h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.startDate}}</div> + </div> </div> - <p class="col-sm-9"> - <table> - {% if post.selfCertification.dataDeletionUponRequest %} - <tr> - <td><b>Deleting data upon request </b></td> - <td>{{post.selfCertification.dataDeletionUponRequest}}</td> - </tr> - {% else %} + {% endif %} + + {% if post.endDate %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>End Date</h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.endDate}}</div> + </div> + </div> + {% endif %} + + {% if post.longDescription %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Long Description</h4> + </div> + <div class="col-12 col-md-9"> + <div class="small-body-text">{{post.longDescription}}</div> + </div> + </div> + {% endif %} + + {% if post.selfCertification %} + <div class="row"> + <div class="col-12 col-md-3"> + <h4>Self Certification</h4> + </div> + <div class="col-12 col-md-9"> + <table> + {% if post.selfCertification.dataDeletionUponRequest %} <tr> - <td><b>Deleting data upon request </b></td> - <td>None</td> + <td><b>Deleting Data Upon Request </b></td> + <td>{{post.selfCertification.dataDeletionUponRequest}}</td> </tr> - {% endif %} - {% if post.selfCertification.discloseAds %} - <tr> - <td><b>Disclose ads </b></td> - <td>{{post.selfCertification.discloseAds}}</td> - </tr> - {% else %} + {% else %} + <tr> + <td><b>Deleting Data Upon Request </b></td> + <td>None</td> + </tr> + {% endif %} + {% if post.selfCertification.discloseAds %} <tr> - <td><b>Disclose ads </b></td> - <td>None</td> + <td><b>Disclose Ads </b></td> + <td>{{post.selfCertification.discloseAds}}</td> </tr> - {% endif %} - {% if post.selfCertification.discloseImageRights %} - <tr> - <td><b>Disclose right to use images </b></td> - <td>{{post.selfCertification.discloseImageRights}}</td> - </tr> - {% else %} + {% else %} + <tr> + <td><b>Disclose Ads </b></td> + <td>None</td> + </tr> + {% endif %} + {% if post.selfCertification.discloseImageRights %} <tr> - <td><b>Disclose right to use images </b></td> - <td>None</td> + <td><b>Disclose Right to Use Images </b></td> + <td>{{post.selfCertification.discloseImageRights}}</td> </tr> - {% endif %} - {% if post.selfCertification.discloseSponsors %} - <tr> - <td><b>Disclose sponsors </b></td> - <td>{{post.selfCertification.discloseSponsors}}</td> - </tr> - {% else %} + {% else %} + <tr> + <td><b>Disclose Right to Use Images </b></td> + <td>None</td> + </tr> + {% endif %} + {% if post.selfCertification.discloseSponsors %} <tr> - <td><b>Disclose sponsors </b></td> - <td>None</td> + <td><b>Disclose Sponsors </b></td> + <td>{{post.selfCertification.discloseSponsors}}</td> </tr> - {% endif %} - {% if post.selfCertification.respectingUserPrivacySetting %} - <tr> - <td><b>Respecting privacy setting </b></td> - <td>{{post.selfCertification.respectingUserPrivacySetting}}</td> - </tr> - {% else %} + {% else %} + <tr> + <td><b>Disclose Sponsors </b></td> + <td>None</td> + </tr> + {% endif %} + {% if post.selfCertification.respectingUserPrivacySetting %} <tr> - <td><b>Respecting privacy setting </b></td> - <td>None</td> + <td><b>Respecting Privacy Setting </b></td> + <td>{{post.selfCertification.respectingUserPrivacySetting}}</td> </tr> - {% endif %} - </table> - </p> - </div> + {% else %} + <tr> + <td><b>Respecting Privacy Setting </b></td> + <td>None</td> + </tr> + {% endif %} + </table> + </div> + </div> + {% endif %} {% endif %} - {% endif %} + </div> - <button class="button button3" onclick="get_url()">View Contribution</button> + <button class="button button2" onclick="get_url()">View Contribution</button> </div> -<div class="action"> - -</div> - </body> - +{% include 'footer.html' %} {% include 'topnav_javascript.html' %} <script> diff --git a/contributions/catalog/webapps/templates/footer.html b/contributions/catalog/webapps/templates/footer.html new file mode 100644 index 00000000..45c91aec --- /dev/null +++ b/contributions/catalog/webapps/templates/footer.html @@ -0,0 +1,7 @@ +<!-- Rokwire footer --> +<div class="rokwire-footer"> + <img src= "{{ url_for('static', filename='powered-by-rokwire-no-i-block.png') }}" + srcset="{{ url_for('static', filename='powered-by-rokwire-no-i-block@2x.png') }} 2x, {{ url_for('static', filename='powered-by-rokwire-no-i-block@3x.png') }} 3x" + alt="footer logo" /> + <div>Version: {{ git_tag }}   SHA: {{ git_sha }}   |   © University of Illinois Board of Trustees   |   <a href="https://www.vpaa.uillinois.edu/resources/web_privacy" class="link">Privacy Policy</a> </div> +</div> diff --git a/contributions/catalog/webapps/templates/head.html b/contributions/catalog/webapps/templates/head.html index a4c2b3fd..87b7cc60 100644 --- a/contributions/catalog/webapps/templates/head.html +++ b/contributions/catalog/webapps/templates/head.html @@ -1,5 +1,7 @@ <meta content="width=device-width, initial-scale=1" name="viewport"> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> +<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css"> +<link rel="stylesheet" href="https://use.typekit.net/qjr3liq.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script> <!-- <link href="{{ url_for('static', filename='css/filter.css') }}" rel="stylesheet">--> diff --git a/contributions/catalog/webapps/templates/style.html b/contributions/catalog/webapps/templates/style.html index 6c49e7dd..539ac8f2 100644 --- a/contributions/catalog/webapps/templates/style.html +++ b/contributions/catalog/webapps/templates/style.html @@ -29,36 +29,6 @@ clear: both; } - /* Style the buttons */ - .btn { - position: relative; - margin-top: 20px; - border: none; - outline: none; - padding: 12px 16px; - background-color: white; - cursor: pointer; - } - - .btn:hover { - background-color: #ddd; - color: white; - } - - .btn.active { - background-color: #666; - color: white; - } - - .i { - cursor: pointer; - } - - - h1 { - font-size: 50px; - word-break: break-all; - } #header { margin: auto; diff --git a/contributions/catalog/webapps/templates/topnav.html b/contributions/catalog/webapps/templates/topnav.html index 1b90cbfa..5aa594a9 100644 --- a/contributions/catalog/webapps/templates/topnav.html +++ b/contributions/catalog/webapps/templates/topnav.html @@ -1,19 +1,32 @@ <div class="topnav" id="myTopnav"> - <a href="{{ url_for('contribute.home') }}"><i class="fa fa fa-home fa-lg"></i> Contributions Catalog</a> - <div id="submit_contribution" style="display: none;"> - <a href="{{ url_for('contribute.create') }}"><i class="fa fa-plus-square fa-lg"></i> Contribute</a> + <div class="topnav-left"> + <div id="catalog-home"> + <a href="https://illinois.edu"> + <img class="block-i" src="{{url_for('static',filename = 'block-i-white-orange.png')}}"> + </a> + <a href="{{ url_for('contribute.home') }}"> + <h1 class="catalog-home">Contributions Catalog</h1> + </a> + </div> + <div id="submit_contribution" class="topnav-contribute" style="display: none;"> + <button class="topnav-contribute-button btn" onclick="location.href = '{{ url_for('contribute.create') }}';" style="outline: none;"> + Contribute <i class="bi bi-plus-lg"></i> + </button> + </div> </div> - <div class="topnav-right" id="nav_greeting" style="display: none; float: right; margin-right: 15px;"> - <meta id="nav-user-data" user="{{user}}"> - <a class="dropbtn" id="user_profile"><i class="fa fa-fw fa-user fa-lg"></i> Hello, {{ user }}! </a> + <div class="topnav-right"> + <div id="nav_greeting" style="display: none;"> + <meta id="nav-user-data" user="{{user}}"> + <div id="user_profile" class="user-greeting">Hello, {{ user }} </div> + </div> + <div id="nav_logout" style="display: none;"> + <button class="topnav-login-logout-button btn" onclick="location.href = '{{ url_for('contribute.logout') }}';" style="outline: none;"> Logout</button> + </div> + <div id="nav_login" style="display: none;"> + <button class="topnav-login-logout-button btn" onclick="location.href = '{{ url_for('contribute.login') }}';" style="outline: none;"> Login</button> + </div> </div> - <div class="topnav-right" id="nav_login" style="display: none; float: right; margin-right: 15px;"> - <a href="{{ url_for('contribute.login') }}"><i class="fa fa-sign-in fa-lg"></i> Login</a> - </div> </div> -<div class="dropdown-content" id="myDropdown" style="display: none"> - <a href="{{ url_for('contribute.logout') }}">Logout</a> -</div> \ No newline at end of file diff --git a/contributions/catalog/webapps/templates/topnav_javascript.html b/contributions/catalog/webapps/templates/topnav_javascript.html index 38737e44..14accb41 100644 --- a/contributions/catalog/webapps/templates/topnav_javascript.html +++ b/contributions/catalog/webapps/templates/topnav_javascript.html @@ -4,30 +4,24 @@ if (user_name == "None") { user_name = ""; } - // var user_name = $('#nav-user-data').data("user"); - // console.log(user_name) - // alert(user_name) var nav_login = document.getElementById('nav_login'); + var nav_logout = document.getElementById('nav_logout'); var nav_greet = document.getElementById('nav_greeting') var nav_user = document.getElementById('user_profile') var submit_btn = document.getElementById('submit_contribution') if (user_name.length > 0) { nav_login.style.display = 'none'; + nav_logout.style.display = 'block' nav_greet.style.display = 'block'; nav_user.style.display = 'block'; submit_btn.style.display = 'block'; } else { nav_login.style.display = 'block'; + nav_logout.style.display = 'none' nav_greet.style.display = 'none'; nav_user.style.display = 'block'; submit_btn.style.display = 'none'; } } - var user_icon = document.getElementById('user_profile'); - user_icon.addEventListener('click', function () { - if (user_icon.style.display === 'block') { - document.getElementById("myDropdown").classList.toggle("show"); - } - }) </script> \ No newline at end of file diff --git a/contributions/contribution.yaml b/contributions/contribution.yaml index e21c6117..a78267f9 100644 --- a/contributions/contribution.yaml +++ b/contributions/contribution.yaml @@ -2,7 +2,7 @@ openapi: 3.0.0 info: title: Rokwire Contributions Building Block API description: Contributions Building Block API Documentation - version: 1.17.0 + version: 1.18.0 servers: - url: https://api.rokwire.illinois.edu description: Production server diff --git a/contributions/requirements.txt b/contributions/requirements.txt index 48952f25..6f63dea9 100644 --- a/contributions/requirements.txt +++ b/contributions/requirements.txt @@ -1,14 +1,14 @@ -Flask==1.1.1 +Flask==2.2.3 itsdangerous==2.0.1 Jinja2==3.0.3 Flask-Cors==3.0.10 pymongo[tls,srv]==3.7.2 requests==2.22.0 pyjwt==2.4.0 -cryptography==3.3.2 +cryptography==39.0.1 python-dotenv==0.10.3 gunicorn==19.9.0 gevent==21.12.0 -connexion[swagger-ui]==2.9.0 +connexion[swagger-ui]==2.10.0 ../lib/auth-middleware diff --git a/eventservice/events.yaml b/eventservice/events.yaml index ac236a6d..a7bb2865 100755 --- a/eventservice/events.yaml +++ b/eventservice/events.yaml @@ -2,7 +2,7 @@ openapi: 3.0.0 info: title: Rokwire Events Building Block API description: Events Building Block API Documentation - version: 1.17.0 + version: 1.18.0 servers: - url: https://api.rokwire.illinois.edu description: Production server diff --git a/eventservice/requirements.txt b/eventservice/requirements.txt index 167cbb26..3d8bd999 100644 --- a/eventservice/requirements.txt +++ b/eventservice/requirements.txt @@ -4,7 +4,7 @@ Jinja2==3.0.3 pymongo[tls,srv]==3.7.2 requests==2.22.0 pyjwt==2.4.0 -cryptography==3.3.2 +cryptography==39.0.1 gunicorn==20.0.4 boto3==1.9.188 python-dotenv==0.10.3 diff --git a/lib/auth-middleware/setup.py b/lib/auth-middleware/setup.py index 5793aab0..80bafd03 100644 --- a/lib/auth-middleware/setup.py +++ b/lib/auth-middleware/setup.py @@ -29,7 +29,7 @@ install_requires=[ 'PyJWT>=2.4.0,<3', 'requests>=2.22.0,<3', - 'cryptography>=3,<4', + 'cryptography>=39', # I would require flask here, but I want to use the version that the # "calling" app uses, and I don't see a way to guarantee that pip # installs the dependency in the correct order (eg. "calling app" first diff --git a/requirements-dev.txt b/requirements-dev.txt index d89f250a..ee0220e1 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,2 @@ -detect-secrets==1.0.3 -pre-commit>=2.0.0,<3 \ No newline at end of file +detect-secrets==1.4.0 +pre-commit>=3.0.0,<4 \ No newline at end of file